Merge branch 'main' into main

This commit is contained in:
Andrei Costescu 2026-07-09 17:10:28 +03:00 committed by GitHub
commit a9212ca9f8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
690 changed files with 19215 additions and 14278 deletions

View file

@ -0,0 +1,41 @@
---
"@uppy/angular": patch
"@uppy/google-photos-picker": patch
"@uppy/google-drive-picker": patch
"@uppy/thumbnail-generator": patch
"@uppy/golden-retriever": patch
"@uppy/image-generator": patch
"@uppy/remote-sources": patch
"@uppy/screen-capture": patch
"@uppy/google-drive": patch
"@uppy/image-editor": patch
"@uppy/transloadit": patch
"@uppy/components": patch
"@uppy/compressor": patch
"@uppy/status-bar": patch
"@uppy/xhr-upload": patch
"@uppy/companion": patch
"@uppy/dashboard": patch
"@uppy/drag-drop": patch
"@uppy/facebook": patch
"@uppy/onedrive": patch
"@uppy/unsplash": patch
"@uppy/dropbox": patch
"@uppy/locales": patch
"@uppy/aws-s3": patch
"@uppy/svelte": patch
"@uppy/webcam": patch
"@uppy/webdav": patch
"@uppy/audio": patch
"@uppy/react": patch
"@uppy/core": patch
"@uppy/form": patch
"@uppy/zoom": patch
"@uppy/box": patch
"@uppy/tus": patch
"@uppy/url": patch
"@uppy/vue": patch
"uppy": patch
---
Bump shared runtime dependencies (preact, nanoid, lodash, classnames, shallow-equal, pretty-bytes, p-queue, tus-js-client, @transloadit/types @transloadit/prettier-bytes v1, is-mobile, exifr, compressorjs, rxjs, tslib). Also includes type-only fixes in `@uppy/companion`'s `jwt.ts` and `request.ts` to track `@types/jsonwebtoken` v9 and `@types/node`.

View file

@ -0,0 +1,5 @@
---
"@uppy/locales": patch
---
@uppy/locales: update Norwegian Bokmål (nb_NO)

View file

@ -0,0 +1,5 @@
---
"@uppy/dashboard": patch
---
fix "My Device" button in dashboard, it now respects the fileManagerSelectionType.

View file

@ -0,0 +1,9 @@
---
"@uppy/components": major
"@uppy/companion": major
"uppy": major
"@uppy/transloadit": minor
"@uppy/locales": minor
---
Remove @uppy/instagram references from all the packages

View file

@ -0,0 +1,5 @@
---
"@uppy/aws-s3": patch
---
Improve type

View file

@ -0,0 +1,5 @@
---
"@uppy/core": patch
---
uploadRemoteFile() now queues token request and websocket request as a single job in the request queue.

View file

@ -0,0 +1,5 @@
---
"@uppy/transloadit": minor
---
Add assemblyStatus and lastAssemblyStatus to transloadit's plugin state

View file

@ -0,0 +1,5 @@
---
"@uppy/tus": major
---
@uppy/tus: don't abort the request on error, so the server response (status + body) is forwarded to the `upload-error` event and `file.response` instead of being reset to status `0`.

View file

@ -0,0 +1,8 @@
---
"@uppy/core": major
"@uppy/companion": major
---
Send token using websocket instead of window.opener.
Breaking in `@uppy/core` because it needs newest version of Companion in order to work.
Breaking in `@uppy/companion` because `companion.socket()` now requires `companionOptions` to be passed as the second argument.

View file

@ -0,0 +1,5 @@
---
"@uppy/transloadit": patch
---
emit updated AssemblyState in 'transloadit:assembly-cancelled' event

View file

@ -0,0 +1,5 @@
---
"@uppy/companion": patch
---
Reduce companion redis key timeouts to 10 min - In theory this shouldn't affect users

View file

@ -0,0 +1,5 @@
---
"@uppy/angular": minor
---
Add support for Angular 21

View file

@ -0,0 +1,5 @@
---
"@uppy/companion": major
---
Upgrade to express 5 - Companion no longer works when used as a middleware with Express 4.

View file

@ -0,0 +1,5 @@
---
"@uppy/companion": patch
---
Port Companion to TypeScript. Not really a breaking change but there could be some unexpected breakage.

View file

@ -44,9 +44,6 @@ COMPANION_DROPBOX_SECRET=***
COMPANION_GOOGLE_KEY=***
COMPANION_GOOGLE_SECRET=***
COMPANION_INSTAGRAM_KEY=***
COMPANION_INSTAGRAM_SECRET=***
COMPANION_FACEBOOK_KEY=***
COMPANION_FACEBOOK_SECRET=***

View file

@ -57,7 +57,7 @@ This is not needed for changing existing components.
## Companion
If youd like to work on features that the basic development version of Uppy
doesnt support, such as Uppy integrations with Instagram/Google Drive/Facebook
doesnt support, such as Uppy integrations with Google Drive/Facebook
etc., you need to set up your `.env` file (copy the contents of `.env.example`
and adjust them based on what you need to work on), and run:
@ -78,7 +78,7 @@ when files are changed.
### How the Authentication and Token mechanism works
This section describes how Authentication works between Companion and Providers.
While this behaviour is the same for all Providers (Dropbox, Instagram, Google
While this behaviour is the same for all Providers (Dropbox, Google
Drive, etc.), we are going to be referring to Dropbox in place of any Provider
throughout this section.

View file

@ -42,7 +42,7 @@ jobs:
node-version: lts/*
- name: Install dependencies
run:
corepack yarn install
corepack yarn install --immutable
env:
# https://docs.cypress.io/guides/references/advanced-installation#Skipping-installation
CYPRESS_INSTALL_BINARY: 0

View file

@ -47,7 +47,7 @@ jobs:
node-version: ${{matrix.node-version}}
- name: Install dependencies
run:
corepack yarn install
corepack yarn install --immutable
- name: Install Playwright Browsers
run: corepack yarn workspace @uppy/dashboard playwright install --with-deps
- name: Build
@ -84,7 +84,7 @@ jobs:
node-version: lts/*
- name: Install dependencies
run:
corepack yarn install
corepack yarn install --immutable
- run: corepack yarn run typecheck
lint_js:

View file

@ -38,35 +38,49 @@ jobs:
path: /tmp/companion-${{ github.sha }}.tar.gz
docker:
name: DockerHub
runs-on: ubuntu-latest
env:
DOCKER_BUILDKIT: 0
COMPOSE_DOCKER_CLI_BUILD: 0
name: DockerHub (${{ matrix.platform }})
strategy:
matrix:
include:
- runner: ubuntu-24.04
platform: linux/amd64
platform_tag: amd64
- runner: ubuntu-24.04-arm
platform: linux/arm64
platform_tag: arm64
runs-on: ${{ matrix.runner }}
steps:
- name: Checkout sources
uses: actions/checkout@v6
- name: Docker meta
id: docker_meta
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0
with:
images: transloadit/companion
tags: |
type=edge
type=raw,value=latest,enable=false
- uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0
- uses: docker/setup-buildx-action@v3
- uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f
- name: Log in to DockerHub
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
with:
username: ${{secrets.DOCKER_USERNAME}}
password: ${{secrets.DOCKER_PASSWORD}}
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
with:
push: true
context: .
platforms: linux/amd64,linux/arm64
platforms: ${{ matrix.platform }}
file: Dockerfile
tags: ${{ steps.docker_meta.outputs.tags }}
labels: ${{ steps.docker_meta.outputs.labels }}
tags: transloadit/companion:edge-${{ matrix.platform_tag }}
docker-manifest:
name: DockerHub manifest
needs: docker
runs-on: ubuntu-latest
steps:
- uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f
- name: Log in to DockerHub
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Publish edge manifest
run: |
docker buildx imagetools create \
--tag transloadit/companion:edge \
transloadit/companion:edge-amd64 \
transloadit/companion:edge-arm64

View file

@ -30,18 +30,6 @@ jobs:
steps:
- name: Checkout sources
uses: actions/checkout@v6
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run:
echo "dir=$(corepack yarn config get cacheFolder)" >> $GITHUB_OUTPUT
- uses: actions/cache@v5
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Install Node.js
uses: actions/setup-node@v6
with:

View file

@ -50,7 +50,7 @@ jobs:
- name: Create Release Pull Request or Publish
id: changesets
uses: changesets/action@v1
uses: changesets/action@a45c4d594aa4e2c509dc14a9f2b3b67ba3780d0d
with:
version: corepack yarn run version
publish: corepack yarn run release
@ -102,7 +102,7 @@ jobs:
# set latest tag for default branch
type=raw,value=latest,enable=true
- uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0
- uses: docker/setup-buildx-action@v3
- uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f
- name: Log in to DockerHub
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
with:

View file

@ -9,5 +9,6 @@ initScope: uppy
nodeLinker: node-modules
npmPublishAccess: public
npmMinimalAgeGate: 2880
npmPublishAccess: public

View file

@ -83,7 +83,7 @@ inline into the page. This, and many more configuration options can be found
here: <https://uppy.io/docs/dashboard/>.
Uppy has many more Plugins besides Xhr and the Dashboard. For example, you can
enable Webcam, Instagram, or video encoding support. Note that for some Plugins,
enable Webcam or video encoding support. Note that for some Plugins,
you will need to run a server side component called: Companion. Those plugins
are marked with a (c) symbol. Alternatively, you can sign up for a free
Transloadit account. Transloadit runs Companion for you, tusd servers to handle

View file

@ -46,7 +46,7 @@ yarn workspace @uppy/[package-name] build
- **Uppy Core** (`@uppy/core`) - Main class that manages plugins, state, and events
- **Plugins** - Modular components for different functionalities:
- **UI Plugins**: Dashboard, Drag & Drop, File Input, Webcam, etc.
- **Provider Plugins**: Google Drive, Dropbox, Instagram, etc. (require Companion)
- **Provider Plugins**: Google Drive, Dropbox, etc. (require Companion)
- **Uploader Plugins**: Tus (resumable), XHR Upload, AWS S3, etc.
- **Utility Plugins**: Golden Retriever (recovery), Thumbnail Generator, etc.

View file

@ -1,4 +1,4 @@
FROM node:22.18.0-alpine AS build
FROM node:22.22.1-alpine AS build
# Create link to node on amd64 so that corepack can find it
RUN if [ "$(uname -m)" == "aarch64" ]; then mkdir -p /usr/local/sbin/ && ln -s /usr/local/bin/node /usr/local/sbin/node; fi
@ -7,28 +7,29 @@ WORKDIR /app
COPY . /app/
RUN apk --update add --virtual native-dep \
make gcc g++ python3 libgcc libstdc++ git && \
# Ensure corepack is enabled (available in official Node images) and
# install only build-time dependencies using a named virtual package.
RUN corepack enable && \
apk add --no-cache --virtual .build-deps build-base python3 libgcc libstdc++ git && \
(cd /app && corepack yarn workspaces focus @uppy/companion) && \
apk del native-dep
apk del .build-deps
RUN cd /app && corepack yarn workspace @uppy/companion build
# Now remove all non-prod dependencies for a leaner image
RUN cd /app && corepack yarn workspaces focus @uppy/companion --production
FROM node:22.18.0-alpine
FROM node:22.22.1-alpine
WORKDIR /app
# copy required files from build stage.
COPY --from=build /app/packages/@uppy/companion/bin /app/bin
COPY --from=build /app/packages/@uppy/companion/lib /app/lib
COPY --from=build /app/packages/@uppy/companion/dist /app/dist
COPY --from=build /app/packages/@uppy/companion/package.json /app/package.json
COPY --from=build /app/packages/@uppy/companion/node_modules /app/node_modules
ENV PATH "${PATH}:/app/node_modules/.bin"
CMD ["node","/app/bin/companion"]
CMD ["node","/app/dist/bin/companion.js"]
# This can be overruled later
EXPOSE 3020

View file

@ -7,7 +7,7 @@ with any application. Its fast, has a comprehensible API and lets you worry
about more important problems than building a file uploader.
- **Fetch** files from local disk, remote URLs, Google Drive, Dropbox, Box,
Instagram or snap and record selfies with a camera
or snap and record selfies with a camera
- **Preview** and edit metadata with a nice interface
- **Upload** to the final destination, optionally process/encode
@ -82,7 +82,7 @@ For the supported frameworks (except Angular) Uppy offers three ways to build us
- Lightweight, modular plugin-based architecture, light on dependencies :zap:
- Resumable file uploads via the open [tus](https://tus.io/) standard, so large
uploads survive network hiccups
- Supports picking files from: Webcam, Dropbox, Box, Google Drive, Instagram,
- Supports picking files from: Webcam, Dropbox, Box, Google Drive,
bypassing the users device where possible, syncing between servers directly
via [@uppy/companion](https://uppy.io/docs/companion)
- Works great with file encoding and processing backends, such as
@ -140,7 +140,7 @@ CDN. In that case `Uppy` will attach itself to the global `window.Uppy` object.
- [Uppy](https://uppy.io/docs/uppy/) — full list of options, methods and events
- [Companion](https://uppy.io/docs/companion/) — setting up and running a
Companion instance, which adds support for Instagram, Dropbox, Box, Google
Companion instance, which adds support for Dropbox, Box, Google
Drive and remote URLs
- [React](https://uppy.io/docs/react/) — components to integrate Uppy UI plugins
with React apps
@ -153,7 +153,7 @@ CDN. In that case `Uppy` will attach itself to the global `window.Uppy` object.
- [`Dashboard`](https://uppy.io/docs/dashboard/) — universal UI with previews,
progress bars, metadata editor and all the cool stuff. Required for most UI
plugins like Webcam and Instagram
plugins like Webcam
- Headless components ([react](https://uppy.io/docs/react/), [svelte](https://uppy.io/docs/svelte/), [vue](https://uppy.io/docs/vue/))
### Sources
@ -166,8 +166,6 @@ CDN. In that case `Uppy` will attach itself to the global `window.Uppy` object.
Google Drive
- ⓒ [`Dropbox`](https://uppy.io/docs/dropbox/) — import files from Dropbox
- ⓒ [`Box`](https://uppy.io/docs/box/) — import files from Box
- ⓒ [`Instagram`](https://uppy.io/docs/instagram/) — import images and videos
from Instagram
- ⓒ [`Facebook`](https://uppy.io/docs/facebook/) — import images and videos from
Facebook
- ⓒ [`OneDrive`](https://uppy.io/docs/onedrive/) — import files from Microsoft
@ -222,7 +220,7 @@ cases, the file input leaves some to be desired:
- Uppy supports editing meta information before uploading.
- Uppy allows cropping images before uploading.
- Theres the situation where people are using their mobile devices and want to
upload on the go, but they have their picture on Instagram, files in Dropbox
upload on the go, but they have files in Dropbox
or a plain file URL from anywhere on the open web. Uppy allows to pick files
from those and push it to the destination without downloading it to your
mobile device first.
@ -272,7 +270,7 @@ If you want resumability with the Tus plugin, use
[one of the tus server implementations](https://tus.io/implementations.html) 👌🏼
And youll need [`@uppy/companion`](https://uppy.io/docs/companion) if youd
like your users to be able to pick files from Instagram, Google Drive, Dropbox
like your users to be able to pick files from Google Drive, Dropbox
or via direct URLs (with more services coming).
## Contributions are welcome

View file

@ -1,5 +1,5 @@
{
"$schema": "https://biomejs.dev/schemas/2.0.5/schema.json",
"$schema": "https://biomejs.dev/schemas/2.4.15/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
@ -14,10 +14,11 @@
"bin/**",
"e2e/**",
"private/**",
"!packages/**/{dist,lib}/**",
"!packages/**/{dist,lib}",
"!node_modules",
"!.svelte-kit",
"!packages/@uppy/components/src/input.css"
"!packages/@uppy/components/src/input.css",
"!examples/angular/**/*.html"
]
},
"formatter": {
@ -25,20 +26,11 @@
"indentStyle": "space",
"formatWithErrors": true
},
"html": {
"experimentalFullSupportEnabled": true
},
"linter": {
"enabled": true,
"includes": [
"packages/**",
"examples/**",
"scripts/**",
"private/**",
"!packages/**/{dist,lib}/**",
"!node_modules",
"!.svelte-kit",
"!packages/@uppy/components/src/input.css",
"!**/*.vue",
"!**/*.svelte"
],
"rules": {
"recommended": true,
"suspicious": {
@ -48,22 +40,23 @@
"useExhaustiveDependencies": "error",
"useHookAtTopLevel": "error",
"noUnusedFunctionParameters": "off",
"noUnusedImports": "error",
"noUnusedPrivateClassMembers": "error",
"noUnusedVariables": {
"level": "error",
"options": {
"ignoreRestSiblings": true
}
}
},
"noNestedComponentDefinitions": "error",
"noReactPropAssignments": "error"
},
"style": {
"noNonNullAssertion": "off"
},
"a11y": {
"noSvgWithoutTitle": "off"
},
"nursery": {
"noNestedComponentDefinitions": "error",
"noReactPropAssign": "error"
"noSvgWithoutTitle": "off",
"useSemanticElements": "off"
}
}
},
@ -80,5 +73,36 @@
"organizeImports": "on"
}
}
}
},
"overrides": [
{
"includes": ["packages/@uppy/companion/**"],
"linter": {
"rules": {
"complexity": {
"useLiteralKeys": "off"
}
}
}
},
{
"includes": ["**/*.vue", "**/*.svelte", "packages/@uppy/vue/**/*.ts"],
"linter": {
"rules": {
"correctness": {
"useHookAtTopLevel": "off",
"useExhaustiveDependencies": "off"
}
}
}
},
{
"includes": ["examples/nextjs/**/*.css"],
"css": {
"parser": {
"tailwindDirectives": true
}
}
}
]
}

View file

@ -1,5 +1,5 @@
<!doctype html>
<html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />

View file

@ -11,11 +11,11 @@
},
"devDependencies": {
"@uppy/companion": "workspace:*",
"body-parser": "^1.20.4",
"body-parser": "^2.2.2",
"cookie-parser": "^1.4.7",
"cors": "^2.8.5",
"dotenv": "^16.0.1",
"express": "^4.22.0",
"dotenv": "^17.4.2",
"express": "^5.2.1",
"express-session": "^1.17.3",
"npm-run-all": "^4.1.5",
"vite": "^7.1.11"

View file

@ -66,4 +66,4 @@ const server = app.listen(3020, () => {
console.log('listening on port 3020')
})
companion.socket(server)
companion.socket(server, options)

View file

@ -15,6 +15,6 @@
"@aws-sdk/s3-request-presigner": "^3.338.0",
"body-parser": "^1.20.4",
"dotenv": "^16.0.0",
"express": "^4.22.0"
"express": "^5.2.1"
}
}

View file

@ -1,5 +1,5 @@
<!doctype html>
<html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Uppy AWS upload example</title>
@ -24,7 +24,8 @@
</footer>
<noscript>You need JavaScript to run this example.</noscript>
<script type="module">
import { Uppy, Dashboard, AwsS3 } from './uppy.min.mjs'
import { AwsS3, Dashboard, Uppy } from './uppy.min.mjs'
function onUploadComplete(result) {
console.log(
'Upload complete! Weve uploaded these files:',
@ -34,7 +35,7 @@
function onUploadSuccess(file, data) {
console.log(
'Upload success! Weve uploaded this file:',
file.meta['name'],
file.meta.name,
)
}
{

View file

@ -1,5 +1,5 @@
<!doctype html>
<html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Uppy AWS upload example</title>
@ -16,7 +16,8 @@
</footer>
<noscript>You need JavaScript to run this example.</noscript>
<script type="module">
import { Uppy, Dashboard, AwsS3 } from './uppy.min.mjs'
import { AwsS3, Dashboard, Uppy } from './uppy.min.mjs'
/**
* This generator transforms a deep object into URL-encodable pairs
* to work with `URLSearchParams` on the client and `body-parser` on the server.
@ -258,7 +259,7 @@
uppy.on('upload-success', (file, data) => {
console.log(
'Upload success! Weve uploaded this file:',
file.meta['name'],
file.meta.name,
)
})
}

View file

@ -1,5 +1,5 @@
<!doctype html>
<html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />

View file

@ -11,14 +11,14 @@
</head>
<body>
<noscript>You need JavaScript enabled for this example to work.</noscript>
<button id="uppyModalOpener">Open Modal</button>
<button type="button" id="uppyModalOpener">Open Modal</button>
<script type="module">
import {
Uppy,
Dashboard,
Webcam,
Tus,
Uppy,
Webcam,
} from 'https://releases.transloadit.com/uppy/v4.18.0/uppy.min.mjs'
const uppy = new Uppy({ debug: true, autoProceed: false })

View file

@ -1,8 +1,12 @@
/** @jsx h */
import { getAllowedHosts, Provider, tokenStorage } from '@uppy/companion-client'
import { UIPlugin } from '@uppy/core'
import { ProviderViews } from '@uppy/provider-views'
import {
getAllowedHosts,
Provider,
tokenStorage,
} from '@uppy/core/companion-client'
import { ProviderViews } from '@uppy/core/provider-views'
const defaultOptions = {}

View file

@ -1,5 +1,5 @@
<!doctype html>
<html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />

View file

@ -4,22 +4,20 @@
"private": true,
"type": "module",
"dependencies": {
"@uppy/companion-client": "workspace:*",
"@uppy/core": "workspace:*",
"@uppy/dashboard": "workspace:*",
"@uppy/google-drive": "workspace:*",
"@uppy/provider-views": "workspace:*",
"@uppy/tus": "workspace:*",
"preact": "^10.26.10"
"preact": "^10.29.2"
},
"engines": {
"node": ">=18.0.0"
},
"devDependencies": {
"@uppy/companion": "workspace:*",
"body-parser": "^1.20.4",
"dotenv": "^16.0.1",
"express": "^4.22.0",
"body-parser": "^2.2.2",
"dotenv": "^17.4.2",
"express": "^5.2.1",
"express-session": "^1.15.6",
"npm-run-all": "^4.1.2",
"vite": "^7.1.11"

View file

@ -1,5 +1,5 @@
<!doctype html>
<html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />

View file

@ -10,8 +10,8 @@
"cors": "^2.8.5"
},
"devDependencies": {
"dotenv": "^16.0.1",
"express": "^4.22.0",
"dotenv": "^17.4.2",
"express": "^5.2.1",
"vite": "^7.1.11"
},
"private": true,

View file

@ -10,23 +10,18 @@
/>
</head>
<body>
<button id="uppyModalOpener">Open Modal</button>
<button type="button" id="uppyModalOpener">Open Modal</button>
<noscript>This web page requires JavaScript to work properly.</noscript>
<script type="module">
import {
Uppy,
Dashboard,
Instagram,
GoogleDrive,
Tus,
Uppy,
} from 'https://releases.transloadit.com/uppy/v4.18.0/uppy.min.mjs'
const uppy = new Uppy({ debug: true, autoProceed: false })
.use(Dashboard, { trigger: '#uppyModalOpener' })
.use(Instagram, {
target: Dashboard,
companionUrl: 'http://localhost:3020',
})
.use(GoogleDrive, {
target: Dashboard,
companionUrl: 'http://localhost:3020',

View file

@ -4,7 +4,7 @@
"dependencies": {
"@uppy/companion": "workspace:*",
"body-parser": "^1.20.4",
"express": "^4.22.0",
"express": "^5.2.1",
"express-session": "^1.15.6",
"light-server": "^2.4.0"
},

View file

@ -32,10 +32,6 @@ const companionOptions = {
key: 'your google key',
secret: 'your google secret',
},
instagram: {
key: 'your instagram key',
secret: 'your instagram secret',
},
dropbox: {
key: 'your dropbox key',
secret: 'your dropbox secret',
@ -75,7 +71,7 @@ app.use((err, req, res) => {
res.status(500).json({ message: err.message, error: err })
})
companion.socket(app.listen(3020))
companion.socket(app.listen(3020), companionOptions)
console.log('Welcome to Companion!')
console.log(`Listening on http://0.0.0.0:${3020}`)

View file

@ -9,7 +9,7 @@
"serve": "vite preview"
},
"dependencies": {
"@tailwindcss/vite": "^4.1.11",
"@tailwindcss/vite": "^4.3.0",
"@uppy/core": "workspace:*",
"@uppy/react": "workspace:*",
"@uppy/remote-sources": "workspace:*",
@ -23,13 +23,14 @@
"devDependencies": {
"@types/react": "^19.0.10",
"@types/react-dom": "^19.0.4",
"@vitejs/plugin-react": "^4.6.0",
"@vitest/browser": "^3.2.4",
"@vitejs/plugin-react": "^6.0.2",
"@vitest/browser": "^4.1.6",
"@vitest/browser-playwright": "^4.1.6",
"msw": "^2.10.4",
"playwright": "1.57.0",
"playwright": "1.60.0",
"typescript": "^5.7.3",
"vite": "^7.1.11",
"vitest": "^3.2.4",
"vitest-browser-react": "^1.0.0"
"vite": "^8.0.14",
"vitest": "^4.1.6",
"vitest-browser-react": "^2.2.0"
}
}

View file

@ -1,4 +1,4 @@
/** biome-ignore-all lint/nursery/useUniqueElementIds: it's fine */
/** biome-ignore-all lint/correctness/useUniqueElementIds: it's fine */
import Uppy, { type UppyFile } from '@uppy/core'
import UppyImageEditor from '@uppy/image-editor'
import {

View file

@ -1,6 +1,6 @@
import { userEvent } from '@vitest/browser/context'
import { setupWorker } from 'msw/browser'
import { afterAll, beforeAll, describe, expect, test } from 'vitest'
import { userEvent } from 'vitest/browser'
import { render } from 'vitest-browser-react'
import { tusHandlers } from '../../shared/tusHandlers.js'
import App from '../src/App'
@ -19,7 +19,7 @@ const createMockFile = (name: string, type: string, size: number = 1024) => {
describe('App', () => {
test('renders all main sections and upload button is initially disabled', async () => {
const screen = render(<App />)
const screen = await render(<App />)
await expect.element(screen.getByText('With list')).toBeInTheDocument()
await expect.element(screen.getByText('With grid')).toBeInTheDocument()
@ -33,7 +33,7 @@ describe('App', () => {
})
test('can add and remove files and upload', async () => {
const screen = render(<App />)
const screen = await render(<App />)
const fileInput = document.getElementById(
'uppy-dropzone-file-input-uppy',
@ -59,7 +59,7 @@ describe('App', () => {
describe('ScreenCapture Component', () => {
test('renders with title, control buttons, and close functionality works', async () => {
const screen = render(<App />)
const screen = await render(<App />)
await screen.getByRole('button', { name: 'Screen Capture' }).click()
@ -90,7 +90,7 @@ describe('ScreenCapture Component', () => {
describe('Webcam Component', () => {
test('renders with title, control buttons, and close functionality works', async () => {
const screen = render(<App />)
const screen = await render(<App />)
await screen.getByRole('button', { name: 'Webcam' }).click()
@ -121,7 +121,7 @@ describe('Webcam Component', () => {
describe('RemoteSource Component', () => {
test('renders login button and login interaction works', async () => {
const screen = render(<App />)
const screen = await render(<App />)
await screen.getByRole('button', { name: 'Dropbox' }).click()
@ -129,6 +129,5 @@ describe('RemoteSource Component', () => {
await expect.element(loginButton).toBeInTheDocument()
await loginButton.click()
await expect.element(loginButton).toBeInTheDocument()
})
})

View file

@ -6,4 +6,11 @@ import { defineConfig } from 'vite'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react(), tailwindcss()],
// @vitejs/plugin-react v5+ no longer adds react/react-dom to resolve.dedupe
// automatically (it did in v4). Without deduping, the linked @uppy/react
// workspace pulls in a second React copy, causing "Invalid hook call".
// https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/CHANGELOG.md (v5.0.0)
resolve: {
dedupe: ['react', 'react-dom'],
},
})

View file

@ -1,13 +1,21 @@
import tailwindcss from '@tailwindcss/vite'
import react from '@vitejs/plugin-react'
import { playwright } from '@vitest/browser-playwright'
import { defineConfig } from 'vitest/config'
export default defineConfig({
plugins: [react(), tailwindcss()],
// @vitejs/plugin-react v5+ no longer adds react/react-dom to resolve.dedupe
// automatically (it did in v4). Without deduping, the linked @uppy/react
// workspace pulls in a second React copy, causing "Invalid hook call".
// https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/CHANGELOG.md (v5.0.0)
resolve: {
dedupe: ['react', 'react-dom'],
},
test: {
browser: {
enabled: true,
provider: 'playwright',
provider: playwright(),
instances: [{ browser: 'chromium' }],
},
},

View file

@ -20,14 +20,14 @@
"@uppy/transloadit": "workspace:*",
"@uppy/tus": "workspace:*",
"@uppy/xhr-upload": "workspace:*",
"express": "^4.22.0",
"express": "^5.2.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router": "^7.12.0"
},
"devDependencies": {
"@react-router/dev": "^7.12.0",
"@types/express": "^4.17.20",
"@types/express": "^5.0.6",
"@types/react": "^18.2.20",
"@types/react-dom": "^18.2.7",
"tsx": "^4.0.0",

View file

@ -41,7 +41,9 @@ async function startServer() {
// TUS upload endpoints (before React Router)
app.all('/api/upload/tus', (req, res) => tusServer.handle(req, res))
app.all('/api/upload/tus/*', (req, res) => tusServer.handle(req, res))
app.all('/api/upload/tus/{*splat}', (req, res) =>
tusServer.handle(req, res),
)
// Handle Chrome DevTools requests silently
app.get('/.well-known/appspecific/com.chrome.devtools.json', (req, res) => {
@ -49,7 +51,7 @@ async function startServer() {
})
// React Router handles all other routes
app.all('*', reactRouterHandler)
app.all('/{*splat}', reactRouterHandler)
const port = process.env.PORT || 3000
const server = app.listen(port, () => {

View file

@ -26,15 +26,16 @@
"@sveltejs/kit": "^2.49.5",
"@sveltejs/vite-plugin-svelte": "^5.0.0",
"@tailwindcss/vite": "^4.0.0",
"@vitest/browser": "^3.2.4",
"@vitest/browser": "^4.1.6",
"@vitest/browser-playwright": "^4.1.6",
"msw": "^2.10.4",
"playwright": "1.57.0",
"playwright": "1.60.0",
"svelte": "^5.0.0",
"svelte-check": "^4.0.0",
"tailwindcss": "^4.0.0",
"typescript": "^5.0.0",
"vite": "^6.2.5",
"vitest": "^3.2.4",
"vitest-browser-svelte": "^1.0.0"
"vitest": "^4.1.6",
"vitest-browser-svelte": "^2.1.1"
}
}

View file

@ -20,7 +20,7 @@ const { getButtonProps, getInputProps: getFileInputProps } = useFileInput()
>
<div class="flex items-center justify-center gap-4">
<input {...getFileInputProps()} class="hidden" />
<button
<button type="button"
{...getButtonProps()}
class="hover:bg-gray-100 transition-colors p-2 rounded-md flex flex-col items-center gap-2 text-sm"
>
@ -30,7 +30,7 @@ const { getButtonProps, getInputProps: getFileInputProps } = useFileInput()
Device
</button>
<button
<button type="button"
onclick={() => openModal('webcam')}
class="hover:bg-gray-100 transition-colors p-2 rounded-md flex flex-col items-center gap-2 text-sm"
>
@ -40,7 +40,7 @@ const { getButtonProps, getInputProps: getFileInputProps } = useFileInput()
Webcam
</button>
<button
<button type="button"
onclick={() => openModal('screen-capture')}
class="hover:bg-gray-100 transition-colors p-2 rounded-md flex flex-col items-center gap-2 text-sm"
>
@ -50,7 +50,7 @@ const { getButtonProps, getInputProps: getFileInputProps } = useFileInput()
Screen Capture
</button>
<button
<button type="button"
onclick={() => openModal('dropbox')}
class="hover:bg-gray-100 transition-colors p-2 rounded-md flex flex-col items-center gap-2 text-sm"
>

View file

@ -24,6 +24,7 @@ const editor = useImageEditor({ file })
</div>
<div class="mb-4">
<!-- biome-ignore lint/a11y/useAltText: alt is provided via editor.getImageProps() spread -->
<img
class="w-full max-h-[400px] rounded-lg border-2"
{...editor.getImageProps()}
@ -41,31 +42,31 @@ const editor = useImageEditor({ file })
</div>
<div class="flex gap-2 flex-wrap mb-4">
<button
<button type="button"
class="bg-gray-200 px-3 py-1 rounded disabled:opacity-50"
{...editor.getRotateButtonProps(-90)}
>
↶ -90°
</button>
<button
<button type="button"
class="bg-gray-200 px-3 py-1 rounded disabled:opacity-50"
{...editor.getRotateButtonProps(90)}
>
↷ +90°
</button>
<button
<button type="button"
class="bg-gray-200 px-3 py-1 rounded disabled:opacity-50"
{...editor.getFlipHorizontalButtonProps()}
>
⇆ Flip
</button>
<button
<button type="button"
class="bg-gray-200 px-3 py-1 rounded disabled:opacity-50"
{...editor.getZoomButtonProps(0.1)}
>
+ Zoom
</button>
<button
<button type="button"
class="bg-gray-200 px-3 py-1 rounded disabled:opacity-50"
{...editor.getZoomButtonProps(-0.1)}
>
@ -74,25 +75,25 @@ const editor = useImageEditor({ file })
</div>
<div class="flex gap-2 flex-wrap mb-4">
<button
<button type="button"
class="bg-gray-200 px-3 py-1 rounded disabled:opacity-50"
{...editor.getCropSquareButtonProps()}
>
1:1
</button>
<button
<button type="button"
class="bg-gray-200 px-3 py-1 rounded disabled:opacity-50"
{...editor.getCropLandscapeButtonProps()}
>
16:9
</button>
<button
<button type="button"
class="bg-gray-200 px-3 py-1 rounded disabled:opacity-50"
{...editor.getCropPortraitButtonProps()}
>
9:16
</button>
<button
<button type="button"
class="bg-gray-200 px-3 py-1 rounded disabled:opacity-50"
{...editor.getResetButtonProps()}
>
@ -101,13 +102,13 @@ const editor = useImageEditor({ file })
</div>
<div class="flex gap-4 justify-end">
<button
<button type="button"
class="bg-gray-500 text-white px-4 py-2 rounded-md"
{...editor.getCancelButtonProps({ onClick: close })}
>
Cancel
</button>
<button
<button type="button"
class="bg-green-500 text-white px-4 py-2 rounded-md disabled:opacity-50 disabled:bg-green-300"
{...editor.getSaveButtonProps({ onClick: close })}
>

View file

@ -42,36 +42,37 @@ const {
<p>{mediaError.message ? `Camera error: ${mediaError.message}` : 'An unknown camera error occurred.'}</p>
</div>
{/if}
<!-- biome-ignore lint/a11y/useMediaCaption: live camera preview does not require captions -->
<video
class="border-2 w-full rounded-lg data-[uppy-mirrored=true]:scale-x-[-1]"
{...videoProps}
></video>
<div class="flex gap-4 flex-wrap mt-4">
<button
<button type="button"
class="bg-blue-500 text-white px-4 py-2 rounded-md disabled:opacity-50 disabled:bg-blue-300"
{...primaryActionButtonProps}
>
{primaryActionButtonLabel}
</button>
<button
<button type="button"
class="bg-blue-500 text-white px-4 py-2 rounded-md disabled:opacity-50 disabled:bg-blue-300"
{...recordButtonProps}
>
Record
</button>
<button
<button type="button"
class="bg-red-500 text-white px-4 py-2 rounded-md disabled:opacity-50 disabled:bg-red-300"
{...stopRecordingButtonProps}
>
Stop
</button>
<button
<button type="button"
class="bg-green-500 text-white px-4 py-2 rounded-md disabled:opacity-50 disabled:bg-green-300"
{...submitButtonProps}
>
Submit
</button>
<button
<button type="button"
class="bg-gray-500 text-white px-4 py-2 rounded-md disabled:opacity-50 disabled:bg-gray-300"
{...discardButtonProps}
>

View file

@ -18,6 +18,7 @@ const dtf = new Intl.DateTimeFormat('en-US', {
timeStyle: 'short',
})
// biome-ignore lint/correctness/noUnusedVariables: used as a Svelte action via use:setFolderCheckboxIndeterminate
function setFolderCheckboxIndeterminate(
node: HTMLInputElement,
item: PartialTreeFolderNode,

View file

@ -14,9 +14,9 @@ let hideUploadButton = false
</script>
<main class="p-5 max-w-xl mx-auto">
<button onclick={() => (disabled = !disabled)}>Toggle dashboard</button>
<button type="button" onclick={() => (disabled = !disabled)}>Toggle dashboard</button>
<Dashboard props={{disabled: disabled}} uppy={uppy} />
<button onclick={() => (hideUploadButton = !hideUploadButton)}>Toggle statusbar</button>
<button type="button" onclick={() => (hideUploadButton = !hideUploadButton)}>Toggle statusbar</button>
<div id="statusbar-container">
<StatusBar props={{ hideUploadButton }} uppy={uppy} />
</div>

View file

@ -1,6 +1,6 @@
import { userEvent } from '@vitest/browser/context'
import { setupWorker } from 'msw/browser'
import { afterAll, beforeAll, describe, expect, test } from 'vitest'
import { userEvent } from 'vitest/browser'
import { render } from 'vitest-browser-svelte'
import { tusHandlers } from '../../shared/tusHandlers.js'
import PropsReactivity from '../src/components/test/props-reactivity.svelte'
@ -20,7 +20,7 @@ const createMockFile = (name: string, type: string, size: number = 1024) => {
describe('App', () => {
test('renders all main sections and upload button is initially disabled', async () => {
const screen = render(App)
const screen = await render(App)
await expect.element(screen.getByText('With list')).toBeInTheDocument()
await expect.element(screen.getByText('With grid')).toBeInTheDocument()
@ -34,7 +34,7 @@ describe('App', () => {
})
test('can add and remove files and upload', async () => {
const screen = render(App)
const screen = await render(App)
const fileInput = document.getElementById(
'uppy-dropzone-file-input-uppy',
@ -60,7 +60,7 @@ describe('App', () => {
describe('ScreenCapture Component', () => {
test('renders with title, control buttons, and close functionality works', async () => {
const screen = render(App)
const screen = await render(App)
await screen
.getByRole('button', { name: 'Screen Capture', exact: true })
@ -93,7 +93,7 @@ describe('ScreenCapture Component', () => {
describe('Webcam Component', () => {
test('renders with title, control buttons, and close functionality works', async () => {
const screen = render(App)
const screen = await render(App)
await screen.getByRole('button', { name: 'Webcam', exact: true }).click()
@ -124,7 +124,7 @@ describe('Webcam Component', () => {
describe('RemoteSource Component', () => {
test('renders login button and login interaction works', async () => {
const screen = render(App)
const screen = await render(App)
await screen.getByRole('button', { name: 'Dropbox', exact: true }).click()
@ -132,12 +132,11 @@ describe('RemoteSource Component', () => {
await expect.element(loginButton).toBeInTheDocument()
await loginButton.click()
await expect.element(loginButton).toBeInTheDocument()
})
})
test('Dashboard reacts to prop changes', async () => {
const screen = render(PropsReactivity)
const screen = await render(PropsReactivity)
const toggleButton = screen.getByText('Toggle dashboard')
const dashboard = screen.container.querySelector('.uppy-Dashboard')
@ -148,7 +147,7 @@ test('Dashboard reacts to prop changes', async () => {
})
test('StatusBar reacts to prop changes', async () => {
const screen = render(PropsReactivity)
const screen = await render(PropsReactivity)
const toggleButton = screen.getByText('Toggle statusbar')
expect(

View file

@ -1,5 +1,6 @@
import { sveltekit } from '@sveltejs/kit/vite'
import tailwindcss from '@tailwindcss/vite'
import { playwright } from '@vitest/browser-playwright'
import { defineConfig } from 'vite'
export default defineConfig({
@ -7,7 +8,7 @@ export default defineConfig({
test: {
browser: {
enabled: true,
provider: 'playwright',
provider: playwright(),
instances: [{ browser: 'chromium' }],
},
},

View file

@ -1,5 +1,5 @@
<!doctype html>
<html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
@ -140,7 +140,7 @@
This API is a one-shot upload UI using a modal overlay. Call the
function and receive a listen to an event with upload results ✌️
</p>
<button onclick="openModal()">Open</button>
<button type="button" onclick="openModal()">Open</button>
<h2>uppy.upload()</h2>
<p>An &lt;input type=file&gt; backed by <code>uppy.upload()</code>:</p>

View file

@ -15,7 +15,7 @@
"@uppy/remote-sources": "workspace:*",
"@uppy/transloadit": "workspace:*",
"@uppy/webcam": "workspace:*",
"express": "^4.22.0",
"express": "^5.2.1",
"he": "^1.2.0"
},
"private": true,

View file

@ -36,7 +36,7 @@ function Footer() {
}
function FormFields(fields) {
// biome-ignore lint/nursery/noNestedComponentDefinitions: not a react component
// biome-ignore lint/correctness/noNestedComponentDefinitions: not a react component
function Field([name, value]) {
if (name === 'transloadit') return ''
let isValueJSON = false
@ -76,7 +76,7 @@ function FormFields(fields) {
}
function UploadsList(uploads) {
// biome-ignore lint/nursery/noNestedComponentDefinitions: not a react component
// biome-ignore lint/correctness/noNestedComponentDefinitions: not a react component
function Upload(upload) {
return `<li>${e(upload.name)}</li>`
}
@ -89,12 +89,12 @@ function UploadsList(uploads) {
}
function ResultsList(results) {
// biome-ignore lint/nursery/noNestedComponentDefinitions: not a react component
// biome-ignore lint/correctness/noNestedComponentDefinitions: not a react component
function Result(result) {
return `<li>${e(result.name)} <a href="${result.ssl_url}" target="_blank">View</a></li>`
}
// biome-ignore lint/nursery/noNestedComponentDefinitions: not a react component
// biome-ignore lint/correctness/noNestedComponentDefinitions: not a react component
function ResultsSection(stepName) {
return `
<h2>${e(stepName)}</h2>

View file

@ -22,12 +22,13 @@
"devDependencies": {
"@tailwindcss/vite": "^4.1.11",
"@vitejs/plugin-vue": "^6.0.1",
"@vitest/browser": "^3.2.4",
"@vitest/browser": "^4.1.6",
"@vitest/browser-playwright": "^4.1.6",
"msw": "^2.10.4",
"playwright": "1.57.0",
"playwright": "1.60.0",
"tailwindcss": "^4.0.0",
"vite": "^7.1.11",
"vitest": "^3.2.4",
"vitest-browser-vue": "^1.0.0"
"vitest": "^4.1.6",
"vitest-browser-vue": "^2.1.0"
}
}

View file

@ -7,7 +7,7 @@
>
<div class="flex items-center justify-center gap-4">
<input v-bind="getFileInputProps()" class="hidden" />
<button
<button type="button"
v-bind="getButtonProps()"
class="hover:bg-gray-100 transition-colors p-2 rounded-md flex flex-col items-center gap-2 text-sm"
>
@ -17,7 +17,7 @@
Device
</button>
<button
<button type="button"
@click="() => props.openModal('webcam')"
class="hover:bg-gray-100 transition-colors p-2 rounded-md flex flex-col items-center gap-2 text-sm"
>
@ -27,7 +27,7 @@
Webcam
</button>
<button
<button type="button"
@click="() => props.openModal('screen-capture')"
class="hover:bg-gray-100 transition-colors p-2 rounded-md flex flex-col items-center gap-2 text-sm"
>
@ -37,7 +37,7 @@
Screen Capture
</button>
<button
<button type="button"
@click="() => props.openModal('dropbox')"
class="hover:bg-gray-100 transition-colors p-2 rounded-md flex flex-col items-center gap-2 text-sm"
>

View file

@ -12,6 +12,7 @@
</div>
<div class="mb-4">
<!-- biome-ignore lint/a11y/useAltText: alt is provided via editor.getImageProps() spread -->
<img
class="w-full max-h-[400px] rounded-lg border-2"
v-bind="editor.getImageProps()"
@ -29,31 +30,31 @@
</div>
<div class="flex gap-2 flex-wrap mb-4">
<button
<button type="button"
class="bg-gray-200 px-3 py-1 rounded disabled:opacity-50"
v-bind="editor.getRotateButtonProps(-90)"
>
-90°
</button>
<button
<button type="button"
class="bg-gray-200 px-3 py-1 rounded disabled:opacity-50"
v-bind="editor.getRotateButtonProps(90)"
>
+90°
</button>
<button
<button type="button"
class="bg-gray-200 px-3 py-1 rounded disabled:opacity-50"
v-bind="editor.getFlipHorizontalButtonProps()"
>
Flip
</button>
<button
<button type="button"
class="bg-gray-200 px-3 py-1 rounded disabled:opacity-50"
v-bind="editor.getZoomButtonProps(0.1)"
>
+ Zoom
</button>
<button
<button type="button"
class="bg-gray-200 px-3 py-1 rounded disabled:opacity-50"
v-bind="editor.getZoomButtonProps(-0.1)"
>
@ -62,25 +63,25 @@
</div>
<div class="flex gap-2 flex-wrap mb-4">
<button
<button type="button"
class="bg-gray-200 px-3 py-1 rounded disabled:opacity-50"
v-bind="editor.getCropSquareButtonProps()"
>
1:1
</button>
<button
<button type="button"
class="bg-gray-200 px-3 py-1 rounded disabled:opacity-50"
v-bind="editor.getCropLandscapeButtonProps()"
>
16:9
</button>
<button
<button type="button"
class="bg-gray-200 px-3 py-1 rounded disabled:opacity-50"
v-bind="editor.getCropPortraitButtonProps()"
>
9:16
</button>
<button
<button type="button"
class="bg-gray-200 px-3 py-1 rounded disabled:opacity-50"
v-bind="editor.getResetButtonProps()"
>
@ -89,13 +90,13 @@
</div>
<div class="flex gap-4 justify-end">
<button
<button type="button"
class="bg-gray-500 text-white px-4 py-2 rounded-md"
v-bind="editor.getCancelButtonProps({ onClick: close })"
>
Cancel
</button>
<button
<button type="button"
class="bg-green-500 text-white px-4 py-2 rounded-md disabled:opacity-50 disabled:bg-green-300"
v-bind="editor.getSaveButtonProps({ onClick: close })"
>

View file

@ -24,31 +24,31 @@
<track kind="captions" />
</video>
<div class="flex gap-4 flex-wrap mt-4">
<button
<button type="button"
class="bg-blue-500 text-white px-4 py-2 rounded-md disabled:opacity-50 disabled:bg-blue-300"
v-bind="primaryActionButtonProps"
>
{{ primaryActionButtonLabel }}
</button>
<button
<button type="button"
class="bg-blue-500 text-white px-4 py-2 rounded-md disabled:opacity-50 disabled:bg-blue-300"
v-bind="recordButtonProps"
>
Record
</button>
<button
<button type="button"
class="bg-red-500 text-white px-4 py-2 rounded-md disabled:opacity-50 disabled:bg-red-300"
v-bind="stopRecordingButtonProps"
>
Stop
</button>
<button
<button type="button"
class="bg-green-500 text-white px-4 py-2 rounded-md disabled:opacity-50 disabled:bg-green-300"
v-bind="submitButtonProps"
>
Submit
</button>
<button
<button type="button"
class="bg-gray-500 text-white px-4 py-2 rounded-md disabled:opacity-50 disabled:bg-gray-300"
v-bind="discardButtonProps"
>

View file

@ -1,6 +1,6 @@
import { userEvent } from '@vitest/browser/context'
import { setupWorker } from 'msw/browser'
import { afterAll, beforeAll, describe, expect, test } from 'vitest'
import { userEvent } from 'vitest/browser'
import { render } from 'vitest-browser-vue'
import { tusHandlers } from '../../shared/tusHandlers.js'
import App from '../src/App.vue'
@ -19,7 +19,7 @@ const createMockFile = (name: string, type: string, size: number = 1024) => {
describe('App', () => {
test('renders all main sections and upload button is initially disabled', async () => {
const screen = render(App)
const screen = await render(App)
await expect.element(screen.getByText('With list')).toBeInTheDocument()
await expect.element(screen.getByText('With grid')).toBeInTheDocument()
@ -33,7 +33,7 @@ describe('App', () => {
})
test('can add and remove files and upload', async () => {
const screen = render(App)
const screen = await render(App)
const fileInput = document.getElementById(
'uppy-dropzone-file-input-uppy',
@ -59,7 +59,7 @@ describe('App', () => {
describe('ScreenCapture Component', () => {
test('renders with title, control buttons, and close functionality works', async () => {
const screen = render(App)
const screen = await render(App)
await screen
.getByRole('button', { name: 'Screen Capture', exact: true })
@ -92,7 +92,7 @@ describe('ScreenCapture Component', () => {
describe('Webcam Component', () => {
test('renders with title, control buttons, and close functionality works', async () => {
const screen = render(App)
const screen = await render(App)
await screen.getByRole('button', { name: 'Webcam', exact: true }).click()
@ -123,7 +123,7 @@ describe('Webcam Component', () => {
describe('RemoteSource Component', () => {
test('renders login button and login interaction works', async () => {
const screen = render(App)
const screen = await render(App)
await screen.getByRole('button', { name: 'Dropbox', exact: true }).click()
@ -131,6 +131,5 @@ describe('RemoteSource Component', () => {
await expect.element(loginButton).toBeInTheDocument()
await loginButton.click()
await expect.element(loginButton).toBeInTheDocument()
})
})

View file

@ -1,5 +1,6 @@
import tailwindcss from '@tailwindcss/vite'
import vue from '@vitejs/plugin-vue'
import { playwright } from '@vitest/browser-playwright'
import { defineConfig } from 'vite'
export default defineConfig({
@ -7,7 +8,7 @@ export default defineConfig({
test: {
browser: {
enabled: true,
provider: 'playwright',
provider: playwright(),
instances: [{ browser: 'chromium' }],
},
},

View file

@ -1,5 +1,5 @@
<!doctype html>
<html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />

View file

@ -6,7 +6,7 @@
"@uppy/dashboard": "workspace:*",
"@uppy/xhr-upload": "workspace:*",
"cors": "^2.8.5",
"express": "^4.22.0",
"express": "^5.2.1",
"multer": "^2.0.2"
},
"devDependencies": {

View file

@ -1,5 +1,5 @@
<!doctype html>
<html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />

View file

@ -1,5 +1,5 @@
<!doctype html>
<html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />

View file

@ -1,5 +1,5 @@
<!doctype html>
<html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />

View file

@ -2,7 +2,7 @@
"name": "@uppy-dev/build",
"version": "0.0.0",
"private": true,
"description": "Extensible JavaScript file upload widget with support for drag&drop, resumable uploads, previews, restrictions, file processing/encoding, remote providers like Instagram, Dropbox, Google Drive, S3 and more :dog:",
"description": "Extensible JavaScript file upload widget with support for drag&drop, resumable uploads, previews, restrictions, file processing/encoding, remote providers like Dropbox, Google Drive, S3 and more :dog:",
"license": "MIT",
"workspaces": [
"examples/*",
@ -29,7 +29,7 @@
"release": "changeset publish"
},
"devDependencies": {
"@biomejs/biome": "2.0.5",
"@biomejs/biome": "2.4.15",
"@changesets/changelog-github": "^0.5.1",
"@changesets/cli": "patch:@changesets/cli@npm%3A2.29.5#~/.yarn/patches/@changesets-cli-npm-2.29.5-68d8030bf3.patch",
"npm-run-all": "^4.1.5",

View file

@ -1,45 +0,0 @@
{
"ignorePatterns": ["projects/**/*"],
"overrides": [
{
"files": ["*.ts"],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:@angular-eslint/recommended",
"plugin:@angular-eslint/template/process-inline-templates"
],
"rules": {
// eslint-disable-line import/newline-after-import
"@angular-eslint/directive-selector": [
"error",
{
"type": "attribute",
"prefix": "app",
"style": "camelCase"
}
],
"@typescript-eslint/semi": ["error", "never"],
"import/no-unresolved": "off",
"import/prefer-default-export": "off",
"@angular-eslint/component-selector": [
"error",
{
"type": "element",
"prefix": "app",
"style": "kebab-case"
}
],
"semi": ["error", "never"]
}
},
{
"files": ["*.html"],
"extends": [
"plugin:@angular-eslint/template/recommended",
"plugin:@angular-eslint/template/accessibility"
],
"rules": {}
}
]
}

View file

@ -9,37 +9,30 @@
},
"private": true,
"dependencies": {
"@angular/animations": "^19.2.17",
"@angular/common": "^19.2.17",
"@angular/compiler": "^19.2.18",
"@angular/core": "^19.2.18",
"@angular/forms": "^19.2.17",
"@angular/platform-browser": "^19.2.17",
"@angular/platform-browser-dynamic": "^19.2.17",
"@angular/router": "^19.2.17",
"@angular/animations": "^21.2.10",
"@angular/common": "^21.2.10",
"@angular/compiler": "^21.2.10",
"@angular/core": "^21.2.10",
"@angular/forms": "^21.2.10",
"@angular/platform-browser": "^21.2.10",
"@angular/platform-browser-dynamic": "^21.2.10",
"@angular/router": "^21.2.10",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
"zone.js": "~0.15.0"
},
"devDependencies": {
"@angular-devkit/build-angular": "^19.0.0",
"@angular-eslint/eslint-plugin": "^18.0.1",
"@angular-eslint/eslint-plugin-template": "^18.0.1",
"@angular/cli": "^19.0.0",
"@angular/compiler-cli": "^19.2.17",
"@angular-devkit/build-angular": "^21.2.8",
"@angular/cli": "^21.2.8",
"@angular/compiler-cli": "^21.2.10",
"@types/jasmine": "~5.1.0",
"@typescript-eslint/eslint-plugin": "^7.2.0",
"@typescript-eslint/parser": "^7.2.0",
"@typescript-eslint/types": "^7.2.0",
"@typescript-eslint/utils": "^7.2.0",
"eslint": "^8.57.0",
"jasmine-core": "~5.1.0",
"karma": "~6.4.0",
"karma-chrome-launcher": "~3.2.0",
"karma-coverage": "~2.2.0",
"karma-jasmine": "~5.1.0",
"karma-jasmine-html-reporter": "~2.1.0",
"ng-packagr": "^19.0.0",
"typescript": "~5.5.4"
"ng-packagr": "^21.2.3",
"typescript": "~5.9.0"
}
}

View file

@ -1,46 +0,0 @@
{
"extends": "../../../.eslintrc.json",
"ignorePatterns": ["!**/*"],
"overrides": [
{
"files": ["*.ts"],
"parserOptions": {
"project": [
"packages/@uppy/angular/projects/angular/tsconfig.lib.json",
"packages/@uppy/angular/projects/angular/tsconfig.spec.json"
],
"createDefaultProgram": true
},
"rules": {
"@angular-eslint/component-selector": [
"error",
{
"type": "element",
"prefix": "uppy",
"style": "kebab-case"
}
],
"@angular-eslint/directive-selector": [
"error",
{
"type": "attribute",
"prefix": "uppy",
"style": "camelCase"
}
],
"dot-notation": "error",
"indent": "error",
"no-empty-function": "off",
"no-shadow": "error",
"no-unused-expressions": "error",
"no-use-before-define": "off",
"quotes": "error",
"semi": "error"
}
},
{
"files": ["*.html"],
"rules": {}
}
]
}

View file

@ -22,11 +22,11 @@
"prepublishOnly": "rm -fr * && cp -r ../../../dist/uppy/angular .."
},
"dependencies": {
"tslib": "^2.0.0"
"tslib": "^2.8.1"
},
"peerDependencies": {
"@angular/common": "^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0",
"@angular/core": "^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0",
"@angular/common": "^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0",
"@angular/core": "^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0",
"@uppy/core": "workspace:^",
"@uppy/dashboard": "workspace:^",
"@uppy/status-bar": "workspace:^"

View file

@ -2,11 +2,7 @@
"extends": ["//"],
"tasks": {
"build": {
"dependsOn": [
"@uppy/core#build",
"@uppy/dashboard#build",
"@uppy/utils#build"
],
"dependsOn": ["@uppy/core#build", "@uppy/dashboard#build"],
"inputs": [
"projects/uppy/angular/src/**/*.{js,ts,jsx,tsx}",
"package.json",

View file

@ -40,17 +40,16 @@
"./package.json": "./package.json"
},
"dependencies": {
"@uppy/utils": "workspace:^",
"preact": "^10.26.10"
"preact": "^10.29.2"
},
"devDependencies": {
"cssnano": "^7.0.7",
"jsdom": "^26.1.0",
"postcss": "^8.5.6",
"cssnano": "^8.0.1",
"jsdom": "^29.1.1",
"postcss": "^8.5.15",
"postcss-cli": "^11.0.1",
"sass": "^1.89.2",
"typescript": "^5.8.3",
"vitest": "^3.2.4"
"vitest": "^4.1.6"
},
"peerDependencies": {
"@uppy/core": "workspace:^"

View file

@ -7,8 +7,8 @@ import type {
} from '@uppy/core'
import { UIPlugin } from '@uppy/core'
import type { LocaleStrings } from '@uppy/utils'
import { getFileTypeExtension } from '@uppy/utils'
import type { LocaleStrings } from '@uppy/core/utils'
import { getFileTypeExtension } from '@uppy/core/utils'
import packageJson from '../package.json' with { type: 'json' }
import locale from './locale.js'
import PermissionsScreen from './PermissionsScreen.js'
@ -284,7 +284,9 @@ export default class Audio<M extends Meta, B extends Body> extends UIPlugin<
#stop = async () => {
if (this.#stream) {
const audioTracks = this.#stream.getAudioTracks()
audioTracks.forEach((track) => track.stop())
audioTracks.forEach((track) => {
track.stop()
})
}
if (this.#recorder) {

View file

@ -1,4 +1,4 @@
import type { I18n } from '@uppy/utils'
import type { I18n } from '@uppy/core/utils'
interface DiscardButtonProps {
onDiscard: () => void

View file

@ -1,4 +1,4 @@
import type { I18n } from '@uppy/utils'
import type { I18n } from '@uppy/core/utils'
import type { h } from 'preact'
interface PermissionsScreenProps {

View file

@ -1,4 +1,4 @@
import type { I18n } from '@uppy/utils'
import type { I18n } from '@uppy/core/utils'
interface RecordButtonProps {
recording: boolean

View file

@ -1,4 +1,4 @@
import type { I18n } from '@uppy/utils'
import type { I18n } from '@uppy/core/utils'
import { useEffect, useRef } from 'preact/hooks'
import AudioSourceSelect, {
type AudioSourceSelectProps,

View file

@ -1,4 +1,4 @@
import type { I18n } from '@uppy/utils'
import type { I18n } from '@uppy/core/utils'
interface SubmitButtonProps {
onSubmit: () => void

View file

@ -7,9 +7,6 @@
"include": ["./src/**/*.*"],
"exclude": ["./src/**/*.test.ts"],
"references": [
{
"path": "../utils/tsconfig.build.json"
},
{
"path": "../core/tsconfig.build.json"
}

View file

@ -6,9 +6,6 @@
},
"include": ["./package.json", "./src/**/*.*"],
"references": [
{
"path": "../utils/tsconfig.build.json"
},
{
"path": "../core/tsconfig.build.json"
}

View file

@ -37,18 +37,15 @@
".": "./lib/index.js",
"./package.json": "./package.json"
},
"dependencies": {
"@uppy/companion-client": "workspace:^",
"@uppy/utils": "workspace:^"
},
"devDependencies": {
"@aws-sdk/client-s3": "^3.362.0",
"@aws-sdk/s3-request-presigner": "^3.362.0",
"@types/node": "^20.19.0",
"@uppy/core": "workspace:^",
"jsdom": "^26.1.0",
"nock": "^13.1.0",
"typescript": "^5.8.3",
"vitest": "^3.2.4",
"vitest": "^4.1.6",
"whatwg-fetch": "3.6.2"
},
"peerDependencies": {

View file

@ -1,5 +1,8 @@
import type { Body, Meta, UppyFile } from '@uppy/core'
import type { RateLimitedQueue, WrapPromiseFunctionType } from '@uppy/utils'
import type {
RateLimitedQueue,
WrapPromiseFunctionType,
} from '@uppy/core/utils'
import type AwsS3Multipart from './index.js'
import type {
AwsS3MultipartOptions,
@ -263,9 +266,9 @@ export class HTTPCommunicationQueue<M extends Meta, B extends Body> {
const data = chunk.getData()
if (method.toUpperCase() === 'POST') {
const formData = new FormData()
Object.entries(fields!).forEach(([key, value]) =>
formData.set(key, value),
)
Object.entries(fields!).forEach(([key, value]) => {
formData.set(key, value)
})
formData.set('file', data)
body = formData
} else {

View file

@ -1,6 +1,6 @@
import type { Uppy } from '@uppy/core'
import type { Body, Meta, UppyFile } from '@uppy/utils'
import { AbortController } from '@uppy/utils'
import type { Body, Meta, UppyFile } from '@uppy/core/utils'
import { AbortController } from '@uppy/core/utils'
import type { HTTPCommunicationQueue } from './HTTPCommunicationQueue.js'
const MB = 1024 * 1024
@ -256,6 +256,7 @@ class MultipartUploader<M extends Meta, B extends Body> {
else this.pause()
}
// biome-ignore lint/correctness/noUnusedPrivateClassMembers: accessed via Symbol in tests
private [Symbol.for('uppy test: getChunkState')]() {
return this.#chunkState
}

View file

@ -1,4 +1,3 @@
import { RequestClient } from '@uppy/companion-client'
import {
BasePlugin,
type DefinePluginOpts,
@ -6,20 +5,16 @@ import {
type PluginOpts,
type Uppy,
} from '@uppy/core'
import type {
Body,
LocalUppyFile,
Meta,
RequestOptions,
UppyFile,
} from '@uppy/utils'
import type { RequestOptions } from '@uppy/core/companion-client'
import { RequestClient } from '@uppy/core/companion-client'
import type { Body, LocalUppyFile, Meta, UppyFile } from '@uppy/core/utils'
import {
createAbortError,
filterFilesToEmitUploadStarted,
filterFilesToUpload,
getAllowedMetaFields,
RateLimitedQueue,
} from '@uppy/utils'
} from '@uppy/core/utils'
import packageJson from '../package.json' with { type: 'json' }
import createSignedURL from './createSignedURL.js'
import { HTTPCommunicationQueue } from './HTTPCommunicationQueue.js'
@ -662,10 +657,11 @@ export default class AwsS3Multipart<
querify: true,
})
const query = new URLSearchParams({ filename, type, ...metadata } as Record<
string,
string
>)
const query = new URLSearchParams({
filename,
...(type != null && { type }),
...metadata,
})
return this.#client.get(`s3/params?${query}`, options)
}

View file

@ -1,5 +1,5 @@
import type { Body } from '@uppy/utils'
import { createAbortError } from '@uppy/utils'
import type { Body } from '@uppy/core/utils'
import { createAbortError } from '@uppy/core/utils'
import type { AwsS3Part } from './index.js'

View file

@ -7,12 +7,6 @@
"include": ["./src/**/*.*"],
"exclude": ["./src/**/*.test.ts"],
"references": [
{
"path": "../companion-client/tsconfig.build.json"
},
{
"path": "../utils/tsconfig.build.json"
},
{
"path": "../core/tsconfig.build.json"
}

View file

@ -2,16 +2,11 @@
"extends": "../../../tsconfig.shared",
"compilerOptions": {
"emitDeclarationOnly": false,
"noEmit": true
"noEmit": true,
"types": ["preact", "node"]
},
"include": ["./package.json", "./src/**/*.*"],
"references": [
{
"path": "../companion-client/tsconfig.build.json"
},
{
"path": "../utils/tsconfig.build.json"
},
{
"path": "../core/tsconfig.build.json"
}

View file

@ -34,10 +34,7 @@
"./package.json": "./package.json"
},
"dependencies": {
"@uppy/companion-client": "workspace:^",
"@uppy/provider-views": "workspace:^",
"@uppy/utils": "workspace:^",
"preact": "^10.26.10"
"preact": "^10.29.2"
},
"peerDependencies": {
"@uppy/core": "workspace:^"

View file

@ -1,9 +1,3 @@
import {
type CompanionPluginOptions,
getAllowedHosts,
Provider,
tokenStorage,
} from '@uppy/companion-client'
import type {
AsyncStore,
Body,
@ -13,9 +7,14 @@ import type {
UppyFile,
} from '@uppy/core'
import { UIPlugin, type Uppy } from '@uppy/core'
import { ProviderViews } from '@uppy/provider-views'
import type { LocaleStrings } from '@uppy/utils'
import {
type CompanionPluginOptions,
getAllowedHosts,
Provider,
tokenStorage,
} from '@uppy/core/companion-client'
import { ProviderViews } from '@uppy/core/provider-views'
import type { LocaleStrings } from '@uppy/core/utils'
// biome-ignore lint/style/useImportType: h is not a type
import { type ComponentChild, h } from 'preact'
import packageJson from '../package.json' with { type: 'json' }

View file

@ -7,15 +7,6 @@
"include": ["./src/**/*.*"],
"exclude": ["./src/**/*.test.ts"],
"references": [
{
"path": "../companion-client/tsconfig.build.json"
},
{
"path": "../provider-views/tsconfig.build.json"
},
{
"path": "../utils/tsconfig.build.json"
},
{
"path": "../core/tsconfig.build.json"
}

View file

@ -6,15 +6,6 @@
},
"include": ["./package.json", "./src/**/*.*"],
"references": [
{
"path": "../companion-client/tsconfig.build.json"
},
{
"path": "../provider-views/tsconfig.build.json"
},
{
"path": "../utils/tsconfig.build.json"
},
{
"path": "../core/tsconfig.build.json"
}

View file

@ -1 +0,0 @@
tsconfig.*

View file

@ -1,301 +0,0 @@
# @uppy/companion-client
## 5.1.1
### Patch Changes
- 0c16fe4: - Split UppyFile into two intefaces distinguished by the `isRemote` boolean:
- LocalUppyFile
- RemoteUppyFile
- Updated dependencies [0c16fe4]
- @uppy/core@5.1.1
- @uppy/utils@7.1.1
## 5.1.0
### Minor Changes
- 5ba2c1c: Introduce the concept of server-side search and add support for it for the Dropbox provider. Previously, only client-side filtering in the currently viewed folder was possible, which was limiting. Now users using Companion with Dropbox can perform a search across their entire account.
### Patch Changes
- Updated dependencies [5ba2c1c]
- @uppy/utils@7.1.0
- @uppy/core@5.1.0
## 5.0.1
### Patch Changes
- 975317d: Removed "main" from package.json, since export maps serve as the contract for the public API.
- Updated dependencies [4b6a76c]
- Updated dependencies [975317d]
- Updated dependencies [9bac4c8]
- @uppy/core@5.0.2
- @uppy/utils@7.0.2
## 5.0.0
### Major Changes
- c5b51f6: ### Export maps for all packages
All packages now have export maps. This is a breaking change in two cases:
1. The css imports have changed from `@uppy[package]/dist/styles.min.css` to `@uppy[package]/css/styles.min.css`
2. You were importing something that wasn't exported from the root, for instance `@uppy/core/lib/foo.js`. You can now only import things we explicitly exported.
#### Changed imports for `@uppy/react`, `@uppy/vue`, and `@uppy/svelte`
Some components, like Dashboard, require a peer dependency to work but 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.
Every component that requires a peer dependency has now been moved to a subpath, such as `@uppy/react/dashboard`, so you only need to install the peer dependencies you need.
**Example for `@uppy/react`:**
**Before:**
```javascript
import { Dashboard, StatusBar } from "@uppy/react";
```
**Now:**
```javascript
import Dashboard from "@uppy/react/dashboard";
import StatusBar from "@uppy/react/status-bar";
```
### Patch Changes
- Updated dependencies [d301c01]
- Updated dependencies [c5b51f6]
- @uppy/utils@7.0.0
- @uppy/core@5.0.0
## 4.5.2
### Patch Changes
- 1b1a9e3: Define "files" in package.json
- Updated dependencies [1b1a9e3]
- @uppy/utils@6.2.2
- @uppy/core@4.5.2
## 4.5.0
### Minor Changes
- 0c24c5a: Use TypeScript compiler instead of Babel
### Patch Changes
- Updated dependencies [0c24c5a]
- Updated dependencies [0c24c5a]
- @uppy/core@4.5.0
- @uppy/utils@6.2.0
## 4.4.2
Released: 2025-05-18
Included in: Uppy v4.16.0
- @uppy/companion-client: don't reject on incorrect origin (Mikael Finstad / #5736)
## 4.4.0
Released: 2025-01-06
Included in: Uppy v4.11.0
- @uppy/angular,@uppy/audio,@uppy/aws-s3,@uppy/box,@uppy/companion-client,@uppy/compressor,@uppy/core,@uppy/dashboard,@uppy/drag-drop,@uppy/drop-target,@uppy/dropbox,@uppy/facebook,@uppy/file-input,@uppy/form,@uppy/golden-retriever,@uppy/google-drive-picker,@uppy/google-drive,@uppy/google-photos-picker,@uppy/google-photos,@uppy/image-editor,@uppy/informer,@uppy/instagram,@uppy/locales,@uppy/onedrive,@uppy/progress-bar,@uppy/provider-views,@uppy/react,@uppy/remote-sources,@uppy/screen-capture,@uppy/status-bar,@uppy/thumbnail-generator,@uppy/transloadit,@uppy/tus,@uppy/unsplash,@uppy/url,@uppy/vue,@uppy/webcam,@uppy/webdav,@uppy/xhr-upload,@uppy/zoom: Remove "paths" from all tsconfig's (Merlijn Vos / #5572)
## 4.2.0
Released: 2024-12-05
Included in: Uppy v4.8.0
- @uppy/companion-client: Fix allowed origins (Mikael Finstad / #5536)
- @uppy/audio,@uppy/aws-s3,@uppy/box,@uppy/companion-client,@uppy/compressor,@uppy/core,@uppy/dashboard,@uppy/drag-drop,@uppy/drop-target,@uppy/dropbox,@uppy/facebook,@uppy/file-input,@uppy/form,@uppy/golden-retriever,@uppy/google-drive,@uppy/google-photos,@uppy/image-editor,@uppy/informer,@uppy/instagram,@uppy/locales,@uppy/onedrive,@uppy/progress-bar,@uppy/provider-views,@uppy/react,@uppy/remote-sources,@uppy/screen-capture,@uppy/status-bar,@uppy/store-default,@uppy/thumbnail-generator,@uppy/transloadit,@uppy/tus,@uppy/unsplash,@uppy/url,@uppy/utils,@uppy/vue,@uppy/webcam,@uppy/xhr-upload,@uppy/zoom: cleanup tsconfig (Mikael Finstad / #5520)
## 4.1.1
Released: 2024-10-31
Included in: Uppy v4.6.0
- @uppy/aws-s3,@uppy/box,@uppy/companion-client,@uppy/core,@uppy/dashboard,@uppy/drag-drop,@uppy/dropbox,@uppy/facebook,@uppy/file-input,@uppy/form,@uppy/golden-retriever,@uppy/google-drive,@uppy/google-photos,@uppy/image-editor,@uppy/informer,@uppy/instagram,@uppy/locales,@uppy/onedrive,@uppy/progress-bar,@uppy/provider-views,@uppy/react-native,@uppy/react,@uppy/redux-dev-tools,@uppy/screen-capture,@uppy/status-bar,@uppy/store-default,@uppy/store-redux,@uppy/svelte,@uppy/thumbnail-generator,@uppy/transloadit,@uppy/tus,@uppy/unsplash,@uppy/url,@uppy/utils,@uppy/vue,@uppy/webcam,@uppy/xhr-upload,@uppy/zoom: Fix links (Anthony Veaudry / #5492)
## 4.0.0
Released: 2024-07-10
Included in: Uppy v4.0.0
- docs,@uppy/companion-client: don't close socket when pausing (Mikael Finstad / #4821)
## 4.0.0-beta.7
Released: 2024-06-04
Included in: Uppy v4.0.0-beta.10
- @uppy/companion-client: do not allow boolean `RequestOptions` (Mikael Finstad / #5198)
- @uppy/companion-client: remove deprecated options (Mikael Finstad / #5198)
- @uppy/companion-client: make `supportsRefreshToken` default (Mikael Finstad / #5198)
- @uppy/companion-client: remove optional chaining (Mikael Finstad / #5198)
- @uppy/companion-client: remove `Socket` (Mikael Finstad / #5198)
## 4.0.0-beta.6
Released: 2024-05-14
Included in: Uppy v4.0.0-beta.7
- @uppy/companion-client,@uppy/dropbox,@uppy/screen-capture,@uppy/unsplash,@uppy/url,@uppy/webcam: Use `title` consistently from locales (Merlijn Vos / #5134)
## 4.0.0-beta.1
Released: 2024-03-28
Included in: Uppy v4.0.0-beta.1
- @uppy/companion-client,@uppy/provider-views,@uppy/status-bar: fix type imports (Antoine du Hamel / #5038)
- @uppy/companion-client: Replace Provider.initPlugin with composition (Merlijn Vos / #4977)
## 3.8.0
Released: 2024-03-27
Included in: Uppy v3.24.0
- @uppy/box,@uppy/companion-client,@uppy/provider-views,@uppy/status-bar: fix type imports (Antoine du Hamel / #5038)
- @uppy/companion-client: Replace Provider.initPlugin with composition (Merlijn Vos / #4977)
## 3.7.4
Released: 2024-02-28
Included in: Uppy v3.23.0
- @uppy/companion-client,@uppy/utils,@uppy/xhr-upload: improvements for #4922 (Mikael Finstad / #4960)
## 3.7.3
Released: 2024-02-22
Included in: Uppy v3.22.2
- @uppy/companion-client: fix body/url on upload-success (Merlijn Vos / #4922)
- @uppy/companion-client: remove unnecessary `'use strict'` directives (Antoine du Hamel / #4943)
- @uppy/companion-client: type changes for provider-views (Antoine du Hamel / #4938)
- @uppy/companion-client: update types (Antoine du Hamel / #4927)
## 3.7.1
Released: 2024-02-19
Included in: Uppy v3.22.0
- @uppy/aws-s3-multipart,@uppy/aws-s3,@uppy/companion-client,@uppy/tus,@uppy/xhr-upload: update `uppyfile` objects before emitting events (antoine du hamel / #4928)
- @uppy/companion-client: fix tests and linter (antoine du hamel / #4890)
- @uppy/companion-client: migrate to ts (merlijn vos / #4864)
- @uppy/companion-client: fix `typeerror` (antoine du hamel)
## 3.7.0
Released: 2023-12-12
Included in: Uppy v3.21.0
- @uppy/companion-client: avoid unnecessary preflight requests (Antoine du Hamel / #4462)
## 3.6.1
Released: 2023-11-24
Included in: Uppy v3.20.0
- @uppy/companion-client: fix log type error (Mikael Finstad / #4766)
- @uppy/companion-client: revert breaking change (Antoine du Hamel / #4801)
## 3.5.0
Released: 2023-10-20
Included in: Uppy v3.18.0
- @uppy/companion-client: fixup! Added Companion OAuth Key type (Murderlon / #4668)
- @uppy/companion-client: Added Companion OAuth Key type (Chris Pratt / #4668)
## 3.4.1
Released: 2023-09-29
Included in: Uppy v3.17.0
- @uppy/companion-client: fix a refresh token race condition (Mikael Finstad / #4695)
## 3.4.0
Released: 2023-09-05
Included in: Uppy v3.15.0
- @uppy/aws-s3-multipart,@uppy/aws-s3,@uppy/companion-client,@uppy/core,@uppy/tus,@uppy/utils,@uppy/xhr-upload: Move remote file upload logic into companion-client (Merlijn Vos / #4573)
## 3.3.0
Released: 2023-08-15
Included in: Uppy v3.14.0
- @uppy/companion-client,@uppy/provider-views: make authentication optional (Dominik Schmidt / #4556)
## 3.1.2
Released: 2023-04-04
Included in: Uppy v3.7.0
- @uppy/companion-client: do not open socket more than once (Artur Paikin)
## 3.1.1
Released: 2022-11-16
Included in: Uppy v3.3.1
- @uppy/companion-client: treat `*` the same as missing header (Antoine du Hamel / #4221)
## 3.1.0
Released: 2022-11-10
Included in: Uppy v3.3.0
- @uppy/companion-client: add support for `AbortSignal` (Antoine du Hamel / #4201)
- @uppy/companion-client: prevent preflight race condition (Mikael Finstad / #4182)
## 3.0.2
Released: 2022-09-25
Included in: Uppy v3.1.0
- @uppy/audio,@uppy/aws-s3-multipart,@uppy/aws-s3,@uppy/box,@uppy/companion-client,@uppy/companion,@uppy/compressor,@uppy/core,@uppy/dashboard,@uppy/drag-drop,@uppy/drop-target,@uppy/dropbox,@uppy/facebook,@uppy/file-input,@uppy/form,@uppy/golden-retriever,@uppy/google-drive,@uppy/image-editor,@uppy/informer,@uppy/instagram,@uppy/locales,@uppy/onedrive,@uppy/progress-bar,@uppy/provider-views,@uppy/react,@uppy/redux-dev-tools,@uppy/remote-sources,@uppy/screen-capture,@uppy/status-bar,@uppy/store-default,@uppy/store-redux,@uppy/svelte,@uppy/thumbnail-generator,@uppy/transloadit,@uppy/tus,@uppy/unsplash,@uppy/url,@uppy/utils,@uppy/vue,@uppy/webcam,@uppy/xhr-upload,@uppy/zoom: add missing entries to changelog for individual packages (Antoine du Hamel / #4092)
## 3.0.0
Released: 2022-08-22
Included in: Uppy v3.0.0
- Switch to ESM
## 2.2.0
Released: 2022-05-30
Included in: Uppy v2.11.0
- @uppy/companion-client: Revert "Revert "@uppy/companion-client: refactor to ESM"" (Antoine du Hamel / #3730)
## 2.1.0
Released: 2022-05-14
Included in: Uppy v2.10.0
- @uppy/companion-client: refactor to ESM (Antoine du Hamel / #3693)
## 2.0.6
Released: 2022-04-07
Included in: Uppy v2.9.2
- @uppy/aws-s3,@uppy/companion-client,@uppy/transloadit,@uppy/utils: Propagate `isNetworkError` through error wrappers (Renée Kooi / #3620)
## 2.0.5
Released: 2022-02-14
Included in: Uppy v2.5.0
- @uppy/companion-client,@uppy/companion,@uppy/provider-views,@uppy/robodog: Finishing touches on Companion dynamic Oauth (Renée Kooi / #2802)

Some files were not shown because too many files have changed in this diff Show more