add back framework wrappers for @uppy/status-bar (#5948)

- added `react` `vue` `svelte` `angular` framwork wrappers for
`@uppy/status-bar`
- `git add -f
packages/@uppy/angular/projects/uppy/angular/src/lib/components/status-bar/`
because
https://transloadit.slack.com/archives/C0FMW9PSB/p1755632185831369?thread_ts=1755526948.473969&cid=C0FMW9PSB
This commit is contained in:
Prakash 2025-09-17 14:10:57 +05:30 committed by GitHub
parent d6b3aa575e
commit 92a0a0d2b8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 334 additions and 0 deletions

View file

@ -0,0 +1,8 @@
---
"@uppy/angular": minor
"@uppy/svelte": minor
"@uppy/react": minor
"@uppy/vue": minor
---
Add back framework wrappers for @uppy/status-bar plugin

View file

@ -0,0 +1,31 @@
import { ChangeDetectionStrategy, Component, type OnInit } from "@angular/core";
import { Uppy } from "@uppy/core";
import type * as StatusBar from "@uppy/status-bar";
import Tus from "@uppy/tus";
import type { Body, Meta } from "@uppy/utils/lib/UppyFile";
import { StatusBarComponent } from "./status-bar.component";
@Component({
selector: "uppy-status-bar-demo",
template: `
<div class="UppyInput"></div>
<uppy-status-bar [uppy]="uppy" [props]="props"></uppy-status-bar>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [StatusBarComponent],
})
export class StatusBarDemoComponent<M extends Meta, B extends Body>
implements OnInit
{
uppy: Uppy<M, B> = new Uppy({ debug: true, autoProceed: true });
props: StatusBar.StatusBarOptions = {
hideUploadButton: true,
hideAfterFinish: false,
};
ngOnInit(): void {
this.uppy
.use(Tus, { endpoint: "https://master.tus.io/files/" });
}
}

View file

@ -0,0 +1,24 @@
import { async, type ComponentFixture, TestBed } from "@angular/core/testing";
import { StatusBarComponent } from "./status-bar.component";
describe("StatusBarComponent", () => {
let component: StatusBarComponent;
let fixture: ComponentFixture<StatusBarComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [StatusBarComponent],
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(StatusBarComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it("should create", () => {
expect(component).toBeTruthy();
});
});

View file

@ -0,0 +1,53 @@
import {
ChangeDetectionStrategy,
Component,
ElementRef,
Input,
inject,
type OnChanges,
type OnDestroy,
type SimpleChanges,
} from "@angular/core";
import { Uppy } from "@uppy/core";
import type { StatusBarOptions } from "@uppy/status-bar";
import StatusBar from "@uppy/status-bar";
import type { Body, Meta } from "@uppy/utils";
import { UppyAngularWrapper } from "../../utils/wrapper";
@Component({
selector: "uppy-status-bar",
template: "",
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
})
export class StatusBarComponent<M extends Meta, B extends Body>
extends UppyAngularWrapper<M, B, StatusBarOptions>
implements OnDestroy, OnChanges
{
el = inject(ElementRef);
@Input() uppy: Uppy<M, B> = new Uppy();
@Input() props: StatusBarOptions = {};
/** Inserted by Angular inject() migration for backwards compatibility */
constructor(...args: unknown[]);
constructor() {
super();
}
ngOnInit() {
this.onMount(
{ id: "angular:StatusBar", target: this.el.nativeElement },
StatusBar,
);
}
ngOnChanges(changes: SimpleChanges): void {
this.handleChanges(changes, StatusBar);
}
ngOnDestroy(): void {
this.uninstall();
}
}

View file

@ -0,0 +1,15 @@
import { moduleMetadata } from "@storybook/angular";
import { StatusBarDemoComponent } from "./status-bar-demo.component";
export default {
title: "Status Bar",
decorators: [
moduleMetadata({
declarations: [StatusBarDemoComponent],
}),
],
};
export const Default = () => ({
component: StatusBarDemoComponent,
});

View file

@ -4,3 +4,4 @@
export { DashboardComponent } from './lib/components/dashboard/dashboard.component'
export { DashboardModalComponent } from './lib/components/dashboard-modal/dashboard-modal.component'
export { StatusBarComponent } from './lib/components/status-bar/status-bar.component'

View file

@ -57,6 +57,7 @@
".": "./lib/index.js",
"./css/style.css": "./dist/styles.css",
"./dashboard": "./lib/Dashboard.js",
"./status-bar": "./lib/StatusBar.js",
"./dashboard-modal": "./lib/DashboardModal.js",
"./package.json": "./package.json"
},
@ -75,6 +76,9 @@
"@uppy/screen-capture": {
"optional": true
},
"@uppy/status-bar": {
"optional": true
},
"@uppy/webcam": {
"optional": true
}

View file

@ -0,0 +1,88 @@
import type { Body, Meta, UnknownPlugin, Uppy } from '@uppy/core'
import StatusBarPlugin, { type StatusBarOptions } from '@uppy/status-bar'
import { Component, createElement as h } from 'react'
import getHTMLProps from './getHTMLProps.js'
import nonHtmlPropsHaveChanged from './nonHtmlPropsHaveChanged.js'
interface StatusBarProps<M extends Meta, B extends Body>
extends StatusBarOptions {
uppy: Uppy<M, B>
}
/**
* React component that renders a status bar containing upload progress and speed,
* processing progress and pause/resume/cancel controls.
*/
class StatusBar<M extends Meta, B extends Body> extends Component<
StatusBarProps<M, B>
> {
private container!: HTMLElement
private plugin!: UnknownPlugin<M, B>
componentDidMount(): void {
this.installPlugin()
}
componentDidUpdate(prevProps: StatusBar<M, B>['props']): void {
if (prevProps.uppy !== this.props.uppy) {
this.uninstallPlugin(prevProps)
this.installPlugin()
} else if (nonHtmlPropsHaveChanged(this.props, prevProps)) {
const { uppy, ...options } = { ...this.props, target: this.container }
this.plugin.setOptions(options)
}
}
componentWillUnmount(): void {
this.uninstallPlugin()
}
installPlugin(): void {
const {
uppy,
hideUploadButton,
hideRetryButton,
hidePauseResumeButton,
hideCancelButton,
showProgressDetails,
hideAfterFinish,
doneButtonHandler,
id,
} = this.props
const options = {
id: id || 'StatusBar',
hideUploadButton,
hideRetryButton,
hidePauseResumeButton,
hideCancelButton,
showProgressDetails,
hideAfterFinish,
doneButtonHandler,
target: this.container,
}
uppy.use(StatusBarPlugin, options)
this.plugin = uppy.getPlugin(options.id)!
}
uninstallPlugin(props = this.props): void {
const { uppy } = props
uppy.removePlugin(this.plugin)
}
render() {
return h('div', {
className: 'uppy-Container',
ref: (container: HTMLElement) => {
this.container = container
},
...getHTMLProps(this.props),
})
}
}
export default StatusBar

View file

@ -26,6 +26,9 @@
},
{
"path": "../webcam/tsconfig.build.json"
},
{
"path": "../status-bar/tsconfig.build.json"
}
]
}

View file

@ -25,6 +25,9 @@
},
{
"path": "../webcam/tsconfig.build.json"
},
{
"path": "../status-bar/tsconfig.build.json"
}
]
}

View file

@ -25,6 +25,10 @@
"types": "./dist/components/DashboardModal.svelte.d.ts",
"svelte": "./dist/components/DashboardModal.svelte"
},
"./status-bar": {
"types": "./dist/components/StatusBar.svelte.d.ts",
"svelte": "./dist/components/StatusBar.svelte"
},
"./package.json": "./package.json"
},
"homepage": "https://uppy.io",
@ -71,6 +75,9 @@
"peerDependenciesMeta": {
"@uppy/dashboard": {
"optional": true
},
"@uppy/status-bar": {
"optional": true
}
},
"publishConfig": {

View file

@ -0,0 +1,42 @@
<script
lang="ts"
generics="M extends import('@uppy/core').Meta, B extends import('@uppy/core').Body"
>
import type { Uppy } from "@uppy/core";
import StatusBarPlugin, { type StatusBarOptions } from "@uppy/status-bar";
import { onDestroy, onMount } from "svelte";
let container: HTMLElement;
let plugin: StatusBarPlugin<M, B>;
export let uppy: Uppy<M, B>;
export let props: StatusBarOptions | undefined = {};
const installPlugin = () => {
const options = {
id: "svelte:StatusBar",
...props,
target: container,
} satisfies StatusBarOptions;
uppy.use(StatusBarPlugin<M, B>, options);
plugin = uppy.getPlugin(options.id) as StatusBarPlugin<M, B>;
};
const uninstallPlugin = (uppyInstance: Uppy<M, B> = uppy) => {
if (plugin != null) uppyInstance.removePlugin(plugin);
};
onMount(() => installPlugin());
onDestroy(() => uninstallPlugin());
$: {
const options = {
id: "svelte:StatusBar",
...props,
target: container,
} satisfies StatusBarOptions;
uppy.setOptions(options);
}
</script>
<div class="uppy-Container" bind:this={container}></div>

View file

@ -31,6 +31,7 @@
".": "./lib/index.js",
"./css/style.css": "./dist/styles.css",
"./dashboard": "./lib/dashboard.js",
"./status-bar": "./lib/status-bar.js",
"./dashboard-modal": "./lib/dashboard-modal.js",
"./package.json": "./package.json"
},
@ -42,6 +43,9 @@
"peerDependenciesMeta": {
"@uppy/dashboard": {
"optional": true
},
"@uppy/status-bar": {
"optional": true
}
},
"publishConfig": {

View file

@ -0,0 +1,39 @@
import type { Uppy } from '@uppy/core'
import StatusBarPlugin, { type StatusBarOptions } from '@uppy/status-bar'
import { defineComponent, h, type PropType, ref } from 'vue'
import useUppy from './useUppy.js'
export default defineComponent({
name: 'StatusBar',
props: {
uppy: {
type: Object as PropType<Uppy<any, any>>,
required: true,
},
props: {
type: Object as PropType<StatusBarOptions>,
},
},
setup(props) {
const containerRef = ref<string>()
const pluginRef = ref<StatusBarPlugin<any, any>>()
const propsRef = ref(props.props)
const onMount = () => {
const { uppy } = props
const options = {
id: 'StatusBar',
...props.props,
target: containerRef.value,
}
uppy.use(StatusBarPlugin, options)
pluginRef.value = uppy.getPlugin(options.id) as StatusBarPlugin<any, any>
}
useUppy(onMount, pluginRef, props.uppy, propsRef)
return () =>
h('div', {
ref: containerRef,
})
},
})

View file

@ -15,6 +15,9 @@
},
{
"path": "../dashboard/tsconfig.build.json"
},
{
"path": "../status-bar/tsconfig.build.json"
}
]
}

View file

@ -14,6 +14,9 @@
},
{
"path": "../dashboard/tsconfig.build.json"
},
{
"path": "../status-bar/tsconfig.build.json"
}
]
}

View file

@ -10001,6 +10001,8 @@ __metadata:
optional: true
"@uppy/screen-capture":
optional: true
"@uppy/status-bar":
optional: true
"@uppy/webcam":
optional: true
languageName: unknown
@ -10097,6 +10099,8 @@ __metadata:
peerDependenciesMeta:
"@uppy/dashboard":
optional: true
"@uppy/status-bar":
optional: true
languageName: unknown
linkType: soft
@ -10218,6 +10222,8 @@ __metadata:
peerDependenciesMeta:
"@uppy/dashboard":
optional: true
"@uppy/status-bar":
optional: true
languageName: unknown
linkType: soft