@@ -4,6 +4,7 @@ export interface CommonPreviewProps<F extends Partial<File> = Partial<File>> { | |||||
file?: F; | file?: F; | ||||
disabled?: boolean; | disabled?: boolean; | ||||
enhanced?: boolean; | enhanced?: boolean; | ||||
mini?: boolean; | |||||
} | } | ||||
export type FilePreviewComponent<T extends CommonPreviewProps = CommonPreviewProps> = (props: T) => React.ReactNode; | export type FilePreviewComponent<T extends CommonPreviewProps = CommonPreviewProps> = (props: T) => React.ReactNode; |
@@ -378,7 +378,7 @@ export const AudioFilePreview = React.forwardRef<AudioFilePreviewDerivedElement, | |||||
<form | <form | ||||
id={formId} | id={formId} | ||||
onSubmit={handleAction} | onSubmit={handleAction} | ||||
className="flex gap-4" | |||||
className="flex gap-4 justify-end" | |||||
> | > | ||||
<fieldset | <fieldset | ||||
disabled={disabled || typeof error !== 'undefined'} | disabled={disabled || typeof error !== 'undefined'} | ||||
@@ -1,42 +0,0 @@ | |||||
import * as React from 'react'; | |||||
import { TextFilePreview } from '../TextFilePreview'; | |||||
import { ImageFilePreview } from '../ImageFilePreview'; | |||||
import { AudioFilePreview } from '../AudioFilePreview'; | |||||
import { VideoFilePreview } from '../VideoFilePreview'; | |||||
import { BinaryFilePreview } from '../BinaryFilePreview'; | |||||
import { ContentType, getContentType } from '@/utils/blob'; | |||||
const FILE_PREVIEW_COMPONENTS: Record<ContentType, React.ElementType> = { | |||||
[ContentType.TEXT]: TextFilePreview, | |||||
[ContentType.IMAGE]: ImageFilePreview, | |||||
[ContentType.AUDIO]: AudioFilePreview, | |||||
[ContentType.VIDEO]: VideoFilePreview, | |||||
[ContentType.BINARY]: BinaryFilePreview, | |||||
}; | |||||
export interface FilePreviewProps { | |||||
fileList?: FileList; | |||||
className?: string; | |||||
} | |||||
export const FilePreview: React.FC<FilePreviewProps> = ({ | |||||
fileList, | |||||
className, | |||||
}) => { | |||||
if ((fileList?.length ?? 0) < 1) { | |||||
return null; | |||||
} | |||||
const f = fileList?.[0]; | |||||
const contentType = getContentType(f?.type, f?.name); | |||||
const FilePreviewComponent = FILE_PREVIEW_COMPONENTS[contentType] ?? BinaryFilePreview; | |||||
return ( | |||||
<FilePreviewComponent | |||||
key={contentType} | |||||
file={f} | |||||
className={className} | |||||
enhanced | |||||
/> | |||||
); | |||||
}; |
@@ -150,7 +150,7 @@ export const ImageFilePreview = React.forwardRef<ImageFilePreviewDerivedElement, | |||||
{enhanced && ( | {enhanced && ( | ||||
<form | <form | ||||
onSubmit={handleAction} | onSubmit={handleAction} | ||||
className="flex gap-4" | |||||
className="flex gap-4 justify-end" | |||||
> | > | ||||
<fieldset | <fieldset | ||||
disabled={disabled || cannotDisplayPicture} | disabled={disabled || cannotDisplayPicture} | ||||
@@ -279,7 +279,7 @@ export const VideoFilePreview = React.forwardRef<VideoFilePreviewDerivedComponen | |||||
<form | <form | ||||
id={formId} | id={formId} | ||||
onSubmit={handleAction} | onSubmit={handleAction} | ||||
className="flex gap-4" | |||||
className="flex gap-4 justify-end" | |||||
> | > | ||||
<fieldset | <fieldset | ||||
disabled={disabled || typeof error !== 'undefined'} | disabled={disabled || typeof error !== 'undefined'} | ||||
@@ -10,6 +10,7 @@ const MIME_TYPE_DESCRIPTIONS = { | |||||
'image/png': 'PNG Image', | 'image/png': 'PNG Image', | ||||
'image/tiff': 'TIFF Image', | 'image/tiff': 'TIFF Image', | ||||
'image/svg+xml': 'SVG Image', | 'image/svg+xml': 'SVG Image', | ||||
'image/webp': 'WEBP Image', | |||||
'audio/wav': 'WAVE Audio', | 'audio/wav': 'WAVE Audio', | ||||
'audio/ogg': 'OGG Audio', | 'audio/ogg': 'OGG Audio', | ||||
'audio/mpeg': 'MPEG Audio', | 'audio/mpeg': 'MPEG Audio', | ||||
@@ -112,6 +113,9 @@ export const getContentType = (mimeType?: string, filename?: string) => { | |||||
} | } | ||||
export const readAsDataURL = (blob: Partial<Blob>) => new Promise<string>((resolve, reject) => { | export const readAsDataURL = (blob: Partial<Blob>) => new Promise<string>((resolve, reject) => { | ||||
// TODO when to revoke these URLs | |||||
// return URL.createObjectURL(blob as Blob); | |||||
const reader = new FileReader(); | const reader = new FileReader(); | ||||
reader.addEventListener('error', () => { | reader.addEventListener('error', () => { | ||||
reject(new Error('Could not read file as data URL')); | reject(new Error('Could not read file as data URL')); | ||||