<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://uppy.io/blog/</id>
    <title>Uppy Blog</title>
    <updated>2025-09-01T00:00:00.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://uppy.io/blog/"/>
    <subtitle>Uppy Blog</subtitle>
    <icon>https://uppy.io/img/logo.svg</icon>
    <entry>
        <title type="html"><![CDATA[Announcing Uppy 5.0: headless components and hooks]]></title>
        <id>https://uppy.io/blog/uppy-5.0/</id>
        <link href="https://uppy.io/blog/uppy-5.0/"/>
        <updated>2025-09-01T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[<img]]></summary>
        <content type="html"><![CDATA[<img src="https://uppy.io/img/blog/5.0/og-image.png" alt="Annoucement image for 5.0, showing a new component in the background">
<p>The dog didn’t eat <em>our</em> homework, so we’re here to show you what we’ve been up
to over the past year. We are proud to announce Uppy 5.0! Our faithful
file-uploading companion has been attending all the training courses and is now
equipped with the most requested feature of all time: truly composable, headless
UI components. For years, developers have found themselves stuck between
Dashboard’s kitchen-sink approach and the bare-bones drag-drop plugin, with
little room to build something that fits just right.</p>
<p>This major release brings headless components and hooks to address those needs.
Everything has been backported to 4.0 as well, so you can get going without the
need to upgrade.</p>
<p>With Uppy 5.0 , you can finally build the exact upload experience your users
deserve – modular, accessible, and tailored to your needs. Whether you need a
simple file picker or a complex multi-source interface, Uppy’s got the building
blocks to make it happen.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="building-your-ui-the-need-for-something-new">Building your UI: the need for something new<a href="https://uppy.io/blog/uppy-5.0/#building-your-ui-the-need-for-something-new" class="hash-link" aria-label="Direct link to Building your UI: the need for something new" title="Direct link to Building your UI: the need for something new" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="one-size-fits-no-one">One size fits no one<a href="https://uppy.io/blog/uppy-5.0/#one-size-fits-no-one" class="hash-link" aria-label="Direct link to One size fits no one" title="Direct link to One size fits no one" translate="no">​</a></h3>
<p>Until now, developers starting with Uppy were forced to choose between either
the full-featured, bundle-size-heavy, and non-customizable <code>dashboard</code> or the
overly barebones <code>drag-drop</code>.</p>
<p>After years of talking to developers on GitHub and the community forum, and
feedback from Transloadit customers, the reality seems to be that the needs of
the majority of people fall somewhere <em>in between</em> <code>dashboard</code> and <code>drag-drop</code>.
Countless issues have been posted about users wanting mostly X, but doing Y
differently for their use case.</p>
<p><code>@uppy/dashboard</code> has tried to accommodate some of these requests over the
years, which introduced overly specific “toggles”, such as
<code>showLinkToFileUploadResult</code>, <code>showProgressDetails</code>, <code>hideUploadButton</code>,
<code>hideRetryButton</code>, <code>hidePauseResumeButton</code>, <code>hideCancelButton</code>,
<code>hideProgressAfterFinish</code>, <code>showRemoveButtonAfterComplete</code>, <code>disableStatusBar</code>,
<code>disableInformer</code>, and <code>disableThumbnailGenerator</code>.</p>
<p>Continuing down this path is not maintainable, nor will we ever reach a set of
toggles at this level of granularity to support a wide range of use cases and
unique requirements.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="fake-promises-of-modular-ui-components">Fake promises of modular UI components<a href="https://uppy.io/blog/uppy-5.0/#fake-promises-of-modular-ui-components" class="hash-link" aria-label="Direct link to Fake promises of modular UI components" title="Direct link to Fake promises of modular UI components" translate="no">​</a></h3>
<p>We built <code>status-bar</code>, <code>progress-bar</code>, <code>image-editor</code>, <code>thumbnail-generator</code>,
<code>informer</code>, and <code>provider-views</code> as separate plugins. At first glance, these
look to be standalone components, but they are tightly coupled to <code>dashboard</code>.
It’s not impossible to use them separately, but there is little flexibility.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="modern-expectations">Modern expectations<a href="https://uppy.io/blog/uppy-5.0/#modern-expectations" class="hash-link" aria-label="Direct link to Modern expectations" title="Direct link to Modern expectations" translate="no">​</a></h3>
<p>Since Uppy’s conception ten years ago, the front-end landscape has changed
significantly. Uppy is even built with a “vanilla-first” approach, because that
was still popular at the time over front-end frameworks.</p>
<p><strong>These days, developers have high expectations when it comes to choosing a
library</strong>. In a world where everything is component driven, OSS UI libraries are
expected to offer truly composable building blocks that are light on bundle
size, and ideally keep accessibility in mind.</p>
<p>If Uppy is to stay relevant in the coming years, a major change is needed in the
way we let users build their uploading UI.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="create-the-ui-of-your-dreams-using-headless-components-and-hooks">Create the UI of your dreams using headless components and hooks<a href="https://uppy.io/blog/uppy-5.0/#create-the-ui-of-your-dreams-using-headless-components-and-hooks" class="hash-link" aria-label="Direct link to Create the UI of your dreams using headless components and hooks" title="Direct link to Create the UI of your dreams using headless components and hooks" translate="no">​</a></h2>
<p><strong>Uppy 5.0 introduces composable UI components and hooks that provide granular
control without sacrificing first-class framework support</strong>. These components
are designed to be lightweight, accessible, and fully customizable, while
maintaining compatibility with <strong>React, Vue, and Svelte</strong>.</p>
<p>Uppy now offers three ways to build user interfaces:</p>
<ol>
<li class=""><strong>Pre-composed, plug-and-play components.</strong> Nothing new here. These are the
old <code>&lt;Dashboard /&gt;</code> and <code>&lt;DragDrop /&gt;</code>. The downside of this option is that
you cannot customize the UI.</li>
<li class=""><strong>Headless components 🆕</strong> These new components are smaller, with styles that
are easier to override. You can compose these together with your own
components.</li>
<li class=""><strong>Hooks 🆕</strong> Use hooks to attach our logic to your own components. There are
no restrictions. Enjoy the freedom to create a truly tailor-made UI.</li>
</ol>
<p>When using the new components or hooks, you can use the
<strong><code>&lt;UppyContextProvider /&gt;</code></strong> to provide the Uppy instance to the components and
hooks.</p>
<div class="theme-tabs-container tabs-container tabList__CuJ"><ul role="tablist" aria-orientation="horizontal" class="tabs"><li role="tab" tabindex="0" aria-selected="true" class="tabs__item tabItem_LNqP tabs__item--active">React</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">Vue</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">Svelte</li></ul><div class="margin-top--md"><div role="tabpanel" class="tabItem_Ymn6"><div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-tsx codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:#393A34">{</span><span class="token imports"> useState </span><span class="token imports punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'react'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports maybe-class-name">Uppy</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@uppy/core'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:#393A34">{</span><span class="token imports"> </span><span class="token imports maybe-class-name">UppyContextProvider</span><span class="token imports"> </span><span class="token imports punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@uppy/react'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">App</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">uppy</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useState</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">Uppy</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">UppyContextProvider</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">uppy</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:#393A34">=</span><span class="token tag script language-javascript punctuation" style="color:#393A34">{</span><span class="token tag script language-javascript" style="color:#00009f">uppy</span><span class="token tag script language-javascript punctuation" style="color:#393A34">}</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">{</span><span class="token comment" style="color:#999988;font-style:italic">/* ... */</span><span class="token punctuation" style="color:#393A34">}</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag class-name" style="color:#00009f">UppyContextProvider</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><div class="language-html codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-html codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">template</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">UppyContextProvider</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">:uppy</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">uppy</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token comment" style="color:#999988;font-style:italic">&lt;!-- ... --&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">UppyContextProvider</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">template</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">script</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">setup</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">lang</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">ts</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">	</span><span class="token script language-javascript keyword module" style="color:#00009f">import</span><span class="token script language-javascript"> </span><span class="token script language-javascript imports maybe-class-name">Uppy</span><span class="token script language-javascript"> </span><span class="token script language-javascript keyword module" style="color:#00009f">from</span><span class="token script language-javascript"> </span><span class="token script language-javascript string" style="color:#e3116c">'@uppy/core'</span><span class="token script language-javascript punctuation" style="color:#393A34">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">	</span><span class="token script language-javascript keyword module" style="color:#00009f">import</span><span class="token script language-javascript"> </span><span class="token script language-javascript imports punctuation" style="color:#393A34">{</span><span class="token script language-javascript imports"> </span><span class="token script language-javascript imports maybe-class-name">UppyContextProvider</span><span class="token script language-javascript imports"> </span><span class="token script language-javascript imports punctuation" style="color:#393A34">}</span><span class="token script language-javascript"> </span><span class="token script language-javascript keyword module" style="color:#00009f">from</span><span class="token script language-javascript"> </span><span class="token script language-javascript string" style="color:#e3116c">'@uppy/vue'</span><span class="token script language-javascript punctuation" style="color:#393A34">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">	</span><span class="token script language-javascript keyword module" style="color:#00009f">import</span><span class="token script language-javascript"> </span><span class="token script language-javascript imports punctuation" style="color:#393A34">{</span><span class="token script language-javascript imports"> computed </span><span class="token script language-javascript imports punctuation" style="color:#393A34">}</span><span class="token script language-javascript"> </span><span class="token script language-javascript keyword module" style="color:#00009f">from</span><span class="token script language-javascript"> </span><span class="token script language-javascript string" style="color:#e3116c">'vue'</span><span class="token script language-javascript punctuation" style="color:#393A34">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">	</span><span class="token script language-javascript keyword" style="color:#00009f">const</span><span class="token script language-javascript"> uppy </span><span class="token script language-javascript operator" style="color:#393A34">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript function" style="color:#d73a49">computed</span><span class="token script language-javascript punctuation" style="color:#393A34">(</span><span class="token script language-javascript punctuation" style="color:#393A34">(</span><span class="token script language-javascript punctuation" style="color:#393A34">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript arrow operator" style="color:#393A34">=&gt;</span><span class="token script language-javascript"> </span><span class="token script language-javascript keyword" style="color:#00009f">new</span><span class="token script language-javascript"> </span><span class="token script language-javascript class-name">Uppy</span><span class="token script language-javascript punctuation" style="color:#393A34">(</span><span class="token script language-javascript punctuation" style="color:#393A34">)</span><span class="token script language-javascript punctuation" style="color:#393A34">)</span><span class="token script language-javascript punctuation" style="color:#393A34">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript"></span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">script</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><br></span></code></pre></div></div></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><div class="language-html codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-html codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">UppyContextProvider</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">{uppy}</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token comment" style="color:#999988;font-style:italic">&lt;!-- ... --&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">UppyContextProvider</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">script</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">lang</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">ts</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">	</span><span class="token script language-javascript keyword module" style="color:#00009f">import</span><span class="token script language-javascript"> </span><span class="token script language-javascript imports maybe-class-name">Uppy</span><span class="token script language-javascript"> </span><span class="token script language-javascript keyword module" style="color:#00009f">from</span><span class="token script language-javascript"> </span><span class="token script language-javascript string" style="color:#e3116c">'@uppy/core'</span><span class="token script language-javascript punctuation" style="color:#393A34">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">	</span><span class="token script language-javascript keyword module" style="color:#00009f">import</span><span class="token script language-javascript"> </span><span class="token script language-javascript imports punctuation" style="color:#393A34">{</span><span class="token script language-javascript imports"> </span><span class="token script language-javascript imports maybe-class-name">UppyContextProvider</span><span class="token script language-javascript imports"> </span><span class="token script language-javascript imports punctuation" style="color:#393A34">}</span><span class="token script language-javascript"> </span><span class="token script language-javascript keyword module" style="color:#00009f">from</span><span class="token script language-javascript"> </span><span class="token script language-javascript string" style="color:#e3116c">'@uppy/svelte'</span><span class="token script language-javascript punctuation" style="color:#393A34">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">	</span><span class="token script language-javascript keyword" style="color:#00009f">const</span><span class="token script language-javascript"> uppy </span><span class="token script language-javascript operator" style="color:#393A34">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript keyword" style="color:#00009f">new</span><span class="token script language-javascript"> </span><span class="token script language-javascript class-name">Uppy</span><span class="token script language-javascript punctuation" style="color:#393A34">(</span><span class="token script language-javascript punctuation" style="color:#393A34">)</span><span class="token script language-javascript punctuation" style="color:#393A34">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript"></span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">script</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><br></span></code></pre></div></div></div></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="new-components">New components<a href="https://uppy.io/blog/uppy-5.0/#new-components" class="hash-link" aria-label="Direct link to New components" title="Direct link to New components" translate="no">​</a></h3>
<p>All components come with sensible defaults, but expose data attributes for
complete styling control. This approach delivers the flexibility developers
need, while maintaining the plug-and-play experience Uppy is known for.</p>
<div class="theme-tabs-container tabs-container tabList__CuJ"><ul role="tablist" aria-orientation="horizontal" class="tabs"><li role="tab" tabindex="0" aria-selected="true" class="tabs__item tabItem_LNqP tabs__item--active">UploadButton</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">Dropzone</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">FilesList</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">FilesGrid</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">Thumbnail</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">ProviderIcon</li></ul><div class="margin-top--md"><div role="tabpanel" class="tabItem_Ymn6"><p>Upload button with inner progres bar and conditional pause/resume buttons</p><p><strong>Attributes</strong></p><ul>
<li class=""><code>data-uppy-element="upload-button"</code></li>
<li class=""><code>data-state="init" | "uploading" | "paused" | "error" | "complete"</code></li>
</ul><div class="browserWindow_KJ5v"><div class="titleBar_A0Ia"><div class="trafficLights_KFjg"><div class="trafficLight_DirP close_eAD9"></div><div class="trafficLight_DirP minimize_DlvY"></div><div class="trafficLight_DirP maximize_EQB6"></div></div></div><div class="content_Mb8g"><div class="wrapper_v5d7"><div style="margin:1rem 0"><input style="display:none" id="uppy-file-input-uppy" type="file" multiple=""><button type="button">Add files</button></div><div></div></div></div></div></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><p>Drag-and-drop zone component for file uploads.</p><p><strong>Props</strong>:</p><ul>
<li class=""><code>width?: string</code></li>
<li class=""><code>height?: string</code></li>
<li class=""><code>note?: string</code></li>
<li class=""><code>noClick?: boolean</code></li>
</ul><div class="browserWindow_KJ5v"><div class="titleBar_A0Ia"><div class="trafficLights_KFjg"><div class="trafficLight_DirP close_eAD9"></div><div class="trafficLight_DirP minimize_DlvY"></div><div class="trafficLight_DirP maximize_EQB6"></div></div></div><div class="content_Mb8g"><div class="wrapper__9Tk"><div></div></div></div></div></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><p>Component for displaying a list view of selected files.</p><p><strong>Props</strong>:</p><ul>
<li class=""><code>editFile?: (file: UppyFile&lt;Meta, Body&gt;) =&gt; void</code></li>
</ul><div class="browserWindow_KJ5v"><div class="titleBar_A0Ia"><div class="trafficLights_KFjg"><div class="trafficLight_DirP close_eAD9"></div><div class="trafficLight_DirP minimize_DlvY"></div><div class="trafficLight_DirP maximize_EQB6"></div></div></div><div class="content_Mb8g"><div class="wrapper_JF00"><div></div></div></div></div></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><p>Grid layout component for displaying files in a grid format.</p><p><strong>Props</strong>:</p><ul>
<li class=""><code>columns?: number</code></li>
<li class=""><code>editFile?: (file: UppyFile&lt;Meta, Body&gt;) =&gt; void</code></li>
</ul><div class="browserWindow_KJ5v"><div class="titleBar_A0Ia"><div class="trafficLights_KFjg"><div class="trafficLight_DirP close_eAD9"></div><div class="trafficLight_DirP minimize_DlvY"></div><div class="trafficLight_DirP maximize_EQB6"></div></div></div><div class="content_Mb8g"><div class="wrapper_trOY"><div></div></div></div></div></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><p>Component for displaying image thumbnails and/or SVG icons.</p><p><strong>Props</strong>:</p><ul>
<li class=""><code>file: UppyFile&lt;Meta, Body&gt;</code></li>
<li class=""><code>width?: string</code></li>
<li class=""><code>height?: string</code></li>
<li class=""><code>images?: boolean</code></li>
</ul><div class="browserWindow_KJ5v"><div class="titleBar_A0Ia"><div class="trafficLights_KFjg"><div class="trafficLight_DirP close_eAD9"></div><div class="trafficLight_DirP minimize_DlvY"></div><div class="trafficLight_DirP maximize_EQB6"></div></div></div><div class="content_Mb8g"><div class="wrapper_wQQc"></div></div></div></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><p>Common icons, such as a webcam, device, Dropbox, Google Drive, OneDrive, etc.</p><p><strong>Props</strong>:</p><ul>
<li class=""><code>provider</code>:
<code>'device' | 'camera' | 'screen-capture' | 'audio' | 'dropbox' | 'facebook' | 'instagram' | 'onedrive' | 'googlephotos' | 'googledrive'</code></li>
<li class=""><code>fill?: string</code></li>
</ul><div class="browserWindow_KJ5v"><div class="titleBar_A0Ia"><div class="trafficLights_KFjg"><div class="trafficLight_DirP close_eAD9"></div><div class="trafficLight_DirP minimize_DlvY"></div><div class="trafficLight_DirP maximize_EQB6"></div></div></div><div class="content_Mb8g"><div class="wrapper_LgXu"><div class="iconContainer_Fwln"><div></div><p class="providerName_m6hy">Device</p></div><div class="iconContainer_Fwln"><div></div><p class="providerName_m6hy">Camera</p></div><div class="iconContainer_Fwln"><div></div><p class="providerName_m6hy">Screen Capture</p></div><div class="iconContainer_Fwln"><div></div><p class="providerName_m6hy">Audio</p></div><div class="iconContainer_Fwln"><div></div><p class="providerName_m6hy">Dropbox</p></div><div class="iconContainer_Fwln"><div></div><p class="providerName_m6hy">Facebook</p></div><div class="iconContainer_Fwln"><div></div><p class="providerName_m6hy">Instagram</p></div><div class="iconContainer_Fwln"><div></div><p class="providerName_m6hy">OneDrive</p></div><div class="iconContainer_Fwln"><div></div><p class="providerName_m6hy">Google Photos</p></div><div class="iconContainer_Fwln"><div></div><p class="providerName_m6hy">Google Drive</p></div></div></div></div></div></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="styling-component-states">Styling component states<a href="https://uppy.io/blog/uppy-5.0/#styling-component-states" class="hash-link" aria-label="Direct link to Styling component states" title="Direct link to Styling component states" translate="no">​</a></h4>
<p>Components expose their internal state through data attributes, enabling precise
CSS targeting.</p>
<div class="language-css codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-css codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token selector" style="color:#00009f">button</span><span class="token selector attribute punctuation" style="color:#393A34">[</span><span class="token selector attribute attr-name" style="color:#00a4db">data-uppy-element</span><span class="token selector attribute operator" style="color:#393A34">=</span><span class="token selector attribute attr-value" style="color:#e3116c">'upload-button'</span><span class="token selector attribute punctuation" style="color:#393A34">]</span><span class="token selector attribute punctuation" style="color:#393A34">[</span><span class="token selector attribute attr-name" style="color:#00a4db">data-state</span><span class="token selector attribute operator" style="color:#393A34">=</span><span class="token selector attribute attr-value" style="color:#e3116c">'init'</span><span class="token selector attribute punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token property" style="color:#36acaa">background-color</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token hexcode color">#3b82f6</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token selector" style="color:#00009f">button</span><span class="token selector attribute punctuation" style="color:#393A34">[</span><span class="token selector attribute attr-name" style="color:#00a4db">data-uppy-element</span><span class="token selector attribute operator" style="color:#393A34">=</span><span class="token selector attribute attr-value" style="color:#e3116c">'upload-button'</span><span class="token selector attribute punctuation" style="color:#393A34">]</span><span class="token selector attribute punctuation" style="color:#393A34">[</span><span class="token selector attribute attr-name" style="color:#00a4db">data-state</span><span class="token selector attribute operator" style="color:#393A34">=</span><span class="token selector attribute attr-value" style="color:#e3116c">'uploading'</span><span class="token selector attribute punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token property" style="color:#36acaa">background-color</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token hexcode color">#f59e0b</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token property" style="color:#36acaa">cursor</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> wait</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token selector" style="color:#00009f">button</span><span class="token selector attribute punctuation" style="color:#393A34">[</span><span class="token selector attribute attr-name" style="color:#00a4db">data-uppy-element</span><span class="token selector attribute operator" style="color:#393A34">=</span><span class="token selector attribute attr-value" style="color:#e3116c">'upload-button'</span><span class="token selector attribute punctuation" style="color:#393A34">]</span><span class="token selector attribute punctuation" style="color:#393A34">[</span><span class="token selector attribute attr-name" style="color:#00a4db">data-state</span><span class="token selector attribute operator" style="color:#393A34">=</span><span class="token selector attribute attr-value" style="color:#e3116c">'complete'</span><span class="token selector attribute punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token property" style="color:#36acaa">background-color</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token hexcode color">#10b981</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token selector" style="color:#00009f">button</span><span class="token selector attribute punctuation" style="color:#393A34">[</span><span class="token selector attribute attr-name" style="color:#00a4db">data-uppy-element</span><span class="token selector attribute operator" style="color:#393A34">=</span><span class="token selector attribute attr-value" style="color:#e3116c">'upload-button'</span><span class="token selector attribute punctuation" style="color:#393A34">]</span><span class="token selector attribute punctuation" style="color:#393A34">[</span><span class="token selector attribute attr-name" style="color:#00a4db">data-state</span><span class="token selector attribute operator" style="color:#393A34">=</span><span class="token selector attribute attr-value" style="color:#e3116c">'error'</span><span class="token selector attribute punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token property" style="color:#36acaa">background-color</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token hexcode color">#ef4444</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="new-hooks">New hooks<a href="https://uppy.io/blog/uppy-5.0/#new-hooks" class="hash-link" aria-label="Direct link to New hooks" title="Direct link to New hooks" translate="no">​</a></h3>
<p>Examples are shown in React, but the same hooks are available in Vue and Svelte.</p>
<div class="theme-tabs-container tabs-container tabList__CuJ"><ul role="tablist" aria-orientation="horizontal" class="tabs"><li role="tab" tabindex="0" aria-selected="true" class="tabs__item tabItem_LNqP tabs__item--active">useDropzone</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">useFileInput</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">useRemoteSource</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">useWebcam</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">useScreenCapture</li></ul><div class="margin-top--md"><div role="tabpanel" class="tabItem_Ymn6"><p>Here is an example that uses hooks to exactly mimic the <code>&lt;Dropzone /&gt;</code>
component.</p><div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-tsx codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports">clsx</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'clsx'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:#393A34">{</span><span class="token imports"> useDropzone </span><span class="token imports punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@uppy/react'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">type</span><span class="token plain"> </span><span class="token class-name">DropzoneProps</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	note</span><span class="token operator" style="color:#393A34">?</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	noClick</span><span class="token operator" style="color:#393A34">?</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">boolean</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">export</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">Dropzone</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> note</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> noClick </span><span class="token punctuation" style="color:#393A34">}</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token maybe-class-name">DropzoneProps</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> getRootProps</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> getInputProps </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useDropzone</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> noClick </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">div</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">data-uppy-element</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">dropzone</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">role</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">presentation</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">			</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">input</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">				</span><span class="token tag spread punctuation" style="color:#393A34">{</span><span class="token tag spread operator" style="color:#393A34">...</span><span class="token tag spread method function property-access" style="color:#d73a49">getInputProps</span><span class="token tag spread punctuation" style="color:#393A34">(</span><span class="token tag spread punctuation" style="color:#393A34">)</span><span class="token tag spread punctuation" style="color:#393A34">}</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">				</span><span class="token tag attr-name" style="color:#00a4db">tabIndex</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:#393A34">=</span><span class="token tag script language-javascript punctuation" style="color:#393A34">{</span><span class="token tag script language-javascript operator" style="color:#393A34">-</span><span class="token tag script language-javascript number" style="color:#36acaa">1</span><span class="token tag script language-javascript punctuation" style="color:#393A34">}</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">				</span><span class="token tag attr-name" style="color:#00a4db">name</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">uppy-dropzone-file-input</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">				</span><span class="token tag attr-name" style="color:#00a4db">className</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">hidden</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">			</span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">			</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">div</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">				</span><span class="token tag spread punctuation" style="color:#393A34">{</span><span class="token tag spread operator" style="color:#393A34">...</span><span class="token tag spread method function property-access" style="color:#d73a49">getRootProps</span><span class="token tag spread punctuation" style="color:#393A34">(</span><span class="token tag spread punctuation" style="color:#393A34">)</span><span class="token tag spread punctuation" style="color:#393A34">}</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">				</span><span class="token tag attr-name" style="color:#00a4db">tabIndex</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:#393A34">=</span><span class="token tag script language-javascript punctuation" style="color:#393A34">{</span><span class="token tag script language-javascript number" style="color:#36acaa">0</span><span class="token tag script language-javascript punctuation" style="color:#393A34">}</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">				</span><span class="token tag attr-name" style="color:#00a4db">className</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:#393A34">=</span><span class="token tag script language-javascript punctuation" style="color:#393A34">{</span><span class="token tag script language-javascript function" style="color:#d73a49">clsx</span><span class="token tag script language-javascript punctuation" style="color:#393A34">(</span><span class="token tag script language-javascript" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag script language-javascript" style="color:#00009f">					</span><span class="token tag script language-javascript string" style="color:#e3116c">'border-2 border-dashed border-gray-300'</span><span class="token tag script language-javascript punctuation" style="color:#393A34">,</span><span class="token tag script language-javascript" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag script language-javascript" style="color:#00009f">					</span><span class="token tag script language-javascript string" style="color:#e3116c">'rounded-lg p-6 bg-gray-50'</span><span class="token tag script language-javascript punctuation" style="color:#393A34">,</span><span class="token tag script language-javascript" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag script language-javascript" style="color:#00009f">					</span><span class="token tag script language-javascript string" style="color:#e3116c">'transition-colors duration-200'</span><span class="token tag script language-javascript punctuation" style="color:#393A34">,</span><span class="token tag script language-javascript" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag script language-javascript" style="color:#00009f">					</span><span class="token tag script language-javascript punctuation" style="color:#393A34">{</span><span class="token tag script language-javascript" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag script language-javascript" style="color:#00009f">						</span><span class="token tag script language-javascript string-property property" style="color:#36acaa">'cursor-pointer hover:bg-blue-50'</span><span class="token tag script language-javascript operator" style="color:#393A34">:</span><span class="token tag script language-javascript" style="color:#00009f"> </span><span class="token tag script language-javascript operator" style="color:#393A34">!</span><span class="token tag script language-javascript" style="color:#00009f">noClick</span><span class="token tag script language-javascript punctuation" style="color:#393A34">,</span><span class="token tag script language-javascript" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag script language-javascript" style="color:#00009f">					</span><span class="token tag script language-javascript punctuation" style="color:#393A34">}</span><span class="token tag script language-javascript punctuation" style="color:#393A34">,</span><span class="token tag script language-javascript" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag script language-javascript" style="color:#00009f">				</span><span class="token tag script language-javascript punctuation" style="color:#393A34">)</span><span class="token tag script language-javascript punctuation" style="color:#393A34">}</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">			</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">				</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">div</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">className</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">flex flex-col items-center justify-center h-full space-y-3</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">					</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">p</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">className</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">text-gray-600</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text">Drop files here or click to add them</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">p</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">				</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">div</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">				</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">note </span><span class="token operator" style="color:#393A34">?</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">					</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">div</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">className</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">text-sm text-gray-500</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">note</span><span class="token punctuation" style="color:#393A34">}</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">div</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">				</span><span class="token operator" style="color:#393A34">:</span><span class="token plain">	</span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">			</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">div</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">		</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">div</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><p>Create a file input button that opens a file picker when clicked and add the
selected files to Uppy.</p><div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-tsx codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:#393A34">{</span><span class="token imports"> useFileInput </span><span class="token imports punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@uppy/react'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">type</span><span class="token plain"> </span><span class="token class-name">FileInputProps</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	multiple</span><span class="token operator" style="color:#393A34">?</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">boolean</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	accept</span><span class="token operator" style="color:#393A34">?</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">export</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">FileInput</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> multiple</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> accept </span><span class="token punctuation" style="color:#393A34">}</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token maybe-class-name">FileInputProps</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> getButtonProps</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> getInputProps </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useFileInput</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> multiple</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> accept </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">div</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">			</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">input</span><span class="token tag" style="color:#00009f"> </span><span class="token tag spread punctuation" style="color:#393A34">{</span><span class="token tag spread operator" style="color:#393A34">...</span><span class="token tag spread method function property-access" style="color:#d73a49">getInputProps</span><span class="token tag spread punctuation" style="color:#393A34">(</span><span class="token tag spread punctuation" style="color:#393A34">)</span><span class="token tag spread punctuation" style="color:#393A34">}</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">className</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">hidden</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">			</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">button</span><span class="token tag" style="color:#00009f"> </span><span class="token tag spread punctuation" style="color:#393A34">{</span><span class="token tag spread operator" style="color:#393A34">...</span><span class="token tag spread method function property-access" style="color:#d73a49">getButtonProps</span><span class="token tag spread punctuation" style="color:#393A34">(</span><span class="token tag spread punctuation" style="color:#393A34">)</span><span class="token tag spread punctuation" style="color:#393A34">}</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text">Add files</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">button</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">		</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">div</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><p>This hook can be used to build a UI for remote sources, such as Dropbox or
Google Drive. It is a bit more complex than the other hooks, because remote
sources involve more moving parts.</p><p>For this hook to work, you must have the
<a class="" href="https://uppy.io/docs/remote-sources/"><code>@uppy/remote-sources</code></a> or the specific provider plugin
(such as <code>@uppy/dropbox</code>) installed, as well as a <a class="" href="https://uppy.io/docs/companion/">Companion</a>
instance.</p><div class="browserWindow_KJ5v"><div class="titleBar_A0Ia"><div class="trafficLights_KFjg"><div class="trafficLight_DirP close_eAD9"></div><div class="trafficLight_DirP minimize_DlvY"></div><div class="trafficLight_DirP maximize_EQB6"></div></div></div><div class="content_Mb8g"><div style="display:flex;justify-content:center;align-items:center;height:100%"><img src="https://uppy.io/img/blog/5.0/remote-source.png" width="600" alt="Remote source demo"></div></div></div><div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-tsx codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">type</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token maybe-class-name">PartialTreeFile</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token maybe-class-name">PartialTreeFolderNode</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@uppy/core'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:#393A34">{</span><span class="token imports"> useRemoteSource </span><span class="token imports punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@uppy/react'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">File</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	item</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	checkbox</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	item</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token maybe-class-name">PartialTreeFile</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token function-variable function" style="color:#d73a49">checkbox</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">item</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token maybe-class-name">PartialTreeFile</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> checked</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">boolean</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">li</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">className</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">flex items-center gap-2 mb-2</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">			</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">input</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">				</span><span class="token tag attr-name" style="color:#00a4db">type</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">checkbox</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">				</span><span class="token tag attr-name" style="color:#00a4db">onChange</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:#393A34">=</span><span class="token tag script language-javascript punctuation" style="color:#393A34">{</span><span class="token tag script language-javascript punctuation" style="color:#393A34">(</span><span class="token tag script language-javascript punctuation" style="color:#393A34">)</span><span class="token tag script language-javascript" style="color:#00009f"> </span><span class="token tag script language-javascript arrow operator" style="color:#393A34">=&gt;</span><span class="token tag script language-javascript" style="color:#00009f"> </span><span class="token tag script language-javascript function" style="color:#d73a49">checkbox</span><span class="token tag script language-javascript punctuation" style="color:#393A34">(</span><span class="token tag script language-javascript" style="color:#00009f">item</span><span class="token tag script language-javascript punctuation" style="color:#393A34">,</span><span class="token tag script language-javascript" style="color:#00009f"> </span><span class="token tag script language-javascript boolean" style="color:#36acaa">false</span><span class="token tag script language-javascript punctuation" style="color:#393A34">)</span><span class="token tag script language-javascript punctuation" style="color:#393A34">}</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">				</span><span class="token tag attr-name" style="color:#00a4db">checked</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:#393A34">=</span><span class="token tag script language-javascript punctuation" style="color:#393A34">{</span><span class="token tag script language-javascript" style="color:#00009f">item</span><span class="token tag script language-javascript punctuation" style="color:#393A34">.</span><span class="token tag script language-javascript property-access" style="color:#00009f">status</span><span class="token tag script language-javascript" style="color:#00009f"> </span><span class="token tag script language-javascript operator" style="color:#393A34">===</span><span class="token tag script language-javascript" style="color:#00009f"> </span><span class="token tag script language-javascript string" style="color:#e3116c">'checked'</span><span class="token tag script language-javascript punctuation" style="color:#393A34">}</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">			</span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">			</span><span class="token punctuation" style="color:#393A34">{</span><span class="token comment" style="color:#999988;font-style:italic">/* thumbnail, name, date... */</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">			</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">div</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">className</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">truncate</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">item</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">data</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">name</span><span class="token punctuation" style="color:#393A34">}</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">div</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">		</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">li</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">Folder</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	item</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	checkbox</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	open</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	item</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token maybe-class-name">PartialTreeFolderNode</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token function-variable function" style="color:#d73a49">checkbox</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">item</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token maybe-class-name">PartialTreeFolderNode</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> checked</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">boolean</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token function-variable function" style="color:#d73a49">open</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">folderId</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token known-class-name class-name">Promise</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">void</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">li</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">className</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">flex items-center gap-2 mb-2</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">			</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">input</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">				</span><span class="token tag attr-name" style="color:#00a4db">type</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">checkbox</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">				</span><span class="token tag attr-name" style="color:#00a4db">onChange</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:#393A34">=</span><span class="token tag script language-javascript punctuation" style="color:#393A34">{</span><span class="token tag script language-javascript punctuation" style="color:#393A34">(</span><span class="token tag script language-javascript punctuation" style="color:#393A34">)</span><span class="token tag script language-javascript" style="color:#00009f"> </span><span class="token tag script language-javascript arrow operator" style="color:#393A34">=&gt;</span><span class="token tag script language-javascript" style="color:#00009f"> </span><span class="token tag script language-javascript function" style="color:#d73a49">checkbox</span><span class="token tag script language-javascript punctuation" style="color:#393A34">(</span><span class="token tag script language-javascript" style="color:#00009f">item</span><span class="token tag script language-javascript punctuation" style="color:#393A34">,</span><span class="token tag script language-javascript" style="color:#00009f"> </span><span class="token tag script language-javascript boolean" style="color:#36acaa">false</span><span class="token tag script language-javascript punctuation" style="color:#393A34">)</span><span class="token tag script language-javascript punctuation" style="color:#393A34">}</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">				</span><span class="token tag attr-name" style="color:#00a4db">checked</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:#393A34">=</span><span class="token tag script language-javascript punctuation" style="color:#393A34">{</span><span class="token tag script language-javascript" style="color:#00009f">item</span><span class="token tag script language-javascript punctuation" style="color:#393A34">.</span><span class="token tag script language-javascript property-access" style="color:#00009f">status</span><span class="token tag script language-javascript" style="color:#00009f"> </span><span class="token tag script language-javascript operator" style="color:#393A34">===</span><span class="token tag script language-javascript" style="color:#00009f"> </span><span class="token tag script language-javascript string" style="color:#e3116c">'checked'</span><span class="token tag script language-javascript punctuation" style="color:#393A34">}</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">			</span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">			</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">button</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">onClick</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:#393A34">=</span><span class="token tag script language-javascript punctuation" style="color:#393A34">{</span><span class="token tag script language-javascript punctuation" style="color:#393A34">(</span><span class="token tag script language-javascript punctuation" style="color:#393A34">)</span><span class="token tag script language-javascript" style="color:#00009f"> </span><span class="token tag script language-javascript arrow operator" style="color:#393A34">=&gt;</span><span class="token tag script language-javascript" style="color:#00009f"> </span><span class="token tag script language-javascript function" style="color:#d73a49">open</span><span class="token tag script language-javascript punctuation" style="color:#393A34">(</span><span class="token tag script language-javascript" style="color:#00009f">item</span><span class="token tag script language-javascript punctuation" style="color:#393A34">.</span><span class="token tag script language-javascript property-access" style="color:#00009f">id</span><span class="token tag script language-javascript punctuation" style="color:#393A34">)</span><span class="token tag script language-javascript punctuation" style="color:#393A34">}</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text">📁 </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">item</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">data</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">name</span><span class="token punctuation" style="color:#393A34">}</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">button</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">		</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">li</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">export</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">Dropbox</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> close </span><span class="token punctuation" style="color:#393A34">}</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token function-variable function" style="color:#d73a49">close</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token comment" style="color:#999988;font-style:italic">// The main hook that provides all the remote source functionality</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> state</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> login</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> logout</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> checkbox</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> open</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> done</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> cancel </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token function" style="color:#d73a49">useRemoteSource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'Dropbox'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token comment" style="color:#999988;font-style:italic">// Show login button if not authenticated</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">!</span><span class="token plain">state</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">authenticated</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">			</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">div</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">className</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">p-4</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">				</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">button</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">onClick</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:#393A34">=</span><span class="token tag script language-javascript punctuation" style="color:#393A34">{</span><span class="token tag script language-javascript punctuation" style="color:#393A34">(</span><span class="token tag script language-javascript punctuation" style="color:#393A34">)</span><span class="token tag script language-javascript" style="color:#00009f"> </span><span class="token tag script language-javascript arrow operator" style="color:#393A34">=&gt;</span><span class="token tag script language-javascript" style="color:#00009f"> </span><span class="token tag script language-javascript function" style="color:#d73a49">login</span><span class="token tag script language-javascript punctuation" style="color:#393A34">(</span><span class="token tag script language-javascript punctuation" style="color:#393A34">)</span><span class="token tag script language-javascript punctuation" style="color:#393A34">}</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text">Login</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">button</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">			</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">div</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">div</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">className</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">w-screen h-screen max-w-3xl max-h-96</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">			</span><span class="token punctuation" style="color:#393A34">{</span><span class="token comment" style="color:#999988;font-style:italic">/* Breadcrumb navigation */</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">			</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">div</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">className</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">flex justify-between items-center bg-gray-100 p-2</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">				</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">state</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">breadcrumbs</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">map</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">breadcrumb</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> index</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">					</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">span</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">key</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:#393A34">=</span><span class="token tag script language-javascript punctuation" style="color:#393A34">{</span><span class="token tag script language-javascript" style="color:#00009f">breadcrumb</span><span class="token tag script language-javascript punctuation" style="color:#393A34">.</span><span class="token tag script language-javascript property-access" style="color:#00009f">id</span><span class="token tag script language-javascript punctuation" style="color:#393A34">}</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">						</span><span class="token punctuation" style="color:#393A34">{</span><span class="token comment" style="color:#999988;font-style:italic">/* ... breadcrumb rendering logic ... */</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">						</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">breadcrumb</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">type</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">===</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'root'</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'Dropbox'</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> breadcrumb</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">data</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">name</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">					</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">span</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">				</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">				</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">button</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">					</span><span class="token tag attr-name" style="color:#00a4db">onClick</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:#393A34">=</span><span class="token tag script language-javascript punctuation" style="color:#393A34">{</span><span class="token tag script language-javascript punctuation" style="color:#393A34">(</span><span class="token tag script language-javascript punctuation" style="color:#393A34">)</span><span class="token tag script language-javascript" style="color:#00009f"> </span><span class="token tag script language-javascript arrow operator" style="color:#393A34">=&gt;</span><span class="token tag script language-javascript" style="color:#00009f"> </span><span class="token tag script language-javascript punctuation" style="color:#393A34">{</span><span class="token tag script language-javascript" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag script language-javascript" style="color:#00009f">						</span><span class="token tag script language-javascript function" style="color:#d73a49">logout</span><span class="token tag script language-javascript punctuation" style="color:#393A34">(</span><span class="token tag script language-javascript punctuation" style="color:#393A34">)</span><span class="token tag script language-javascript punctuation" style="color:#393A34">;</span><span class="token tag script language-javascript" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag script language-javascript" style="color:#00009f">						</span><span class="token tag script language-javascript function" style="color:#d73a49">close</span><span class="token tag script language-javascript punctuation" style="color:#393A34">(</span><span class="token tag script language-javascript punctuation" style="color:#393A34">)</span><span class="token tag script language-javascript punctuation" style="color:#393A34">;</span><span class="token tag script language-javascript" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag script language-javascript" style="color:#00009f">					</span><span class="token tag script language-javascript punctuation" style="color:#393A34">}</span><span class="token tag script language-javascript punctuation" style="color:#393A34">}</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">				</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">					Logout</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">				</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">button</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">			</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">div</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">			</span><span class="token punctuation" style="color:#393A34">{</span><span class="token comment" style="color:#999988;font-style:italic">/* File/folder list */</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">			</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">ul</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">className</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">p-4 flex-1 overflow-y-auto</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">				</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">state</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">loading</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">?</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">					</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">p</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text">loading...</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">p</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">				</span><span class="token operator" style="color:#393A34">:</span><span class="token plain">	state</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">partialTree</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">map</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">item</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">						</span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">item</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">type</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">===</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'file'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">							</span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">File</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">key</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:#393A34">=</span><span class="token tag script language-javascript punctuation" style="color:#393A34">{</span><span class="token tag script language-javascript" style="color:#00009f">item</span><span class="token tag script language-javascript punctuation" style="color:#393A34">.</span><span class="token tag script language-javascript property-access" style="color:#00009f">id</span><span class="token tag script language-javascript punctuation" style="color:#393A34">}</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">item</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:#393A34">=</span><span class="token tag script language-javascript punctuation" style="color:#393A34">{</span><span class="token tag script language-javascript" style="color:#00009f">item</span><span class="token tag script language-javascript punctuation" style="color:#393A34">}</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">checkbox</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:#393A34">=</span><span class="token tag script language-javascript punctuation" style="color:#393A34">{</span><span class="token tag script language-javascript" style="color:#00009f">checkbox</span><span class="token tag script language-javascript punctuation" style="color:#393A34">}</span><span class="token tag" style="color:#00009f"> </span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">						</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">						</span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">item</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">type</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">===</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'folder'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">							</span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">								</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">Folder</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">									</span><span class="token tag attr-name" style="color:#00a4db">key</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:#393A34">=</span><span class="token tag script language-javascript punctuation" style="color:#393A34">{</span><span class="token tag script language-javascript" style="color:#00009f">item</span><span class="token tag script language-javascript punctuation" style="color:#393A34">.</span><span class="token tag script language-javascript property-access" style="color:#00009f">id</span><span class="token tag script language-javascript punctuation" style="color:#393A34">}</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">									</span><span class="token tag attr-name" style="color:#00a4db">item</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:#393A34">=</span><span class="token tag script language-javascript punctuation" style="color:#393A34">{</span><span class="token tag script language-javascript" style="color:#00009f">item</span><span class="token tag script language-javascript punctuation" style="color:#393A34">}</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">									</span><span class="token tag attr-name" style="color:#00a4db">checkbox</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:#393A34">=</span><span class="token tag script language-javascript punctuation" style="color:#393A34">{</span><span class="token tag script language-javascript" style="color:#00009f">checkbox</span><span class="token tag script language-javascript punctuation" style="color:#393A34">}</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">									</span><span class="token tag attr-name" style="color:#00a4db">open</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:#393A34">=</span><span class="token tag script language-javascript punctuation" style="color:#393A34">{</span><span class="token tag script language-javascript" style="color:#00009f">open</span><span class="token tag script language-javascript punctuation" style="color:#393A34">}</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">								</span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">							</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">						</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">						</span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">					</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">				</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">			</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">ul</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">			</span><span class="token punctuation" style="color:#393A34">{</span><span class="token comment" style="color:#999988;font-style:italic">/* Action bar when items are selected */</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">			</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">state</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">selectedAmount</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">				</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">div</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">className</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">flex items-center gap-4 bg-gray-100 p-2</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">					</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">button</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">						</span><span class="token tag attr-name" style="color:#00a4db">onClick</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:#393A34">=</span><span class="token tag script language-javascript punctuation" style="color:#393A34">{</span><span class="token tag script language-javascript punctuation" style="color:#393A34">(</span><span class="token tag script language-javascript punctuation" style="color:#393A34">)</span><span class="token tag script language-javascript" style="color:#00009f"> </span><span class="token tag script language-javascript arrow operator" style="color:#393A34">=&gt;</span><span class="token tag script language-javascript" style="color:#00009f"> </span><span class="token tag script language-javascript punctuation" style="color:#393A34">{</span><span class="token tag script language-javascript" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag script language-javascript" style="color:#00009f">							</span><span class="token tag script language-javascript function" style="color:#d73a49">done</span><span class="token tag script language-javascript punctuation" style="color:#393A34">(</span><span class="token tag script language-javascript punctuation" style="color:#393A34">)</span><span class="token tag script language-javascript punctuation" style="color:#393A34">;</span><span class="token tag script language-javascript" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag script language-javascript" style="color:#00009f">							</span><span class="token tag script language-javascript function" style="color:#d73a49">close</span><span class="token tag script language-javascript punctuation" style="color:#393A34">(</span><span class="token tag script language-javascript punctuation" style="color:#393A34">)</span><span class="token tag script language-javascript punctuation" style="color:#393A34">;</span><span class="token tag script language-javascript" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag script language-javascript" style="color:#00009f">						</span><span class="token tag script language-javascript punctuation" style="color:#393A34">}</span><span class="token tag script language-javascript punctuation" style="color:#393A34">}</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">					</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">						Done</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">					</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">button</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">					</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">button</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">onClick</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:#393A34">=</span><span class="token tag script language-javascript punctuation" style="color:#393A34">{</span><span class="token tag script language-javascript punctuation" style="color:#393A34">(</span><span class="token tag script language-javascript punctuation" style="color:#393A34">)</span><span class="token tag script language-javascript" style="color:#00009f"> </span><span class="token tag script language-javascript arrow operator" style="color:#393A34">=&gt;</span><span class="token tag script language-javascript" style="color:#00009f"> </span><span class="token tag script language-javascript function" style="color:#d73a49">cancel</span><span class="token tag script language-javascript punctuation" style="color:#393A34">(</span><span class="token tag script language-javascript punctuation" style="color:#393A34">)</span><span class="token tag script language-javascript punctuation" style="color:#393A34">}</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text">Cancel</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">button</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">					</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">p</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text">Selected </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">state</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">selectedAmount</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain-text"> items</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">p</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">				</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">div</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">			</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">		</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">div</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><p>This hook can be used to build a UI for the <a class="" href="https://uppy.io/docs/webcam/"><code>webcam</code></a> plugin.</p><p>You also need to install <code>@uppy/webcam</code> and initialize it on the Uppy instance.</p><div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-tsx codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:#393A34">{</span><span class="token imports"> useWebcam </span><span class="token imports punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@uppy/react'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">export</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">Webcam</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		start</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		stop</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		getVideoProps</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		getSnapshotButtonProps</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		getRecordButtonProps</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		getStopRecordingButtonProps</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		getSubmitButtonProps</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		getDiscardButtonProps</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		state</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useWebcam</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token function-variable function" style="color:#d73a49">onSubmit</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token function" style="color:#d73a49">useEffect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token function" style="color:#d73a49">start</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">			</span><span class="token function" style="color:#d73a49">stop</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">start</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> stop</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">div</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">className</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">p-4 max-w-lg w-full</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">			</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">ErrorDisplay</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">error</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:#393A34">=</span><span class="token tag script language-javascript punctuation" style="color:#393A34">{</span><span class="token tag script language-javascript" style="color:#00009f">state</span><span class="token tag script language-javascript punctuation" style="color:#393A34">.</span><span class="token tag script language-javascript property-access" style="color:#00009f">cameraError</span><span class="token tag script language-javascript punctuation" style="color:#393A34">}</span><span class="token tag" style="color:#00009f"> </span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">			</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">video</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">				</span><span class="token tag attr-name" style="color:#00a4db">className</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">border-2 w-full rounded-lg data-[uppy-mirrored=true]:scale-x-[-1]</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">				</span><span class="token tag spread punctuation" style="color:#393A34">{</span><span class="token tag spread operator" style="color:#393A34">...</span><span class="token tag spread method function property-access" style="color:#d73a49">getVideoProps</span><span class="token tag spread punctuation" style="color:#393A34">(</span><span class="token tag spread punctuation" style="color:#393A34">)</span><span class="token tag spread punctuation" style="color:#393A34">}</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">			</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">				</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">track</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">kind</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">captions</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">			</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">video</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">			</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">div</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">className</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">flex gap-4 flex-wrap mt-4</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">				</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">button</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">					</span><span class="token tag attr-name" style="color:#00a4db">className</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">bg-blue-500 text-white px-4 py-2 rounded-md disabled:opacity-50 disabled:bg-blue-300</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">					</span><span class="token tag spread punctuation" style="color:#393A34">{</span><span class="token tag spread operator" style="color:#393A34">...</span><span class="token tag spread method function property-access" style="color:#d73a49">getSnapshotButtonProps</span><span class="token tag spread punctuation" style="color:#393A34">(</span><span class="token tag spread punctuation" style="color:#393A34">)</span><span class="token tag spread punctuation" style="color:#393A34">}</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">				</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">					Snapshot</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">				</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">button</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">				</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">button</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">					</span><span class="token tag attr-name" style="color:#00a4db">className</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">bg-blue-500 text-white px-4 py-2 rounded-md disabled:opacity-50 disabled:bg-blue-300</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">					</span><span class="token tag spread punctuation" style="color:#393A34">{</span><span class="token tag spread operator" style="color:#393A34">...</span><span class="token tag spread method function property-access" style="color:#d73a49">getRecordButtonProps</span><span class="token tag spread punctuation" style="color:#393A34">(</span><span class="token tag spread punctuation" style="color:#393A34">)</span><span class="token tag spread punctuation" style="color:#393A34">}</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">				</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">					Record</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">				</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">button</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">				</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">button</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">					</span><span class="token tag attr-name" style="color:#00a4db">className</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">bg-red-500 text-white px-4 py-2 rounded-md disabled:opacity-50 disabled:bg-red-300</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">					</span><span class="token tag spread punctuation" style="color:#393A34">{</span><span class="token tag spread operator" style="color:#393A34">...</span><span class="token tag spread method function property-access" style="color:#d73a49">getStopRecordingButtonProps</span><span class="token tag spread punctuation" style="color:#393A34">(</span><span class="token tag spread punctuation" style="color:#393A34">)</span><span class="token tag spread punctuation" style="color:#393A34">}</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">				</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">					Stop</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">				</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">button</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">				</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">button</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">					</span><span class="token tag attr-name" style="color:#00a4db">className</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">bg-green-500 text-white px-4 py-2 rounded-md disabled:opacity-50 disabled:bg-green-300</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">					</span><span class="token tag spread punctuation" style="color:#393A34">{</span><span class="token tag spread operator" style="color:#393A34">...</span><span class="token tag spread method function property-access" style="color:#d73a49">getSubmitButtonProps</span><span class="token tag spread punctuation" style="color:#393A34">(</span><span class="token tag spread punctuation" style="color:#393A34">)</span><span class="token tag spread punctuation" style="color:#393A34">}</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">				</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">					Submit</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">				</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">button</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">				</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">button</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">					</span><span class="token tag attr-name" style="color:#00a4db">className</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">bg-gray-500 text-white px-4 py-2 rounded-md disabled:opacity-50 disabled:bg-gray-300</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">					</span><span class="token tag spread punctuation" style="color:#393A34">{</span><span class="token tag spread operator" style="color:#393A34">...</span><span class="token tag spread method function property-access" style="color:#d73a49">getDiscardButtonProps</span><span class="token tag spread punctuation" style="color:#393A34">(</span><span class="token tag spread punctuation" style="color:#393A34">)</span><span class="token tag spread punctuation" style="color:#393A34">}</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">				</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">					Discard</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">				</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">button</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">			</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">div</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">		</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">div</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><p>This hook can be used to build a UI for the
<a class="" href="https://uppy.io/docs/screen-capture/"><code>screen-capture</code></a> plugin.</p><p>You also need to install <code>@uppy/screen-capture</code> and initialize it on the Uppy
instance.</p><div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-tsx codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:#393A34">{</span><span class="token imports"> useScreenCapture </span><span class="token imports punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@uppy/react'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">export</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">ScreenCapture</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		start</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		stop</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		getVideoProps</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		getSnapshotButtonProps</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		getRecordButtonProps</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		getStopRecordingButtonProps</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		getSubmitButtonProps</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		getDiscardButtonProps</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		state</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useScreenCapture</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token function-variable function" style="color:#d73a49">onSubmit</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token function" style="color:#d73a49">useEffect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token function" style="color:#d73a49">start</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">			</span><span class="token function" style="color:#d73a49">stop</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">start</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> stop</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">div</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">className</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">p-4 max-w-lg w-full</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">			</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">ErrorDisplay</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">error</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:#393A34">=</span><span class="token tag script language-javascript punctuation" style="color:#393A34">{</span><span class="token tag script language-javascript" style="color:#00009f">state</span><span class="token tag script language-javascript punctuation" style="color:#393A34">.</span><span class="token tag script language-javascript property-access" style="color:#00009f">cameraError</span><span class="token tag script language-javascript punctuation" style="color:#393A34">}</span><span class="token tag" style="color:#00009f"> </span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">			</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">video</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">				</span><span class="token tag attr-name" style="color:#00a4db">className</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">border-2 w-full rounded-lg data-[uppy-mirrored=true]:scale-x-[-1]</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">				</span><span class="token tag spread punctuation" style="color:#393A34">{</span><span class="token tag spread operator" style="color:#393A34">...</span><span class="token tag spread method function property-access" style="color:#d73a49">getVideoProps</span><span class="token tag spread punctuation" style="color:#393A34">(</span><span class="token tag spread punctuation" style="color:#393A34">)</span><span class="token tag spread punctuation" style="color:#393A34">}</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">			</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">				</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">track</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">kind</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">captions</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">			</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">video</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">			</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">div</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">className</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">flex gap-4 flex-wrap mt-4</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">				</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">button</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">					</span><span class="token tag attr-name" style="color:#00a4db">className</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">bg-blue-500 text-white px-4 py-2 rounded-md disabled:opacity-50 disabled:bg-blue-300</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">					</span><span class="token tag spread punctuation" style="color:#393A34">{</span><span class="token tag spread operator" style="color:#393A34">...</span><span class="token tag spread method function property-access" style="color:#d73a49">getSnapshotButtonProps</span><span class="token tag spread punctuation" style="color:#393A34">(</span><span class="token tag spread punctuation" style="color:#393A34">)</span><span class="token tag spread punctuation" style="color:#393A34">}</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">				</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">					Snapshot</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">				</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">button</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">				</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">button</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">					</span><span class="token tag attr-name" style="color:#00a4db">className</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">bg-blue-500 text-white px-4 py-2 rounded-md disabled:opacity-50 disabled:bg-blue-300</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">					</span><span class="token tag spread punctuation" style="color:#393A34">{</span><span class="token tag spread operator" style="color:#393A34">...</span><span class="token tag spread method function property-access" style="color:#d73a49">getRecordButtonProps</span><span class="token tag spread punctuation" style="color:#393A34">(</span><span class="token tag spread punctuation" style="color:#393A34">)</span><span class="token tag spread punctuation" style="color:#393A34">}</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">				</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">					Record</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">				</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">button</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">				</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">button</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">					</span><span class="token tag attr-name" style="color:#00a4db">className</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">bg-red-500 text-white px-4 py-2 rounded-md disabled:opacity-50 disabled:bg-red-300</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">					</span><span class="token tag spread punctuation" style="color:#393A34">{</span><span class="token tag spread operator" style="color:#393A34">...</span><span class="token tag spread method function property-access" style="color:#d73a49">getStopRecordingButtonProps</span><span class="token tag spread punctuation" style="color:#393A34">(</span><span class="token tag spread punctuation" style="color:#393A34">)</span><span class="token tag spread punctuation" style="color:#393A34">}</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">				</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">					Stop</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">				</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">button</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">				</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">button</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">					</span><span class="token tag attr-name" style="color:#00a4db">className</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">bg-green-500 text-white px-4 py-2 rounded-md disabled:opacity-50 disabled:bg-green-300</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">					</span><span class="token tag spread punctuation" style="color:#393A34">{</span><span class="token tag spread operator" style="color:#393A34">...</span><span class="token tag spread method function property-access" style="color:#d73a49">getSubmitButtonProps</span><span class="token tag spread punctuation" style="color:#393A34">(</span><span class="token tag spread punctuation" style="color:#393A34">)</span><span class="token tag spread punctuation" style="color:#393A34">}</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">				</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">					Submit</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">				</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">button</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">				</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">button</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">					</span><span class="token tag attr-name" style="color:#00a4db">className</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">bg-gray-500 text-white px-4 py-2 rounded-md disabled:opacity-50 disabled:bg-gray-300</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">					</span><span class="token tag spread punctuation" style="color:#393A34">{</span><span class="token tag spread operator" style="color:#393A34">...</span><span class="token tag spread method function property-access" style="color:#d73a49">getDiscardButtonProps</span><span class="token tag spread punctuation" style="color:#393A34">(</span><span class="token tag spread punctuation" style="color:#393A34">)</span><span class="token tag spread punctuation" style="color:#393A34">}</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">				</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">					Discard</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">				</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">button</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">			</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">div</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain-text">		</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">div</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div></div></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="putting-it-all-together">Putting it all together<a href="https://uppy.io/blog/uppy-5.0/#putting-it-all-together" class="hash-link" aria-label="Direct link to Putting it all together" title="Direct link to Putting it all together" translate="no">​</a></h3>
<p>Here you can play around with the new components and hooks in all three
frameworks. These examples are also available on Uppy’s
<a href="https://github.com/transloadit/uppy/tree/main/examples" target="_blank" rel="noopener noreferrer" class="">GitHub</a>.</p>
<div class="theme-tabs-container tabs-container tabList__CuJ"><ul role="tablist" aria-orientation="horizontal" class="tabs"><li role="tab" tabindex="0" aria-selected="true" class="tabs__item tabItem_LNqP tabs__item--active">React</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">Vue</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">Svelte</li></ul><div class="margin-top--md"><div role="tabpanel" class="tabItem_Ymn6"><iframe style="width:100%;height:600px" src="https://stackblitz.com/github/transloadit/uppy/tree/main/examples/react?embed=1&amp;view=editor&amp;showSidebar=1&amp;hideTerminal=1&amp;ctl=1&amp;file=src%2FApp.tsx"></iframe></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><iframe style="width:100%;height:600px" src="https://stackblitz.com/github/transloadit/uppy/tree/main/examples/vue?embed=1&amp;view=editor&amp;showSidebar=1&amp;hideTerminal=1&amp;ctl=1&amp;file=src%2FApp.vue"></iframe></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><iframe style="width:100%;height:600px" src="https://stackblitz.com/github/transloadit/uppy/tree/main/examples/sveltekit?embed=1&amp;view=editor&amp;showSidebar=1&amp;hideTerminal=1&amp;ctl=1&amp;file=src%2Froutes%2F%2Bpage.svelte"></iframe></div></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="give-feedback">Give feedback<a href="https://uppy.io/blog/uppy-5.0/#give-feedback" class="hash-link" aria-label="Direct link to Give feedback" title="Direct link to Give feedback" translate="no">​</a></h3>
<p>It is still early days with the new components and hooks and we are looking for
feedback to improve. Don’t hesitate to reach out to us!</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="export-maps-for-all-packages">Export maps for all packages<a href="https://uppy.io/blog/uppy-5.0/#export-maps-for-all-packages" class="hash-link" aria-label="Direct link to Export maps for all packages" title="Direct link to Export maps for all packages" translate="no">​</a></h2>
<p>All packages now have export maps. This is a breaking change in two cases:</p>
<ol>
<li class="">The css imports have changed from <code>@uppy[package]/dist/styles.min.css</code> to
<code>@uppy[package]/css/styles.min.css</code></li>
<li class="">You were importing something that wasn’t exported from the root, for instance
<code>@uppy/core/lib/foo.js</code>. You can now only import things the packages
explicitly export.</li>
</ol>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="changed-imports-for-react-vue-and-svelte">Changed imports for React, Vue and Svelte<a href="https://uppy.io/blog/uppy-5.0/#changed-imports-for-react-vue-and-svelte" class="hash-link" aria-label="Direct link to Changed imports for React, Vue and Svelte" title="Direct link to Changed imports for React, Vue and Svelte" translate="no">​</a></h3>
<p>Some components, like Dashboard, require a peer dependency to work. However,
since all components were exported from a single file, you were forced to
install all peer dependencies – even if you never imported, for instance, the
status bar component.</p>
<p>Every component that requires a peer dependency has now been moved to a subpath,
such as <code>@uppy/react/dashboard</code>. As a result, you only have to install the peer
dependencies you need.</p>
<p>Before:</p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword module" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:#393A34">{</span><span class="token imports"> </span><span class="token imports maybe-class-name">Dashboard</span><span class="token imports"> </span><span class="token imports punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword module" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@uppy/react'</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<p>Now:</p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword module" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports maybe-class-name">Dashboard</span><span class="token plain"> </span><span class="token keyword module" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@uppy/react/dashboard'</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="deprecations">Deprecations<a href="https://uppy.io/blog/uppy-5.0/#deprecations" class="hash-link" aria-label="Direct link to Deprecations" title="Direct link to Deprecations" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="merged-ui-plugins">Merged UI plugins<a href="https://uppy.io/blog/uppy-5.0/#merged-ui-plugins" class="hash-link" aria-label="Direct link to Merged UI plugins" title="Direct link to Merged UI plugins" translate="no">​</a></h3>
<p><code>@uppy/status-bar</code> and <code>@uppy/informer</code> have been merged into <code>@uppy/dashboard</code>.
These components have always been tightly coupled to <code>@uppy/dashboard</code> and with
the advent of the new headless components and hooks, we want to go all-in those
components and remove the confusing, inflexible ones.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="old-plugins">Old plugins<a href="https://uppy.io/blog/uppy-5.0/#old-plugins" class="hash-link" aria-label="Direct link to Old plugins" title="Direct link to Old plugins" translate="no">​</a></h3>
<ul>
<li class=""><code>@uppy/store-redux</code> can be recreated by consumers, should they need it.</li>
<li class=""><code>@uppy/redux-dev-tools</code> is no longer needed.</li>
<li class=""><code>@uppy/progress-bar</code>, <code>@uppy/drag-drop</code>, <code>@uppy/file-input</code> and are superseded
by the new components and hooks.</li>
<li class=""><code>@uppy/aws-s3-multipart</code> has been merged in <code>@uppy/aws-s3</code> for over a year
now.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="overhauled-tooling">Overhauled tooling<a href="https://uppy.io/blog/uppy-5.0/#overhauled-tooling" class="hash-link" aria-label="Direct link to Overhauled tooling" title="Direct link to Overhauled tooling" translate="no">​</a></h2>
<p>As the components started to age, so did our tooling. We put a lot of effort
into migrating to a more modern monorepo setup.</p>
<p>A fun example is comparing the
<a href="https://github.com/transloadit/uppy/blob/24fd4158a99aebdb50df8717c9a5d92707d16084/package.json" target="_blank" rel="noopener noreferrer" class="">before</a>
and <a href="https://github.com/transloadit/uppy/blob/main/package.json" target="_blank" rel="noopener noreferrer" class="">after</a> of our
<code>package.json</code>.</p>
<ul>
<li class="">Instead of global build scripts with lots of conditionals for packages, every
package now has its own build script.</li>
<li class="">Use the TypeScript compiler instead of Babel for transpiling.</li>
<li class="">Introduced <a href="https://turbo.build/" target="_blank" rel="noopener noreferrer" class="">Turbo</a> for faster builds.</li>
<li class="">Migrated from Cypress to
<a href="https://vitest.dev/guide/browser/" target="_blank" rel="noopener noreferrer" class="">Vitest Browser Mode</a>.</li>
<li class="">Migrated from Eslint and Prettier to <a href="https://biomejs.dev/" target="_blank" rel="noopener noreferrer" class="">Biome</a>.</li>
<li class="">Migrated from our custom release tooling to
<a href="https://github.com/changesets/changesets" target="_blank" rel="noopener noreferrer" class="">Changesets</a>.</li>
<li class="">And more smaller clean ups</li>
</ul>
<hr>
<p>That’s all we have for you today! We hope you’re excited to play around with
this latest version of your favorite file uploading companion that loves to play
fetch, and doesn’t chew on your shoes.</p>]]></content>
        <author>
            <name>Mikael Finstad</name>
            <email>mikael@transloadit.com</email>
        </author>
        <author>
            <name>Merlijn Vos</name>
            <email>merlijn@transloadit.com</email>
        </author>
        <author>
            <name>Prakash</name>
            <email>prakash@transloadit.com</email>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[New Uppy 4.0 major: TypeScript rewrite, Google Photos, React hooks, and much more]]></title>
        <id>https://uppy.io/blog/uppy-4.0/</id>
        <link href="https://uppy.io/blog/uppy-4.0/"/>
        <updated>2024-07-10T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Hold on to your leashes, folks! Uppy 4.0 is here, and it’s more exciting than a]]></summary>
        <content type="html"><![CDATA[<img decoding="async" loading="lazy" src="https://uppy.io/img/blog/4.0/preview.jpg" alt="Screenshot of Uppy Dashboard with text outlining the major new features in 4.0" class="img_ev3q">
<p>Hold on to your leashes, folks! Uppy 4.0 is here, and it’s more exciting than a
tennis ball at the dog park! Our beloved Uppy mascot, the adorable coding
canine, has been hard at work fetching all the latest updates for you.</p>
<p>From a full TypeScript makeover to shiny new React hooks, and even Google Photos
integration – this release is so packed with treats that we’re almost wagging
our tails in excitement. Without further a-dog, let’s dig into what makes Uppy
4.0 the goodest of good boys in file uploading!</p>
<p><a href="https://www.producthunt.com/posts/uppy-4-0?embed=true&amp;utm_source=badge-featured&amp;utm_medium=badge&amp;utm_souce=badge-uppy-4-0" target="_blank" rel="noopener noreferrer" class=""><img decoding="async" loading="lazy" src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=473003&amp;theme=light" alt="Uppy 4.0 - TypeScript rewrite, Google Photos, and much more | Product Hunt" style="width:250px;height:54px" width="250" height="54" class="img_ev3q"></a></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="migration-guide">Migration guide<a href="https://uppy.io/blog/uppy-4.0/#migration-guide" class="hash-link" aria-label="Direct link to Migration guide" title="Direct link to Migration guide" translate="no">​</a></h2>
<p>This post covers the most exciting new features of Uppy 4.0. We have an
accompanying <a class="" href="https://uppy.io/docs/guides/migration-guides/">migration guide</a> to help you
transition to 4.0.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="typescript-rewrite">TypeScript rewrite<a href="https://uppy.io/blog/uppy-4.0/#typescript-rewrite" class="hash-link" aria-label="Direct link to TypeScript rewrite" title="Direct link to TypeScript rewrite" translate="no">​</a></h2>
<p>In the year 2024, people expect excellent types from their libraries. We used to
author types separately by hand, but they were often inconsistent or incomplete.
As of now, Uppy has been completely rewritten in TypeScript!</p>
<p>From now on you’ll be in safe hands when working with Uppy, whether it’s setting
the right options, building plugins, or listening to events.</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> Uppy </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@uppy/core'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> uppy </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">Uppy</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// Event name autocompletion and inferred argument types</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">uppy</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">on</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'file-added'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">file</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token builtin">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">file</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<p>One important thing to note is the new generics on <code>@uppy/core</code>.</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> Uppy </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@uppy/core'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// xhr-upload is for uploading to your own back end.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> XHRUpload </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@uppy/xhr-upload'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// Your own metadata on files</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">type</span><span class="token plain"> </span><span class="token class-name">Meta</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> myCustomMetadata</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// The response from your server</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">type</span><span class="token plain"> </span><span class="token class-name">Body</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> someThingMyBackendReturns</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> uppy </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">Uppy</span><span class="token class-name operator" style="color:#393A34">&lt;</span><span class="token class-name">Meta</span><span class="token class-name punctuation" style="color:#393A34">,</span><span class="token class-name"> Body</span><span class="token class-name operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">use</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">XHRUpload</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	endpoint</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'/upload'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> id </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> uppy</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">addFile</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	name</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'example.jpg'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	data</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">Blob</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	meta</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> myCustomMetadata</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'foo'</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// This is now typed</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> myCustomMetadata </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> uppy</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getFile</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">id</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">meta</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> uppy</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">upload</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// This is strictly typed too</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> someThingMyBackendReturns </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> uppy</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getFile</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">id</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">response</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">body</span><span class="token operator" style="color:#393A34">!</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<p>Happy inferring!</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="merging-the-two-aws-s3-plugins">Merging the two AWS S3 plugins<a href="https://uppy.io/blog/uppy-4.0/#merging-the-two-aws-s3-plugins" class="hash-link" aria-label="Direct link to Merging the two AWS S3 plugins" title="Direct link to Merging the two AWS S3 plugins" translate="no">​</a></h2>
<p>We used to have two separate plugins for uploading to S3 and S3-compatible
services: <code>@uppy/aws-s3</code> and <code>@uppy/aws-s3-multpart</code>. They have different use
cases. The advantages of multipart uploads are:</p>
<ul>
<li class="">Improved throughput – You can upload parts in parallel to improve throughput.</li>
<li class="">Quick recovery from any network issues – Smaller part size minimizes the
impact of restarting a failed upload due to a network error.</li>
<li class="">Pause and resume object uploads – You can upload object parts over time. After
you initiate a multipart upload, there is no expiry; you must explicitly
complete or stop the multipart upload.</li>
<li class="">Begin an upload before you know the final object size – You can upload an
object as you are creating it.</li>
</ul>
<p>However, the downside is request overhead, as it needs to do creation, signing,
and completion requests besides the upload requests. For example, if you are
uploading files that are only a couple kilobytes with a 100ms roundtrip latency,
you are spending 400ms on overhead and only a few milliseconds on uploading.
This really adds up if you upload a lot of small files.</p>
<p>AWS – and the internet in general, from what we found – tends to agree that
<strong>you don’t want to use multipart uploads for files under 100 MB</strong>. This
sometimes puts users of our libraries in an awkward position, though, as their
end users may not exclusively upload very large files, or only small files. In
this case, a portion of their users get a subpar experience.</p>
<hr>
<p>We’ve merged the two plugins into <code>@uppy/aws-s3</code> with a new
<a class="" href="https://uppy.io/docs/aws-s3/#shouldusemultipartfile"><code>shouldUseMultipart</code></a> option! By default,
it switches to multipart uploads if the file is larger than 100 MB. You can pass
a <code>boolean</code> or a function to determine this per file.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="react-hooks">React hooks<a href="https://uppy.io/blog/uppy-4.0/#react-hooks" class="hash-link" aria-label="Direct link to React hooks" title="Direct link to React hooks" translate="no">​</a></h2>
<p>People working with React are more likely to create their own user interface on
top of Uppy than those working with “vanilla” setups. Working with our pre-built
UI components is a plug-and-play experience, but building on top of Uppy’s state
with React primitives has been tedious.</p>
<p>To address this, we’re introducing two new hooks: <code>useUppyState</code> and
<code>useUppyEvent</code>. Thanks to the TypeScript rewrite, we can now do powerful
inference in hooks as well.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="useuppystateuppy-selector"><code>useUppyState(uppy, selector)</code><a href="https://uppy.io/blog/uppy-4.0/#useuppystateuppy-selector" class="hash-link" aria-label="Direct link to useuppystateuppy-selector" title="Direct link to useuppystateuppy-selector" translate="no">​</a></h3>
<p>Use this hook when you need to read Uppy’s state.</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> useState </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'react'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> Uppy </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@uppy/core'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> useUppyState </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@uppy/react'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// IMPORTANT: passing an initializer function</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// to prevent Uppy from being recreated on every render.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">uppy</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useState</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">Uppy</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> files </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useUppyState</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">uppy</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">state</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> state</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">files</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> totalProgress </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useUppyState</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">uppy</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">state</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> state</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">totalProgress</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// We can also get a specific plugin state.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// Note that the value on `plugins` depends on the `id` of the plugin.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> metaFields </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useUppyState</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	uppy</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">state</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> state</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">plugins</span><span class="token operator" style="color:#393A34">?.</span><span class="token plain">Dashboard</span><span class="token operator" style="color:#393A34">?.</span><span class="token plain">metaFields</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<p>You can see all the values you can access on the
<a href="https://github.com/transloadit/uppy/blob/dab8082a4e67c3e7f109eacfbd6c3185f117dc60/packages/%40uppy/core/src/Uppy.ts#L156" target="_blank" rel="noopener noreferrer" class=""><code>State</code></a>
type.</p>
<p>Using this hook, you can also access the state of any Uppy plugin. For example,
in order to access the state of <code>ImageEditor</code>, you would have to look at the
types of the plugin.</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">type</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> State </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@uppy/core'</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="useuppyeventuppy-event-callback"><code>useUppyEvent(uppy, event, callback)</code><a href="https://uppy.io/blog/uppy-4.0/#useuppyeventuppy-event-callback" class="hash-link" aria-label="Direct link to useuppyeventuppy-event-callback" title="Direct link to useuppyeventuppy-event-callback" translate="no">​</a></h3>
<p>Listen to Uppy <a class="" href="https://uppy.io/docs/uppy/#events">events</a> in a React component.</p>
<p>The hook returns <code>[results, clear]</code>. <code>results</code> is an array of values from the
event. Depending on the event, this can be empty or have up to three values.
<code>clear</code> is a function to clear the <code>results</code> array.</p>
<p>Values remain in state until the next event (if that ever comes)&nbsp;or the moment
when the state is manually cleared. Depending on your use case, you may want to
keep the values in state or clear the state after something else happened.</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> useState </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'react'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> Uppy </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@uppy/core'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> Transloadit </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@uppy/transloadit'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> useUppyEvent </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@uppy/react'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// IMPORTANT: passing an initializer function</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// to prevent Uppy from being recreated on every render.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">uppy</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useState</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">Uppy</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">results</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> clearResults</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useUppyEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">uppy</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'transloadit:result'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">stepName</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> result</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> assembly</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> results</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// strongly typed</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">useUppyEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">uppy</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'cancel-all'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token comment" style="color:#999988;font-style:italic">// Handle event here.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="google-photos">Google Photos<a href="https://uppy.io/blog/uppy-4.0/#google-photos" class="hash-link" aria-label="Direct link to Google Photos" title="Direct link to Google Photos" translate="no">​</a></h2>
<p>An often requested feature is finally here: Google Photos support!</p>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>Uppy can bring in files from the cloud with <a class="" href="https://uppy.io/docs/companion/">Companion</a>.</p><p>Companion is a hosted, standalone, or middleware server that takes away the
complexity of authentication and the cost of downloading files from remote
sources, such as Instagram, Google Drive, and others.</p><p>This means a 5 GB video isn’t eating into your users’ data plans and you don’t
have to worry about OAuth.</p></div></div>
<p><video src="/img/blog/4.0/google-photos.mp4" controls=""></video></p>
<p><a class="" href="https://uppy.io/docs/google-drive/"><code>@uppy/google-drive</code></a> and
<a class="" href="https://uppy.io/docs/google-photos-picker/"><code>@uppy/google-photos-picker</code></a> are separate
plugins. However, you can use the same OAuth app for both these plugins. Be sure
to enable “Photos Library API” in your OAuth app, though!</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="ux-improvements-for-viewing-remote-files">UX improvements for viewing remote files<a href="https://uppy.io/blog/uppy-4.0/#ux-improvements-for-viewing-remote-files" class="hash-link" aria-label="Direct link to UX improvements for viewing remote files" title="Direct link to UX improvements for viewing remote files" translate="no">​</a></h2>
<p>When using <a class="" href="https://uppy.io/docs/dashboard/">Dashboard</a> with any of our remote sources (Google
Drive, Facebook, etc.) you use our internal <code>@uppy/provider-views</code> plugin to
navigate the folders and select files. In Uppy 4.0, we are making a few quality
of life improvements for users. The main changes are described in the table
below.</p>
<table style="text-align:left;font-size:15px">
  <tbody>
    <tr>
      <td colspan="2">
        <b style="font-size:17px">Folder states: checked, unchecked, partial</b>
        <p style="margin-bottom:0">In 4.0, we introduce a new folder state – a "partially checked" folder. A folder acquires this state when certain files within the folder are "checked", and other files are "unchecked".</p>
      </td>
    </tr>
    <tr>
      <th style="padding-top:0;padding-bottom:0">PREVIOUSLY</th>
      <th style="padding-top:0;padding-bottom:0">NOW</th>
    </tr>
    <tr>
      <td style="width:50%"><video src="/img/blog/4.0/partial-old.mp4" controls=""></video></td>
      <td style="width:50%"><video src="/img/blog/4.0/partial-new.mp4" controls=""></video></td>
    </tr>
    <tr>
      <td colspan="2">
        <b style="font-size:17px">Cache</b>
        <p style="margin-bottom:0">When navigating in and out of folders, you no longer have to wait for the same API call — results are cached.</p>
      </td>
    </tr>
    <tr>
      <th style="padding-top:0;padding-bottom:0">PREVIOUSLY</th>
      <th style="padding-top:0;padding-bottom:0">NOW</th>
    </tr>
    <tr>
      <td style="width:50%"><video src="/img/blog/4.0/cache-old.mp4" controls=""></video></td>
      <td style="width:50%"><video src="/img/blog/4.0/cache-new.mp4" controls=""></video></td>
    </tr>
    <tr>
      <td colspan="2">
        <b style="font-size:17px">Restrictions</b>
        <p style="margin-bottom:0">
          Uppy supports file <a class="" href="https://uppy.io/docs/uppy/#restrictions">restrictions</a>, such as maximum number of files and maximum file size. In 4.0, we reworked our restrictions UI – users will get immediate feedback upon exceeding the number of selected files, and get a chance to re-enter the correct number of files after their first upload attempt.
        </p>
      </td>
    </tr>
    <tr>
      <th style="padding-top:0;padding-bottom:0">PREVIOUSLY</th>
      <th style="padding-top:0;padding-bottom:0">NOW</th>
    </tr>
    <tr>
      <td style="width:50%"><video src="/img/blog/4.0/restrictions-old.mp4" controls=""></video></td>
      <td style="width:50%"><video src="/img/blog/4.0/restrictions-new.mp4" controls=""></video></td>
    </tr>
  </tbody></table>
<p>We’re confident this turns our interface for remote sources into the most
advanced one out there. We’ve seen some competing libraries not even aggregating
results beyond the first page returned by the provider API.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="revamped-options-for-uppyxhr-upload">Revamped options for <code>@uppy/xhr-upload</code><a href="https://uppy.io/blog/uppy-4.0/#revamped-options-for-uppyxhr-upload" class="hash-link" aria-label="Direct link to revamped-options-for-uppyxhr-upload" title="Direct link to revamped-options-for-uppyxhr-upload" translate="no">​</a></h2>
<p>In previous versions, the <code>@uppy/xhr-upload</code> plugin had the options
<code>getResponseData</code>, <code>getResponseError</code>, <code>validateStatus</code> and
<code>responseUrlFieldName</code>. These were inflexible and too specific. Now we have
hooks similar to <code>@uppy/tus</code>:</p>
<ul>
<li class=""><code>onBeforeRequest</code> to manipulate the request before it is sent.</li>
<li class=""><code>shouldRetry</code> to determine if a request should be retried. By default, three
retries with exponential backoff. After three attempts it will throw an error,
regardless of whether you returned <code>true</code>.</li>
<li class=""><code>onAfterResponse</code> called after a successful response, but before Uppy resolves
the upload.</li>
</ul>
<p>You could, for instance, use them to refresh your auth token when it expires:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword module" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports maybe-class-name">Uppy</span><span class="token plain"> </span><span class="token keyword module" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@uppy/core'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword module" style="color:#00009f">import</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">XHR</span><span class="token plain"> </span><span class="token keyword module" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@uppy/xhr-upload'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> token </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword null nil" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getAuthToken</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> res </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:#00009f">await</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">fetch</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'/auth/token'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> json </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:#00009f">await</span><span class="token plain"> res</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">json</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword control-flow" style="color:#00009f">return</span><span class="token plain"> json</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">token</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">Uppy</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">use</span><span class="token punctuation" style="color:#393A34">(</span><span class="token constant" style="color:#36acaa">XHR</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token literal-property property" style="color:#36acaa">endpoint</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'&lt;your-endpoint&gt;'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token comment" style="color:#999988;font-style:italic">// Called again for every retry too.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onBeforeRequest</span><span class="token punctuation" style="color:#393A34">(</span><span class="token parameter">xhr</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword control-flow" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">!</span><span class="token plain">token</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">			token </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:#00009f">await</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getAuthToken</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		xhr</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">setRequestHeader</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'Authorization'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:#e3116c">`</span><span class="token template-string string" style="color:#e3116c">Bearer </span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#393A34">${</span><span class="token template-string interpolation">token</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#393A34">}</span><span class="token template-string template-punctuation string" style="color:#e3116c">`</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onAfterResponse</span><span class="token punctuation" style="color:#393A34">(</span><span class="token parameter">xhr</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword control-flow" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">xhr</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">status</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">===</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">401</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">			token </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:#00009f">await</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getAuthToken</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<p>Check out the <code>@uppy/xhr-upload</code> <a class="" href="https://uppy.io/docs/xhr-upload/">docs</a> for more info.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="simpler-configuration-for-uppytransloadit">Simpler configuration for <code>@uppy/transloadit</code><a href="https://uppy.io/blog/uppy-4.0/#simpler-configuration-for-uppytransloadit" class="hash-link" aria-label="Direct link to simpler-configuration-for-uppytransloadit" title="Direct link to simpler-configuration-for-uppytransloadit" translate="no">​</a></h2>
<p>To get started with <code>@uppy/transloadit</code>, you would configure
<a class="" href="https://uppy.io/docs/transloadit/#assemblyoptions"><code>assemblyOptions</code></a> with your auth key,
template ID, and other optional values. <code>assemblyOptions</code> can be an object or a
function, which is called per file, which returns an object:</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">{</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	"params": {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		"auth": { "key": "key-from-transloadit" },</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		"template_id": "id-from-transloadit",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		"steps": {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">			// Overruling Template at runtime</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		},</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		"notify_url": "https://your-domain.com/assembly-status"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	},</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	"signature": "generated-signature",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	"fields": {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		// Dynamic or static fields to send along</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span></code></pre></div></div>
<p>When you go to production, you always want to make sure to set the <code>signature</code>.
<strong>Not using
<a href="https://transloadit.com/docs/topics/signature-authentication/" target="_blank" rel="noopener noreferrer" class="">Signature Authentication</a>
can be a security risk</strong>. Signature Authentication is a security measure that
can prevent outsiders from tampering with your Assembly Instructions.</p>
<p>This means the majority of implementers will write something like this, as
recommended:</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> Uppy </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@uppy/core'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> Transloadit</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">type</span><span class="token plain"> </span><span class="token class-name">AssemblyOptions</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@uppy/transloadit'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">Uppy</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">use</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">Transloadit</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">assemblyOptions</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">file</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> response </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">fetch</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'/transloadit-params'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> response</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">json</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> AssemblyOptions</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<p>However, now you are making a request to your back end for <em>every file</em>, while
the response likely remains the same, unless you are setting dynamic <code>fields</code>
per file.</p>
<p><strong>This has now been improved to</strong>:</p>
<ul>
<li class="">Only call <code>assemblyOptions()</code> once.</li>
<li class=""><code>fields</code> is for global variables in your
<a href="https://transloadit.com/docs/topics/templates/" target="_blank" rel="noopener noreferrer" class="">template</a>.</li>
<li class="">All metadata on your files is automatically sent along to Transloadit. This
will end up in <code>file.user_meta</code> for you to dynamically access in your Template
<em>per file</em>.</li>
</ul>
<p>You can read more about Assembly Variables in the
<a href="https://transloadit.com/docs/topics/assembly-variables/" target="_blank" rel="noopener noreferrer" class="">docs</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="companion">Companion<a href="https://uppy.io/blog/uppy-4.0/#companion" class="hash-link" aria-label="Direct link to Companion" title="Direct link to Companion" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="streaming-uploads-by-default">Streaming uploads by default<a href="https://uppy.io/blog/uppy-4.0/#streaming-uploads-by-default" class="hash-link" aria-label="Direct link to Streaming uploads by default" title="Direct link to Streaming uploads by default" translate="no">​</a></h3>
<p>Streaming uploads are now the default in Companion. This comes with greatly
improved upload speeds and allows uploading up to hundreds of gigabytes without
needing a large server storage. We found that this improves speeds by about 37%
for a Google Drive upload of a 1 GB file
(<a href="https://github.com/transloadit/uppy/pull/4046#issuecomment-1235697937" target="_blank" rel="noopener noreferrer" class="">source</a>).
This feature was also available before, but we wanted to have more real-world
usage before setting it as the default.</p>
<p>With streaming upload disabled, the whole file will be downloaded first. The
upload will then start when the download has completely finished.</p>
<p>When streaming upload is enabled, Companion will start downloading the file from
the provider (such as Google Drive), while at the same time starting the upload
to the destination (such as Tus), and sending every chunk of data consecutively.</p>
<p>For more information, see the <a class="" href="https://uppy.io/docs/companion/">Companion docs</a>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="corsorigins-option-is-now-required"><code>corsOrigins</code> option is now required<a href="https://uppy.io/blog/uppy-4.0/#corsorigins-option-is-now-required" class="hash-link" aria-label="Direct link to corsorigins-option-is-now-required" title="Direct link to corsorigins-option-is-now-required" translate="no">​</a></h3>
<p>As a security measure, we now require the
<a class="" href="https://uppy.io/docs/companion/#corsorigins-required"><code>corsOrigins</code></a> option to be set.</p>
<p>It serves two purposes: it sets the <code>Access-Control-Allow-Origin</code> header as well
as the target origin for <code>window.postMessage()</code>, which is needed to communicate
the OAuth token from the new tab you used to log in to a provider back to
Companion.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="and-more">And more<a href="https://uppy.io/blog/uppy-4.0/#and-more" class="hash-link" aria-label="Direct link to And more" title="Direct link to And more" translate="no">​</a></h2>
<p>The 4.0 release contains over 170 contributions, many too small to mention, but
together resulting in Uppy continuing to grow and improve. We closely listen to
the community and are always looking for ways to improve the experience, for
users and developers alike.</p>
<p>Ready to upgrade? Be sure to check out the
<a class="" href="https://uppy.io/docs/guides/migration-guides/">migration guide</a>.</p>
<p><a href="https://www.producthunt.com/posts/uppy-4-0?embed=true&amp;utm_source=badge-featured&amp;utm_medium=badge&amp;utm_souce=badge-uppy-4-0" target="_blank" rel="noopener noreferrer" class=""><img decoding="async" loading="lazy" src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=473003&amp;theme=light" alt="Uppy 4.0 - TypeScript rewrite, Google Photos, and much more | Product Hunt" style="width:250px;height:54px" width="250" height="54" class="img_ev3q"></a></p>]]></content>
        <author>
            <name>Antoine du Hamel</name>
            <email>antoine@transloadit.com</email>
        </author>
        <author>
            <name>Evgenia Karunus</name>
            <email>lakesare@gmail.com</email>
        </author>
        <author>
            <name>Mikael Finstad</name>
            <email>mikael@transloadit.com</email>
        </author>
        <author>
            <name>Merlijn Vos</name>
            <email>merlijn@transloadit.com</email>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[🎄 Uppy 3.13 to 3.21: Typescript Saga: the beginning, Image Editor improvements, Dashboard auto-install]]></title>
        <id>https://uppy.io/blog/2023/07/3.13-3.21/</id>
        <link href="https://uppy.io/blog/2023/07/3.13-3.21/"/>
        <updated>2023-12-23T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[It’s this time of the year again! Make yourself cozy]]></summary>
        <content type="html"><![CDATA[<img decoding="async" loading="lazy" src="https://uppy.io/img/blog/3.13-3.21/dog-coding-laptop-mars-christmas-tree-2.jpg" alt="Drawing of a dog with a laptop and Christmas tree on Mars" class="img_ev3q">
<p>It’s this time of the year again! Make yourself cozy
<a href="https://www.youtube.com/watch?v=ouqtX6WWL1U" target="_blank" rel="noopener noreferrer" class="">by the fire</a>, and let us help you
unwrap the gifts Uppy has prepared for you.</p>
<p>We proud of all the improvements and amazing new features and bug fixes we were
able to introduce this year. The highlights being: conditional S3 multipart and
signing S3 uploads on the client, speedy handling of 10-50k file uploads,
refresh tokens (useful when the token expires mid-upload for a large amount of
files / slow connections), server-sent events and new <code>assemblyOptions</code> for the
Transloadit plugin, Dashboard Single File mode (<code>singleFileFullScreen</code>),
improved ETA in the Status Bar, a bunch of new languages, including Hindi,
Mexican Spanish and Catalan.</p>
<p>This one, however, is a recent Uppy updates post, covering releases from
<a href="https://github.com/transloadit/uppy/compare/uppy%403.13.0...uppy%403.21.0" target="_blank" rel="noopener noreferrer" class=""><code>3.13.0</code> to <code>3.21.0</code></a>:
announcing the switch to Typescript, Dashboard can now auto-install plugins,
support for Catalan language, a heap of bug fixes for Tus, Companion, AWS S3,
and more.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="typescript">Typescript<a href="https://uppy.io/blog/2023/07/3.13-3.21/#typescript" class="hash-link" aria-label="Direct link to Typescript" title="Direct link to Typescript" translate="no">​</a></h2>
<p>We are excited to announce that we are working hard to refactor Uppy Core and
all plugins source files to TypeScript. We have a build setup in place that
temporarily supports both <code>.ts</code> and <code>.js</code> files in our monorepo. And a helper
utility that takes a package name and does the initial renaming and Typescript
config. Then we go through the list of plugins one by one. We begun with
<code>@uppy/utils</code> and <code>@uppy/core</code>, since most other packages depend on those. Now
we are moving to the rest, one by one.</p>
<p>This work so far is only affecting Uppy internals. In published packages we are
using the manually crafted <code>d.ts</code> files, as before. We are planning to flip the
switch and introduce some breaking changes in the next Uppy major, due to be
released in the first quater of 2024.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="core">Core<a href="https://uppy.io/blog/2023/07/3.13-3.21/#core" class="hash-link" aria-label="Direct link to Core" title="Direct link to Core" translate="no">​</a></h2>
<ul>
<li class="">Allow duplicate files with <code>onBeforeFileAdded</code>.</li>
<li class="">Fixed<code>onBeforeFileAdded</code> with Golden Retriever.</li>
<li class="">Simplify types with class generic and type more events.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="image-editor">Image Editor<a href="https://uppy.io/blog/2023/07/3.13-3.21/#image-editor" class="hash-link" aria-label="Direct link to Image Editor" title="Direct link to Image Editor" translate="no">​</a></h2>
<p>We have a whole separate blog post about the recent rotation improvements in the
Image Editor, so please read that, if you are interested. Other changes include:</p>
<ul>
<li class="">Fixed labels on all buttons, centered the rotation slider label.</li>
<li class="">Limited cropbox movements.</li>
<li class="">Fixed to respect <code>cropperOptions.initialAspectRatio</code>.</li>
<li class="">Change the checkered background color, make it semi-transparent.</li>
<li class="">Fixed granular rotation: <code>[-45, 45]</code> instead of <code>[-45, 44]</code>.</li>
<li class="">Removed 1px black lines.</li>
<li class="">Made <code>file-editor:cancel</code> event fire when the Image Editor’s “cancel” button
is pressed.</li>
</ul>
<video muted="" autoplay="" loop="" src="/img/blog/3.13-3.21/crop.mov" type="video/mp4">
</video>
<img decoding="async" loading="lazy" alt="Editor semi-transparant checkered background" src="https://uppy.io/img/blog/3.13-3.21/editor.jpg" class="img_ev3q">
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="dashboard">Dashboard<a href="https://uppy.io/blog/2023/07/3.13-3.21/#dashboard" class="hash-link" aria-label="Direct link to Dashboard" title="Direct link to Dashboard" translate="no">​</a></h2>
<p>Dashboard can now automatically discover and install compatible plugins without
<code>target</code> option. This lets you use a much more condense syntax:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> uppy </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">Uppy</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">use</span><span class="token punctuation" style="color:#393A34">(</span><span class="token maybe-class-name">ImageEditor</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">use</span><span class="token punctuation" style="color:#393A34">(</span><span class="token maybe-class-name">Dashboard</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">use</span><span class="token punctuation" style="color:#393A34">(</span><span class="token maybe-class-name">Webcam</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">use</span><span class="token punctuation" style="color:#393A34">(</span><span class="token maybe-class-name">GoogleDrive</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>tip</div><div class="admonitionContent_BuS1"><p>The old way via <code>.use(ImageEditor, { target: Dashboard })</code> and
<code>.use(Dashboard, { plugins: ['Webcam', 'GoogleDrive'] })</code> still works, but we
encourage you to use the new syntax.</p></div></div>
<p>Bug fixes:</p>
<ul>
<li class="">Remove <code>.uppy-Dashboard-isFixed</code> CSS class when <code>uppy.close()</code> is invoked.</li>
<li class="">When <code>showAddFilesPanel: true</code>, <code>aria-hidden</code> should be the opposite.</li>
<li class="">Don’t cancel all files and Assemblies when clicking “done”.</li>
<li class="">Update Dashboard’s blue color to meet WCAG contrast requirements.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="aws-s3">AWS S3<a href="https://uppy.io/blog/2023/07/3.13-3.21/#aws-s3" class="hash-link" aria-label="Direct link to AWS S3" title="Direct link to AWS S3" translate="no">​</a></h2>
<ul>
<li class="">Fixed <code>TypeError</code>, fixed <code>uploadURL</code> when using <code>PUT</code>.</li>
<li class="">Pass <code>signal</code> as separate arg for backward compat; pass the <code>uploadURL</code> back
to the caller.</li>
<li class="">Refresh file before calling user-defined functions.</li>
<li class="">Made sure we retry signature request.</li>
<li class="">Use uppercase HTTP method names.</li>
<li class="">Call <code>#setCompanionHeaders</code> in <code>setOptions</code>.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="companion">Companion<a href="https://uppy.io/blog/2023/07/3.13-3.21/#companion" class="hash-link" aria-label="Direct link to Companion" title="Direct link to Companion" translate="no">​</a></h2>
<p>One of the most notable changes in Companion is on the client side, we’ve made
authentication optional, allowing for more provider types, with publicly
accessable links, for example.</p>
<p>In Companion Client we were able to drop the now unnecessary preflight requests,
improving upload speeds and latency yet again.</p>
<p>Other notable changes and fixes:</p>
<ul>
<li class="">Allow dynamic S3 bucket.</li>
<li class="">Companion+client stability fixes, error handling and retries.</li>
<li class="">Catch “invalid initialization vector” instead of crashing.</li>
<li class="">Added Onedrive refresh tokens.</li>
<li class="">Fixed <code>authProvider</code> property inconsistency.</li>
<li class="">Fixed accelerated endpoints for presigned POST.</li>
<li class="">Fixed double tus uploads.</li>
<li class="">Fixed onedrive pagination.</li>
<li class="">Fixed Redis key default TTL.</li>
<li class="">Fixed Uploader.js metadata normalisation.</li>
<li class="">Make CSRF protection helpers available to providers.</li>
<li class="">Refactor <code>getProtectedHttpAgent</code> to make TS happy.</li>
<li class="">Unify redis initialization.</li>
<li class="">Use deferred length for tus streams.</li>
<li class="">Fixed a refresh token race condition.</li>
<li class="">Fixed edge case for pagination on root.</li>
<li class="">Fixed instagram/facebook auth error regression; uploadRemoteFile undefined;
ProviderView error on empty plugin.icon.</li>
<li class="">Added getBucket metadata argument.</li>
<li class="">Added missing credentialsURL for box.</li>
<li class="">Added test endpoint for dynamic oauth creds.</li>
<li class="">Added Companion OAuth Key type.</li>
<li class="">Aliased “removeListener” as “off” in Redis emitter.</li>
<li class="">Use user-defined <code>onSuccess</code>, <code>onError</code>, and <code>onProgress</code> callbacks in
<code>@uppy/tus</code>.</li>
<li class="">Invoke headers function for remote uploads.</li>
<li class="">Send certain Onedrive errors to the user.</li>
<li class="">Upgraded Node.js docker version.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="frameworks-integraions">Frameworks Integraions<a href="https://uppy.io/blog/2023/07/3.13-3.21/#frameworks-integraions" class="hash-link" aria-label="Direct link to Frameworks Integraions" title="Direct link to Frameworks Integraions" translate="no">​</a></h2>
<ul>
<li class="">Angular: upgraded to Angular 16.x.</li>
<li class="">Svelte: Fixed TS build command.</li>
<li class="">Vue: added export for FileInput.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="locales">Locales<a href="https://uppy.io/blog/2023/07/3.13-3.21/#locales" class="hash-link" aria-label="Direct link to Locales" title="Direct link to Locales" translate="no">​</a></h2>
<ul>
<li class="">Added Catalan locale <code>ca_ES</code>.</li>
<li class="">Added missing translations to <code>de_DE</code>.</li>
<li class="">Update Farsi.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="transloadit">Transloadit<a href="https://uppy.io/blog/2023/07/3.13-3.21/#transloadit" class="hash-link" aria-label="Direct link to Transloadit" title="Direct link to Transloadit" translate="no">​</a></h2>
<ul>
<li class="">Emit assembly progress events.</li>
<li class="">Removed Socket.io — it’s server-sent events with fallback to polling now.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="misc">Misc<a href="https://uppy.io/blog/2023/07/3.13-3.21/#misc" class="hash-link" aria-label="Direct link to Misc" title="Direct link to Misc" translate="no">​</a></h2>
<ul>
<li class="">Added Prettier, migrated to Vitest for Uppy core and Uppy plugins.</li>
<li class="">Update <code>file.meta.name</code> after compression, becase format/extension might have
changed.</li>
<li class="">use latest Node.js version for tests.</li>
<li class="">Migrate to AWS-SDK V3 syntax.</li>
<li class="">Move remote file upload logic into companion-client.</li>
</ul>
<p>Happy holidays and see you in 2024!</p>]]></content>
        <author>
            <name>Antoine du Hamel</name>
            <email>antoine@transloadit.com</email>
        </author>
        <author>
            <name>Merlijn Vos</name>
            <email>merlijn@transloadit.com</email>
        </author>
        <author>
            <name>Artur Paikin</name>
            <email>artur@transloadit.com</email>
        </author>
        <author>
            <name>Mikael Finstad</name>
            <email>mikael@transloadit.com</email>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Scaling Images on Rotation]]></title>
        <id>https://uppy.io/blog/2023-10-25-image-editor/</id>
        <link href="https://uppy.io/blog/2023-10-25-image-editor/"/>
        <updated>2023-12-08T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[We recently released an “image scaling on rotation” feature for Uppy’s]]></summary>
        <content type="html"><![CDATA[<p>We recently released an “image scaling on rotation” feature for Uppy’s
<a href="https://uppy.io/docs/image-editor/" target="_blank" rel="noopener noreferrer" class="">Image Editor</a>, an often-requested feature
that we’re super proud to be able to announce.</p>
<p>In this blog post, we’ll be taking a peek behind the curtain, as we take a
detailed look into the development of this feature, and our thought-process
approaching it.</p>
<p>Before we start though, take a look below at a comparison between how Uppy’s
Image Editor used to handle image rotations, and how it handles them now.</p>

  
  
  <table textalign:="">
  <thead>
  <tr>
    <th colspan="{2}">
      Rotation
    </th>
  </tr><tr>
    <th>Without scaling</th>
    <th>With scaling</th>
  </tr>
  </thead><tbody>
  <tr>
  <td>
    <video controls="" muted="" autoplay="">
      <source src="/img/blog/2023-10-25-image-editor/without-scaling.mov" type="video/mp4">
    </video>
  </td><td>
    <video controls="" muted="" autoplay="">
      <source src="/img/blog/2023-10-25-image-editor/with-scaling.mov" type="video/mp4">
    </video>
  </td>
  </tr>
  </tbody></table>
<p>Without further ado, let’s dive into some of the finer technical details, so you
can follow along and implement this feature into your own image editor.</p>
<p>The above UI is present in many image editors - for example, the default image
editors on iOS and Android both employ it. Often users expect this behaviour
too, leading to some confusion when their images are left with ugly corners
after a rotation.</p>
<p>We implemented this in Uppy’s Image Editor last week, and the solution turned
out to be non-trivial. Since this is a pretty ubiquitous task to solve for all
image editors, we decided to release our solution to the world and write out a
post about it, instead of keeping it hidden away as part of internal notes.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-steps">3 Steps<a href="https://uppy.io/blog/2023-10-25-image-editor/#3-steps" class="hash-link" aria-label="Direct link to 3 Steps" title="Direct link to 3 Steps" translate="no">​</a></h2>
<p>There are <strong>3 steps</strong> to our scaling implementation:</p>
<ol>
<li class="">Ask your designer what scaling on rotation should look like</li>
<li class="">Find the <code>.scale()</code> function</li>
<li class="">Calculating the geometry</li>
</ol>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-trust-your-designer">1. Trust your designer<a href="https://uppy.io/blog/2023-10-25-image-editor/#1-trust-your-designer" class="hash-link" aria-label="Direct link to 1. Trust your designer" title="Direct link to 1. Trust your designer" translate="no">​</a></h3>
<p>When I first approached this task, my gut-instinct was to go for the “rotated
rectangle inscribed within another rectangle” solution so that the largest-area
inscription possible is achieved. This route turned out to be an unpleasant user
experience, so take this as an important lesson in trusting your designer, and
consulting them first on what the user might want.</p>
<p>Alternatively, you can choose to trust our designer’s advice by:</p>
<ul>
<li class="">always rotating the image around the center of the image (intersection of the
diagonals)</li>
<li class="">just enlarging the image to remove any empty corners</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-find-the-scale-function">2. Find the <code>.scale()</code> function<a href="https://uppy.io/blog/2023-10-25-image-editor/#2-find-the-scale-function" class="hash-link" aria-label="Direct link to 2-find-the-scale-function" title="Direct link to 2-find-the-scale-function" translate="no">​</a></h3>
<p>To enlarge the image in a way that covers empty corners, we first need a scaling
function. Uppy uses <a href="https://github.com/fengyuanchen/cropperjs" target="_blank" rel="noopener noreferrer" class="">cropperjs v1.x</a>
as an image editing library, which exposes the <code>cropper.scale(scalingFactor)</code>
function. Most image editing libraries are likely to have a similar function,
but of course feel free to code one yourself if you feel up to the challenge.</p>
<p>Importantly, the scaling function should
<a href="https://en.wikipedia.org/wiki/Scaling_(geometry)#Uniform_scaling" target="_blank" rel="noopener noreferrer" class="">uniformly enlarge</a>
the image <em>around its center</em>, where the <code>scalingFactor</code> is determined by
<code>desiredHeight/oldHeight</code>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-calculate-the-geometry">3. Calculate the geometry<a href="https://uppy.io/blog/2023-10-25-image-editor/#3-calculate-the-geometry" class="hash-link" aria-label="Direct link to 3. Calculate the geometry" title="Direct link to 3. Calculate the geometry" translate="no">​</a></h3>
<p>Now, we want to draw our before-rotation &amp; after-rotation shapes on the same
picture, and apply some trigonometry. If you need to brush up on the mathematics
behind this, we recommend watching the following Khan Academy lessons on
<a href="https://www.khanacademy.org/test-prep/praxis-math/praxis-math-lessons/gtp--praxis-math--lessons--geometry/a/gtp--praxis-math--article--angles--lesson" target="_blank" rel="noopener noreferrer" class="">how angles work</a>
and
<a href="https://www.khanacademy.org/math/geometry/hs-geo-trig/hs-geo-trig-ratios-intro/a/finding-trig-ratios-in-right-triangles" target="_blank" rel="noopener noreferrer" class="">how sines and cosines work</a>,
as these cover everything you’ll need to follow along.</p>
<p>In the images below, we see what happens on rotation by default. To remove the
empty corners, the user would have to drag around the edges of the cropbox. What
we can do instead is scale the image (in the directions shown by the &lt;span
style={{ color: <code>rgb(127, 194, 65)</code> }}&gt;green arrows) so that these
corners disappear.</p>

  
  <table background:="">
  <thead>
  <tr><th colspan="{2}">What happens on rotation</th></tr>
  </thead><tbody>
  <tr>
  <td width="50%">
    <img decoding="async" loading="lazy" maxwidth:="" src="https://uppy.io/img/blog/2023-10-25-image-editor/1a.jpg" class="img_ev3q">
  </td><td width="50%">
    <img decoding="async" loading="lazy" maxwidth:="" src="https://uppy.io/img/blog/2023-10-25-image-editor/1b.jpg" class="img_ev3q">
  </td>
  </tr>
  </tbody></table>
<p>So, to cover up these checkered corners, we will need to scale the image. If we
cover up the larger corner, the smaller corner will get covered up
automatically, so our code takes the form of
<code>scale(Math.max(scalingFactor1, scalingFactor2))</code>. These two scaling factors are
calculated very similarly, so we’ll only focus on calculating only one of them
in this tutorial (although the full solution is given in the conclusion).</p>
<p>In the images below, the &lt;span style={{ color: <code>rgb(127, 194, 65)</code> }}&gt;green
rectangle represents the desired dimensions of our image after it’s
scaled. Our scaling function (and hopefully yours) is defined in such a way that
if we have the image of height <code>h</code>, and we want to scale it up to height <code>H</code>, we
need to execute <code>.scale(H/h)</code>. Since we already know <code>h</code>, as it’s the height of
our image, we only need to find <code>H</code> to complete our scaling function.</p>

  
  <table background:="">
  <thead>
  <tr><th colspan="{2}">We want to find H</th></tr>
  </thead><tbody>
  <tr>
  <td width="50%">
    <img decoding="async" loading="lazy" src="https://uppy.io/img/blog/2023-10-25-image-editor/2a.jpg" class="img_ev3q">
  </td><td width="50%">
    <img decoding="async" loading="lazy" src="https://uppy.io/img/blog/2023-10-25-image-editor/2b.jpg" class="img_ev3q">
  </td>
  </tr>
  </tbody></table>
<p>For the rest of the tutorial, the following steps are then automatic - as we
know all the angles in the image, we know the image’s width and height, and we
know to find <code>H</code>.</p>
<p padding:="">The easiest way to go about it, is to first annotate the image with all the
relevant angles. We’ll be using <span color:="">blue </span> for the rotation angle
 <code>α</code>, and <span color:="">pink </span>
for <code>90 - α</code>:</p>

  <table background:="" textalign:="">
  <thead display:="" width:="">
  <tr><th>Color all angles</th></tr>
  </thead><tbody display:="" width:="">
  <tr>
  <td>
    <img decoding="async" loading="lazy" width:="" src="https://uppy.io/img/blog/2023-10-25-image-editor/3.jpg" class="img_ev3q">
  </td>
  </tr>
  </tbody></table>
<p>We can then find <code>H</code>, by adding the two outer sides of these triangles.</p>

  
  <table background:="">
  <thead>
  <tr><th colspan="{2}">Add two triangle sides: H = sin(α - 90) * h + sin(α) * w</th></tr>
  </thead><tbody>
  <tr>
  <td width="50%">
    <img decoding="async" loading="lazy" src="https://uppy.io/img/blog/2023-10-25-image-editor/4a.jpg" class="img_ev3q">
  </td><td width="50%">
    <img decoding="async" loading="lazy" src="https://uppy.io/img/blog/2023-10-25-image-editor/4b.jpg" class="img_ev3q">
  </td>
  </tr>
  </tbody></table>
<p>So, now we have our desired <code>H</code>! We know one of our scaling factors is <code>H/h</code>.
Now, we just need to find our other scaling factor, which is <code>W/w</code>. This follows
a similar process, and you can find the calculations as part of the full
solution below.</p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">scalingFactor</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">max</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">scalingFactor1</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> scalingFactor2</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">max</span><span class="token punctuation" style="color:#393A34">(</span><span class="token constant" style="color:#36acaa">H</span><span class="token operator" style="color:#393A34">/</span><span class="token plain">h</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">W</span><span class="token operator" style="color:#393A34">/</span><span class="token plain">w</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">max</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">sin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">α </span><span class="token operator" style="color:#393A34">-</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">90</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> h </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">sin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">α</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> w</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">/</span><span class="token plain"> h</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">sin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">α</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> h </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">sin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">α </span><span class="token operator" style="color:#393A34">-</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">90</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> w</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">/</span><span class="token plain"> w</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><br></span></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="conclusion">Conclusion<a href="https://uppy.io/blog/2023-10-25-image-editor/#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion" translate="no">​</a></h2>
<p>In Uppy, our code ended up looking like this:</p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getScalingFactor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token parameter">w</span><span class="token parameter punctuation" style="color:#393A34">,</span><span class="token parameter"> h</span><span class="token parameter punctuation" style="color:#393A34">,</span><span class="token parameter"> rotationAngle</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> α </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token known-class-name class-name">Math</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">abs</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">toRadians</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">rotationAngle</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> scalingFactor </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token known-class-name class-name">Math</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">max</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token punctuation" style="color:#393A34">(</span><span class="token known-class-name class-name">Math</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">sin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">α</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> w </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token known-class-name class-name">Math</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">cos</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">α</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> h</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">/</span><span class="token plain"> h</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token punctuation" style="color:#393A34">(</span><span class="token known-class-name class-name">Math</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">sin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">α</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> h </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token known-class-name class-name">Math</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">cos</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">α</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> w</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">/</span><span class="token plain"> w</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword control-flow" style="color:#00009f">return</span><span class="token plain"> scalingFactor</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> image </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> cropper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">getImageData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> scaleFactor </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getScalingFactor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">image</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">width</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> image</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">height</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> rotationAngle</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">cropper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">scale</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">scaleFactor</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<p>You can see the full version
<a href="https://github.com/transloadit/uppy/blob/12e08ada02b9080bd5e1d19526bdf8a2010e62a1/packages/%40uppy/image-editor/src/utils/getScaleFactorThatRemovesDarkCorners.js" target="_blank" rel="noopener noreferrer" class="">on GitHub</a>.</p>
<details class="details_lb9f alert alert--info details_b_Ee" data-collapsed="true"><summary>Bonus content: our founder’s (Tim Koschuetzki) initial scribbled notes with the solution</summary><div><div class="collapsibleContent_i85q">
  <!-- -->
  <img decoding="async" loading="lazy" src="https://uppy.io/img/blog/2023-10-25-image-editor/tim.jpg" class="img_ev3q">
</div></div></details>]]></content>
        <author>
            <name>Evgenia Karunus</name>
            <email>lakesare@gmail.com</email>
        </author>
        <author>
            <name>Tim Koschuetzki</name>
            <email>tim@transloadit.com</email>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Uppy 3.3 to 3.13: conditional S3 multipart, signing on the client, speedy handling of 10k files and much much more]]></title>
        <id>https://uppy.io/blog/2023/07/3.3-3.13/</id>
        <link href="https://uppy.io/blog/2023/07/3.3-3.13/"/>
        <updated>2023-07-26T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[This is a big Uppy update post, covering releases from]]></summary>
        <content type="html"><![CDATA[<img decoding="async" loading="lazy" src="https://uppy.io/img/blog/3.4-3.13/single-file-mode.jpg" class="border img_ev3q" alt="Screenshot of the new Uppy website homepage">
<p>This is a big Uppy update post, covering releases from
<a href="https://github.com/transloadit/uppy/compare/uppy%403.4.0...uppy%403.13.0" target="_blank" rel="noopener noreferrer" class=""><code>3.3.0</code> to <code>3.13.0</code></a>!</p>
<p>In this issue: the long-awaited unified S3 plugin which can switch between
regular and multipart uploads, improved performance when adding and validating
10k+ files, and stability improvements and bug fixes. The Transloadit plugin is
now also easier to configure and leaner in bundle size, since we removed
<code>socket.io-client</code> in favor of
<a href="https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events" target="_blank" rel="noopener noreferrer" class="">Server-Sent Events</a>.</p>
<p>Please make a cup of something tasty ☕️ (in a non-spillable container), as this
will be quite a ride.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="aws-s3">AWS S3<a href="https://uppy.io/blog/2023/07/3.3-3.13/#aws-s3" class="hash-link" aria-label="Direct link to AWS S3" title="Direct link to AWS S3" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="merging-of-the-plugins">Merging of the plugins<a href="https://uppy.io/blog/2023/07/3.3-3.13/#merging-of-the-plugins" class="hash-link" aria-label="Direct link to Merging of the plugins" title="Direct link to Merging of the plugins" translate="no">​</a></h3>
<p>After years of separating regular non-multipart uploads and multipart uploads,
we are finally merging the two sibling plugins: <code>@uppy/aws-s3</code> and
<code>@uppy/aws-s3-multpart</code>. Here’s the brief version of what you need to know, with
details to follow in the next section:</p>
<ul>
<li class=""><code>@uppy/aws-s3-multipart</code> is deprecated. You should use <code>@uppy/aws-s3</code> and set
the <code>shouldUseMultipart: true</code> option to get the same “multipart always
enabled” behavior. We plan to keep <code>@uppy/aws-s3-multipart</code> around as an alias
for the next major cycle and add a warning at the install when Uppy 4.0.0 will
be released.</li>
<li class=""><code>@uppy/aws-s3</code> now hosts two plugins:
<ul>
<li class="">the legacy one, untouched, to guarantee backward compatibility. We plan to
get rid of it in the next major, we recommend moving away from it and report
if you see something missing in the new plugin.</li>
<li class="">the new merged plugin, available if you pass
<a href="https://uppy.io/docs/aws-s3/#shouldusemultipartfile" target="_blank" rel="noopener noreferrer" class=""><code>shouldUseMultipart</code></a>
option.</li>
</ul>
</li>
</ul>
<p>Our plan for this merge is to maintain the backward compatibility until the next
major, while also providing forward compatibility so you can try our new plugin
and give us some feedback before we remove the old code for good.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="conditional-multipart-explained">Conditional Multipart Explained<a href="https://uppy.io/blog/2023/07/3.3-3.13/#conditional-multipart-explained" class="hash-link" aria-label="Direct link to Conditional Multipart Explained" title="Direct link to Conditional Multipart Explained" translate="no">​</a></h3>
<p>Multipart and “regular” uploads have different use cases. The advantages of
multipart uploads are:</p>
<ul>
<li class=""><strong>Improved throughput</strong> – You can upload parts in parallel to improve
throughput.</li>
<li class=""><strong>Quick recovery from any network issues</strong> – Smaller part size minimizes the
impact of restarting a failed upload due to a network error.</li>
<li class=""><strong>Pause and resume object uploads</strong> – You can upload object parts over time.
After you initiate a multipart upload, there is no expiry; you must explicitly
complete or stop the multipart upload.</li>
<li class=""><strong>Begin an upload before you know the final object size</strong> – You can upload an
object as you are creating it.</li>
</ul>
<p>However, the downside is <em>request overhead</em>, as it needs to do creation,
signing, and completion requests besides the upload requests. For example, if
you are uploading files that are only a couple kilobytes with a 100ms roundtrip
latency, you are spending 400ms on overhead and only a few milliseconds on
uploading. This really adds up if you upload a lot of small files.</p>
<p>So now you can use just one plugin, the <code>@uppy/aws-s3</code>, and enable multipart
conditionally, even per-file:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">uppy</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">use</span><span class="token punctuation" style="color:#393A34">(</span><span class="token maybe-class-name">AwsS3</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token function" style="color:#d73a49">shouldUseMultipart</span><span class="token punctuation" style="color:#393A34">(</span><span class="token parameter">file</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token comment" style="color:#999988;font-style:italic">// Use multipart only for files larger than 100MiB.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword control-flow" style="color:#00009f">return</span><span class="token plain"> file</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">size</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">100</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">**</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">20</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<p>or</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">uppy</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">use</span><span class="token punctuation" style="color:#393A34">(</span><span class="token maybe-class-name">AwsS3</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token literal-property property" style="color:#36acaa">shouldUseMultipart</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<p>Please see the new
<a href="https://uppy.io/docs/aws-s3/#shouldusemultipartfile" target="_blank" rel="noopener noreferrer" class=""><code>shouldUseMultipart: boolean | function</code></a>
option for details.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="signing-on-the-client">Signing on the client<a href="https://uppy.io/blog/2023/07/3.3-3.13/#signing-on-the-client" class="hash-link" aria-label="Direct link to Signing on the client" title="Direct link to Signing on the client" translate="no">​</a></h3>
<p>By default, when you upload to S3 with Uppy, every file, or every chunk in case
of Multipart, needs to be signed on the server. For many small files or files
with many chunks this means a few additional requests per file/chunk of the
upload.</p>
<p>To address this issue and speed up the uploads by roughly 20%, we are
introducing a new option: <code>getTemporarySecurityCredentials: boolean | function</code>.
When <code>true</code>, both S3 and S3 Multipart uploads will be signed on the client using
the
<a href="https://docs.aws.amazon.com/STS/latest/APIReference/API_GetFederationToken.html" target="_blank" rel="noopener noreferrer" class="">AWS Security Federation Token</a>,
created once per user (until it expires) on your backend rather than a unique
signed URL for every single chunk.</p>
<div class="theme-admonition theme-admonition-caution admonition_xJq3 alert alert--warning"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>caution</div><div class="admonitionContent_BuS1"><p>You should opt-in into this only if you are comfortable giving end users direct
access to signing files for your bucket.</p></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="stability-and-bug-fixes">Stability and bug fixes<a href="https://uppy.io/blog/2023/07/3.3-3.13/#stability-and-bug-fixes" class="hash-link" aria-label="Direct link to Stability and bug fixes" title="Direct link to Stability and bug fixes" translate="no">​</a></h3>
<ul>
<li class="">We’ve improved the internal handling of <code>RateLimitedQueue</code> to make
<a href="https://github.com/transloadit/uppy/pull/4424" target="_blank" rel="noopener noreferrer" class="">retries more robust</a> and
increased
<a href="https://github.com/transloadit/uppy/pull/4542" target="_blank" rel="noopener noreferrer" class="">priority of <code>abort</code> and <code>complete</code></a>
requests.</li>
<li class="">While we were at it, we’ve also fixed
<a href="https://github.com/transloadit/uppy/pull/4528" target="_blank" rel="noopener noreferrer" class="">resuming in single-chunk uploads</a>,
and improved
<a href="https://github.com/transloadit/uppy/pull/4508" target="_blank" rel="noopener noreferrer" class="">chunk size calculation</a>.</li>
<li class=""><a href="https://github.com/transloadit/uppy/pull/4526" target="_blank" rel="noopener noreferrer" class="">Golden Retriever integration with S3 Multipart</a>
was fixed.</li>
</ul>
<p>Additionally, we’ve disabled pause-resume buttons in the UI for remote S3
Multipart uploads —&nbsp;they are not supported on Companion, so the UI now reflects
that.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="core">Core<a href="https://uppy.io/blog/2023/07/3.3-3.13/#core" class="hash-link" aria-label="Direct link to Core" title="Direct link to Core" translate="no">​</a></h2>
<p>Performance of adding and uploading big batches of files has (yet again) been
greatly improved with refactors in both Uppy Core and Provider Views (that’s
what we internally call all remote UIs: Instagram, Unsplash, Dropbox).</p>
<p>We’ve been able to achieve this by
<a href="https://github.com/transloadit/uppy/pull/4402" target="_blank" rel="noopener noreferrer" class="">refactoring out totals validation for Restrictions (maxTotalFileSize, maxNumberOfFiles)</a>:
instead of doing it for each file, we perform the check at the end, after all
the files have been added/validated. This was confirmed to work with 10k+ files!
🚀</p>
<img decoding="async" loading="lazy" src="https://uppy.io/img/blog/3.4-3.13/10k-files.jpg" class="border img_ev3q" alt="Uppy UI with over 10k files selected from a remote source">
<p>We’ve also fixed an issue with delayed throttled progress events, which could
lead to incorrect progress.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="transloadit">Transloadit<a href="https://uppy.io/blog/2023/07/3.3-3.13/#transloadit" class="hash-link" aria-label="Direct link to Transloadit" title="Direct link to Transloadit" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="assemblyoptions">assemblyOptions<a href="https://uppy.io/blog/2023/07/3.3-3.13/#assemblyoptions" class="hash-link" aria-label="Direct link to assemblyOptions" title="Direct link to assemblyOptions" translate="no">​</a></h3>
<p>We’ve introduced a new option called
<a href="https://uppy.io/docs/transloadit/#assemblyoptions" target="_blank" rel="noopener noreferrer" class=""><code>assemblyOptions: object | function</code></a>,
which replaces the <code>getAssemblyOptions</code>, <code>params</code> and <code>fields</code> (those are now
deprecated and will be removed in the next major).</p>
<p>Here’s how you can use the new option as an object:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">uppy</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">use</span><span class="token punctuation" style="color:#393A34">(</span><span class="token maybe-class-name">Transloadit</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token literal-property property" style="color:#36acaa">assemblyOptions</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token literal-property property" style="color:#36acaa">params</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">			</span><span class="token literal-property property" style="color:#36acaa">auth</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token literal-property property" style="color:#36acaa">key</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'key-from-transloadit'</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">			</span><span class="token literal-property property" style="color:#36acaa">template_id</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'id-from-transloadit'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">			</span><span class="token literal-property property" style="color:#36acaa">steps</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">				</span><span class="token comment" style="color:#999988;font-style:italic">// Overruling Template at runtime</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">			</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token literal-property property" style="color:#36acaa">signature</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'generated-signature'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token literal-property property" style="color:#36acaa">fields</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">			</span><span class="token comment" style="color:#999988;font-style:italic">// Dynamic or static fields to send along</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<p>And here’s an example with a function, to be able to set meta fields per-file,
for instance:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">uppy</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">use</span><span class="token punctuation" style="color:#393A34">(</span><span class="token maybe-class-name">Transloadit</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token function" style="color:#d73a49">assemblyOptions</span><span class="token punctuation" style="color:#393A34">(</span><span class="token parameter">file</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword control-flow" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">			</span><span class="token literal-property property" style="color:#36acaa">params</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">				</span><span class="token literal-property property" style="color:#36acaa">auth</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token literal-property property" style="color:#36acaa">key</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'TRANSLOADIT_AUTH_KEY_HERE'</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">				</span><span class="token literal-property property" style="color:#36acaa">template_id</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'xyz'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">			</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">			</span><span class="token literal-property property" style="color:#36acaa">fields</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">				</span><span class="token literal-property property" style="color:#36acaa">caption</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> file</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">meta</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">caption</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">			</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="server-sent-events">Server-sent events<a href="https://uppy.io/blog/2023/07/3.3-3.13/#server-sent-events" class="hash-link" aria-label="Direct link to Server-sent events" title="Direct link to Server-sent events" translate="no">​</a></h3>
<p>Historically Transloadit supported progress updates via Socket.io. It is a
robust and stable package, but came with a “price-tag” in the form of bundle
size:
<a href="https://bundlephobia.com/package/socket.io-client@4.7.1" target="_blank" rel="noopener noreferrer" class="">38.3 kB Minified</a>. So
it’s been on our minds for a while to replace it with something more
lightweight, without breaking backwards-compatibility for the older clients (so
simply removing Socket.io on the server in favor of plain WebSockets is not
desireable).</p>
<p>The answer —
<a href="https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events" target="_blank" rel="noopener noreferrer" class="">Server-sent events</a>.
It’s a simple low-overhead one-way connection from Transloadit servers to
<code>@uppy/transloadit</code>. As was the case with Socket.io, we fall back to HTTP
polling every 2 seconds if SSE connection fails for some reason.</p>
<p>Socket.io is still around in <code>@uppy/transloadit</code>, but will be removed soon, once
SSE proves itself in production.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="bug-fixes">Bug fixes<a href="https://uppy.io/blog/2023/07/3.3-3.13/#bug-fixes" class="hash-link" aria-label="Direct link to Bug fixes" title="Direct link to Bug fixes" translate="no">​</a></h3>
<ul>
<li class="">Reset <code>tus</code> key in the file on error, so retried files are re-uploaded.</li>
<li class="">Clean up event listener to prevent cancelled assemblies.</li>
<li class="">Make sure <code>fields</code> is not nullish when there are no files in Assembly.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="companion">Companion<a href="https://uppy.io/blog/2023/07/3.3-3.13/#companion" class="hash-link" aria-label="Direct link to Companion" title="Direct link to Companion" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="refresh-tokens">Refresh tokens<a href="https://uppy.io/blog/2023/07/3.3-3.13/#refresh-tokens" class="hash-link" aria-label="Direct link to Refresh tokens" title="Direct link to Refresh tokens" translate="no">​</a></h3>
<p>We’ve
<a href="https://github.com/transloadit/uppy/pull/4448" target="_blank" rel="noopener noreferrer" class="">implemented refresh tokens</a> for
Dropbox and Google Drive to solve issued where tokens would expire in the middle
of a long upload and then the upload would fail.</p>
<p>Here’s how it’s implemented in Companion:</p>
<ul>
<li class="">We changed the logic when receiving a 401 from Companion, Uppy will now call a
new <code>/:provider/refresh-token</code> endpoint which will give uppy a new access
token.</li>
<li class=""><code>refresh_token</code> is now stored inside uppy auth token along with <code>access_token</code>
(encrypted JWT) for providers that give a refresh token (before only
<code>access_token</code> was stored, now we store both as a <code>JSON.stringify</code>’d
document).</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="bug-fixes-and-improvements">Bug fixes and improvements<a href="https://uppy.io/blog/2023/07/3.3-3.13/#bug-fixes-and-improvements" class="hash-link" aria-label="Direct link to Bug fixes and improvements" title="Direct link to Bug fixes and improvements" translate="no">​</a></h3>
<ul>
<li class="">Fixed a bug with non-ASCII metadata crashed Companion. The AWS SDK doesn’t
encode metadata by itself, so now we do it in Companion.</li>
<li class="">Switched from aws-sdk v2 to @aws-sdk/* v3</li>
<li class="">Upgraded Grant dependency</li>
<li class="">We now send expire info for non-multipart uploads and added connection
keep-alive to Dropbox to improve connection stability</li>
<li class="">Merged Provider and SearchProvider internal remote source classes.</li>
<li class="">Increased max limits for remote file list operations and fixed part listing in
S3</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="url">Url<a href="https://uppy.io/blog/2023/07/3.3-3.13/#url" class="hash-link" aria-label="Direct link to Url" title="Direct link to Url" translate="no">​</a></h2>
<p>We’ve upgraded the Url plugin to use <code>filename</code> from <code>Content-Disposition</code>
header of the file you are importing, instead of relying on the url (but kept
the latter as a fallback) (#4489). So now your files have proper names instead
of <code>noname</code>.</p>
<img decoding="async" loading="lazy" src="https://uppy.io/img/blog/3.4-3.13/url-name.jpg" class="border img_ev3q" alt="Uppy UI with a file selected with the Url plugin">
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="dashboard-and-status-bar">Dashboard and Status Bar<a href="https://uppy.io/blog/2023/07/3.3-3.13/#dashboard-and-status-bar" class="hash-link" aria-label="Direct link to Dashboard and Status Bar" title="Direct link to Dashboard and Status Bar" translate="no">​</a></h2>
<p>Single File Mode has been improved to adapt to height of less than 400px — the
UI turns back to grid in this case. We are also not using <code>fit: cover</code> anymore
to avoid cropping important parts of the image:</p>
<img decoding="async" loading="lazy" src="https://uppy.io/img/blog/3.4-3.13/single-file-mode.jpg" class="border img_ev3q" alt="Uppy UI with single file">
<p>We’ve also added an option to disable the Single File mode, as it can be
unwanted in certain use cases:
<a href="https://uppy.io/docs/dashboard/#singlefilefullscreen" target="_blank" rel="noopener noreferrer" class=""><code>singleFileFullScreen</code></a>.</p>
<p>If you wrapped Uppy Dashboard in a <code>&lt;form&gt;</code> element, it could be accidentally
submitted when a user pressed Enter to save meta fields or entering urls. Now
we’ve
<a href="https://github.com/transloadit/uppy/pull/4283" target="_blank" rel="noopener noreferrer" class="">added a <code>form=""</code> attribute, connected to an empty <code>&lt;form&gt;</code></a>
in document root to prevent the outer form from being submitted.</p>
<p>A bug has been fixed that allowed clicking on buttons and links in Dashboard
<a href="https://uppy.io/docs/dashboard/#disabled" target="_blank" rel="noopener noreferrer" class="">disabled mode</a>.</p>
<p>Range selection of remote files has been fixed, you can now shift+click to
select multiple files again. We’ve added the <code>VirtualList</code> component which is
already used in Uppy “selected files” screen to remote file lists. So now
scrolling through 10k+ files is breeze 🌬️</p>
<img decoding="async" loading="lazy" src="https://uppy.io/img/blog/3.4-3.13/range-selection.jpg" class="border img_ev3q" alt="Dashboard UI with range selection">
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="status-bar">Status Bar<a href="https://uppy.io/blog/2023/07/3.3-3.13/#status-bar" class="hash-link" aria-label="Direct link to Status Bar" title="Direct link to Status Bar" translate="no">​</a></h3>
<ul>
<li class="">Fixed ETA when Uppy recovers its state.</li>
<li class="">Remove throttled component to fix a bug where state would become shared
between multiple status bars on a page.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="locales">Locales<a href="https://uppy.io/blog/2023/07/3.3-3.13/#locales" class="hash-link" aria-label="Direct link to Locales" title="Direct link to Locales" translate="no">​</a></h2>
<p>We’ve added support for Hindi and Mexican Spanish. French, Spanish and Chinese
locales have been improved.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="uploaders">Uploaders<a href="https://uppy.io/blog/2023/07/3.3-3.13/#uploaders" class="hash-link" aria-label="Direct link to Uploaders" title="Direct link to Uploaders" translate="no">​</a></h2>
<ul>
<li class="">Fixed an issue where sockets were opened right away, ignoring the
<code>RateLimitedQueue</code>, which led to bugs in all plugins that handle remote
uploads. Additionally, when file is removed (or all are canceled), we call
<code>controller.abort</code> on queued requests.</li>
<li class="">Fixed a bug with sockets being closed, while the upload was still in progress.</li>
<li class="">In XHR Upload we’ve added support for arrays in metadata and an
<code>'upload-stalled'</code> event.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="miscellaneous">Miscellaneous<a href="https://uppy.io/blog/2023/07/3.3-3.13/#miscellaneous" class="hash-link" aria-label="Direct link to Miscellaneous" title="Direct link to Miscellaneous" translate="no">​</a></h2>
<ul>
<li class=""><code>@uppy/golden-retriever</code> has been refactored refactor to modernize the
codebase.</li>
<li class="">We’ve switched more non-critical errors to warnings.</li>
<li class="">Improved fallbacks for the drag &amp; drop API.</li>
<li class="">The React Native example has been modernized and updated.</li>
<li class=""><code>uppy.resetProgress()</code> in Core has been fixed.</li>
</ul>
<p>We hope you’ve enjoyed this update posts and all the fixes and features we’ve
worked on! As always, please see the full changelog on GitHub:
<a href="https://github.com/transloadit/uppy/compare/uppy%403.4.0...uppy%403.13.0" target="_blank" rel="noopener noreferrer" class="">3.4.0 — 3.13.0</a>.</p>]]></content>
        <author>
            <name>Merlijn Vos</name>
            <email>merlijn@transloadit.com</email>
        </author>
        <author>
            <name>Artur Paikin</name>
            <email>artur@transloadit.com</email>
        </author>
        <author>
            <name>Antoine du Hamel</name>
            <email>antoine@transloadit.com</email>
        </author>
        <author>
            <name>Mikael Finstad</name>
            <email>mikael@transloadit.com</email>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[New Uppy.io and docs]]></title>
        <id>https://uppy.io/blog/2023-05-new-website/</id>
        <link href="https://uppy.io/blog/2023-05-new-website/"/>
        <updated>2023-05-10T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[We are excited to announce that our new website, documentation and blog are now]]></summary>
        <content type="html"><![CDATA[<img decoding="async" loading="lazy" src="https://uppy.io/img/blog/new-website/homepage.png" class="border img_ev3q" alt="Screenshot of the new Uppy website homepage">
<p>We are excited to announce that our new website, documentation and blog are now
live out of beta, ready for you to enjoy on <a href="https://uppy.io/" target="_blank" rel="noopener noreferrer" class="">Uppy.io</a>! Let us
know what you think <a href="https://twitter.com/uppy_io" target="_blank" rel="noopener noreferrer" class="">on twitter</a>.</p>
<p>The first iteration of the Uppy website was built by Artur and Kevin over 7
years ago, using <a href="https://hexo.io/" target="_blank" rel="noopener noreferrer" class="">Hexo</a> static site generator as a base. It
served us well, but over time Hexo got less maintained, our docs more messy, and
quite a few places were collecting dust.</p>
<p>About a year ago Merlijn set on a task to refresh the Uppy documentation
experience, rewriting most of the docs from the ground up, with everyone on the
team contributing in their area of Uppy knowledge.
<a href="https://docusaurus.io/" target="_blank" rel="noopener noreferrer" class="">Docusaurus</a> 🦕 was chosen as one of the top modern
tools for documentation.</p>
<p><img decoding="async" loading="lazy" alt="Screenshot of the Uppy website showing a documentation page with new design" src="https://uppy.io/assets/images/dashboard-docs-e2995a541161834109482c6667565081.png" width="3410" height="2002" class="img_ev3q"></p>
<p>Most of the plugin’s docs now explain when you should use it (and sometimes when
not), followed by how to install, tips and details and links to CodeSandbox
samples.</p>
<p>And for desert, we now have a swift website-wide search in the top bar, powered
by <a href="https://www.algolia.com/" target="_blank" rel="noopener noreferrer" class="">Algolia</a>, give it a go!</p>
<p><img decoding="async" loading="lazy" alt="Screenshot of the Uppy website showing the search interface" src="https://uppy.io/assets/images/search-9d346638aecf9ab33680181a8f7f821a.png" width="3450" height="1832" class="img_ev3q"></p>
<p>Enjoy the new <a href="https://uppy.io/" target="_blank" rel="noopener noreferrer" class="">uppy.io</a>!</p>]]></content>
        <author>
            <name>Merlijn Vos</name>
            <email>merlijn@transloadit.com</email>
        </author>
        <author>
            <name>Artur Paikin</name>
            <email>artur@transloadit.com</email>
        </author>
        <author>
            <name>Antoine du Hamel</name>
            <email>antoine@transloadit.com</email>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[🎄 Uppy 3.1-3.3: Improved AWS S3 Multipart, Single File Mode]]></title>
        <id>https://uppy.io/blog/2022/12/3.3/</id>
        <link href="https://uppy.io/blog/2022/12/3.3/"/>
        <updated>2022-12-23T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[🎅🐶 Ho-ho-ho, we are about to wrap up another year for Uppy! Three minor]]></summary>
        <content type="html"><![CDATA[<p><img decoding="async" loading="lazy" src="https://uppy.io/assets/images/dashboard-christmas-7bdeb276706cce5b1944c93b7680ccfa.jpg" width="1400" height="1097" class="img_ev3q"></p>
<p>🎅🐶 Ho-ho-ho, we are about to wrap up another year for Uppy! Three <code>minor</code>
releases ago we’ve introduced Uppy 3.0. It’s time to give you an update on
what’s been cooking in the Uppy-Transloadit headquarters (besides cranberry
sauce) for the past couple of months.</p>
<p>In short: AWS S3 Multipart stability improvements, Single File Mode for the
Dashboard, more tests and bugfixes, new locales.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="safer-aws-s3-multipart-uploads-on-slow-connections">Safer AWS S3 Multipart uploads on slow connections<a href="https://uppy.io/blog/2022/12/3.3/#safer-aws-s3-multipart-uploads-on-slow-connections" class="hash-link" aria-label="Direct link to Safer AWS S3 Multipart uploads on slow connections" title="Direct link to Safer AWS S3 Multipart uploads on slow connections" translate="no">​</a></h2>
<p><code>@uppy/aws-s3-multipart</code> has been serving well for people who prefer a
<em>client-to_s3</em> setup with Uppy. However, some uploads could occasionally fail in
poor network conditions. It turned out, simultaneously signing and uploading
many chunks at once saturated the HTTP/1.1 connection limit, which lead to
signatures expiring by the time Uppy started uploading the next chunk.</p>
<p>We’ve refactored our internal queue mechanism to sign chunks right before we
begin uploading them to the remote server. When the upload is paused, the queue
is emptied and re-populated again on resume. The default <code>limit</code> for this plugin
has been set to <code>6</code> and the default S3 signature expiry has been lifted from
<code>300</code> to <code>800</code> seconds.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="single-file-mode">Single File Mode<a href="https://uppy.io/blog/2022/12/3.3/#single-file-mode" class="hash-link" aria-label="Direct link to Single File Mode" title="Direct link to Single File Mode" translate="no">​</a></h2>
<p>Often times people only want to upload a single file (most commonly an image)
via Uppy. But the Dashboard UI is tailored to handling many files at once, and
it used to display the single image as a small, sad-looking block in the corner.
This ends now! (Actually, it ended a few releases ago, figure of speech).</p>
<img decoding="async" loading="lazy" src="https://uppy.io/img/blog/3.1-3.3/single-file-mode.jpg" class="border img_ev3q">
<p>With only one file selected, we’ll display it large and centered, and make sure
to re-generate the image preview so it’s <code>600px</code> wide, looking nice and sleek on
modern displays.</p>
<p>See <a href="https://github.com/transloadit/uppy/pull/4188" target="_blank" rel="noopener noreferrer" class="">PR #4188</a> for more
screenshots.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="bug-fixes-and-upgrades">Bug fixes and Upgrades<a href="https://uppy.io/blog/2022/12/3.3/#bug-fixes-and-upgrades" class="hash-link" aria-label="Direct link to Bug fixes and Upgrades" title="Direct link to Bug fixes and Upgrades" translate="no">​</a></h2>
<p>We’ve upgraded Typescript to <code>v4.8</code> and Jest to <code>v29</code>, among other tools and
packages.</p>
<p>We are now additionally testing that Uppy packages are correctly bundled with
the latest Rollup, Webpack, Parcel, Vite, and ESBuild.</p>
<p>Notable bug fixes:</p>
<ul>
<li class="">XHR Upload: Queue requests for socket token for remote files</li>
<li class="">Core: Prevent crashes when a file is removed before the upload starts</li>
<li class="">Golden Retriever: Fixed upload retries</li>
<li class="">AWS S3 and XHR Upload: Fixed Cannot mark a queued request as done in
MiniXHRUpload</li>
<li class="">Webcam: Set default videoConstraints</li>
<li class="">Image Editor: Fix controls in small Dashboard</li>
</ul>
<p>See the full list in the
<a href="https://github.com/transloadit/uppy/blob/main/CHANGELOG.md" target="_blank" rel="noopener noreferrer" class="">changelog</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="companion">Companion<a href="https://uppy.io/blog/2022/12/3.3/#companion" class="hash-link" aria-label="Direct link to Companion" title="Direct link to Companion" translate="no">​</a></h2>
<p>And of course, this festive season we are not forgetting Companion under the
tree:</p>
<ul>
<li class="">Throttle progress by time</li>
<li class="">Added workaround for S3 accelerated endpoints</li>
<li class="">Send expire info for non-multipart uploads</li>
<li class="">Send expiry time alongside S3 signed requests</li>
<li class="">Added support for AbortSignal</li>
<li class="">Prevent preflight race condition</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="locales">Locales<a href="https://uppy.io/blog/2022/12/3.3/#locales" class="hash-link" aria-label="Direct link to Locales" title="Direct link to Locales" translate="no">​</a></h2>
<p>Uzbek language pack was added, while Polish and Ukrainian language packs were
updated.</p>
<hr>
<p>That’s it for our updates! Stay tuned for more in 2023 and happy holidays (if
you are celebrating)! Cheers. In the meantime, we are driving home, driving home
for Christmas. Yeah.</p>
<p><img decoding="async" loading="lazy" src="https://uppy.io/assets/images/driving-home-0b068883d13788971c4bd54faf9e66f6.gif" width="480" height="270" class="img_ev3q"></p>]]></content>
        <author>
            <name>Antoine du Hamel</name>
            <email>antoine@transloadit.com</email>
        </author>
        <author>
            <name>Artur Paikin</name>
            <email>artur@transloadit.com</email>
        </author>
        <author>
            <name>Mikael Finstad</name>
            <email>mikael@transloadit.com</email>
        </author>
        <author>
            <name>Merlijn Vos</name>
            <email>merlijn@transloadit.com</email>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Uppy 3.0: Future-proof, conveniently easy, stable as ever]]></title>
        <id>https://uppy.io/blog/2022/09/3.0/</id>
        <link href="https://uppy.io/blog/2022/09/3.0/"/>
        <updated>2022-09-13T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Screenshot of Uppy 3.0.0 UI]]></summary>
        <content type="html"><![CDATA[<p><img decoding="async" loading="lazy" alt="Screenshot of Uppy 3.0.0 UI" src="https://uppy.io/assets/images/uppy-3-0-71a46f198071d75565646ce69236acec.jpg" width="1200" height="630" class="img_ev3q"></p>
<blockquote>
<p>For those new to Uppy, coming from Reddit, Hacker News and Product Hunt today:
Uppy is a popular open source file uploader for the browser. Pick files from
local disk or camera, remote sources like Instagram, Unsplash, Dropbox etc,
record audio and screencasts. Crop and tweak images with the image editor
plugin. Supports resumable uploads to a tus.io server, AWS S3 (and many others
with similar API like DigitalOcean), multipart.
<a href="https://uppy.io/examples/dashboard" target="_blank" rel="noopener noreferrer" class="">Try it</a>!</p>
</blockquote>
<p>Uppy is turning three! When you’re counting in
<a href="https://www.akc.org/expert-advice/health/how-to-calculate-dog-years-to-human-years/" target="_blank" rel="noopener noreferrer" class="">dog years</a>
– which we most certainly are – that’s 29 already. An age like that signifies
proper adulthood. For Uppy, this means it’s ready to stay loyal, but without the
silly mistakes (read: bugs). Uppy also underwent (ESM) surgery to keep it
strolling by your side in the current ecosystem, and received other behavioral
improvements 🐶</p>
<p>TL;DR: ESM transition, native mobile camera, new Remote Sources plugin, sweeping
Companion rewrite and streaming support, <code>async</code>/<code>await</code> everything, React 18
and Vue 3 support, all examples rewritten.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="esm-surgery">ESM surgery<a href="https://uppy.io/blog/2022/09/3.0/#esm-surgery" class="hash-link" aria-label="Direct link to ESM surgery" title="Direct link to ESM surgery" translate="no">​</a></h2>
<p><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules" target="_blank" rel="noopener noreferrer" class="">ECMAScript Modules</a>
(ESM) are the future and we’re ready to adopt it. Benefits over CommonJS
include: improved security, better tree shaking, and a syntax that can be
understood natively by browsers, which can greatly improve the DX if the tools
are configured to take advantage of that.</p>
<p>Following in the footsteps of many other packages, we now only ship Uppy core
and its plugins as ESM. For Uppy 2.x, we were shipping CommonJS.</p>
<p>If you are already using ESM or the CDN builds, nothing changes for you! If you
are using CommonJS, you may have to add extra tooling for everything to work, or
consider refactoring your codebase to ESM. Please refer to the
<a href="https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c" target="_blank" rel="noopener noreferrer" class="">Pure ESM package gist</a>
for more information and help on how to do that.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="less-integration-code-with-the-new-remote-sources-preset">Less integration code with the new remote sources preset<a href="https://uppy.io/blog/2022/09/3.0/#less-integration-code-with-the-new-remote-sources-preset" class="hash-link" aria-label="Direct link to Less integration code with the new remote sources preset" title="Direct link to Less integration code with the new remote sources preset" translate="no">​</a></h2>
<p>We’ve introduced a new Uppy preset plugin,
<a class="" href="https://uppy.io/docs/remote-sources/"><code>@uppy/remote-sources</code></a>, which combines Instagram,
Facebook, Google Drive, Box, Unsplash, Dropbox, One Drive, Zoom and any other
remote cloud sources that Uppy will support in the future. The plugin only works
with Dashboard and allows you to enable all the above sources in a single line.</p>
<p>Before, you had to manually include every cloud provider / remote source:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">uppy</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">use</span><span class="token punctuation" style="color:#393A34">(</span><span class="token maybe-class-name">Instagram</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token literal-property property" style="color:#36acaa">companionUrl</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">COMPANION_URL</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token literal-property property" style="color:#36acaa">companionAllowedHosts</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">COMPANION_ALLOWED_HOSTS</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">use</span><span class="token punctuation" style="color:#393A34">(</span><span class="token maybe-class-name">GoogleDrive</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token literal-property property" style="color:#36acaa">companionUrl</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">COMPANION_URL</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token literal-property property" style="color:#36acaa">companionAllowedHosts</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">COMPANION_ALLOWED_HOSTS</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">use</span><span class="token punctuation" style="color:#393A34">(</span><span class="token maybe-class-name">OneDrive</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token literal-property property" style="color:#36acaa">companionUrl</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">COMPANION_URL</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token literal-property property" style="color:#36acaa">companionAllowedHosts</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">COMPANION_ALLOWED_HOSTS</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">use</span><span class="token punctuation" style="color:#393A34">(</span><span class="token maybe-class-name">Instagram</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token literal-property property" style="color:#36acaa">companionUrl</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">COMPANION_URL</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token literal-property property" style="color:#36acaa">companionAllowedHosts</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">COMPANION_ALLOWED_HOSTS</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">use</span><span class="token punctuation" style="color:#393A34">(</span><span class="token maybe-class-name">Facebook</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token literal-property property" style="color:#36acaa">companionUrl</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">COMPANION_URL</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token literal-property property" style="color:#36acaa">companionAllowedHosts</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">COMPANION_ALLOWED_HOSTS</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">use</span><span class="token punctuation" style="color:#393A34">(</span><span class="token maybe-class-name">Unsplash</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token literal-property property" style="color:#36acaa">companionUrl</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">COMPANION_URL</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token literal-property property" style="color:#36acaa">companionAllowedHosts</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">COMPANION_ALLOWED_HOSTS</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// ...</span><br></span></code></pre></div></div>
<p>After:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">uppy</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">use</span><span class="token punctuation" style="color:#393A34">(</span><span class="token maybe-class-name">RemoteSources</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token literal-property property" style="color:#36acaa">companionUrl</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">COMPANION_URL</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<p>To get started, check out the <a class="" href="https://uppy.io/docs/remote-sources/"><code>RemoteSources</code> docs</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="robodog-ends-its-service">Robodog ends its service<a href="https://uppy.io/blog/2022/09/3.0/#robodog-ends-its-service" class="hash-link" aria-label="Direct link to Robodog ends its service" title="Direct link to Robodog ends its service" translate="no">​</a></h2>
<p>Uppy is flexible and extensible through plugins, but the integration code could
sometimes prove daunting. This is what brought <a class="" href="https://uppy.io/docs/transloadit/">Robodog</a> to
life. It served as an alternative with the same features, but with a more
ergonomic and minimal API.</p>
<p>It did, however, come with its own set of new problems:</p>
<ul>
<li class="">Robodog tries to do the exact same thing as Uppy, but looks like an entirely
different product.</li>
<li class="">Users are faced with a confusing choice between using Robodog or using Uppy
directly.</li>
<li class="">Robodog is more ergonomic because it’s limited. When hitting such a limit, the
user has to refactor everything to Uppy using plugins.</li>
</ul>
<p>This has now led us to deprecating Robodog and embracing Uppy for its strong
suits: modularity and flexibility. At the same time, we’re also introducing
something to take away some of the repetitive integration code:
<a class="" href="https://uppy.io/docs/remote-sources/"><code>@uppy/remote-sources</code></a>.</p>
<p>Are you using Robodog in your code base? You can check out the
<a href="https://uppy.io/docs/guides/migration-guides/#migrate-from-robodog-to-uppy-plugins" target="_blank" rel="noopener noreferrer" class="">migration guide</a>
to see how you can transition to Uppy plugins without losing functionality. We
have committed ourselves to extending Robodog support for one year to give our
users more time to migrate.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="native-mobile-camera">Native mobile camera<a href="https://uppy.io/blog/2022/09/3.0/#native-mobile-camera" class="hash-link" aria-label="Direct link to Native mobile camera" title="Direct link to Native mobile camera" translate="no">​</a></h2>
<p>As you are probably aware, Uppy’s Webcam plugin provides a nice UI for desktop
devices to take pictures and record videos. Up until 3.0, the same UI was
utilized on mobile as well.</p>
<p>Since most mobile devices have a system UI for taking pictures and recording
videos – which is usually better than any custom solution we can offer – we’ve
introduced a new option called <code>mobileNativeCamera</code> for the Webcam plugin:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">uppy</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">use</span><span class="token punctuation" style="color:#393A34">(</span><span class="token maybe-class-name">Webcam</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token literal-property property" style="color:#36acaa">mobileNativeCamera</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">isMobile</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token literal-property property" style="color:#36acaa">tablet</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<p>By default, it uses the <a href="https://github.com/juliangruber/is-mobile" target="_blank" rel="noopener noreferrer" class=""><code>is-mobile</code></a>
package to detect mobile devices, like smartphones and tablets, but you can
manually set this option to <code>true</code> or <code>false</code> if you wish. When enabled, instead
of the usual Camera/Webcam Uppy UI, users will be presented with buttons that
open their device’s native camera interface:</p>
<p><img decoding="async" loading="lazy" alt="Uppy native camera UI" src="https://uppy.io/assets/images/native-camera-d180107e4e1d511e85c203b1d6b49cb9.jpg" width="1430" height="1321" class="img_ev3q"></p>
<p><a class="" href="https://uppy.io/docs/webcam/#videoconstraints"><code>videoConstraints.facingMode</code></a> is also
supported by this option via the
<a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/capture" target="_blank" rel="noopener noreferrer" class=""><code>capture</code></a>
attribute (in the browsers and devices that respect it).</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">uppy</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">use</span><span class="token punctuation" style="color:#393A34">(</span><span class="token maybe-class-name">Webcam</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token literal-property property" style="color:#36acaa">videoConstraints</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token literal-property property" style="color:#36acaa">facingMode</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'user'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<p>The same applies to <a class="" href="https://uppy.io/docs/webcam/#modes"><code>modes</code></a>, allowing you to enable only
video or only photos.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="devotedly-stable">Devotedly stable<a href="https://uppy.io/blog/2022/09/3.0/#devotedly-stable" class="hash-link" aria-label="Direct link to Devotedly stable" title="Direct link to Devotedly stable" translate="no">​</a></h2>
<p>Since the Uppy 2.7.0 release, <strong>we’ve fixed over 95 bugs!</strong> This includes fixes
to bugs that made uploading less stable, documentation corrections, and
dependency upgrades.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="companion-turns-40">Companion turns 4.0<a href="https://uppy.io/blog/2022/09/3.0/#companion-turns-40" class="hash-link" aria-label="Direct link to Companion turns 4.0" title="Direct link to Companion turns 4.0" translate="no">​</a></h2>
<p>Everyone’s favorite Companion also received some love.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="streaming-upload">Streaming upload<a href="https://uppy.io/blog/2022/09/3.0/#streaming-upload" class="hash-link" aria-label="Direct link to Streaming upload" title="Direct link to Streaming upload" translate="no">​</a></h3>
<p>Streaming upload can now also be enabled in Companion when using Tus. This comes
with greatly improved upload speeds and allows uploading up to hundreds of
gigabytes without needing a large server storage. We found that this improves
speeds by about 37% for a Google Drive upload of a 1 GB file
(<a href="https://github.com/transloadit/uppy/pull/4046#issuecomment-1235697937" target="_blank" rel="noopener noreferrer" class="">source</a>).
This feature was also available before Companion 4.0, but it didn’t work with
Tus until now.</p>
<p>With streaming upload disabled (default), the whole file will be downloaded
first. The upload will then start when the download has completely finished.</p>
<p>When streaming upload is enabled, Companion will start downloading the file from
the provider (such as Google Drive), while at the same time starting the upload
to the destination (such as Tus), and sending every chunk of data consecutively.</p>
<p>For more information, see the <a class="" href="https://uppy.io/docs/companion/">Companion docs</a>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="event-emitter">Event emitter<a href="https://uppy.io/blog/2022/09/3.0/#event-emitter" class="hash-link" aria-label="Direct link to Event emitter" title="Direct link to Event emitter" translate="no">​</a></h3>
<p>Companion now has a server-side event emitter that can be used to detect when
uploads start, finish and fail, without having to depend on the client (so it
works even when users have closed their browser).</p>
<p>Example code:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> app</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> emitter </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> companion</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">app</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">options</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">emitter</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">on</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'upload-start'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token parameter punctuation" style="color:#393A34">{</span><span class="token parameter"> token </span><span class="token parameter punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'Upload started'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> token</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onUploadEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token parameter punctuation" style="color:#393A34">{</span><span class="token parameter"> action</span><span class="token parameter punctuation" style="color:#393A34">,</span><span class="token parameter"> payload </span><span class="token parameter punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword control-flow" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">action </span><span class="token operator" style="color:#393A34">===</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'success'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">			emitter</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">off</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">token</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> onUploadEvent</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// avoid listener leak</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">			</span><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'Upload finished'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> token</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> payload</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">url</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:#00009f">else</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">action </span><span class="token operator" style="color:#393A34">===</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'error'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">			emitter</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">off</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">token</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> onUploadEvent</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// avoid listener leak</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">			</span><span class="token console class-name">console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'Upload failed'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> payload</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	emitter</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">on</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">token</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> onUploadEvent</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="internal-improvements">Internal improvements<a href="https://uppy.io/blog/2022/09/3.0/#internal-improvements" class="hash-link" aria-label="Direct link to Internal improvements" title="Direct link to Internal improvements" translate="no">​</a></h3>
<p>Companion’s internal request code and Providers have been rewritten to
<code>async</code>/<code>await</code>, which has greatly simplified and reduced the amount of code.
This will lead to less bugs and security issues, and make it easier to implement
new custom Providers.</p>
<p>We have also replaced the deprecated
<a href="https://github.com/request/request" target="_blank" rel="noopener noreferrer" class=""><code>request</code></a> library with
<a href="https://github.com/sindresorhus/got" target="_blank" rel="noopener noreferrer" class=""><code>got</code></a>. This also removed the need for
<a href="https://github.com/simov/purest" target="_blank" rel="noopener noreferrer" class=""><code>purest</code></a>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="and-more">And more!<a href="https://uppy.io/blog/2022/09/3.0/#and-more" class="hash-link" aria-label="Direct link to And more!" title="Direct link to And more!" translate="no">​</a></h3>
<ul>
<li class=""><a class="" href="https://uppy.io/docs/compressor/">Compressor</a> is officially stable. The Compressor plugin for
Uppy optimizes images (JPEG, PNG), saving on average up to 60% in size. It has
proven itself through extensive battle testing.</li>
<li class=""><a class="" href="https://uppy.io/docs/aws-s3/">AWS S3 Multipart</a> also became more stable this release, as a
result of us hammering out some of the last edge cases with lots of files
and/or huge files.</li>
<li class="">React 18 is now supported in <a class="" href="https://uppy.io/docs/react/"><code>@uppy/react</code></a>, Vue 3 is supported
for <a class="" href="https://uppy.io/docs/vue/"><code>@uppy/vue</code></a>, and Angular 14 for
<a class="" href="https://uppy.io/docs/angular/"><code>@uppy/angular</code></a>.</li>
<li class="">Our <a href="https://github.com/transloadit/uppy/tree/main/examples" target="_blank" rel="noopener noreferrer" class="">examples</a> have
received a fresh round of updates to keep them relevant.</li>
</ul>
<hr>
<p><img decoding="async" loading="lazy" alt="Animate picture of a visibly happy dog getting a head massage" src="https://uppy.io/assets/images/dog-enjoys-875f8d3432b4fa5d05df0255f83c655a.gif" width="400" height="286" class="img_ev3q"></p>
<p>For more details, see the full
<a href="https://github.com/transloadit/uppy/blob/HEAD/CHANGELOG.md#1300" target="_blank" rel="noopener noreferrer" class="">changelog</a> and
the <a class="" href="https://uppy.io/docs/guides/migration-guides/">migration guide</a>.</p>
<p>That’s it from us for now! As you can see, Uppy may be slowly turning into an
old dog, but we’re still committed to keep teaching it new tricks. We hope
you’ll enjoy this latest major release, and all the features and improvements it
includes. We can’t wait to hear your thoughts about it on
<a href="https://twitter.com/uppy_io" target="_blank" rel="noopener noreferrer" class="">Twitter</a>!</p>]]></content>
        <author>
            <name>Antoine du Hamel</name>
            <email>antoine@transloadit.com</email>
        </author>
        <author>
            <name>Artur Paikin</name>
            <email>artur@transloadit.com</email>
        </author>
        <author>
            <name>Mikael Finstad</name>
            <email>mikael@transloadit.com</email>
        </author>
        <author>
            <name>Merlijn Vos</name>
            <email>merlijn@transloadit.com</email>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Uppy 2.4-2.7: Image Compressor, Transloadit Rate Limiting, ESM]]></title>
        <id>https://uppy.io/blog/2022/03/2.4-2.7/</id>
        <link href="https://uppy.io/blog/2022/03/2.4-2.7/"/>
        <updated>2022-03-11T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[We’re always looking for opportunities to teach Uppy cool new tricks, and the]]></summary>
        <content type="html"><![CDATA[<p>We’re always looking for opportunities to teach Uppy cool new tricks, and the
past few months have been no exception. Since our
<a href="https://uppy.io/blog/2021/12/2.1-2.3/" target="_blank" rel="noopener noreferrer" class="">most recent post</a> in December, Uppy has
continued to receive a steady stream of updates. This post covers all the
improvements made in Uppy versions 2.4 through 2.7. Changes and additions
include: image compression, improved Transloadit rate limiting and a lighter
Dashboard plugin. We’ve also moved our end-to-end tests to Cypress, and are
slowly converting plugins to ES modules (ESM).</p>
<img decoding="async" loading="lazy" class="border img_ev3q" alt="Uppy Compressor plugin showing compressed images notification" src="https://uppy.io/img/blog/2.4-2.7/compressor.jpg">
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="compressor">Compressor<a href="https://uppy.io/blog/2022/03/2.4-2.7/#compressor" class="hash-link" aria-label="Direct link to Compressor" title="Direct link to Compressor" translate="no">​</a></h2>
<p>Some of the most commonly uploaded files on the internet are images — photos,
stock images, screenshots, and documents scans. Uppy now includes a new plugin
called <code>@uppy/compressor</code> that optimizes images (JPEG, PNG), saving on average
up to 60% in size (roughly 18 MB for 10 images). It uses
<a href="https://github.com/fengyuanchen/compressorjs" target="_blank" rel="noopener noreferrer" class="">Compressor.js</a> under the hood.</p>
<p><a href="https://uppy.io/docs/compressor/" target="_blank" rel="noopener noreferrer" class="">Read the docs</a> and
<a href="https://uppy.io/examples/dashboard/" target="_blank" rel="noopener noreferrer" class="">try Compressor in action</a>.</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword module" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports maybe-class-name">Uppy</span><span class="token plain"> </span><span class="token keyword module" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@uppy/core'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword module" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports maybe-class-name">Compressor</span><span class="token plain"> </span><span class="token keyword module" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@uppy/compressor'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> uppy </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">Uppy</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">uppy</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">use</span><span class="token punctuation" style="color:#393A34">(</span><span class="token maybe-class-name">Compressor</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<p><code>@uppy/compressor</code> is also the first plugin that we are releasing as ESM,
backwards compatible as CJS, to test out how this works. Please report any
issues.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="hosted-companion-custom-credentials">Hosted Companion custom credentials<a href="https://uppy.io/blog/2022/03/2.4-2.7/#hosted-companion-custom-credentials" class="hash-link" aria-label="Direct link to Hosted Companion custom credentials" title="Direct link to Hosted Companion custom credentials" translate="no">​</a></h2>
<p>It cannot be overstated that our
<a href="https://transloadit.com/docs/sdks/uppy/" target="_blank" rel="noopener noreferrer" class="">Transloadit-hosted</a>
<a href="https://uppy.io/docs/companion/" target="_blank" rel="noopener noreferrer" class="">Companion Plugin</a> is the easiest secure way to
allow your users pick files from cloud sources like Google Drive, Instagram,
Box, etc. via Uppy. Up until now, however, that meant your users had to
authenticate their cloud account with Transloadit, preventing you from showing
your own logo instead. That has now been fixed! Head to <code>Transloadit Console</code> /
<code>Credentials</code>, scroll down to <code>Third-party Credentials</code>, click on
<code>Add new Credentials</code>, select <code>Companion OAuth</code>, and voilà!</p>
<img decoding="async" loading="lazy" class="border img_ev3q" alt="Transloadit Companion 3rd party credentials" src="https://uppy.io/img/blog/2.4-2.7/companion-3rd-party-oauth.jpg">
<p>Try it out with the
<a href="https://transloadit.com/pricing/" target="_blank" rel="noopener noreferrer" class="">free Transloadit Community Plan — 5GB / month and access to Companion</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="transloadit-rate-limiting">Transloadit rate limiting<a href="https://uppy.io/blog/2022/03/2.4-2.7/#transloadit-rate-limiting" class="hash-link" aria-label="Direct link to Transloadit rate limiting" title="Direct link to Transloadit rate limiting" translate="no">​</a></h2>
<p>We’ve added rate limiting to Transloadit
<a href="https://github.com/transloadit/uppy/pull/3429" target="_blank" rel="noopener noreferrer" class="">assembly creation and status polling</a>,
and <a href="https://github.com/transloadit/uppy/pull/3394" target="_blank" rel="noopener noreferrer" class="">tus retries</a>:</p>
<blockquote>
<p>When the remote server responds with HTTP 429, all requests are paused for a
while in the hope that it can resolve the rate limiting. Failed requests are
now also queued up after the retry delay. Before, they were scheduled for
retry without being queued up, which would sometimes end up overflowing the
limit option.</p>
</blockquote>
<p>As a result of this change, uploading many files at once has become even more
robust.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="move-to-esm">Move to ESM<a href="https://uppy.io/blog/2022/03/2.4-2.7/#move-to-esm" class="hash-link" aria-label="Direct link to Move to ESM" title="Direct link to Move to ESM" translate="no">​</a></h2>
<p>The JavaScript ecosystem is moving towards ESM, and we want to follow suit. We
are slowly starting to adopt ESM in Uppy packages. To do so, we integrated a
plugin into our build system that transpiles ESM source code to CommonJS syntax,
which is distributed with the npm package. Nothing will change on your end,
though – we know that not everyone is using tooling that support ESM, so we’re
holding on to CommonJS for the time being. Our plan is to refactor all official
Uppy plugins to ESM before Uppy 3.0 is released, and drop CommonJS in favor of
ESM in the npm packages at that point.</p>
<p>For details, see <a href="https://github.com/transloadit/uppy/pull/3468" target="_blank" rel="noopener noreferrer" class="">PR 3468</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="end-to-end-move-to-cypress">End to end: move to Cypress<a href="https://uppy.io/blog/2022/03/2.4-2.7/#end-to-end-move-to-cypress" class="hash-link" aria-label="Direct link to End to end: move to Cypress" title="Direct link to End to end: move to Cypress" translate="no">​</a></h2>
<p>Uppy has had end to end from the start, but the developer experience was less
than ideal with custom Webdriver.io + Selenium. The transition to
<a href="https://github.com/transloadit/uppy/pull/3444" target="_blank" rel="noopener noreferrer" class="">Cypress</a> allows us to write
tests with ease and comfort, backed by great documentation.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="lighter-bundle">Lighter Bundle<a href="https://uppy.io/blog/2022/03/2.4-2.7/#lighter-bundle" class="hash-link" aria-label="Direct link to Lighter Bundle" title="Direct link to Lighter Bundle" translate="no">​</a></h2>
<p>We continue to look for ways to reduce Uppy’s bundle size and modernize our
build toolchain. This time, we’ve replaced the
<a href="https://github.com/exif-js/exif-js" target="_blank" rel="noopener noreferrer" class="">Exifr.js</a> legacy bundle with the modern one
without IE polyfills. Our Browserify bundler has been replaced with a modern and
more efficient ESBuild.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="companion-improvements">Companion improvements<a href="https://uppy.io/blog/2022/03/2.4-2.7/#companion-improvements" class="hash-link" aria-label="Direct link to Companion improvements" title="Direct link to Companion improvements" translate="no">​</a></h2>
<ul>
<li class="">Improved private IP check (#3403)</li>
<li class="">Implement periodic ping functionality (#3246)</li>
<li class="">Fix broken thumbnails for Box and Dropbox (#3460)</li>
<li class="">Fix unpslash author meta, sanitize metadata to strings and improve Companion
tests (#3478)</li>
</ul>
<p>That’s it for today! See the full
<a href="https://github.com/transloadit/uppy/blob/master/CHANGELOG.md#1300" target="_blank" rel="noopener noreferrer" class="">changelog</a>
for more details.</p>]]></content>
        <author>
            <name>Antoine du Hamel</name>
            <email>antoine@transloadit.com</email>
        </author>
        <author>
            <name>Artur Paikin</name>
            <email>artur@transloadit.com</email>
        </author>
        <author>
            <name>Mikael Finstad</name>
            <email>mikael@transloadit.com</email>
        </author>
        <author>
            <name>Merlijn Vos</name>
            <email>merlijn@transloadit.com</email>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[🎄 Uppy 2.1-2.3: Audio plugin, fast and efficient streaming for Companion, production-ready Unsplash, and more]]></title>
        <id>https://uppy.io/blog/2021/12/2.1-2.3/</id>
        <link href="https://uppy.io/blog/2021/12/2.1-2.3/"/>
        <updated>2021-12-15T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Last Christmas, we gave you Uppy 1.24, but]]></summary>
        <content type="html"><![CDATA[<p>Last Christmas, we gave you <a href="https://uppy.io/blog/2020/12/1.24/" target="_blank" rel="noopener noreferrer" class="">Uppy 1.24</a>, but
this very next year, we’ll take it away (since it’s outdated by now) and give
you a brand-new Uppy 2.3 🎁!</p>
<p>After the <a href="https://uppy.io/blog/2021/08/2.0/" target="_blank" rel="noopener noreferrer" class="">release</a> of our latest major
version, 2.0.0, we’ve been busy with many things. First of all is the
long-awaited Audio plugin to record and upload live audio directly. We then
worked on adding a fast and efficient streaming interface to Companion and made
Unsplash production ready. Housekeeping was also part of the job: we made Status
Bar improvements, moved from npm to Yarn 3, did some refactoring, and updated
dependencies.</p>
<p>Last but not least, we got the issue count down from around 110 since 2.0.0 to
around 45 now.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="audio-plugin">Audio plugin<a href="https://uppy.io/blog/2021/12/2.1-2.3/#audio-plugin" class="hash-link" aria-label="Direct link to Audio plugin" title="Direct link to Audio plugin" translate="no">​</a></h2>
<p>Uppy now has a new <code>@uppy/audio</code> plugin for recording audio memos, sounds,
jingling bells, Christmas carols, and all your holiday cheer. Check it out on
the <a href="https://uppy.io/examples/dashboard/" target="_blank" rel="noopener noreferrer" class="">demo page</a>.</p>
<video alt="Audio plugin demo" muted="" autoplay="" loop="">
  <source src="/img/blog/2.1-2.3/audio-demo.mp4" type="video/mp4">
  Your browser does not support the video tag: https://uppy.io/img/blog/2.1-2.3/audio-demo.mp4
</video>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="uppyunsplash-is-now-production-ready"><code>@uppy/unsplash</code> is now production ready<a href="https://uppy.io/blog/2021/12/2.1-2.3/#uppyunsplash-is-now-production-ready" class="hash-link" aria-label="Direct link to uppyunsplash-is-now-production-ready" title="Direct link to uppyunsplash-is-now-production-ready" translate="no">​</a></h2>
<p>The Unsplash plugin has received an update, providing attribution to the image
authors and adding some polish to make it look better. Being fully brand
compliant with Unsplash means it’s now production ready. You can demo the plugin
on the <a href="https://uppy.io/examples/dashboard" target="_blank" rel="noopener noreferrer" class="">website</a> or read the
<a href="https://uppy.io/docs/unsplash/" target="_blank" rel="noopener noreferrer" class="">docs</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="new-streaming-interface-for-companion">New streaming interface for Companion<a href="https://uppy.io/blog/2021/12/2.1-2.3/#new-streaming-interface-for-companion" class="hash-link" aria-label="Direct link to New streaming interface for Companion" title="Direct link to New streaming interface for Companion" translate="no">​</a></h2>
<p><a href="https://uppy.io/docs/companion/" target="_blank" rel="noopener noreferrer" class="">Companion</a> handles the server-to-server communication between your
server and file storage providers such as Google Drive, Dropbox, Instagram, and
the like. This bypasses the client (so a 5 GB video isn’t eating into your
users’ data plans) and files are directly uploaded to the final destination.
Companion is made to be effortlessly integrate-able with Uppy.</p>
<p>It used to work by downloading the requested file from a remote provider on the
server to then start uploading it to the destination. This did the job, but it’s
wasn’t ideal.</p>
<p>We now built streaming support into Companion, which means the download and
upload can happen simultaneously. This can result in <strong>two times faster
uploads</strong>, because we no longer have to wait for files to finish downloading
before starting the upload process. It’s especially useful for large files and
removes the need for a lot of storage space on the server, as data will be
buffered in memory.</p>
<p>You can enable this by setting <code>streamingUpload</code> in the Companion
<a href="https://uppy.io/docs/companion/#options" target="_blank" rel="noopener noreferrer" class="">options</a>.</p>
<p><strong>NOTE:</strong> Streaming is turned off by default. Do not turn it on yet if you’re
using TUS for uploads, due to
<a href="https://github.com/tus/tus-js-client/issues/275" target="_blank" rel="noopener noreferrer" class="">this tus-js-client bug</a>.</p>
<p>Interested in using Companion? You can use Transloadit-hosted Companion on every
<a href="https://transloadit.com/pricing/" target="_blank" rel="noopener noreferrer" class="">Plan</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="status-bar-error-state-improvements">Status Bar error state improvements<a href="https://uppy.io/blog/2021/12/2.1-2.3/#status-bar-error-state-improvements" class="hash-link" aria-label="Direct link to Status Bar error state improvements" title="Direct link to Status Bar error state improvements" translate="no">​</a></h2>
<p>The Status Bar plugin would get confused about upload errors in Uppy, and we’ve
addressed this:</p>
<ul>
<li class="">The error state is now shown in case of only <em>one</em> failed file instead of
<em>all</em> failed files. The plugin used to get stuck in the uploading state when a
single file failed.</li>
<li class="">Added “X of X files uploaded” below “Upload failed” for extra context.</li>
<li class="">Improved the error details button styling in the Status Bar and the file info
card.</li>
<li class="">Status Bar state is set to complete if the user manually removes the failed
files.</li>
</ul>
<p><img decoding="async" loading="lazy" alt="status bar improvements screenshot" src="https://uppy.io/assets/images/status-bar-improvements-b57b432fbbd9ad9b7efad2690877f1f5.jpg" width="1200" height="879" class="img_ev3q"></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="internal-housekeeping">Internal housekeeping<a href="https://uppy.io/blog/2021/12/2.1-2.3/#internal-housekeeping" class="hash-link" aria-label="Direct link to Internal housekeeping" title="Direct link to Internal housekeeping" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="yarn-v3-instead-of-npm">Yarn v3 instead of npm<a href="https://uppy.io/blog/2021/12/2.1-2.3/#yarn-v3-instead-of-npm" class="hash-link" aria-label="Direct link to Yarn v3 instead of npm" title="Direct link to Yarn v3 instead of npm" translate="no">​</a></h3>
<p>We’ve switched the Uppy repo to Yarn 3 to improve package install performance.
With our complex dependency graph and over thirty packages in a monorepo, we are
seeing install times reduced by more than a few minutes!</p>
<p>We are using <a href="https://github.com/nodejs/corepack" target="_blank" rel="noopener noreferrer" class="">Corepack</a> to make sure all
Uppy contributors are using the same version of Yarn. If you are an Uppy
contributor, please run the following commands to enable Corepack:</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">corepack -v || npm i -g corepack # install Corepack if not already installed</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">yarn -v || corepack enable # install Yarn through Corepack if not already installed</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">yarn || corepack yarn install # install npm dependencies using yarn</span><br></span></code></pre></div></div>
<p><a href="https://github.com/transloadit/uppy/pull/3237" target="_blank" rel="noopener noreferrer" class="">View the PR</a></p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="refactor-locale-scripts--generate-types-and-docs">Refactor locale scripts &amp; generate types and docs<a href="https://uppy.io/blog/2021/12/2.1-2.3/#refactor-locale-scripts--generate-types-and-docs" class="hash-link" aria-label="Direct link to Refactor locale scripts &amp; generate types and docs" title="Direct link to Refactor locale scripts &amp; generate types and docs" translate="no">​</a></h3>
<p>This is an internal change, but important nonetheless. Our locales now live in a
separate <code>locale.js</code> file for every plugin instead of <code>this.defaultLocale</code> in
the class. The docs and types are automatically updated when we add or remove
new locale strings.</p>
<p><a href="https://github.com/transloadit/uppy/pull/3276" target="_blank" rel="noopener noreferrer" class="">View the PR</a>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="automated-release-scripts">Automated release scripts<a href="https://uppy.io/blog/2021/12/2.1-2.3/#automated-release-scripts" class="hash-link" aria-label="Direct link to Automated release scripts" title="Direct link to Automated release scripts" translate="no">​</a></h3>
<p>A lot of things need to happen when we’re publishing a new release. A complete
redo of the automation script is now available for quick and secure releases.</p>
<p>Here are some highlights:</p>
<ul>
<li class="">Releaser runs <code>yarn release</code> and will get a series of
<a href="https://github.com/terkelg/prompts" target="_blank" rel="noopener noreferrer" class="">prompts</a> to set up a release.</li>
<li class="">A changelog will be generated.</li>
<li class="">The contributions table will be updated.</li>
<li class="">GitHub Actions will create a release candidate pull request.</li>
<li class="">When approved, GitHub Actions automatically merges, publishes to the npm
public registry, and creates CDN bundles.</li>
</ul>
<p><a href="https://github.com/transloadit/uppy/pull/3304" target="_blank" rel="noopener noreferrer" class="">View the PR</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="and-more">And more<a href="https://uppy.io/blog/2021/12/2.1-2.3/#and-more" class="hash-link" aria-label="Direct link to And more" title="Direct link to And more" translate="no">​</a></h2>
<ul>
<li class="">google-drive: plugin has been updated for brand compliance (#3178)</li>
<li class="">google-drive: sort Google Drive list by name #3069</li>
<li class="">status-bar: now shows all details on mobile when <code>showProgressDetails</code> is
<code>true</code> (#3174)</li>
<li class="">core: move <code>Uppy</code> class to its own module (#3225)</li>
<li class="">angular: fix component crash by loosening <code>package.json</code> version constraints
(#3210)</li>
<li class="">drop-target: exposed events (#3238)</li>
<li class="">companion: add <code>maxFileSize</code> option in companion for safety #3159</li>
<li class="">companion: new AWS S3 multipart presigned URL batching endpoint #3056</li>
<li class="">companion: improve CORS default headers #3167</li>
<li class="">companion: use GET instead of HEAD for <code>getURLMeta</code> for better server
compatibility (especially signed S3 URLs) #3048</li>
<li class="">companion: deprecate missing <code>uploadUrls</code> option (will be required in the
future) #3182</li>
<li class="">companion: close window on auth callback error and show error to user #3143</li>
<li class="">companion: cut off length of file names to avoid AWS error #3048</li>
<li class="">companion: safely escape <code>&lt;script&gt;</code> injected code in Companion’s send-token.js
#3101</li>
<li class="">companion: upgrade aws-sdk #3334</li>
<li class="">companion: improve logging #3103</li>
<li class="">companion: change Provider/SearchProvider API to async and use streams instead
#3159</li>
</ul>
<p>Happy Holidays from the Uppy team! Enjoy Christmas and New Year, stay safe, take
a walk outside. See you in 2022!</p>]]></content>
        <author>
            <name>Antoine du Hamel</name>
            <email>antoine@transloadit.com</email>
        </author>
        <author>
            <name>Artur Paikin</name>
            <email>artur@transloadit.com</email>
        </author>
        <author>
            <name>Mikael Finstad</name>
            <email>mikael@transloadit.com</email>
        </author>
        <author>
            <name>Merlijn Vos</name>
            <email>merlijn@transloadit.com</email>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Uppy 2.0.0: smaller, faster, modular plugins, Preact X, stricter types, and much more]]></title>
        <id>https://uppy.io/blog/2021/08/2.0/</id>
        <link href="https://uppy.io/blog/2021/08/2.0/"/>
        <updated>2021-08-30T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Today, our tails are positively wagging with excitement about the release of]]></summary>
        <content type="html"><![CDATA[<p>Today, our tails are positively wagging with excitement about the release of
Uppy 2.0! This latest version is on average 25% smaller and up to a thousand
times faster, thanks to dropping support for IE11 and a lot of refactoring work.
We’ve upgraded many dependencies, most notably Preact 8 to Preact X, greatly
improved TypeScript support and screen reader accessibility, paid technical
debt, and added support for multiple messages in the Informer plugin.</p>
<p>Chow down on all the juicy bits and pieces inside! And make sure to
<a href="https://uppy.io/examples" target="_blank" rel="noopener noreferrer" class="">try Uppy live demo</a>.</p>
<p><img decoding="async" loading="lazy" alt="Uppy 2.0 cover banner" src="https://uppy.io/assets/images/uppy-2-0-cover-1e95fd5e9bcdf0f841e1ceb04f3f4595.jpg" width="1200" height="630" class="img_ev3q"></p>
<blockquote>
<p>Uppy is a sleek, modular JavaScript file uploader that integrates seamlessly
with any application. It is made for developers who want to provide their
users with the ability to see image previews, edit metadata, pick large files
directly from Dropbox, restore selected files when a tab was accidentally
closed, or crop an image in-browser before sending.</p>
</blockquote>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="a-pup-no-more">A pup no more<a href="https://uppy.io/blog/2021/08/2.0/#a-pup-no-more" class="hash-link" aria-label="Direct link to A pup no more" title="Direct link to A pup no more" translate="no">​</a></h2>
<p>Ever since the first introduction of Uppy
<a class="" href="https://uppy.io/blog/2016/07/uppy-begins/">five years ago</a> (or 36 in
<a href="https://www.akc.org/expert-advice/health/how-to-calculate-dog-years-to-human-years/" target="_blank" rel="noopener noreferrer" class="">dog-years</a>),
we’ve always referred to our project as ‘the next open source file uploader for
web browsers’. The release of <a class="" href="https://uppy.io/blog/2019/04/1.0/">Uppy 1.0</a> a little over two
years ago, however, soon led to a steep increase in adoption. Uppy now boasts
over
<a href="https://github.com/transloadit/uppy/stargazers" target="_blank" rel="noopener noreferrer" class="">24,000 stargazers on GitHub</a>,
making it the undisputed top dog in the world of file uploaders 🌍</p>
<p>With that in mind, we felt it was high time to give Uppy some more much-needed
trimming. We want to take this opportunity to break with the past, to make the
project leaner – and to pave the way for an even brighter future for Uppy!</p>
<img decoding="async" loading="lazy" class="border img_ev3q" alt="Uppy 2.0 UI with files" src="https://uppy.io/img/blog/2.0/uppy-ui-with-files.jpg">
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="table-of-contents">Table of Contents<a href="https://uppy.io/blog/2021/08/2.0/#table-of-contents" class="hash-link" aria-label="Direct link to Table of Contents" title="Direct link to Table of Contents" translate="no">​</a></h2>
<ul>
<li class=""><a href="https://uppy.io/blog/2021/08/2.0/#highlights-since-10" class="">Highlights since 1.0</a></li>
<li class=""><a href="https://uppy.io/blog/2021/08/2.0/#smaller-bundles" class="">Smaller bundles</a></li>
<li class=""><a href="https://uppy.io/blog/2021/08/2.0/#faster" class="">Faster</a></li>
<li class=""><a href="https://uppy.io/blog/2021/08/2.0/#preact-x-and-upgraded-dependencies" class="">Preact X and upgraded dependencies</a></li>
<li class=""><a href="https://uppy.io/blog/2021/08/2.0/#plugin-is-replaced-with-baseplugin-and-uiplugin" class=""><code>Plugin</code> is replaced with <code>BasePlugin</code> and <code>UIPlugin</code></a></li>
<li class=""><a href="https://uppy.io/blog/2021/08/2.0/#strict-typescript-types-by-default" class="">Strict TypeScript types by default</a></li>
<li class=""><a href="https://uppy.io/blog/2021/08/2.0/#batch-pre-signing-urls-for-aws-s3-multipart" class="">Batch pre-signing URL's for AWS S3 Multipart</a></li>
<li class=""><a href="https://uppy.io/blog/2021/08/2.0/#and-more" class="">And more</a></li>
<li class=""><a href="https://uppy.io/blog/2021/08/2.0/#what-future-remains-for-10" class="">What future remains for 1.0?</a></li>
<li class=""><a href="https://uppy.io/blog/2021/08/2.0/#thats-it" class="">That's it</a></li>
</ul>
<video alt="Video demo showing updated Uppy 2.0 UI" muted="" autoplay="" loop="">
  <source src="/images/uppy-2-0-demo-aug-2021.mp4" type="video/mp4">
  Your browser does not support the video tag: https://uppy.io/images/uppy-2-0-demo-aug-2021.mp4
</video>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="highlights-since-10">Highlights since 1.0<a href="https://uppy.io/blog/2021/08/2.0/#highlights-since-10" class="hash-link" aria-label="Direct link to Highlights since 1.0" title="Direct link to Highlights since 1.0" translate="no">​</a></h2>
<p>A lot of things have happened since we released Uppy 1.0 in April of 2019. In
case you have missed some of our 1.x releases, here is a small overview. We have
added:</p>
<ul>
<li class="">Official integrations for <a class="" href="https://uppy.io/blog/2020/11/1.23/">Vue</a>
(<a class="" href="https://uppy.io/blog/2021/04/1.27/">3</a>), <a class="" href="https://uppy.io/blog/2021/07/1.30/">Angular</a>, and
<a class="" href="https://uppy.io/blog/2020/12/1.24/">Svelte</a></li>
<li class=""><a class="" href="https://uppy.io/blog/2020/12/1.24/">Hooks</a> for the React integration</li>
<li class="">Support for picking files from <a class="" href="https://uppy.io/blog/2020/11/1.23/">Box</a>,
<a class="" href="https://uppy.io/blog/2020/10/1.22/">Unsplash</a>, <a class="" href="https://uppy.io/blog/2020/04/1.10/">Facebook</a>, and
<a class="" href="https://uppy.io/blog/2020/04/1.10/">OneDrive</a></li>
<li class=""><a class="" href="https://uppy.io/blog/2021/05/1.29/">“Ghost” files</a>, as part of a revamped Golden Retriever
plugin, which makes recovering lost files even more intuitive</li>
<li class="">Support for 25 more languages (bringing it to a total of
<a class="" href="https://uppy.io/docs/locales/#list-of-locales">37</a>)</li>
<li class=""><a class="" href="https://uppy.io/blog/2020/04/1.13/">Dark mode</a></li>
<li class="">an <a class="" href="https://uppy.io/blog/2020/07/1.18-image-editor/">Image Editor</a></li>
<li class="">And four new core team members: <a href="https://github.com/ajkachnic" target="_blank" rel="noopener noreferrer" class="">@ajkachnic</a>,
<a href="https://github.com/mifi" target="_blank" rel="noopener noreferrer" class="">@mifi</a>, <a href="https://github.com/aduh95" target="_blank" rel="noopener noreferrer" class="">@aduh95</a>, and
<a href="https://github.com/murderlon" target="_blank" rel="noopener noreferrer" class="">@murderlon</a></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="smaller-bundles">Smaller bundles<a href="https://uppy.io/blog/2021/08/2.0/#smaller-bundles" class="hash-link" aria-label="Direct link to Smaller bundles" title="Direct link to Smaller bundles" translate="no">​</a></h2>
<p>With 2.0, following in the footsteps of Microsoft, we are dropping support for
IE11. As a result, we are able to remove all built-in polyfills, and the new
bundle size is <strong>25% smaller</strong>! If you want your app to still support older
browsers (such as IE11), you may need to add the following polyfills to your
bundle:</p>
<ul>
<li class=""><a href="https://github.com/mo/abortcontroller-polyfill" target="_blank" rel="noopener noreferrer" class="">abortcontroller-polyfill</a></li>
<li class=""><a href="https://github.com/zloirock/core-js" target="_blank" rel="noopener noreferrer" class="">core-js</a></li>
<li class=""><a href="https://github.com/mozdevs/mediaDevices-getUserMedia-polyfill" target="_blank" rel="noopener noreferrer" class="">md-gum-polyfill</a></li>
<li class=""><a href="https://github.com/que-etc/resize-observer-polyfill" target="_blank" rel="noopener noreferrer" class="">resize-observer-polyfill</a></li>
<li class=""><a href="https://github.com/github/fetch" target="_blank" rel="noopener noreferrer" class="">whatwg-fetch</a></li>
</ul>
<p>If you're using a bundler, you need import these before Uppy:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword module" style="color:#00009f">import</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'core-js'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword module" style="color:#00009f">import</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'whatwg-fetch'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword module" style="color:#00009f">import</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'abortcontroller-polyfill/dist/polyfill-patch-fetch'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// Order matters here: AbortController needs fetch, which needs Promise (provided by core-js).</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword module" style="color:#00009f">import</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'md-gum-polyfill'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword module" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports maybe-class-name">ResizeObserver</span><span class="token plain"> </span><span class="token keyword module" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'resize-observer-polyfill'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token dom variable" style="color:#36acaa">window</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access maybe-class-name">ResizeObserver</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">??=</span><span class="token plain"> </span><span class="token maybe-class-name">ResizeObserver</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword module" style="color:#00009f">export</span><span class="token plain"> </span><span class="token exports punctuation" style="color:#393A34">{</span><span class="token exports"> </span><span class="token exports keyword module" style="color:#00009f">default</span><span class="token exports"> </span><span class="token exports punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword module" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@uppy/core'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword module" style="color:#00009f">export</span><span class="token plain"> </span><span class="token exports operator" style="color:#393A34">*</span><span class="token plain"> </span><span class="token keyword module" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@uppy/core'</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<p>If you're using Uppy from a CDN, we now provide two bundles: one for up-to-date
browsers that do not include polyfills and use modern syntax, and one for legacy
browsers. When migrating, be mindful about the types of browsers you want to
support:</p>
<div class="language-html codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-html codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">&lt;!-- Modern browsers (recommended) --&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">script</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">src</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">https://releases.transloadit.com/uppy/v2.0.1/uppy.min.js</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token script"></span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">script</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">&lt;!-- Legacy browsers (IE11+) --&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">script</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">	</span><span class="token tag attr-name" style="color:#00a4db">nomodule</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">	</span><span class="token tag attr-name" style="color:#00a4db">src</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">https://releases.transloadit.com/uppy/v2.0.1/uppy.legacy.min.js</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f"></span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token script"></span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">script</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">script</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">type</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">module</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">	</span><span class="token script language-javascript keyword module" style="color:#00009f">import</span><span class="token script language-javascript"> </span><span class="token script language-javascript string" style="color:#e3116c">'https://releases.transloadit.com/uppy/v2.0.1/uppy.min.js'</span><span class="token script language-javascript punctuation" style="color:#393A34">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript"></span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">script</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><br></span></code></pre></div></div>
<p>Please note that while you may be able to get 2.0 to work in IE11 this way, we
do not officially support it anymore.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="faster">Faster<a href="https://uppy.io/blog/2021/08/2.0/#faster" class="hash-link" aria-label="Direct link to Faster" title="Direct link to Faster" translate="no">​</a></h2>
<p>Uppy now loads faster thanks to the decreased bundle size. With Uppy 1.0, adding
many files (hundreds or even thousands) used to take dozens of seconds. Uppy 2.0
does the same thing in mere milliseconds! So, at least for this specific use
case, we feel comfortable in claiming that you may see your loading times go
<strong>up to a thousand times faster</strong>.</p>
<p>This was made possible by avoiding having to re-render all the file components
whenever something changes, using <code>memoize</code> and <code>virtual-list</code> (allowing us to
only render what is actually visible on screen). In addition, multiple files are
now added to state in one go via <code>uppy.addFiles(Array)</code> as opposed to before,
when <code>uppy.addFile(File)</code> + <code>uppy.setState</code> were being called in a loop.</p>
<p>Before optimizations:</p>
<p><img decoding="async" loading="lazy" src="https://uppy.io/assets/images/uppy-performance-before-b2a473c8bdbee03af5ea1c6a13d781fc.gif" width="800" height="438" class="img_ev3q"></p>
<p>And after:</p>
<p><img decoding="async" loading="lazy" src="https://uppy.io/assets/images/uppy-performance-after-f44f25665c7970c71d9c5c93c5009a6d.gif" width="800" height="438" class="img_ev3q"></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="preact-x-and-upgraded-dependencies">Preact X and upgraded dependencies<a href="https://uppy.io/blog/2021/08/2.0/#preact-x-and-upgraded-dependencies" class="hash-link" aria-label="Direct link to Preact X and upgraded dependencies" title="Direct link to Preact X and upgraded dependencies" translate="no">​</a></h2>
<p>We’ve upgraded almost all of Uppy’s dependencies. This includes the migration to
Preact X. All plugins that depend on Preact have been upgraded from <code>8.2.9</code> to
the latest version <code>10.5.13</code>. If you’d like your custom plugin to continue
working with Uppy 2.0, it also needs to be using latest version of Preact.</p>
<p>Other notable upgrades include browserify to <code>v10</code>, typescript to <code>v4.3</code>,
autoprefixer to <code>v10</code>, and lerna to <code>v4</code>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="plugin-is-replaced-with-baseplugin-and-uiplugin"><code>Plugin</code> is replaced with <code>BasePlugin</code> and <code>UIPlugin</code><a href="https://uppy.io/blog/2021/08/2.0/#plugin-is-replaced-with-baseplugin-and-uiplugin" class="hash-link" aria-label="Direct link to plugin-is-replaced-with-baseplugin-and-uiplugin" title="Direct link to plugin-is-replaced-with-baseplugin-and-uiplugin" translate="no">​</a></h2>
<p><a class="" href="https://uppy.io/docs/uppy/"><code>@uppy/core</code></a> provided a <code>Plugin</code> class for creating plugins. This was
used for any official plugin, but also for users who want to create their own
custom plugin. However, <code>Plugin</code> always came bundled with Preact, even if the
plugin itself didn't add any UI elements.</p>
<p>As of Uppy 2.0.0, <code>Plugin</code> has been replaced with <code>BasePlugin</code> and <code>UIPlugin</code>.
<code>BasePlugin</code> is the minimum you need to create a plugin and <code>UIPlugin</code> adds
Preact for rendering user interfaces.</p>
<p><strong>Note:</strong> some bundlers will include <code>UIPlugin</code> (and therefore Preact) if you
import from <code>@uppy/core</code>. To make sure this does not happen, you can import
<code>Uppy</code> and <code>BasePlugin</code> directly:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword module" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports maybe-class-name">Uppy</span><span class="token plain"> </span><span class="token keyword module" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@uppy/core/lib/Uppy.js'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword module" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports maybe-class-name">BasePlugin</span><span class="token plain"> </span><span class="token keyword module" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@uppy/core/lib/BasePlugin.js'</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<p>Interested in creating your own plugin? Check out the
<a class="" href="https://uppy.io/docs/guides/building-plugins/">“writing plugins”</a> guide.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="strict-typescript-types-by-default">Strict TypeScript types by default<a href="https://uppy.io/blog/2021/08/2.0/#strict-typescript-types-by-default" class="hash-link" aria-label="Direct link to Strict TypeScript types by default" title="Direct link to Strict TypeScript types by default" translate="no">​</a></h2>
<p>Uppy used to have loose types by default and strict types as an opt-in. The
default export was a function that returned the <code>Uppy</code> class, and the types came
bundled with the default export (<code>Uppy.SomeType</code>).</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> Uppy </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@uppy/core'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> Tus </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@uppy/tus'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> uppy </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token generic-function function" style="color:#d73a49">Uppy</span><span class="token generic-function generic class-name operator" style="color:#393A34">&lt;</span><span class="token generic-function generic class-name">Uppy</span><span class="token generic-function generic class-name punctuation" style="color:#393A34">.</span><span class="token generic-function generic class-name">StrictTypes</span><span class="token generic-function generic class-name operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">uppy</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">use</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">Tus</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	invalidOption</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// this will make the compilation fail!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<p>Uppy is now strictly typed by default and loose types have been removed. The
default export is the <code>Uppy</code> class and not a function. This means you need to
call <code>Uppy</code> with the <code>new</code> keyword when initializing it.</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// ...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> uppy </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">Uppy</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">uppy</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">use</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">Tus</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	invalidOption</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// this will make the compilation fail!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<p>Uppy types are now individual exports and should be imported separately.</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">type</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> PluginOptions</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> UIPlugin</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> PluginTarget </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@uppy/core'</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="event-types">Event types<a href="https://uppy.io/blog/2021/08/2.0/#event-types" class="hash-link" aria-label="Direct link to Event types" title="Direct link to Event types" translate="no">​</a></h3>
<p><a class="" href="https://uppy.io/docs/uppy/"><code>@uppy/core</code></a> provides an <a class="" href="https://uppy.io/docs/uppy/#onevent-action"><code>.on</code></a> method to
listen to <a class="" href="https://uppy.io/docs/uppy/#events">events</a>. The types for these events were loose
and allowed for invalid events to be passed, such as
<code>uppy.on('upload-errrOOOoooOOOOOrrrr')</code>.</p>
<p>Events have received a big update thanks to <a href="https://github.com/Hawxy" target="_blank" rel="noopener noreferrer" class="">@Hawxy</a>,
making them more strict and accurate.</p>
<p>A breaking change was required to make this happen:</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// Before:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">type</span><span class="token plain"> </span><span class="token class-name">Meta</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> myCustomMetadata</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// Invalid event</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">uppy</span><span class="token punctuation" style="color:#393A34">.</span><span class="token generic-function function" style="color:#d73a49">on</span><span class="token generic-function generic class-name operator" style="color:#393A34">&lt;</span><span class="token generic-function generic class-name">Meta</span><span class="token generic-function generic class-name operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'upload-errrOOOoooOOOOOrrrr'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token comment" style="color:#999988;font-style:italic">// ...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// After:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// Normal event signature</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">uppy</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">on</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'complete'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">result</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> successResults </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> result</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">successful</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// Custom signature</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">type</span><span class="token plain"> </span><span class="token class-name">Meta</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> myCustomMetadata</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// Notice how the custom type has now become the second argument</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">uppy</span><span class="token punctuation" style="color:#393A34">.</span><span class="token generic-function function" style="color:#d73a49">on</span><span class="token generic-function generic class-name operator" style="color:#393A34">&lt;</span><span class="token generic-function generic class-name string" style="color:#e3116c">'complete'</span><span class="token generic-function generic class-name punctuation" style="color:#393A34">,</span><span class="token generic-function generic class-name"> Meta</span><span class="token generic-function generic class-name operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'complete'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">result</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token comment" style="color:#999988;font-style:italic">// The passed type is now merged into the `meta` types.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> meta </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> result</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">successful</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">meta</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">myCustomMetadata</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<p>Plugins that add their own events can merge with existing ones in <code>@uppy/core</code>
with <code>declare module '@uppy/core' { ... }</code>. This is a TypeScript pattern called
<a href="https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation" target="_blank" rel="noopener noreferrer" class="">module augmentation</a>.
For instance, when using <a class="" href="https://uppy.io/docs/dashboard/"><code>@uppy/dashboard</code></a>:</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">uppy</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">on</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'dashboard:file-edit-start'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">file</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> fileName </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> file</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">name</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="batch-pre-signing-urls-for-aws-s3-multipart">Batch pre-signing URLs for AWS S3 Multipart<a href="https://uppy.io/blog/2021/08/2.0/#batch-pre-signing-urls-for-aws-s3-multipart" class="hash-link" aria-label="Direct link to Batch pre-signing URLs for AWS S3 Multipart" title="Direct link to Batch pre-signing URLs for AWS S3 Multipart" translate="no">​</a></h2>
<p>The <a class="" href="https://uppy.io/docs/aws-s3/"><code>@uppy/aws-s3-multipart</code></a> plugin can be used to upload files
directly to an S3 bucket using S3’s Multipart upload strategy. With this
strategy, files are chopped up in parts of 5MB+ each, so they can be uploaded
concurrently. It is also very reliable: if a single part fails to upload, only
that 5MB chunk has to be retried.</p>
<p>However, in Uppy 1.0, every part had to make the trip to the server to generate
a pre-signed URL. This meant that a 1GB file uploaded in 5MB chunks would
require two hundred trips to the server.</p>
<p>As of Uppy 2.0.0, we now pre-sign URLs in batches. That same 1GB file now only
takes fifty trips to the server (if the limit was four).</p>
<p>This is now the new default. Thanks to
<a href="https://github.com/martin-brennan" target="_blank" rel="noopener noreferrer" class="">@martin-brennan</a> for this contribution!</p>
<p>Do you care about reliable uploads? You could also consider <a class="" href="https://uppy.io/docs/tus/"><code>@uppy/tus</code></a>
with a self-hosted or Transloadit Tus server. Tus can resume uploads, supports
smaller chunks, and offers increased upload speeds.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="and-more">And more<a href="https://uppy.io/blog/2021/08/2.0/#and-more" class="hash-link" aria-label="Direct link to And more" title="Direct link to And more" translate="no">​</a></h2>
<ul>
<li class="">The <code>.run</code> method on the <code>Uppy</code> instance has been removed. This method was
already obsolete and only logged a warning. As of this major version, it no
longer exists.</li>
<li class=""><a class="" href="https://uppy.io/docs/informer/"><code>@uppy/informer</code></a> now supports showing multiple notifications at
the same time. The notifications themselves have also been improved.</li>
<li class="">Improved screen reader accessibility for checkboxes and the 'remove file'
button for <a class="" href="https://uppy.io/docs/dashboard/"><code>@uppy/dashboard</code></a>.</li>
<li class="">Sort files and folders alphabetically in the Google Drive provider.</li>
<li class="">Polished our code base with improved eslint rules, private field methods, and
other modern JavaScript features that help us write more intention-revealing
and safe code.</li>
<li class="">To make Uppy more friendly towards new contributors, we have renamed our
<code>master</code> branch to <code>main</code>.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-future-remains-for-10">What future remains for 1.0?<a href="https://uppy.io/blog/2021/08/2.0/#what-future-remains-for-10" class="hash-link" aria-label="Direct link to What future remains for 1.0?" title="Direct link to What future remains for 1.0?" translate="no">​</a></h2>
<p>Uppy 1.0 will continue to receive bug fixes for three more months (until
<time datetime="2021-12-01">1 December 2021</time>), security fixes for one more
year (until <time datetime="2022-09-01">1 September 2022</time>), but no more
new features after today. Exceptions are unlikely, but <em>can</em> be made – to
accommodate those with commercial support contracts, for example.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="thats-it">That's it!<a href="https://uppy.io/blog/2021/08/2.0/#thats-it" class="hash-link" aria-label="Direct link to That's it!" title="Direct link to That's it!" translate="no">​</a></h2>
<p>We hope you'll waste no time in taking Uppy 2.0 out for a walk. When you do,
please let us know what you thought of it on
<a href="https://www.reddit.com/r/javascript/comments/penbr7/uppy_file_uploader_20_smaller_and_faster_modular/" target="_blank" rel="noopener noreferrer" class="">Reddit</a>,
<a href="https://news.ycombinator.com/item?id=28359287" target="_blank" rel="noopener noreferrer" class="">HN</a>, ProductHunt, or
<a href="https://twitter.com/uppy_io/status/1432399270846603264" target="_blank" rel="noopener noreferrer" class="">Twitter</a>. We're howling
at the moon to hear from you!</p>]]></content>
        <author>
            <name>Antoine du Hamel</name>
            <email>antoine@transloadit.com</email>
        </author>
        <author>
            <name>Artur Paikin</name>
            <email>artur@transloadit.com</email>
        </author>
        <author>
            <name>Mikael Finstad</name>
            <email>mikael@transloadit.com</email>
        </author>
        <author>
            <name>Merlijn Vos</name>
            <email>merlijn@transloadit.com</email>
        </author>
        <author>
            <name>Renée Kooi</name>
            <email>github@kooi.me</email>
        </author>
        <author>
            <name>Andrew Kachnic</name>
            <email>andrew@transloadit.com</email>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Uppy 1.30: Angular integration, granular image rotation, Google Drive shortcuts]]></title>
        <id>https://uppy.io/blog/2021/07/1.30/</id>
        <link href="https://uppy.io/blog/2021/07/1.30/"/>
        <updated>2021-07-02T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Uppy 1.30 introduces the long-awaited Angular integration (beta), granular image]]></summary>
        <content type="html"><![CDATA[<p>Uppy 1.30 introduces the long-awaited Angular integration (beta), granular image
rotation and Google Drive shortcuts.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="angular-integration">Angular integration<a href="https://uppy.io/blog/2021/07/1.30/#angular-integration" class="hash-link" aria-label="Direct link to Angular integration" title="Direct link to Angular integration" translate="no">​</a></h2>
<p>Uppy now has an official Angular integration! It’s still in beta, so please try
it out and do let us know how we can improve through
<a href="https://mobile.twitter.com/uppy_io/" target="_blank" rel="noopener noreferrer" class="">Twitter</a> or
<a href="https://github.com/transloadit/uppy" target="_blank" rel="noopener noreferrer" class="">GitHub</a>. The original draft implementation
was made by <a href="https://github.com/adammedford" target="_blank" rel="noopener noreferrer" class="">Adam Medford</a>, then finalized,
polished and brought to release today by
<a href="https://github.com/ajkachnic" target="_blank" rel="noopener noreferrer" class="">Andrew Kachnic</a> 👏</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">npm install @uppy/angular</span><br></span></code></pre></div></div>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// app.component.ts</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> Component </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@angular/core'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> Uppy </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@uppy/core'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token decorator at operator" style="color:#393A34">@</span><span class="token decorator function" style="color:#d73a49">Component</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	selector</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'app-root'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">export</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">AppComponent</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	uppy</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> Uppy </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">Uppy</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> debug</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> autoProceed</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<div class="language-html codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-html codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">&lt;!--- app.component.html --&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">uppy-dashboard</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">[uppy]</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">uppy</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">uppy-dashboard</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><br></span></code></pre></div></div>
<p>The following plugins are available as Angular component wrappers:</p>
<ul>
<li class=""><code>&lt;uppy-dashboard /&gt;</code></li>
<li class=""><code>&lt;uppy-drag-drop /&gt;</code></li>
<li class=""><code>&lt;uppy-progress-bar /&gt;</code></li>
<li class=""><code>&lt;uppy-status-bar /&gt;</code></li>
</ul>
<p>See the <a class="" href="https://uppy.io/docs/angular/">Angular docs</a> for more details.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="granular-image-rotation">Granular image rotation<a href="https://uppy.io/blog/2021/07/1.30/#granular-image-rotation" class="hash-link" aria-label="Direct link to Granular image rotation" title="Direct link to Granular image rotation" translate="no">​</a></h2>
<p><code>@uppy/image-editor</code> plugin received a new option <code>granularRotate: true</code> that
allows for granular image rotation: be it 12° or 59° — just adjust the slider to
your liking.</p>
<video alt="" muted="" autoplay="" loop="">
  <source src="/img/blog/1.30/granular-rotation.mp4" type="video/mp4">
  Your browser does not support the video tag: https://uppy.io/img/blog/1.30/granular-rotation.mp4
</video>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="google-drive-shortcuts">Google Drive Shortcuts<a href="https://uppy.io/blog/2021/07/1.30/#google-drive-shortcuts" class="hash-link" aria-label="Direct link to Google Drive Shortcuts" title="Direct link to Google Drive Shortcuts" translate="no">​</a></h2>
<p>Google Drive shortcuts, much like in a desktop OS, are pointers to files or
folders that can be stored in another folder or drive. Uppy now supports
shortcuts – you will see them alongside your usual files and folders.</p>
<p><img decoding="async" loading="lazy" src="https://uppy.io/assets/images/drive-shortcut-8e2ea1eb3b003abb51d0c1f080b3f11c.png" width="1400" height="898" class="img_ev3q"></p>
<p><img decoding="async" loading="lazy" src="https://uppy.io/assets/images/uppy-shortcut-bcc51c3d4b0990a0ae9a8fa8dd5384a1.png" width="1200" height="940" class="img_ev3q"></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="misc">Misc<a href="https://uppy.io/blog/2021/07/1.30/#misc" class="hash-link" aria-label="Direct link to Misc" title="Direct link to Misc" translate="no">​</a></h2>
<ul>
<li class="">@uppy/react: allowed HTML attributes to be passed via props (#2891 /
@ajkachnic)</li>
<li class="">@uppy/drag-drop: Expose drag-drop events (#2914 / @Murderlon)</li>
<li class="">@uppy/companion: add <code>logClientVersion</code> option (#2855 / @mifi)</li>
<li class="">build: Fix eslint uppy package imports (#2915 / @Murderlon)</li>
</ul>
<p>See the
<a href="https://github.com/transloadit/uppy/blob/master/CHANGELOG.md#1300" target="_blank" rel="noopener noreferrer" class="">changelog</a>
for more details.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="download">Download<a href="https://uppy.io/blog/2021/07/1.30/#download" class="hash-link" aria-label="Direct link to Download" title="Direct link to Download" translate="no">​</a></h2>
<p><a href="https://releases.transloadit.com/uppy/v1.29.1/uppy-v1.30.0.zip" target="_blank" rel="noopener noreferrer" class="TryButton">Download
Uppy 1.30 Bundle</a></p>
<p><small>Or <a href="https://uppy.io/docs/" target="_blank" rel="noopener noreferrer" class="">include from CDN</a>. Note that it’s highly
recommended to pick and choose specific Uppy plugins that you need, and install
them with <code>npm</code> or <code>yarn</code>. This is because the bundle includes all Uppy plugins
at once.</small></p>]]></content>
        <author>
            <name>Artur Paikin</name>
            <email>artur@transloadit.com</email>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Uppy 1.29: Golden Retriever, disableLocalFiles, Webcam previews, uppy.logout]]></title>
        <id>https://uppy.io/blog/2021/05/1.29/</id>
        <link href="https://uppy.io/blog/2021/05/1.29/"/>
        <updated>2021-05-31T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[In Uppy 1.29, we’ve revamped the Golden Retriever plugin with support for]]></summary>
        <content type="html"><![CDATA[<p>In Uppy 1.29, we’ve revamped the Golden Retriever plugin with support for
partially recovered “ghost” files, added a <code>disableLocalFiles</code> option to the
Dashboard, enabled the ability to preview webcam videos before submitting and
provided an <code>uppy.logout()</code> method, along with an assortment of Companion
improvements.</p>
<video alt="Demo of Uppy Golden Retriever file restore plugin in action" muted="" autoplay="" loop="">
  <source src="/img/blog/1.29/ghosts-demo.mp4" type="video/mp4">
  Your browser does not support the video tag: https://uppy.io/img/blog/1.29/ghosts-demo.mp4
</video>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="golden-retriever">Golden Retriever<a href="https://uppy.io/blog/2021/05/1.29/#golden-retriever" class="hash-link" aria-label="Direct link to Golden Retriever" title="Direct link to Golden Retriever" translate="no">​</a></h2>
<p><a class="" href="https://uppy.io/docs/golden-retriever/">Golden Retriever</a> (<code>@uppy/golden-retriever</code>) is Uppy’s
innovative plugin that recovers users’ files after an accidentally closed
tab/window or a browser crash. Golden Retriever was first
<a class="" href="https://uppy.io/blog/2017/07/golden-retriever/">introduced a few years ago</a>, during
Transloadit’s company meetup in Berlin, and now it finally underwent a proper
refactor.</p>
<p><img decoding="async" loading="lazy" src="https://uppy.io/assets/images/golden-retriever-all-recovered-b38cff840844494f6aa86cc305d4039a.png" width="1200" height="880" class="img_ev3q"></p>
<p>In this release, we’re adding support for “ghosts” — files for which we’ve
restored the metadata, but were unable to recover the data blob itself (usually
due to its size). In this case, users will see a ghost icon over the file and a
“Re-select” button to pick the file again.</p>
<p><img decoding="async" loading="lazy" src="https://uppy.io/assets/images/golden-retriever-ghost-9e9b02b8ae7f4416a8b4026bc3461bac.png" width="1200" height="940" class="img_ev3q"></p>
<p>You can try Golden Retriever in action on
<a href="https://uppy.io/examples/dashboard/" target="_blank" rel="noopener noreferrer" class="">the Dashboard example page</a>.</p>
<center><img decoding="async" loading="lazy" src="https://uppy.io/img/blog/golden-retriever/catch-fail-2.gif" alt="Golden Retriever failing to catch something" title="Good try, girl!" class="img_ev3q"></center>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="dashboard-disablelocalfiles">Dashboard: <code>disableLocalFiles</code><a href="https://uppy.io/blog/2021/05/1.29/#dashboard-disablelocalfiles" class="hash-link" aria-label="Direct link to dashboard-disablelocalfiles" title="Direct link to dashboard-disablelocalfiles" translate="no">​</a></h2>
<p>The <code>disableLocalFiles: true</code> option will disable drag &amp; drop, and hide the
“Browse” and “My Device” buttons, allowing only uploads from plugins, such as
Webcam, Screen Capture, Google Drive or Instagram.</p>
<p><img decoding="async" loading="lazy" src="https://uppy.io/assets/images/disableLocalFiles-4446a558b5557cef7389050794daf7d5.png" width="1494" height="1094" class="img_ev3q"></p>
<p><a href="https://uppy.io/docs/dashboard/#disableLocalFiles" target="_blank" rel="noopener noreferrer" class="">Docs: disableLocalFiles</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="webcam-previews">Webcam Previews<a href="https://uppy.io/blog/2021/05/1.29/#webcam-previews" class="hash-link" aria-label="Direct link to Webcam Previews" title="Direct link to Webcam Previews" translate="no">​</a></h2>
<p>When recording a video with the <code>@uppy/webcam</code> plugin, you will now be given the
opportunity to play it back and review before submitting. If you happen to not
like the crab mask you’ve used, you can re-record the video using a more
appropriate baby Yoda or duckface mask.</p>
<video alt="Demo of Uppy Golden Retriever file restore plugin in action" muted="" autoplay="" loop="">
  <source src="/img/blog/1.29/webcam-preview-demo.mp4" type="video/mp4">
  Your browser does not support the video tag: https://uppy.io/img/blog/1.29/webcam-preview-demo.mp4
</video>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="uppylogout">uppy.logout()<a href="https://uppy.io/blog/2021/05/1.29/#uppylogout" class="hash-link" aria-label="Direct link to uppy.logout()" title="Direct link to uppy.logout()" translate="no">​</a></h2>
<p>When your users log out of your app, you might want to also log them out of any
cloud providers they might have used through Uppy, for extra security.</p>
<p><code>uppy.logout()</code> calls <code>provider.logout()</code> on each remote provider plugin, like
Google Drive, Instagram, Dropbox, etc.</p>
<p><a href="https://uppy.io/docs/uppy/#uppy-logout" target="_blank" rel="noopener noreferrer" class="">Docs: uppy-logout</a></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="companion">Companion<a href="https://uppy.io/blog/2021/05/1.29/#companion" class="hash-link" aria-label="Direct link to Companion" title="Direct link to Companion" translate="no">​</a></h2>
<ul>
<li class="">@uppy/companion-client: rethrow original error objects (#2889 /
@goto-bus-stop)</li>
<li class="">Pull out metric middleware logic (#2854 / @mifi)</li>
<li class="">Smaller Heroku deployment (#2845 / @goto-bus-stop)</li>
<li class="">Bump redis from 2.8.0 to 3.1.1 (#2865 / @dependabot, @ kiloreux)</li>
<li class="">add chunkSize Companion option (#2881 / @mifi)</li>
<li class="">fix NRP TypeScript errors (#2884 / @mifi)</li>
<li class="">support relative redirect URLs in responses (#2901 / @ goto-bus-stop)</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="misc">Misc<a href="https://uppy.io/blog/2021/05/1.29/#misc" class="hash-link" aria-label="Direct link to Misc" title="Direct link to Misc" translate="no">​</a></h2>
<ul>
<li class="">core: use AggregateError when available (#2869 / @aduh95)</li>
<li class="">build: upgrade TypeScript (#2856 / @ajkachnic)</li>
<li class="">webcam: improve MIME type detection to solve issue in iOS Safari (#2851 /
@dominiceden)</li>
</ul>
<p>See
<a href="https://github.com/transloadit/uppy/blob/master/CHANGELOG.md#1291" target="_blank" rel="noopener noreferrer" class="">changelog</a>
for details.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="download">Download<a href="https://uppy.io/blog/2021/05/1.29/#download" class="hash-link" aria-label="Direct link to Download" title="Direct link to Download" translate="no">​</a></h2>
<p><a href="https://releases.transloadit.com/uppy/v1.29.1/uppy-v1.29.1.zip" target="_blank" rel="noopener noreferrer" class="TryButton">Download
Uppy 1.29.1</a></p>
<p><small>Or <a href="https://uppy.io/docs/" target="_blank" rel="noopener noreferrer" class="">include from CDN</a>. Note that it’s highly
recommended to pick and choose specific Uppy plugins that you need, and install
them with <code>npm</code> or <code>yarn</code>. This is because the bundle includes all Uppy plugins
at once.</small></p>]]></content>
        <author>
            <name>Artur Paikin</name>
            <email>artur@transloadit.com</email>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Uppy 1.27: Drop Target plugin, Vue 3 support, Dashboard dynamic meta fields, “Shared with me” in Google Drive]]></title>
        <id>https://uppy.io/blog/2021/04/1.27/</id>
        <link href="https://uppy.io/blog/2021/04/1.27/"/>
        <updated>2021-04-05T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[In Uppy 1.27 we’ve added a new @uppy/drop-target plugin, enabled support for]]></summary>
        <content type="html"><![CDATA[<p>In Uppy 1.27 we’ve added a new <code>@uppy/drop-target</code> plugin, enabled support for
Vue 3, introduced dynamic <code>metaFields</code> option for Dashboard, Google Drive now
lists documents that have been shared with you.</p>
<video alt="Demo video showing Uppy with Drop Target plugin which allows accepting drag and drop anywhere on a page" poster="/img/blog/1.26/dashboard-disabled.jpg" muted="" autoplay="" loop="">
  <source src="/img/blog/1.27/drop-target.mp4" type="video/mp4">
  Your browser does not support the video tag: https://uppy.io/img/blog/1.27/drop-target.mp4
</video>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="drop-target">Drop Target<a href="https://uppy.io/blog/2021/04/1.27/#drop-target" class="hash-link" aria-label="Direct link to Drop Target" title="Direct link to Drop Target" translate="no">​</a></h2>
<p>With <code>@uppy/drop-target</code> it is now possible to turn your whole app / page (or
any other element, like <code>&lt;textarea&gt;</code>, for instance) into a drag-and-drop area:</p>
<p><img decoding="async" loading="lazy" alt="Uppy Dashboard UI with drop target plugin" src="https://uppy.io/assets/images/drop-target-ece163fa99fef8451195acc5d4077e73.jpg" width="1600" height="812" class="img_ev3q"></p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">uppy</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">use</span><span class="token punctuation" style="color:#393A34">(</span><span class="token maybe-class-name">DropTarget</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token literal-property property" style="color:#36acaa">target</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token dom variable" style="color:#36acaa">document</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">body</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="google-drive-shared-with-me">Google Drive “Shared with me”<a href="https://uppy.io/blog/2021/04/1.27/#google-drive-shared-with-me" class="hash-link" aria-label="Direct link to Google Drive “Shared with me”" title="Direct link to Google Drive “Shared with me”" translate="no">​</a></h2>
<p>If you connect Uppy to Google Drive, you’ll now see a new virtual folder called
“Shared with me” — there you’ll find (hard to guess, I know), documents that
have been shared with you.</p>
<p><img decoding="async" loading="lazy" alt="Google Drive “Shared with me” folder" src="https://uppy.io/assets/images/shared-with-me-caed07cd7437ba1a316ab05327ce55e7.jpg" width="1226" height="968" class="img_ev3q"></p>
<p><a href="https://github.com/transloadit/uppy/pull/2758" target="_blank" rel="noopener noreferrer" class="">PR #2758</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="dashboard-dynamic-metafields">Dashboard Dynamic <code>metaFields</code><a href="https://uppy.io/blog/2021/04/1.27/#dashboard-dynamic-metafields" class="hash-link" aria-label="Direct link to dashboard-dynamic-metafields" title="Direct link to dashboard-dynamic-metafields" translate="no">​</a></h2>
<p>Sometimes you may want to show specific meta fields for certain type of files.
For instance, you may want to show location and alt attribute for images. Now,
instead of setting a fixed array of fields, you can pass a function that will be
called for each file, returning an array of fields from it:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">use</span><span class="token punctuation" style="color:#393A34">(</span><span class="token maybe-class-name">Dashboard</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token literal-property property" style="color:#36acaa">trigger</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'#pick-files'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function-variable function" style="color:#d73a49">metaFields</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token parameter">file</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> fields </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token literal-property property" style="color:#36acaa">id</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'name'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token literal-property property" style="color:#36acaa">name</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'File name'</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword control-flow" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">file</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">type</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">startsWith</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'image/'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      fields</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">push</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token literal-property property" style="color:#36acaa">id</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'location'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token literal-property property" style="color:#36acaa">name</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'Photo Location'</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      fields</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">push</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token literal-property property" style="color:#36acaa">id</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'alt'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token literal-property property" style="color:#36acaa">name</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'Alt text'</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword control-flow" style="color:#00009f">return</span><span class="token plain"> fields</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><br></span></code></pre></div></div>
<p>See <a href="https://uppy.io/docs/dashboard/#metaFields" target="_blank" rel="noopener noreferrer" class="">Dashboard <code>metaFields</code></a> docs
for details.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="vue-3">Vue 3<a href="https://uppy.io/blog/2021/04/1.27/#vue-3" class="hash-link" aria-label="Direct link to Vue 3" title="Direct link to Vue 3" translate="no">​</a></h2>
<p><code>@uppy/vue</code> integration now supports Vue 3! This is done by checking the
arguments of the <code>render</code> function and determining whether it is using Vue 2 or
3, and then returning the appropriate rendering method.</p>
<p><a href="https://github.com/transloadit/uppy/pull/2755" target="_blank" rel="noopener noreferrer" class="">PR #2755</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="companion-cors-and-better-testing">Companion CORS and Better Testing<a href="https://uppy.io/blog/2021/04/1.27/#companion-cors-and-better-testing" class="hash-link" aria-label="Direct link to Companion CORS and Better Testing" title="Direct link to Companion CORS and Better Testing" translate="no">​</a></h2>
<p>In Companion, we’ve improved unit testing DX
(<a href="https://github.com/transloadit/uppy/pull/2827" target="_blank" rel="noopener noreferrer" class="">#2827</a>) and switched to using
the <code>cors</code> module instead of custom cors logic
(<a href="https://github.com/transloadit/uppy/pull/2823" target="_blank" rel="noopener noreferrer" class="">#2823</a>).</p>
<p>@coreprocess submited a fix that allows Companion to serve on a subpath
(<a href="https://github.com/transloadit/uppy/pull/2797" target="_blank" rel="noopener noreferrer" class="">#2797</a>), and added Redis pubsub
scope setting (<a href="https://github.com/transloadit/uppy/pull/2804" target="_blank" rel="noopener noreferrer" class="">#2804</a>)!</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="npm-7">npm 7<a href="https://uppy.io/blog/2021/04/1.27/#npm-7" class="hash-link" aria-label="Direct link to npm 7" title="Direct link to npm 7" translate="no">​</a></h2>
<p>We’ve finally upgraded our monorepo to npm 7 and
<a href="https://docs.npmjs.com/cli/v7/using-npm/workspaces" target="_blank" rel="noopener noreferrer" class="">Workspaces</a>. If you are a
contributor, please upgrade <code>npm install npm -g</code>, as npm 7 is now required for
the Uppy repo.</p>
<p><a href="https://github.com/transloadit/uppy/pull/2835" target="_blank" rel="noopener noreferrer" class="">PR #2835</a></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="new-linter-rules">New Linter Rules<a href="https://uppy.io/blog/2021/04/1.27/#new-linter-rules" class="hash-link" aria-label="Direct link to New Linter Rules" title="Direct link to New Linter Rules" translate="no">​</a></h2>
<p>Quite a few new rules have been added to our eslint-config, which is now mostly
<code>eslint-config-transloadit</code> with some custom uppy-specific overrides.</p>
<p><a href="https://github.com/transloadit/uppy/pull/2796" target="_blank" rel="noopener noreferrer" class="">PR #2796</a></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="misc">Misc<a href="https://uppy.io/blog/2021/04/1.27/#misc" class="hash-link" aria-label="Direct link to Misc" title="Direct link to Misc" translate="no">​</a></h2>
<ul>
<li class="">@uppy/xhr-upload: Set headers just before the upload in case options changed
(#2781 / @rart)</li>
<li class="">@uppy/aws-s3-multipart: Aws-s3-multipart sends outdated file info to
upload-success event (#2828 / @goto-bus-stop)</li>
<li class="">@uppy/aws-s3: removeUploader triggered on uninstall (#2824 / @slawexxx44)</li>
<li class="">@uppy/webcam: Fix issue where the modes: <code>['audio-only']</code> option was ignored
when getting tracks from the media stream (#2810 / @dominiceden)</li>
<li class="">website: Website improvements (#2803 / @nqst)</li>
</ul>
<p>See
<a href="https://github.com/transloadit/uppy/blob/master/CHANGELOG.md#1270" target="_blank" rel="noopener noreferrer" class="">changelog</a>
for details.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="download">Download<a href="https://uppy.io/blog/2021/04/1.27/#download" class="hash-link" aria-label="Direct link to Download" title="Direct link to Download" translate="no">​</a></h2>
<p><a href="https://releases.transloadit.com/uppy/v1.27.0/uppy-v1.27.0.zip" target="_blank" rel="noopener noreferrer" class="TryButton">Download
Uppy 1.27.0</a></p>
<p><small>Or <a href="https://uppy.io/docs/" target="_blank" rel="noopener noreferrer" class="">include from CDN</a>. Note that it’s highly
recommended to pick and choose specific Uppy plugins that you need, and install
them with <code>npm</code> or <code>yarn</code>. This is because the bundle includes all Uppy plugins
at once.</small></p>]]></content>
        <author>
            <name>Artur Paikin</name>
            <email>artur@transloadit.com</email>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Uppy 1.26: Dashboard “disabled”, per-file headers]]></title>
        <id>https://uppy.io/blog/2021/02/1.26/</id>
        <link href="https://uppy.io/blog/2021/02/1.26/"/>
        <updated>2021-02-26T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Uppy 1.26 brings a new disabled option for the Dashboad, ability to set]]></summary>
        <content type="html"><![CDATA[<p>Uppy 1.26 brings a new <code>disabled</code> option for the Dashboad, ability to set
headers per file with XHR Upload, and fixes for the Transloadit plugin.</p>
<p><img decoding="async" loading="lazy" alt="Uppy Dashboard UI with disabled state" src="https://uppy.io/assets/images/dashboard-disabled-6df98c5e4209d6d4290c96d100fe9617.jpg" width="1219" height="959" class="img_ev3q"></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="dashboard-disabled">Dashboard “Disabled”<a href="https://uppy.io/blog/2021/02/1.26/#dashboard-disabled" class="hash-link" aria-label="Direct link to Dashboard “Disabled”" title="Direct link to Dashboard “Disabled”" translate="no">​</a></h2>
<p>You can now specify a <code>disabled</code> option for the Dashboard, in order to make it
non-interactive and grayed out. Users won’t be able to click on buttons or drop
files.</p>
<p>This is useful when you need to confitionally enable/disable file uploading or
manipulation, based on a condition in your app.</p>
<video alt="Demo video showing Uppy with Dashboard disabled vs enabled state" poster="/img/blog/1.26/dashboard-disabled.jpg" muted="" autoplay="" loop="">
  <source src="/img/blog/1.26/dashboard-disabled-vs-enabled.mp4" type="video/mp4">
  Your browser does not support the video tag: https://uppy.io/img/blog/img/blog/1.26/dashboard-disabled-vs-enabled.mp4
</video>
<p>This option can be set on init:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">uppy</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">use</span><span class="token punctuation" style="color:#393A34">(</span><span class="token maybe-class-name">Dashboard</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token literal-property property" style="color:#36acaa">disabled</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<p>and via API:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> dashboard </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> uppy</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">getPlugin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'Dashboard'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">dashboard</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">setOptions</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token literal-property property" style="color:#36acaa">disabled</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">userNameInput</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">addEventListener</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'change'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	dashboard</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">setOptions</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token literal-property property" style="color:#36acaa">disabled</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">false</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<p><a href="https://uppy.io/docs/dashboard/#disabled-false" target="_blank" rel="noopener noreferrer" class="">See the docs</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="xhr-upload-per-file-headers">XHR Upload Per File headers<a href="https://uppy.io/blog/2021/02/1.26/#xhr-upload-per-file-headers" class="hash-link" aria-label="Direct link to XHR Upload Per File headers" title="Direct link to XHR Upload Per File headers" translate="no">​</a></h2>
<p><code>@uppy/xhr-upload</code> now accept a <code>headers: (file) =&gt; {}</code> function, so you can do:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">uppy</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">use</span><span class="token punctuation" style="color:#393A34">(</span><span class="token maybe-class-name">XHRUpload</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token function-variable function" style="color:#d73a49">headers</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token parameter">file</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token literal-property property" style="color:#36acaa">authorization</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:#e3116c">`</span><span class="token template-string string" style="color:#e3116c">bearer </span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#393A34">${</span><span class="token template-string interpolation">global</span><span class="token template-string interpolation punctuation" style="color:#393A34">.</span><span class="token template-string interpolation property-access">userToken</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#393A34">}</span><span class="token template-string template-punctuation string" style="color:#e3116c">`</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token string-property property" style="color:#36acaa">'header-name'</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> file</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">meta</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">someMetaValue</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<p>to determine file-specific headers.</p>
<p>The function syntax for <code>headers</code> is only available if the <code>bundle</code> option is
<code>false</code> (the default). <code>bundle</code> uploads share only one set of headers.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="build-system-improvements">Build System Improvements<a href="https://uppy.io/blog/2021/02/1.26/#build-system-improvements" class="hash-link" aria-label="Direct link to Build System Improvements" title="Direct link to Build System Improvements" translate="no">​</a></h2>
<ul>
<li class="">build: set legacy-peer-deps for npm 7. We have some peerDependency mismatches
in our install tree. In npm 6 this was OK (maybe reason for a warning) but in
npm 7 they hard fail the install</li>
<li class="">build: added npm version check (33e656cad32b865f960dbd88abf4d3839c8377f0 /
@goto-bus-stop)</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="transloadit-plugin">Transloadit Plugin<a href="https://uppy.io/blog/2021/02/1.26/#transloadit-plugin" class="hash-link" aria-label="Direct link to Transloadit Plugin" title="Direct link to Transloadit Plugin" translate="no">​</a></h2>
<ul>
<li class="">Fixed a case where the plugin used stale file data.</li>
<li class="">Fixed polling fallback bugs.</li>
<li class="">Url concatenation is now more robust.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="misc">Misc<a href="https://uppy.io/blog/2021/02/1.26/#misc" class="hash-link" aria-label="Direct link to Misc" title="Direct link to Misc" translate="no">​</a></h2>
<ul>
<li class="">@uppy/companion: Docker tag release (#2771 / @kiloreux)</li>
<li class="">@uppy/companion: Companion should respect previously set value for
Accesss-Control-Allow-Methods (#2726 / @tim-kos, @mifi, @so-steve)</li>
<li class="">@uppy/transloadit: fix polling fallback bugs (#2759 / @goto-bus-stop)</li>
<li class="">@uppy/utils: added mp4 file type support — Safari 14.0 on Mac records audio
using audio/mp4 MIME type which isn't currently recognised by Uppy (#2753 /
@dominiceden)</li>
</ul>
<p>See
<a href="https://github.com/transloadit/uppy/blob/master/CHANGELOG.md#1260" target="_blank" rel="noopener noreferrer" class="">changelog</a>
for details.</p>]]></content>
        <author>
            <name>Artur Paikin</name>
            <email>artur@transloadit.com</email>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Uppy 1.25: right-to-left scripts, Ukrainian translation, Companion improvements]]></title>
        <id>https://uppy.io/blog/2021/01/1.25/</id>
        <link href="https://uppy.io/blog/2021/01/1.25/"/>
        <updated>2021-01-29T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Uppy 1.25 adds support for right-to-left scripts, Ukrainian translation and]]></summary>
        <content type="html"><![CDATA[<p>Uppy 1.25 adds support for right-to-left scripts, Ukrainian translation and
various improvements for Companion.</p>
<p>Just see how cool this looks, and read further for a video demo and some behind
the scenes implementation sorcery:</p>
<p><img decoding="async" loading="lazy" alt="Uppy Dashboard UI flipped for right-to-left Arabic language" src="https://uppy.io/assets/images/right-to-left-0fae5444f3b207778e206525cdd3a6ff.jpg" width="1212" height="954" class="img_ev3q"></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="right-to-left-scripts">Right-to-left scripts<a href="https://uppy.io/blog/2021/01/1.25/#right-to-left-scripts" class="hash-link" aria-label="Direct link to Right-to-left scripts" title="Direct link to Right-to-left scripts" translate="no">​</a></h2>
<p>Renée have improved support for right-to-left scripts (such as Arabic, Farsi,
Hebrew). This means that Uppy UI can now be mirrored, like how you might see on
sites like
<a href="https://ar.wikipedia.org/wiki/%D8%A7%D9%84%D8%B5%D9%81%D8%AD%D8%A9_%D8%A7%D9%84%D8%B1%D8%A6%D9%8A%D8%B3%D9%8A%D8%A9" target="_blank" rel="noopener noreferrer" class="">Wikipedia</a>.</p>
<video alt="Demo video showing Uppy with right-to-left mirrored UI" poster="/img/blog/1.25/right-to-left.jpg" muted="" autoplay="" loop="">
  <source src="/img/blog/1.25/right-to-left.mp4" type="video/mp4">
  Your browser does not support the video tag: https://uppy.io/img/blog/img/blog/1.25/right-to-left.mp4
</video>
<p>HTML <code>dir</code> attribute can be used to set the direction — any parent element of
the Dashboard may have it. It’s good practice for sites to add a dir attribute
on <code>&lt;html&gt;</code> element, but for backwards compatibility the Dashboard will default
to left-to-right rendering.</p>
<p>The text direction can also be set in code using the new <code>direction</code> option for
the Dashboard plugin. This is useful for the modal dashboard, which would
typically be mounted in the <code>&lt;body&gt;</code> element, so there is no other parent
element that you could set the <code>dir</code> attribute on (aside from <code>&lt;body&gt;</code> and
<code>&lt;html&gt;</code>, which sites <em>should</em> do, but may not).</p>
<blockquote>
<p>Head over to the
<a href="https://github.com/transloadit/uppy/pull/2705" target="_blank" rel="noopener noreferrer" class="">#2705 PR description and code</a>,
if you are interested in how this is implemented, using new CSS properties
like <code>inline-start</code> and <code>inline-end</code> with <code>postcss-logical</code> and
<code>postcss-dir-pseudo-class</code> for the fallback.</p>
</blockquote>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="locales">Locales<a href="https://uppy.io/blog/2021/01/1.25/#locales" class="hash-link" aria-label="Direct link to Locales" title="Direct link to Locales" translate="no">​</a></h2>
<p><a href="https://github.com/elkebab" target="_blank" rel="noopener noreferrer" class="">@DenysNosov</a> contributed a Ukrainian translation
and fixes for Russian grammar!</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="integration-guide">Integration Guide<a href="https://uppy.io/blog/2021/01/1.25/#integration-guide" class="hash-link" aria-label="Direct link to Integration Guide" title="Direct link to Integration Guide" translate="no">​</a></h2>
<p>Andrew, who’s been on fire recently adding Vue and Svelte integrations for Uppy,
has taken the time to share his experience and has written an “Adding a new
integration” guide, in case you’d like to help befriend Uppy with your favorite
framework or library.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="companion">Companion<a href="https://uppy.io/blog/2021/01/1.25/#companion" class="hash-link" aria-label="Direct link to Companion" title="Direct link to Companion" translate="no">​</a></h2>
<ul>
<li class="">Added support for setting 3rd party credentials in runtime</li>
<li class="">Metadata is now passed to S3</li>
<li class="">Support for <code>opts.companionCookiesRule</code> rule</li>
<li class="">Delete tus error’s <code>originalRequest</code> field before propagating error</li>
<li class="">Companion now uses multi-stage docker build</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="misc">Misc<a href="https://uppy.io/blog/2021/01/1.25/#misc" class="hash-link" aria-label="Direct link to Misc" title="Direct link to Misc" translate="no">​</a></h2>
<ul>
<li class="">@uppy/dashboard: emit fileId on both file-edit-start and file-edit-complete
events</li>
<li class="">@uppy/box: added Box to Uppy CDN</li>
</ul>
<p>See
<a href="https://github.com/transloadit/uppy/blob/master/CHANGELOG.md#1250" target="_blank" rel="noopener noreferrer" class="">changelog</a>
for details.</p>]]></content>
        <author>
            <name>Artur Paikin</name>
            <email>artur@transloadit.com</email>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Uppy 1.24: 🎅 Happy Holidays — Svelte, React hook, Auto Open Image Editor]]></title>
        <id>https://uppy.io/blog/2020/12/1.24/</id>
        <link href="https://uppy.io/blog/2020/12/1.24/"/>
        <updated>2020-12-24T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Uppy 1.24 adds an experimental Svelte integration, additional React components,]]></summary>
        <content type="html"><![CDATA[<p>Uppy 1.24 adds an experimental Svelte integration, additional React components,
<code>autoOpenFileEditor</code> option for Dashboard, and a Norwegian (bokmål) translation!</p>
<p><img decoding="async" loading="lazy" src="https://uppy.io/assets/images/uppy-svelte-db0a92474ec31b56b47af36c6181c90f.png" width="1006" height="968" class="img_ev3q"></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="svelte">Svelte<a href="https://uppy.io/blog/2020/12/1.24/#svelte" class="hash-link" aria-label="Direct link to Svelte" title="Direct link to Svelte" translate="no">​</a></h2>
<p>Last month we introduced the first release of official Vue.js components for
Uppy. This month, we're releasing <code>@uppy/svelte</code>: a set of components for the
Svelte framework. Credit, once again, goes to
<a href="https://github.com/ajkachnic" target="_blank" rel="noopener noreferrer" class="">Andrew Kachnic</a> (and special thanks to
<a href="https://github.com/adammedford" target="_blank" rel="noopener noreferrer" class="">Adam Medford</a>)!</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">npm install @uppy/svelte</span><br></span></code></pre></div></div>
<div class="language-html codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-html codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">main</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">&lt;Dashboard uppy={uppy} plugins={['Webcam']} /&gt;</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">main</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">script</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">	</span><span class="token script language-javascript keyword module" style="color:#00009f">import</span><span class="token script language-javascript"> </span><span class="token script language-javascript imports punctuation" style="color:#393A34">{</span><span class="token script language-javascript imports"> </span><span class="token script language-javascript imports maybe-class-name">Dashboard</span><span class="token script language-javascript imports"> </span><span class="token script language-javascript imports punctuation" style="color:#393A34">}</span><span class="token script language-javascript"> </span><span class="token script language-javascript keyword module" style="color:#00009f">from</span><span class="token script language-javascript"> </span><span class="token script language-javascript string" style="color:#e3116c">'@uppy/svelte'</span><span class="token script language-javascript punctuation" style="color:#393A34">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">	</span><span class="token script language-javascript keyword module" style="color:#00009f">import</span><span class="token script language-javascript"> </span><span class="token script language-javascript imports maybe-class-name">Uppy</span><span class="token script language-javascript"> </span><span class="token script language-javascript keyword module" style="color:#00009f">from</span><span class="token script language-javascript"> </span><span class="token script language-javascript string" style="color:#e3116c">'@uppy/core'</span><span class="token script language-javascript punctuation" style="color:#393A34">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">	</span><span class="token script language-javascript keyword module" style="color:#00009f">import</span><span class="token script language-javascript"> </span><span class="token script language-javascript imports maybe-class-name">Webcam</span><span class="token script language-javascript"> </span><span class="token script language-javascript keyword module" style="color:#00009f">from</span><span class="token script language-javascript"> </span><span class="token script language-javascript string" style="color:#e3116c">'@uppy/webcam'</span><span class="token script language-javascript punctuation" style="color:#393A34">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">	</span><span class="token script language-javascript keyword" style="color:#00009f">let</span><span class="token script language-javascript"> uppy </span><span class="token script language-javascript operator" style="color:#393A34">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript keyword" style="color:#00009f">new</span><span class="token script language-javascript"> </span><span class="token script language-javascript class-name">Uppy</span><span class="token script language-javascript punctuation" style="color:#393A34">(</span><span class="token script language-javascript punctuation" style="color:#393A34">)</span><span class="token script language-javascript punctuation" style="color:#393A34">.</span><span class="token script language-javascript method function property-access" style="color:#d73a49">use</span><span class="token script language-javascript punctuation" style="color:#393A34">(</span><span class="token script language-javascript maybe-class-name">Webcam</span><span class="token script language-javascript punctuation" style="color:#393A34">)</span><span class="token script language-javascript punctuation" style="color:#393A34">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript"></span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">script</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><br></span></code></pre></div></div>
<p>Please see <a href="https://uppy.io/docs/svelte/" target="_blank" rel="noopener noreferrer" class="">the Uppy Svelte documentation</a> for all
the components.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="react">React<a href="https://uppy.io/blog/2020/12/1.24/#react" class="hash-link" aria-label="Direct link to React" title="Direct link to React" translate="no">​</a></h2>
<p>The <code>@uppy/react</code> package now contains <code>&lt;FileInput /&gt;</code>, a wrapper for the
<code>@uppy/file-input</code> plugin. It can render simple HTML file input or button, for
situations where a flashy user interface is not desired.</p>
<p>Additionally, <code>useUppy()</code> is our first React Hook, made to manage the lifecycle
of Uppy instances. Without this, it's easy to accidentally create many garbage
Uppy instances in modern React code.</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword module" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:#393A34">{</span><span class="token imports"> </span><span class="token imports maybe-class-name">FileInput</span><span class="token imports punctuation" style="color:#393A34">,</span><span class="token imports"> useUppy </span><span class="token imports punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword module" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@uppy/react'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword module" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports maybe-class-name">Uppy</span><span class="token plain"> </span><span class="token keyword module" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@uppy/core'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword module" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports maybe-class-name">Tus</span><span class="token plain"> </span><span class="token keyword module" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@uppy/tus'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function maybe-class-name" style="color:#d73a49">MyUploader</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> uppy </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useUppy</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token keyword control-flow" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">Uppy</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">use</span><span class="token punctuation" style="color:#393A34">(</span><span class="token maybe-class-name">Tus</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token literal-property property" style="color:#36acaa">endpoint</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'https://tusd.tusdemo.net'</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token comment" style="color:#999988;font-style:italic">// useUppy() will automatically `.close()` the Uppy instance for us when</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token comment" style="color:#999988;font-style:italic">// MyUploader unmounts.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword control-flow" style="color:#00009f">return</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token maybe-class-name">FileInput</span><span class="token plain"> uppy</span><span class="token operator" style="color:#393A34">=</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">uppy</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">/</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>This does not solve all our problems yet: dynamic configuration is still
difficult to do right, due to the mismatch between React's declarative and
Uppy's imperative style. We hope to add more documentation and tools to bridge
the gap in the new year.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="locales">Locales<a href="https://uppy.io/blog/2020/12/1.24/#locales" class="hash-link" aria-label="Direct link to Locales" title="Direct link to Locales" translate="no">​</a></h2>
<p><a href="https://github.com/elkebab" target="_blank" rel="noopener noreferrer" class="">@elkebab</a> contributed a Norwegian translation!</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="auto-open-image-editor">Auto Open Image Editor<a href="https://uppy.io/blog/2020/12/1.24/#auto-open-image-editor" class="hash-link" aria-label="Direct link to Auto Open Image Editor" title="Direct link to Auto Open Image Editor" translate="no">​</a></h2>
<p>If you are using Image Editor plugin with the Dashboard, there’s a new option
<a href="https://uppy.io/docs/dashboard/#autoOpenFileEditor-false" target="_blank" rel="noopener noreferrer" class=""><code>autoOpenFileEditor</code></a>,
which will open Image Editor automatically for the first image that was added to
Uppy.</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> uppy </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">Uppy</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">use</span><span class="token punctuation" style="color:#393A34">(</span><span class="token maybe-class-name">Dashboard</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token literal-property property" style="color:#36acaa">autoOpenFileEditor</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<img decoding="async" loading="lazy" class="border img_ev3q" src="https://uppy.io/img/blog/1.24/image-editor-alone.jpg" alt="Uppy Image Editor in Dashboard">
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="misc">Misc<a href="https://uppy.io/blog/2020/12/1.24/#misc" class="hash-link" aria-label="Direct link to Misc" title="Direct link to Misc" translate="no">​</a></h2>
<ul>
<li class="">@uppy/core: new event <code>files-added</code> with all files added in one batch (#2681 /
@arturi)</li>
<li class="">@uppy/utils: Add archive mime types (#2703 / @ahmedkandel)</li>
<li class="">@uppy/companion: fix crash when Dropbox API returns an error (#2687 /
@ifedapoolarewaju)</li>
</ul>
<p>See
<a href="https://github.com/transloadit/uppy/blob/master/CHANGELOG.md#1240" target="_blank" rel="noopener noreferrer" class="">changelog</a>
for details.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="happy-holidays">Happy Holidays!<a href="https://uppy.io/blog/2020/12/1.24/#happy-holidays" class="hash-link" aria-label="Direct link to Happy Holidays!" title="Direct link to Happy Holidays!" translate="no">​</a></h2>
<p>Many thanks to all our contributors and users over the past year! Uppy has
gained quite a few new features and important improvements in 2020 (despite
everything going on offline!). We hope to see you again soon in our first
release of 2021 :)</p>]]></content>
        <author>
            <name>Renée Kooi</name>
            <email>github@kooi.me</email>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Uppy 1.23: Vue.js, Box, Done button and cloud file restrictions]]></title>
        <id>https://uppy.io/blog/2020/11/1.23/</id>
        <link href="https://uppy.io/blog/2020/11/1.23/"/>
        <updated>2020-11-30T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Uppy 1.23 brings Vue.js components 💥, Box file service support, a “Done” button]]></summary>
        <content type="html"><![CDATA[<p>Uppy 1.23 brings Vue.js components 💥, Box file service support, a “Done” button
for the Status Bar + Dashboard, and a better cloud file restrictions UI.</p>
<p><img decoding="async" loading="lazy" alt="Vue.js Uppy code sample" src="https://uppy.io/assets/images/vue-code-cover-93b2416dbbff70749807f4b77d0eceae.png" width="1156" height="1522" class="img_ev3q"></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="vuejs">Vue.js<a href="https://uppy.io/blog/2020/11/1.23/#vuejs" class="hash-link" aria-label="Direct link to Vue.js" title="Direct link to Vue.js" translate="no">​</a></h2>
<p>We’ve had <a href="https://uppy.io/docs/react/" target="_blank" rel="noopener noreferrer" class="">Uppy React components</a> available for
quite some time now. With the increasing popularity of Vue.js library, we’re
proud to announce it’s now much easier to use
<a href="https://uppy.io/docs/vue/" target="_blank" rel="noopener noreferrer" class="">Uppy with Vue</a>, thanks to the amazing work by
<a href="https://mobile.twitter.com/su_andrewk" target="_blank" rel="noopener noreferrer" class="">Andrew Kachnic</a>:</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">npm install @uppy/vue</span><br></span></code></pre></div></div>
<div class="language-html codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-html codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">template</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">div</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">id</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">app</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">dashboard</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">:uppy</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">uppy</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">:plugins</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">['Webcam']</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">div</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">template</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">script</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">	</span><span class="token script language-javascript keyword module" style="color:#00009f">import</span><span class="token script language-javascript"> </span><span class="token script language-javascript imports punctuation" style="color:#393A34">{</span><span class="token script language-javascript imports"> </span><span class="token script language-javascript imports maybe-class-name">Dashboard</span><span class="token script language-javascript imports"> </span><span class="token script language-javascript imports punctuation" style="color:#393A34">}</span><span class="token script language-javascript"> </span><span class="token script language-javascript keyword module" style="color:#00009f">from</span><span class="token script language-javascript"> </span><span class="token script language-javascript string" style="color:#e3116c">'@uppy/vue'</span><span class="token script language-javascript punctuation" style="color:#393A34">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">	</span><span class="token script language-javascript keyword module" style="color:#00009f">import</span><span class="token script language-javascript"> </span><span class="token script language-javascript string" style="color:#e3116c">'@uppy/core/css/style.css'</span><span class="token script language-javascript punctuation" style="color:#393A34">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">	</span><span class="token script language-javascript keyword module" style="color:#00009f">import</span><span class="token script language-javascript"> </span><span class="token script language-javascript string" style="color:#e3116c">'@uppy/dashboard/css/style.css'</span><span class="token script language-javascript punctuation" style="color:#393A34">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">	</span><span class="token script language-javascript keyword module" style="color:#00009f">import</span><span class="token script language-javascript"> </span><span class="token script language-javascript imports maybe-class-name">Uppy</span><span class="token script language-javascript"> </span><span class="token script language-javascript keyword module" style="color:#00009f">from</span><span class="token script language-javascript"> </span><span class="token script language-javascript string" style="color:#e3116c">'@uppy/core'</span><span class="token script language-javascript punctuation" style="color:#393A34">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">	</span><span class="token script language-javascript keyword module" style="color:#00009f">import</span><span class="token script language-javascript"> </span><span class="token script language-javascript imports maybe-class-name">Webcam</span><span class="token script language-javascript"> </span><span class="token script language-javascript keyword module" style="color:#00009f">from</span><span class="token script language-javascript"> </span><span class="token script language-javascript string" style="color:#e3116c">'@uppy/webcam'</span><span class="token script language-javascript punctuation" style="color:#393A34">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">	</span><span class="token script language-javascript keyword module" style="color:#00009f">export</span><span class="token script language-javascript"> </span><span class="token script language-javascript keyword module" style="color:#00009f">default</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:#393A34">{</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">		</span><span class="token script language-javascript literal-property property" style="color:#36acaa">name</span><span class="token script language-javascript operator" style="color:#393A34">:</span><span class="token script language-javascript"> </span><span class="token script language-javascript string" style="color:#e3116c">'App'</span><span class="token script language-javascript punctuation" style="color:#393A34">,</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">		</span><span class="token script language-javascript literal-property property" style="color:#36acaa">components</span><span class="token script language-javascript operator" style="color:#393A34">:</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:#393A34">{</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">			</span><span class="token script language-javascript maybe-class-name">Dashboard</span><span class="token script language-javascript punctuation" style="color:#393A34">,</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">		</span><span class="token script language-javascript punctuation" style="color:#393A34">}</span><span class="token script language-javascript punctuation" style="color:#393A34">,</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">		</span><span class="token script language-javascript literal-property property" style="color:#36acaa">computed</span><span class="token script language-javascript operator" style="color:#393A34">:</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:#393A34">{</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">			</span><span class="token script language-javascript function-variable function" style="color:#d73a49">uppy</span><span class="token script language-javascript operator" style="color:#393A34">:</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:#393A34">(</span><span class="token script language-javascript punctuation" style="color:#393A34">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript arrow operator" style="color:#393A34">=&gt;</span><span class="token script language-javascript"> </span><span class="token script language-javascript keyword" style="color:#00009f">new</span><span class="token script language-javascript"> </span><span class="token script language-javascript class-name">Uppy</span><span class="token script language-javascript punctuation" style="color:#393A34">(</span><span class="token script language-javascript punctuation" style="color:#393A34">)</span><span class="token script language-javascript punctuation" style="color:#393A34">.</span><span class="token script language-javascript method function property-access" style="color:#d73a49">use</span><span class="token script language-javascript punctuation" style="color:#393A34">(</span><span class="token script language-javascript maybe-class-name">Webcam</span><span class="token script language-javascript punctuation" style="color:#393A34">)</span><span class="token script language-javascript punctuation" style="color:#393A34">,</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">		</span><span class="token script language-javascript punctuation" style="color:#393A34">}</span><span class="token script language-javascript punctuation" style="color:#393A34">,</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">		</span><span class="token script language-javascript function" style="color:#d73a49">beforeDestroy</span><span class="token script language-javascript punctuation" style="color:#393A34">(</span><span class="token script language-javascript punctuation" style="color:#393A34">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:#393A34">{</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">			</span><span class="token script language-javascript keyword" style="color:#00009f">this</span><span class="token script language-javascript punctuation" style="color:#393A34">.</span><span class="token script language-javascript property-access">uppy</span><span class="token script language-javascript punctuation" style="color:#393A34">.</span><span class="token script language-javascript method function property-access" style="color:#d73a49">close</span><span class="token script language-javascript punctuation" style="color:#393A34">(</span><span class="token script language-javascript punctuation" style="color:#393A34">)</span><span class="token script language-javascript punctuation" style="color:#393A34">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">		</span><span class="token script language-javascript punctuation" style="color:#393A34">}</span><span class="token script language-javascript punctuation" style="color:#393A34">,</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">	</span><span class="token script language-javascript punctuation" style="color:#393A34">}</span><span class="token script language-javascript punctuation" style="color:#393A34">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript"></span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">script</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><br></span></code></pre></div></div>
<p><code>@uppy/vue</code> package provides components for all of the most popular Uppy UI
plugins:</p>
<ul>
<li class=""><code>&lt;dashboard /&gt;</code> - renders an inline <code>@uppy/dashboard</code></li>
<li class=""><code>&lt;dashboard-modal /&gt;</code> - renders a <code>@uppy/dashboard</code> modal</li>
<li class=""><code>&lt;drag-drop /&gt;</code> - renders a <code>@uppy/drag-drop</code> area</li>
<li class=""><code>&lt;progress-bar /&gt;</code> - renders a <code>@uppy/progress-bar</code></li>
<li class=""><code>&lt;status-bar /&gt;</code> - renders a <code>@uppy/status-bar</code></li>
</ul>
<p>Check out the <a href="https://uppy.io/docs/vue/" target="_blank" rel="noopener noreferrer" class="">Vue documentation</a> for details.</p>
<p>Angular and Svelte support is on our list next.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="cloud-file-restrictions">Cloud File Restrictions<a href="https://uppy.io/blog/2020/11/1.23/#cloud-file-restrictions" class="hash-link" aria-label="Direct link to Cloud File Restrictions" title="Direct link to Cloud File Restrictions" translate="no">​</a></h2>
<p>Dropbox, Instagram, Google Drive and other cloud providers now immediately gray
out files that won’t pass Uppy restrictions set by the developer:</p>
<p><img decoding="async" loading="lazy" alt="Google Drive restrictions example" src="https://uppy.io/assets/images/restrictions-1-735ee426cdbcb47e91c24ddfc162b03e.jpg" width="1400" height="707" class="img_ev3q"></p>
<p><img decoding="async" loading="lazy" alt="Instagram restrictions example" src="https://uppy.io/assets/images/restrictions-2-bd022c92c78fe86eed007875030d4cfc.jpg" width="1400" height="809" class="img_ev3q"></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="done-button">Done Button<a href="https://uppy.io/blog/2020/11/1.23/#done-button" class="hash-link" aria-label="Direct link to Done Button" title="Direct link to Done Button" translate="no">​</a></h2>
<p>If <a href="https://uppy.io/docs/dashboard/#doneButtonHandler" target="_blank" rel="noopener noreferrer" class=""><code>doneButtonHandler</code></a>
option is passed to the Status Bar plugin, it will render a “Done” button in
place of Pause/Resume/Cancel buttons, once the upload/encoding is done. The
behaviour of the “Done” button is defined by the handler function — can be used
to close file picker modals or clear the upload state.</p>
<img decoding="async" loading="lazy" class="border img_ev3q" alt="Status Bar Done button UI" src="https://uppy.io/img/blog/1.23/status-bar-done.jpg">
<p>By default the Done button will close the Dashboard modal window and reset Uppy
state.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="box-file-provider">Box File Provider<a href="https://uppy.io/blog/2020/11/1.23/#box-file-provider" class="hash-link" aria-label="Direct link to Box File Provider" title="Direct link to Box File Provider" translate="no">​</a></h2>
<p>Thanks to <a href="https://github.com/cartfisk" target="_blank" rel="noopener noreferrer" class="">@cartfisk</a> Uppy gains support for Box
file service. You can add try it out by doing <code>npm install @uppy/box</code> and
upgrading <code>@uppy/companion</code> to the latest version.</p>
<p>Bragging moment, here’s what
<a href="https://github.com/transloadit/uppy/pull/2549#issue-491527196" target="_blank" rel="noopener noreferrer" class="">@cartfish had to say about Uppy</a>:</p>
<blockquote>
<p>Hope this is useful! Hats off to the awesome React integration, easy
contribution workflow, helpful docs, and readable, clean code. 10/10.</p>
</blockquote>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="image-editor-optional-buttons">Image Editor Optional Buttons<a href="https://uppy.io/blog/2020/11/1.23/#image-editor-optional-buttons" class="hash-link" aria-label="Direct link to Image Editor Optional Buttons" title="Direct link to Image Editor Optional Buttons" translate="no">​</a></h2>
<p><code>@uppy/image-editor</code> plugin got support for optional buttons — you can choose to
hide or show just the ones you need — crop, rotate, square, landscape, etc.
Thanks, <a href="https://github.com/lamartire" target="_blank" rel="noopener noreferrer" class="">@lamartire</a>!</p>
<p>See new <a href="https://uppy.io/docs/image-editor/#Options" target="_blank" rel="noopener noreferrer" class=""><code>actions</code></a> property in the
Image Editor’s options.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="misc">Misc<a href="https://uppy.io/blog/2020/11/1.23/#misc" class="hash-link" aria-label="Direct link to Misc" title="Direct link to Misc" translate="no">​</a></h2>
<ul>
<li class="">@uppy/robodog: Update addTransloaditPlugin.js to include missing configurable
Transloadit plugin options (#2612 / @ethanwillis)</li>
<li class="">@uppy/core: add <code>uppy.opts.infoTimeout</code> (#2619 / @arturi)</li>
<li class="">@uppy/onedrive: fix OneDrive for Business (#2536 / @szh)</li>
<li class="">@uppy/image-editor: show “edit” icon even when metaFields are not specified
(#2614 / @arturi)</li>
<li class="">test: added test DeepFrozenStore with deepFreeze to try and assert that state
in not mutated anywhere by accident (#2607 / @arturi)</li>
<li class="">build: switched from Travis to GitHub Actions (@goto-bus-stop)</li>
</ul>
<p>As always, you can find the full list of changes and package versions, as well
as future plans, in our
<a href="https://github.com/transloadit/uppy/blob/master/CHANGELOG.md" target="_blank" rel="noopener noreferrer" class="">changelog</a>.</p>]]></content>
        <author>
            <name>Artur Paikin</name>
            <email>artur@transloadit.com</email>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[🎃 Uppy 1.22: Webcam camera source, Unsplash and maxTotalFileSize]]></title>
        <id>https://uppy.io/blog/2020/10/1.22/</id>
        <link href="https://uppy.io/blog/2020/10/1.22/"/>
        <updated>2020-10-30T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Uppy 1.22 (the spooky Halloween edition) adds a new Unsplash provider, Webcam]]></summary>
        <content type="html"><![CDATA[<p>Uppy 1.22 (the spooky Halloween edition) adds a new Unsplash provider, Webcam
camera selector dropdown and a <code>maxTotalFileSize</code> restriction.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="webcam-camera-source">Webcam Camera Source<a href="https://uppy.io/blog/2020/10/1.22/#webcam-camera-source" class="hash-link" aria-label="Direct link to Webcam Camera Source" title="Direct link to Webcam Camera Source" translate="no">​</a></h2>
<p>If your device has multiple cameras, you can now choose which one you want to
use (if you allow the
<a href="https://uppy.io/docs/webcam/#showVideoSourceDropdown-false" target="_blank" rel="noopener noreferrer" class="">showVideoSourceDropdown</a>
option).</p>
<p><img decoding="async" loading="lazy" src="https://uppy.io/assets/images/webcam-dropdown-full-584bce2c916573ac10d1aa02ad93311a.png" width="1000" height="731" class="img_ev3q"></p>
<p><img decoding="async" loading="lazy" src="https://uppy.io/assets/images/webcam-dropdown-short-1a53f0ea55f1e41124aae73369ffe840.png" width="1000" height="205" class="img_ev3q"></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="maxtotalfilesize">maxTotalFileSize<a href="https://uppy.io/blog/2020/10/1.22/#maxtotalfilesize" class="hash-link" aria-label="Direct link to maxTotalFileSize" title="Direct link to maxTotalFileSize" translate="no">​</a></h2>
<p>New <code>maxTotalFileSize</code> restriction makes sure the total size of all the files
selected isn’t over a certain threshold:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> uppy </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">Uppy</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token literal-property property" style="color:#36acaa">restrictions</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token literal-property property" style="color:#36acaa">maxTotalFileSize</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">104857600</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="unsplash">Unsplash<a href="https://uppy.io/blog/2020/10/1.22/#unsplash" class="hash-link" aria-label="Direct link to Unsplash" title="Direct link to Unsplash" translate="no">​</a></h2>
<p><a href="https://unsplash.com/" target="_blank" rel="noopener noreferrer" class="">Unsplash</a> is a popular website dedicated to sharing free
stock photography. With a new Uppy plugin you can search for “trains”, “New
York” or “Harry Potter” images and upload them where needed:</p>
<p><img decoding="async" loading="lazy" src="https://uppy.io/assets/images/unsplash-50a5909bde76cf3cb4eb212882870567.jpg" width="1000" height="735" class="img_ev3q"></p>
<p>The plugin launches in beta, but you can already try it out by installing
<code>@uppy/unsplash</code> and upgrading <code>@uppy/companion</code> to the latest version (2.1.0).</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="misc">Misc<a href="https://uppy.io/blog/2020/10/1.22/#misc" class="hash-link" aria-label="Direct link to Misc" title="Direct link to Misc" translate="no">​</a></h2>
<ul>
<li class="">@uppy/companion: add option to hide welcome and metrics (#2521 / @szh)</li>
<li class="">@uppy/companion: add more test cases to companion tests (#2585 /
@ifedapoolarewaju)</li>
<li class="">@uppy/companion: upgrade prometheus (fixes memory leak) (#2600 /
@ifedapoolarewaju)</li>
<li class="">@uppy/locales: update th_TH.js (#2571 / @dogrocker)</li>
<li class="">@uppy/locales: add missing camera translations to de_DE (#2574 / @ferdiusa)</li>
<li class="">@uppy/locales: update el_GR.js with more proper wording for Drag'n'Drop (#2578
/ @aalepis)</li>
<li class="">@uppy/core: add postprocess progress when upload success (#2535 / @mejiaej)</li>
<li class="">@uppy/react: Webpack5: Fix react imports (#2589 / @olemoign)</li>
<li class="">@uppy/thumbnail-generator: Add support for png thumbnails (#2603 / @SxDx)</li>
<li class="">website: mobile issues fixes + compact Companion migration table (#2593 /
@nqst)</li>
</ul>
<p>As always, you can find the full list of changes and package versions, as well
as future plans, in our
<a href="https://github.com/transloadit/uppy/blob/master/CHANGELOG.md" target="_blank" rel="noopener noreferrer" class="">changelog</a>.</p>]]></content>
        <author>
            <name>Artur Paikin</name>
            <email>artur@transloadit.com</email>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[Companion 2.0 is here]]></title>
        <id>https://uppy.io/blog/2020/09/companion-2.0/</id>
        <link href="https://uppy.io/blog/2020/09/companion-2.0/"/>
        <updated>2020-09-09T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[We are happy to announce version 2.0 of Companion! 🎉 After maintaining and]]></summary>
        <content type="html"><![CDATA[<p>We are happy to announce version 2.0 of Companion! 🎉 After maintaining and
improving the 1.x series for over a year, we're now releasing a major version
bump on the Companion package. The drive on this release is mainly towards
fixing some terminology inconsistencies and aligning with Node.js LTS to ease
the maintenance burden.</p>
<p>So what are the changes you can expect with Companion 2.0?</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="node--v10">Node &gt;= v10<a href="https://uppy.io/blog/2020/09/companion-2.0/#node--v10" class="hash-link" aria-label="Direct link to Node >= v10" title="Direct link to Node >= v10" translate="no">​</a></h2>
<p>Node.js 8.x has reached end-of-life. Consequently, Companion 2.0 has dropped
support for Node.js 6.x and Node.js 8.x, and now requires that you run at least
Node.js 10.20.1.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="renamed-provider-options">Renamed provider options<a href="https://uppy.io/blog/2020/09/companion-2.0/#renamed-provider-options" class="hash-link" aria-label="Direct link to Renamed provider options" title="Direct link to Renamed provider options" translate="no">​</a></h2>
<p>Pre 2.0, there were inconsistencies in relation to the provider names. In some
places, the Google Drive provider was referred to as <em>google</em> (e.g., in
<code>providerOptions</code>) while in some other places, it was referred to as <em>drive</em>
(e.g., the server endpoints <code>/drive/list</code>). Companion 2.0 now consistently uses
the name <em>drive</em> everywhere. Similarly, the OneDrive provider was made to have
the consistent name <em>onedrive</em>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="changed-redirect-uris">Changed Redirect URIs<a href="https://uppy.io/blog/2020/09/companion-2.0/#changed-redirect-uris" class="hash-link" aria-label="Direct link to Changed Redirect URIs" title="Direct link to Changed Redirect URIs" translate="no">​</a></h2>
<p>On the topic of consistent naming, we have also made some changes to the
redirect URIs supplied during the OAuth process. For example, in the case of
Google Drive, the form of the old redirect URI was
<code>https://mycompanionwebsite.tld/connect/google/callback</code>. In Companion 2.0, this
is now changed to <code>https://mycompanionwebsite.tld/drive/redirect</code>. This is a
Breaking Change: you will need to make the corresponding changes to your
redirect URIs on your Providers' API Dashboards.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="compatibility-with-uppy-1x-client">Compatibility with Uppy 1.x client<a href="https://uppy.io/blog/2020/09/companion-2.0/#compatibility-with-uppy-1x-client" class="hash-link" aria-label="Direct link to Compatibility with Uppy 1.x client" title="Direct link to Compatibility with Uppy 1.x client" translate="no">​</a></h2>
<p>Companion 2.0 is compatible with any Uppy 1.x version, so you don't have to
worry about upgrading your Uppy client installations when you upgrade Companion
on your server.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="will-companion-v1-still-receive-updates">Will Companion v1 still receive updates?<a href="https://uppy.io/blog/2020/09/companion-2.0/#will-companion-v1-still-receive-updates" class="hash-link" aria-label="Direct link to Will Companion v1 still receive updates?" title="Direct link to Will Companion v1 still receive updates?" translate="no">​</a></h2>
<p>Companion 1.x will continue to receive security patches until March 1, 2021.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="migrating-from-companion-1x-to-2x">Migrating from Companion 1.x to 2.x<a href="https://uppy.io/blog/2020/09/companion-2.0/#migrating-from-companion-1x-to-2x" class="hash-link" aria-label="Direct link to Migrating from Companion 1.x to 2.x" title="Direct link to Migrating from Companion 1.x to 2.x" translate="no">​</a></h2>
<p>Given the breaking changes, we've created a
<a href="https://uppy.io/docs/companion/#Migrating-v1-to-v2" target="_blank" rel="noopener noreferrer" class="">migration tutorial for upgrading from Companion v1 to v2</a>.</p>]]></content>
        <author>
            <name>Ifedapo Olarewaju</name>
            <email>ifedapo@transloadit.com</email>
        </author>
    </entry>
</feed>