Skip to content

Commit

Permalink
vue port
Browse files Browse the repository at this point in the history
  • Loading branch information
juliusmarminge committed Feb 17, 2025
1 parent 578566f commit 31876ca
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 38 deletions.
24 changes: 13 additions & 11 deletions packages/vue/src/components/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import type {
UseUploadthingProps,
} from "../types";
import { __useUploadThingInternal } from "../useUploadThing";
import { Cancel, progressWidths, Spinner, usePaste } from "./shared";
import { Cancel, Spinner, usePaste } from "./shared";

export type ButtonStyleFieldCallbackArgs = {
__runtime: "vue";
Expand Down Expand Up @@ -96,6 +96,7 @@ export const generateUploadButton = <TRouter extends FileRouter>(
void $props.onClientUploadComplete?.(res);
uploadProgress.value = 0;
},
uploadProgressGranularity: $props.uploadProgressGranularity,
onUploadProgress: (p) => {
uploadProgress.value = p;
$props.onUploadProgress?.(p);
Expand Down Expand Up @@ -215,7 +216,7 @@ export const generateUploadButton = <TRouter extends FileRouter>(
return (
<span class="z-50">
<span class="block group-hover:hidden">
{uploadProgress.value}%
{Math.round(uploadProgress.value)}%
</span>
<Cancel cn={cn} class="hidden size-4 group-hover:block" />
</span>
Expand Down Expand Up @@ -287,11 +288,11 @@ export const generateUploadButton = <TRouter extends FileRouter>(

const labelClass = computed(() =>
cn(
"group relative flex h-10 w-36 cursor-pointer items-center justify-center overflow-hidden rounded-md border-none text-base text-white after:transition-[width] after:duration-500 focus-within:ring-2 focus-within:ring-blue-600 focus-within:ring-offset-2",
state.value === "disabled" && "cursor-not-allowed bg-blue-400",
state.value === "uploading" &&
`bg-blue-400 after:absolute after:left-0 after:h-full after:bg-blue-600 after:content-[''] ${progressWidths[uploadProgress.value]}`,
state.value === "ready" && "bg-blue-600",
"group relative flex h-10 w-36 cursor-pointer items-center justify-center overflow-hidden rounded-md text-white after:transition-[width] after:duration-500 focus-within:ring-2 focus-within:ring-blue-600 focus-within:ring-offset-2",
"disabled:pointer-events-none",
"data-[state=disabled]:cursor-not-allowed data-[state=readying]:cursor-not-allowed",
"data-[state=disabled]:bg-blue-400 data-[state=ready]:bg-blue-600 data-[state=readying]:bg-blue-400 data-[state=uploading]:bg-blue-400",
"after:absolute after:left-0 after:h-full after:w-[var(--progress-width)] after:content-[''] data-[state=uploading]:after:bg-blue-600",
styleFieldToClassName($props.appearance?.button, styleFieldArg.value),
),
);
Expand All @@ -306,12 +307,13 @@ export const generateUploadButton = <TRouter extends FileRouter>(
),
);

const containerStyle = computed(() =>
styleFieldToCssObject(
const containerStyle = computed(() => ({
"--progress-width": `${uploadProgress.value}%`,
...styleFieldToCssObject(
$props.appearance?.container,
styleFieldArg.value,
),
);
}));
const labelStyle = computed(() =>
styleFieldToCssObject($props.appearance?.button, styleFieldArg.value),
);
Expand All @@ -320,7 +322,7 @@ export const generateUploadButton = <TRouter extends FileRouter>(
return (
<div
class={containerClass.value}
style={containerStyle.value ?? {}}
style={containerStyle.value}
data-state={state.value}
>
<label
Expand Down
25 changes: 15 additions & 10 deletions packages/vue/src/components/dropzone.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import type {
UseUploadthingProps,
} from "../types";
import { __useUploadThingInternal } from "../useUploadThing";
import { Cancel, progressWidths, Spinner, usePaste } from "./shared";
import { Cancel, Spinner, usePaste } from "./shared";

export type DropzoneStyleFieldCallbackArgs = {
__runtime: "vue";
Expand Down Expand Up @@ -120,6 +120,7 @@ export const generateUploadDropzone = <TRouter extends FileRouter>(
void $props.onClientUploadComplete?.(res);
uploadProgress.value = 0;
},
uploadProgressGranularity: $props.uploadProgressGranularity,
onUploadProgress: (p) => {
uploadProgress.value = p;
$props.onUploadProgress?.(p);
Expand Down Expand Up @@ -311,7 +312,7 @@ export const generateUploadDropzone = <TRouter extends FileRouter>(
return (
<span class="z-50">
<span class="block group-hover:hidden">
{uploadProgress.value}%
{Math.round(uploadProgress.value)}%
</span>
<Cancel cn={cn} class="hidden size-4 group-hover:block" />
</span>
Expand Down Expand Up @@ -356,12 +357,12 @@ export const generateUploadDropzone = <TRouter extends FileRouter>(
);
const buttonClass = computed(() =>
cn(
"group relative mt-4 flex h-10 w-36 cursor-pointer items-center justify-center overflow-hidden rounded-md border-none text-base text-white after:transition-[width] after:duration-500 focus-within:ring-2 focus-within:ring-blue-600 focus-within:ring-offset-2",
state.value === "disabled" && "cursor-not-allowed bg-blue-400",
state.value === "uploading" &&
`bg-blue-400 after:absolute after:left-0 after:h-full after:bg-blue-600 after:content-[''] ${progressWidths[uploadProgress.value]}`,
state.value === "ready" && "bg-blue-600",
"group relative mt-4 flex h-10 w-36 items-center justify-center overflow-hidden rounded-md border-none text-base text-white",
"after:absolute after:left-0 after:h-full after:w-[var(--progress-width)] after:bg-blue-600 after:transition-[width] after:duration-500 after:content-['']",
"focus-within:ring-2 focus-within:ring-blue-600 focus-within:ring-offset-2",
"disabled:pointer-events-none",
"data-[state=disabled]:cursor-not-allowed data-[state=readying]:cursor-not-allowed",
"data-[state=disabled]:bg-blue-400 data-[state=ready]:bg-blue-600 data-[state=readying]:bg-blue-400 data-[state=uploading]:bg-blue-400",
styleFieldToClassName($props.appearance?.button, styleFieldArg.value),
),
);
Expand All @@ -381,9 +382,13 @@ export const generateUploadDropzone = <TRouter extends FileRouter>(
styleFieldArg.value,
),
);
const buttonStyle = computed(() =>
styleFieldToCssObject($props.appearance?.button, styleFieldArg.value),
);
const buttonStyle = computed(() => ({
"--progress-width": `${uploadProgress.value}%`,
...styleFieldToCssObject(
$props.appearance?.button,
styleFieldArg.value,
),
}));

return () => {
return (
Expand Down
14 changes: 0 additions & 14 deletions packages/vue/src/components/shared.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,3 @@ export const Cancel = Vue.defineComponent(
},
{ props: ["cn"] },
);

export const progressWidths: Record<number, string> = {
0: "after:w-0",
10: "after:w-[10%]",
20: "after:w-[20%]",
30: "after:w-[30%]",
40: "after:w-[40%]",
50: "after:w-[50%]",
60: "after:w-[60%]",
70: "after:w-[70%]",
80: "after:w-[80%]",
90: "after:w-[90%]",
100: "after:w-[100%]",
};
9 changes: 9 additions & 0 deletions packages/vue/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type {
ExtendObjectIf,
FetchEsque,
MaybePromise,
ProgressGranularity,
UploadThingError,
} from "@uploadthing/shared";
import type {
Expand Down Expand Up @@ -63,6 +64,14 @@ export type UseUploadthingProps<
* Called when presigned URLs have been retrieved and the file upload is about to begin
*/
onUploadBegin?: ((fileName: string) => void) | undefined;
/**
* Control how granular the upload progress is reported
* - "all" - No filtering is applied, all progress events are reported
* - "fine" - Progress is reported in increments of 1%
* - "coarse" - Progress is reported in increments of 10%
* @default "coarse"
*/
uploadProgressGranularity?: ProgressGranularity | undefined;
/**
* Called continuously as the file is uploaded to the storage provider
*/
Expand Down
10 changes: 7 additions & 3 deletions packages/vue/src/useUploadThing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type {
import {
INTERNAL_DO_NOT_USE__fatalClientError,
resolveMaybeUrlArg,
roundProgress,
unwrap,
UploadAbortedError,
UploadThingError,
Expand Down Expand Up @@ -63,6 +64,7 @@ export function __useUploadThingInternal<
fetch: FetchEsque,
opts?: UseUploadthingProps<TRouter[TEndpoint]>,
) {
const progressGranularity = opts?.uploadProgressGranularity ?? "coarse";
const { uploadFiles, routeRegistry } = genUploader<TRouter>({
fetch,
url,
Expand Down Expand Up @@ -95,10 +97,12 @@ export function __useUploadThingInternal<
fileProgress.value.set(progress.file, progress.progress);
let sum = 0;
fileProgress.value.forEach((p) => {
sum += p;
sum = Math.min(100, sum + p);
});
const averageProgress =
Math.floor(sum / fileProgress.value.size / 10) * 10;
const averageProgress = roundProgress(
sum / fileProgress.value.size,
progressGranularity,
);
if (averageProgress !== uploadProgress.value) {
opts.onUploadProgress(averageProgress);
uploadProgress.value = averageProgress;
Expand Down

0 comments on commit 31876ca

Please sign in to comment.