- render () {
- const file = this.props.files[this.props.fileCardFor]
- const showEditButton = this.props.canEditFile(file)
+
+ )
}
-
-export default FileCard
diff --git a/packages/@uppy/provider-views/package.json b/packages/@uppy/provider-views/package.json
index ec4f4f3b0..92ec8111b 100644
--- a/packages/@uppy/provider-views/package.json
+++ b/packages/@uppy/provider-views/package.json
@@ -22,6 +22,7 @@
"dependencies": {
"@uppy/utils": "workspace:^",
"classnames": "^2.2.6",
+ "nanoid": "^4.0.0",
"preact": "^10.5.13"
},
"peerDependencies": {
diff --git a/packages/@uppy/provider-views/src/Browser.jsx b/packages/@uppy/provider-views/src/Browser.jsx
index 6c0e1b97e..06d2bf7bd 100644
--- a/packages/@uppy/provider-views/src/Browser.jsx
+++ b/packages/@uppy/provider-views/src/Browser.jsx
@@ -1,10 +1,8 @@
import { h } from 'preact'
import classNames from 'classnames'
-
import remoteFileObjToLocal from '@uppy/utils/lib/remoteFileObjToLocal'
-
-import Filter from './Filter.jsx'
+import SearchFilterInput from './SearchFilterInput.jsx'
import FooterActions from './FooterActions.jsx'
import Item from './Item/index.jsx'
@@ -26,13 +24,19 @@ function Browser (props) {
showTitles,
i18n,
validateRestrictions,
- showFilter,
- filterQuery,
- filterInput,
+ isLoading,
+ showSearchFilter,
+ search,
+ searchTerm,
+ clearSearch,
+ searchOnInput,
+ searchInputLabel,
+ clearSearchLabel,
getNextFolder,
cancel,
done,
columns,
+ noResultsLabel,
} = props
const selected = currentSelection.length
@@ -44,30 +48,46 @@ function Browser (props) {
`uppy-ProviderBrowser-viewType--${viewType}`,
)}
>
-
-
- {headerComponent}
+ {headerComponent && (
+
-
+ )}
- {showFilter && (
-
+ {showSearchFilter && (
+
+
+
)}
{(() => {
+ if (isLoading) {
+ return (
+
+ {i18n('loading')}
+
+ )
+ }
+
if (!folders.length && !files.length) {
return (
- {i18n('noFilesFound')}
+ {noResultsLabel}
)
}
diff --git a/packages/@uppy/provider-views/src/Filter.jsx b/packages/@uppy/provider-views/src/Filter.jsx
deleted file mode 100644
index b6ae191e9..000000000
--- a/packages/@uppy/provider-views/src/Filter.jsx
+++ /dev/null
@@ -1,51 +0,0 @@
-import { h, Component } from 'preact'
-
-export default class Filter extends Component {
- constructor (props) {
- super(props)
- this.preventEnterPress = this.preventEnterPress.bind(this)
- }
-
- // eslint-disable-next-line class-methods-use-this
- preventEnterPress (ev) {
- if (ev.keyCode === 13) {
- ev.stopPropagation()
- ev.preventDefault()
- }
- }
-
- render () {
- const { i18n, filterInput, filterQuery } = this.props
- return (
-
-
filterQuery(e)}
- value={filterInput}
- />
-
- {filterInput && (
-
- )}
-
- )
- }
-}
diff --git a/packages/@uppy/provider-views/src/Item/components/GridLi.jsx b/packages/@uppy/provider-views/src/Item/components/GridLi.jsx
index 482352cec..9bebc55e3 100644
--- a/packages/@uppy/provider-views/src/Item/components/GridLi.jsx
+++ b/packages/@uppy/provider-views/src/Item/components/GridLi.jsx
@@ -1,4 +1,5 @@
import { h } from 'preact'
+import classNames from 'classnames'
function GridListItem (props) {
const {
@@ -15,6 +16,13 @@ function GridListItem (props) {
children,
} = props
+ const checkBoxClassName = classNames(
+ 'uppy-u-reset',
+ 'uppy-ProviderBrowserItem-checkbox',
+ 'uppy-ProviderBrowserItem-checkbox--grid',
+ { 'uppy-ProviderBrowserItem-checkbox--is-checked': isChecked },
+ )
+
return (
-
- {itemIconEl}
-
- {showTitles && title}
-
- {children}
-
+ {itemIconEl}
+ {showTitles && title}
+ {children}
)
diff --git a/packages/@uppy/provider-views/src/Item/index.jsx b/packages/@uppy/provider-views/src/Item/index.jsx
index f3c05cc21..4648bafe6 100644
--- a/packages/@uppy/provider-views/src/Item/index.jsx
+++ b/packages/@uppy/provider-views/src/Item/index.jsx
@@ -42,6 +42,7 @@ export default (props) => {
target="_blank"
rel="noopener noreferrer"
className="uppy-ProviderBrowserItem-author"
+ tabIndex="-1"
>
{author.name}
diff --git a/packages/@uppy/provider-views/src/ProviderView/ProviderView.jsx b/packages/@uppy/provider-views/src/ProviderView/ProviderView.jsx
index e7af61f24..8d97cd093 100644
--- a/packages/@uppy/provider-views/src/ProviderView/ProviderView.jsx
+++ b/packages/@uppy/provider-views/src/ProviderView/ProviderView.jsx
@@ -53,6 +53,7 @@ export default class ProviderView extends View {
// Logic
this.filterQuery = this.filterQuery.bind(this)
+ this.clearFilter = this.clearFilter.bind(this)
this.getFolder = this.getFolder.bind(this)
this.getNextFolder = this.getNextFolder.bind(this)
this.logout = this.logout.bind(this)
@@ -162,9 +163,12 @@ export default class ProviderView extends View {
}).catch(this.handleError)
}
- filterQuery (e) {
- const state = this.plugin.getPluginState()
- this.plugin.setPluginState({ ...state, filterInput: e ? e.target.value : '' })
+ filterQuery (input) {
+ this.plugin.setPluginState({ filterInput: input })
+ }
+
+ clearFilter () {
+ this.plugin.setPluginState({ filterInput: '' })
}
/**
@@ -329,6 +333,7 @@ export default class ProviderView extends View {
render (state, viewOptions = {}) {
const { authenticated, didFirstRender } = this.plugin.getPluginState()
+ const { i18n } = this.plugin.uppy
if (!didFirstRender) {
this.preFirstRender()
@@ -346,7 +351,7 @@ export default class ProviderView extends View {
title: this.plugin.title,
logout: this.logout,
username: this.username,
- i18n: this.plugin.uppy.i18n,
+ i18n,
}
const browserProps = {
@@ -360,7 +365,17 @@ export default class ProviderView extends View {
getNextFolder: this.getNextFolder,
getFolder: this.getFolder,
filterItems: this.sharedHandler.filterItems,
- filterQuery: this.filterQuery,
+
+ // For SearchFilterInput component
+ showSearchFilter: targetViewOptions.showFilter,
+ search: this.filterQuery,
+ clearSearch: this.clearFilter,
+ searchTerm: filterInput,
+ searchOnInput: true,
+ searchInputLabel: i18n('filter'),
+ clearSearchLabel: i18n('resetFilter'),
+
+ noResultsLabel: i18n('noFilesFound'),
logout: this.logout,
handleScroll: this.handleScroll,
listAllFiles: this.listAllFiles,
@@ -370,7 +385,6 @@ export default class ProviderView extends View {
title: this.plugin.title,
viewType: targetViewOptions.viewType,
showTitles: targetViewOptions.showTitles,
- showFilter: targetViewOptions.showFilter,
showBreadcrumbs: targetViewOptions.showBreadcrumbs,
pluginIcon: this.plugin.icon,
i18n: this.plugin.uppy.i18n,
diff --git a/packages/@uppy/provider-views/src/SearchFilterInput.jsx b/packages/@uppy/provider-views/src/SearchFilterInput.jsx
new file mode 100644
index 000000000..5177660d5
--- /dev/null
+++ b/packages/@uppy/provider-views/src/SearchFilterInput.jsx
@@ -0,0 +1,101 @@
+import { h, Fragment } from 'preact'
+import { useEffect, useState, useCallback } from 'preact/hooks'
+import { nanoid } from 'nanoid/non-secure'
+// import debounce from 'lodash.debounce'
+
+export default function SearchFilterInput (props) {
+ const {
+ search,
+ searchOnInput,
+ searchTerm,
+ showButton,
+ inputLabel,
+ clearSearchLabel,
+ buttonLabel,
+ clearSearch,
+ inputClassName,
+ buttonCSSClassName,
+ } = props
+ const [searchText, setSearchText] = useState(searchTerm ?? '')
+ // const debouncedSearch = debounce((q) => search(q), 1000)
+
+ const validateAndSearch = useCallback((ev) => {
+ ev.preventDefault()
+ search(searchText)
+ }, [search, searchText])
+
+ const handleInput = useCallback((ev) => {
+ const inputValue = ev.target.value
+ setSearchText(inputValue)
+ if (searchOnInput) search(inputValue)
+ }, [setSearchText, searchOnInput, search])
+
+ const handleReset = () => {
+ setSearchText('')
+ if (clearSearch) clearSearch()
+ }
+
+ const [form] = useState(() => {
+ const formEl = document.createElement('form')
+ formEl.setAttribute('tabindex', '-1')
+ formEl.id = nanoid()
+ return formEl
+ })
+
+ useEffect(() => {
+ document.body.appendChild(form)
+ form.addEventListener('submit', validateAndSearch)
+ return () => {
+ form.removeEventListener('submit', validateAndSearch)
+ document.body.removeChild(form)
+ }
+ }, [form, validateAndSearch])
+
+ return (
+
+
+ {
+ !showButton && (
+
+ )
+ }
+ {
+ !showButton && searchText && (
+
+ )
+ }
+ {
+ showButton && (
+
+ )
+ }
+
+ )
+}
diff --git a/packages/@uppy/provider-views/src/SearchProviderView/Header.jsx b/packages/@uppy/provider-views/src/SearchProviderView/Header.jsx
deleted file mode 100644
index 0a84d9a60..000000000
--- a/packages/@uppy/provider-views/src/SearchProviderView/Header.jsx
+++ /dev/null
@@ -1,32 +0,0 @@
-import { h } from 'preact'
-
-const SUBMIT_KEY = 13
-
-export default (props) => {
- const { searchTerm, i18n, search } = props
-
- const handleKeyPress = (ev) => {
- if (ev.keyCode === SUBMIT_KEY) {
- ev.stopPropagation()
- ev.preventDefault()
- search(ev.target.value)
- }
- }
-
- return (
-
- )
-}
diff --git a/packages/@uppy/provider-views/src/SearchProviderView/InputView.jsx b/packages/@uppy/provider-views/src/SearchProviderView/InputView.jsx
deleted file mode 100644
index 92ea0672b..000000000
--- a/packages/@uppy/provider-views/src/SearchProviderView/InputView.jsx
+++ /dev/null
@@ -1,36 +0,0 @@
-import { h } from 'preact'
-
-export default ({ i18n, search }) => {
- let input
- const validateAndSearch = () => {
- if (input.value) {
- search(input.value)
- }
- }
- const handleKeyPress = (ev) => {
- if (ev.keyCode === 13) {
- validateAndSearch()
- }
- }
-
- return (
-
- { input = input_ }}
- data-uppy-super-focusable
- />
-
-
- )
-}
diff --git a/packages/@uppy/provider-views/src/SearchProviderView/SearchProviderView.jsx b/packages/@uppy/provider-views/src/SearchProviderView/SearchProviderView.jsx
index cf8b1d8eb..ad07679f6 100644
--- a/packages/@uppy/provider-views/src/SearchProviderView/SearchProviderView.jsx
+++ b/packages/@uppy/provider-views/src/SearchProviderView/SearchProviderView.jsx
@@ -1,16 +1,15 @@
import { h } from 'preact'
-import SearchInput from './InputView.jsx'
+import SearchFilterInput from '../SearchFilterInput.jsx'
import Browser from '../Browser.jsx'
-import LoaderView from '../Loader.jsx'
-import Header from './Header.jsx'
import CloseWrapper from '../CloseWrapper.js'
import View from '../View.js'
import packageJson from '../../package.json'
/**
- * Class to easily generate generic views for Provider plugins
+ * SearchProviderView, used for Unsplash and future image search providers.
+ * Extends generic View, shared with regular providers like Google Drive and Instagram.
*/
export default class SearchProviderView extends View {
static VERSION = packageJson.version
@@ -35,7 +34,8 @@ export default class SearchProviderView extends View {
// Logic
this.search = this.search.bind(this)
- this.triggerSearchInput = this.triggerSearchInput.bind(this)
+ this.clearSearch = this.clearSearch.bind(this)
+ this.resetPluginState = this.resetPluginState.bind(this)
this.addFile = this.addFile.bind(this)
this.handleScroll = this.handleScroll.bind(this)
this.donePicking = this.donePicking.bind(this)
@@ -43,8 +43,7 @@ export default class SearchProviderView extends View {
// Visual
this.render = this.render.bind(this)
- // Set default state for the plugin
- this.plugin.setPluginState({
+ this.defaultState = {
isInputMode: true,
files: [],
folders: [],
@@ -52,7 +51,10 @@ export default class SearchProviderView extends View {
filterInput: '',
currentSelection: [],
searchTerm: null,
- })
+ }
+
+ // Set default state for the plugin
+ this.plugin.setPluginState(this.defaultState)
}
// eslint-disable-next-line class-methods-use-this
@@ -60,19 +62,15 @@ export default class SearchProviderView extends View {
// Nothing.
}
- clearSelection () {
- this.plugin.setPluginState({
- currentSelection: [],
- isInputMode: true,
- files: [],
- searchTerm: null,
- })
+ resetPluginState () {
+ this.plugin.setPluginState(this.defaultState)
}
#updateFilesAndInputMode (res, files) {
this.nextPageQuery = res.nextPageQuery
res.items.forEach((item) => { files.push(item) })
this.plugin.setPluginState({
+ currentSelection: [],
isInputMode: false,
files,
searchTerm: res.searchedFor,
@@ -95,8 +93,12 @@ export default class SearchProviderView extends View {
)
}
- triggerSearchInput () {
- this.plugin.setPluginState({ isInputMode: true })
+ clearSearch () {
+ this.plugin.setPluginState({
+ currentSelection: [],
+ files: [],
+ searchTerm: null,
+ })
}
async handleScroll (event) {
@@ -123,12 +125,13 @@ export default class SearchProviderView extends View {
const promises = currentSelection.map((file) => this.addFile(file))
this.sharedHandler.loaderWrapper(Promise.all(promises), () => {
- this.clearSelection()
+ this.resetPluginState()
}, () => {})
}
render (state, viewOptions = {}) {
const { didFirstRender, isInputMode, searchTerm } = this.plugin.getPluginState()
+ const { i18n } = this.plugin.uppy
if (!didFirstRender) {
this.preFirstRender()
@@ -148,43 +151,49 @@ export default class SearchProviderView extends View {
handleScroll: this.handleScroll,
done: this.donePicking,
cancel: this.cancelPicking,
- headerComponent: Header({
- search: this.search,
- i18n: this.plugin.uppy.i18n,
- searchTerm,
- }),
+
+ // For SearchFilterInput component
+ showSearchFilter: targetViewOptions.showFilter,
+ search: this.search,
+ clearSearch: this.clearSearch,
+ searchTerm,
+ searchOnInput: false,
+ searchInputLabel: i18n('search'),
+ clearSearchLabel: i18n('resetSearch'),
+
+ noResultsLabel: i18n('noSearchResults'),
title: this.plugin.title,
viewType: targetViewOptions.viewType,
showTitles: targetViewOptions.showTitles,
showFilter: targetViewOptions.showFilter,
+ isLoading: loading,
showBreadcrumbs: targetViewOptions.showBreadcrumbs,
pluginIcon: this.plugin.icon,
- i18n: this.plugin.uppy.i18n,
+ i18n,
uppyFiles: this.plugin.uppy.getFiles(),
validateRestrictions: (...args) => this.plugin.uppy.validateRestrictions(...args),
}
- if (loading) {
- return (
-
-
-
- )
- }
-
if (isInputMode) {
return (
-
-
+
+
+
+
)
}
return (
-
+
{/* eslint-disable-next-line react/jsx-props-no-spreading */}
diff --git a/packages/@uppy/provider-views/src/style.scss b/packages/@uppy/provider-views/src/style.scss
index 66cbfcf88..4ec4a06cd 100644
--- a/packages/@uppy/provider-views/src/style.scss
+++ b/packages/@uppy/provider-views/src/style.scss
@@ -203,79 +203,21 @@
vertical-align: middle;
}
-// Filter
-
-.uppy-ProviderBrowser-filter {
- position: relative;
- display: flex;
- align-items: center;
- width: 100%;
- height: 30px;
- margin-top: 10px;
- margin-bottom: 5px;
- background-color: $white;
-
- [data-uppy-theme="dark"] & {
- background-color: $gray-900;
- }
-}
-
-.uppy-ProviderBrowser-filterIcon {
- position: absolute;
- z-index: $zIndex-3;
- width: 12px;
- height: 12px;
- color: $gray-400;
- inset-inline-start: 16px;
-}
-
-.uppy-ProviderBrowser-filterInput {
- z-index: $zIndex-2;
- width: 100%;
- height: 30px;
- margin: 0 8px;
- font-size: 12px;
- font-family: $font-family-base;
- line-height: 1.4;
- background-color: transparent;
- border: 0;
- border-radius: 4px;
- outline: 0;
- padding-inline-start: 27px;
-
- [data-uppy-theme="dark"] & {
- color: $gray-200;
- background-color: $gray-900;
- }
-}
-
-.uppy-ProviderBrowser-filterInput:focus {
- background-color: $gray-100;
- outline: 0;
-
- [data-uppy-theme="dark"] & {
- background-color: $gray-800;
- }
-}
-
-.uppy-ProviderBrowser-filterInput::placeholder {
- color: $gray-500;
- opacity: 1;
-}
-
// Search
-.uppy-ProviderBrowser-search {
+.uppy-ProviderBrowser-searchFilter {
position: relative;
display: flex;
align-items: center;
width: 100%;
height: 30px;
- margin-top: 2px;
- margin-bottom: 2px;
+ padding-left: 8px;
+ padding-right: 8px;
+ margin-top: 15px;
+ margin-bottom: 15px;
}
-.uppy-ProviderBrowser-searchInput {
+.uppy-ProviderBrowser-searchFilterInput {
z-index: $zIndex-2;
width: 100%;
height: 30px;
@@ -287,37 +229,63 @@
border-radius: 4px;
outline: 0;
padding-inline-start: 30px;
+ padding-inline-end: 30px;
color: $gray-800;
+ &::-webkit-search-cancel-button {
+ display: none;
+ }
+
[data-uppy-theme="dark"] & {
color: $gray-200;
background-color: $gray-900;
}
}
-.uppy-ProviderBrowser-searchInput:focus {
+.uppy-ProviderBrowser-searchFilterInput:focus {
background-color: $gray-300;
- outline: 0;
+ border: 0;
[data-uppy-theme="dark"] & {
background-color: $gray-800;
}
}
-.uppy-ProviderBrowser-searchIcon {
+.uppy-ProviderBrowser-searchFilterIcon {
position: absolute;
z-index: $zIndex-3;
width: 12px;
height: 12px;
color: $gray-600;
- inset-inline-start: 10px;
+ inset-inline-start: 16px;
}
-.uppy-ProviderBrowser-searchInput::placeholder {
+.uppy-ProviderBrowser-searchFilterInput::placeholder {
color: $gray-500;
opacity: 1;
}
+.uppy-ProviderBrowser-searchFilterReset {
+ @include blue-border-focus;
+ border-radius: 3px;
+ position: absolute;
+ z-index: $zIndex-3;
+ width: 22px;
+ height: 22px;
+ padding: 6px;
+ color: $gray-500;
+ cursor: pointer;
+ inset-inline-end: 16px;
+
+ &:hover {
+ color: $gray-600;
+ }
+
+ svg {
+ vertical-align: text-top;
+ }
+}
+
.uppy-ProviderBrowser-userLogout {
@include highlight-focus;
// for focus
diff --git a/packages/@uppy/provider-views/src/style/uppy-ProviderBrowser-viewType--grid.scss b/packages/@uppy/provider-views/src/style/uppy-ProviderBrowser-viewType--grid.scss
index e7ae5170f..45ca75190 100644
--- a/packages/@uppy/provider-views/src/style/uppy-ProviderBrowser-viewType--grid.scss
+++ b/packages/@uppy/provider-views/src/style/uppy-ProviderBrowser-viewType--grid.scss
@@ -81,30 +81,6 @@
text-align: center;
border-radius: 4px;
- .uppy.uppy-ProviderBrowserItem-inner-relative {
- position: relative;
- }
-
- .uppy-ProviderBrowserItem-author {
- position: absolute;
- display: none;
- bottom: 0;
- left: 0;
- width: 100%;
- background: rgba(black, 0.3);
- color: white;
- font-weight: 500;
- font-size: 12px;
- margin: 0;
- padding: 5px;
- text-decoration: none;
-
- &:hover {
- background: rgba(black, 0.4);
- text-decoration: underline;
- }
- }
-
// Always show the author on touch devices
// https://www.w3.org/TR/mediaqueries-4/#hover
@media (hover: none) {
@@ -125,6 +101,26 @@
}
}
+ .uppy-ProviderBrowserItem-author {
+ position: absolute;
+ display: none;
+ bottom: 0;
+ left: 0;
+ width: 100%;
+ background: rgba(black, 0.3);
+ color: white;
+ font-weight: 500;
+ font-size: 12px;
+ margin: 0;
+ padding: 5px;
+ text-decoration: none;
+
+ &:hover {
+ background: rgba(black, 0.4);
+ text-decoration: underline;
+ }
+ }
+
// Checkbox
.uppy-ProviderBrowserItem-checkbox {
position: absolute;
diff --git a/packages/@uppy/provider-views/src/style/uppy-SearchProvider-input.scss b/packages/@uppy/provider-views/src/style/uppy-SearchProvider-input.scss
index a7e0ea4d7..10c588b87 100644
--- a/packages/@uppy/provider-views/src/style/uppy-SearchProvider-input.scss
+++ b/packages/@uppy/provider-views/src/style/uppy-SearchProvider-input.scss
@@ -21,6 +21,10 @@
.uppy-size--md & {
margin-bottom: 20px;
}
+
+ &::-webkit-search-cancel-button {
+ display: none;
+ }
}
.uppy-SearchProvider-searchButton {
diff --git a/packages/@uppy/unsplash/src/Unsplash.jsx b/packages/@uppy/unsplash/src/Unsplash.jsx
index fdf79f8bc..2dafe0990 100644
--- a/packages/@uppy/unsplash/src/Unsplash.jsx
+++ b/packages/@uppy/unsplash/src/Unsplash.jsx
@@ -47,6 +47,7 @@ export default class Unsplash extends UIPlugin {
this.view = new SearchProviderViews(this, {
provider: this.provider,
viewType: 'unsplash',
+ showFilter: true,
})
const { target } = this.opts
diff --git a/packages/@uppy/url/package.json b/packages/@uppy/url/package.json
index 6df1a1e33..32f6cb14c 100644
--- a/packages/@uppy/url/package.json
+++ b/packages/@uppy/url/package.json
@@ -25,6 +25,7 @@
"dependencies": {
"@uppy/companion-client": "workspace:^",
"@uppy/utils": "workspace:^",
+ "nanoid": "^4.0.0",
"preact": "^10.5.13"
},
"peerDependencies": {
diff --git a/packages/@uppy/url/src/UrlUI.jsx b/packages/@uppy/url/src/UrlUI.jsx
index 039b10dac..f1edf16bb 100644
--- a/packages/@uppy/url/src/UrlUI.jsx
+++ b/packages/@uppy/url/src/UrlUI.jsx
@@ -1,17 +1,27 @@
import { h, Component } from 'preact'
+import { nanoid } from 'nanoid/non-secure'
class UrlUI extends Component {
+ form = document.createElement('form')
+
+ constructor (props) {
+ super(props)
+ this.form.id = nanoid()
+ }
+
componentDidMount () {
this.input.value = ''
+ this.form.addEventListener('submit', this.#handleSubmit)
+ document.body.appendChild(this.form)
}
- #handleKeyPress = (ev) => {
- if (ev.keyCode === 13) {
- this.#handleSubmit()
- }
+ componentWillUnmount () {
+ this.form.removeEventListener('submit', this.#handleSubmit)
+ document.body.removeChild(this.form)
}
- #handleSubmit = () => {
+ #handleSubmit = (ev) => {
+ ev.preventDefault()
const { addFile } = this.props
const preparedValue = this.input.value.trim()
addFile(preparedValue)
@@ -26,14 +36,14 @@ class UrlUI extends Component {
type="text"
aria-label={i18n('enterUrlToImport')}
placeholder={i18n('enterUrlToImport')}
- onKeyUp={this.#handleKeyPress}
ref={(input) => { this.input = input }}
data-uppy-super-focusable
+ form={this.form.id}
/>
diff --git a/yarn.lock b/yarn.lock
index f2c6a8fe3..f376926b7 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -8954,6 +8954,7 @@ __metadata:
dependencies:
"@uppy/utils": "workspace:^"
classnames: ^2.2.6
+ nanoid: ^4.0.0
preact: ^10.5.13
peerDependencies:
"@uppy/core": "workspace:^"
@@ -9162,6 +9163,7 @@ __metadata:
dependencies:
"@uppy/companion-client": "workspace:^"
"@uppy/utils": "workspace:^"
+ nanoid: ^4.0.0
preact: ^10.5.13
peerDependencies:
"@uppy/core": "workspace:^"
@@ -27599,8 +27601,8 @@ __metadata:
"preact@patch:preact@npm:10.10.0#.yarn/patches/preact-npm-10.10.0-dd04de05e8.patch::locator=%40uppy-dev%2Fbuild%40workspace%3A.":
version: 10.10.0
- resolution: "preact@patch:preact@npm%3A10.10.0#.yarn/patches/preact-npm-10.10.0-dd04de05e8.patch::version=10.10.0&hash=a66388&locator=%40uppy-dev%2Fbuild%40workspace%3A."
- checksum: f610d7f206e8cd71739023c3dbeae13fcaf9f9e6488295e2ae28f71c615d216c9b1d8b2fa2d616a629276948ee58a8d16fe77b8b7bc2e8d4aee1101e3336fe2b
+ resolution: "preact@patch:preact@npm%3A10.10.0#.yarn/patches/preact-npm-10.10.0-dd04de05e8.patch::version=10.10.0&hash=e9860f&locator=%40uppy-dev%2Fbuild%40workspace%3A."
+ checksum: 8fefec89ac68b5bd8fc0c4f1672beb7585c878663f9e929de85ff0f5c6d12dc49d9910867d7c9ef2bc449ec09512241574e08cb0546bdb3a34600891db5e0a96
languageName: node
linkType: hard