mirror of
https://github.com/transloadit/uppy.git
synced 2026-07-18 00:55:35 +00:00
- Create image editor abstraction in `@uppy/components`
- Refactor `Editor` (Preact) and `ImageEditor` (Uppy plugin) to put all
methods in the Uppy plugin class so they can be reused by the headless
abstraction
- Create framework hooks for React, Vue, Svelte
- Update all examples to showcase the new hook
- Symlink the `cropper.scss` (just regular CSS) from
`@uppy/image-editor` into `@uppy/components`, update `build:css` in all
framework packages to copy that file too into their own `dist/` output.
- cropper-js needs basic CSS to do the rotations and stuff which would
be very tedious to write yourself so we ship that CSS file to consumers
too so they can just import it.
- Fix memory leak where we created the image on each render inside the
original Preact plugin UI
```ts
import type { UppyFile } from '@uppy/core'
import { useImageEditor } from '@uppy/react'
interface ImageEditorProps {
file: UppyFile<any, any>
close: () => void
}
export function ImageEditor({ file, close }: ImageEditorProps) {
const {
state,
getImageProps,
getSaveButtonProps,
getCancelButtonProps,
getRotateButtonProps,
getFlipHorizontalButtonProps,
getZoomButtonProps,
getCropSquareButtonProps,
getCropLandscapeButtonProps,
getCropPortraitButtonProps,
getResetButtonProps,
getRotationSliderProps,
} = useImageEditor({ file })
return (
<div className="p-4 max-w-2xl w-full">
<div className="flex justify-between items-center mb-4">
<h2 className="text-xl font-bold">Edit Image</h2>
<button
type="button"
onClick={close}
className="text-gray-500 hover:text-gray-700"
>
✕
</button>
</div>
<div className="mb-4">
{/* biome-ignore lint/a11y/useAltText: alt is provided by getImageProps() */}
<img
className="w-full max-h-[400px] rounded-lg border-2"
{...getImageProps()}
/>
</div>
<div className="mb-4">
<label className="block text-sm font-medium mb-2">
Fine Rotation: {state.angle}°
<input className="w-full mt-1" {...getRotationSliderProps()} />
</label>
</div>
<div className="flex gap-2 flex-wrap mb-4">
<button
className="bg-gray-200 px-3 py-1 rounded disabled:opacity-50"
{...getRotateButtonProps(-90)}
>
↶ -90°
</button>
<button
className="bg-gray-200 px-3 py-1 rounded disabled:opacity-50"
{...getRotateButtonProps(90)}
>
↷ +90°
</button>
<button
className="bg-gray-200 px-3 py-1 rounded disabled:opacity-50"
{...getFlipHorizontalButtonProps()}
>
⇆ Flip
</button>
<button
className="bg-gray-200 px-3 py-1 rounded disabled:opacity-50"
{...getZoomButtonProps(0.1)}
>
+ Zoom
</button>
<button
className="bg-gray-200 px-3 py-1 rounded disabled:opacity-50"
{...getZoomButtonProps(-0.1)}
>
- Zoom
</button>
</div>
<div className="flex gap-2 flex-wrap mb-4">
<button
className="bg-gray-200 px-3 py-1 rounded disabled:opacity-50"
{...getCropSquareButtonProps()}
>
1:1
</button>
<button
className="bg-gray-200 px-3 py-1 rounded disabled:opacity-50"
{...getCropLandscapeButtonProps()}
>
16:9
</button>
<button
className="bg-gray-200 px-3 py-1 rounded disabled:opacity-50"
{...getCropPortraitButtonProps()}
>
9:16
</button>
<button
className="bg-gray-200 px-3 py-1 rounded disabled:opacity-50"
{...getResetButtonProps()}
>
Reset
</button>
</div>
<div className="flex gap-4 justify-end">
<button
className="bg-gray-500 text-white px-4 py-2 rounded-md"
{...getCancelButtonProps({ onClick: close })}
>
Cancel
</button>
<button
className="bg-green-500 text-white px-4 py-2 rounded-md disabled:opacity-50 disabled:bg-green-300"
{...getSaveButtonProps({ onClick: close })}
>
Save
</button>
</div>
</div>
)
}
export default ImageEditor
```
https://github.com/user-attachments/assets/4b0a99cc-8489-41a2-aa3b-ce88110025bf
---------
Co-authored-by: Prakash <qxprakash@gmail.com>
|
||
|---|---|---|
| .. | ||
| src | ||
| .npmignore | ||
| CHANGELOG.md | ||
| LICENSE | ||
| package.json | ||
| README.md | ||
| tsconfig.build.json | ||
| tsconfig.json | ||
| turbo.json | ||
@uppy/react
React component wrappers around Uppy’s officially maintained UI plugins.
Uppy is being developed by the folks at Transloadit, a versatile file encoding service.
Example
/** @jsx React */
import React from 'react'
import Uppy from '@uppy/core'
import { DashboardModal } from '@uppy/react'
const uppy = new Uppy()
class Example extends React.Component {
state = { open: false }
render() {
const { open } = this.state
return (
<DashboardModal
uppy={uppy}
open={open}
onRequestClose={this.handleClose}
/>
)
}
// ..snip..
}
Installation
$ npm install @uppy/react
Alternatively, you can also use this plugin in a pre-built bundle from
Transloadit’s CDN: Smart CDN. In that case Uppy will attach itself to the
global window.Uppy object. See the
main Uppy documentation for instructions.
Documentation
Documentation for this plugin can be found on the Uppy website.