1- import { ComponentProps , useId , useState } from 'react' ;
1+ import { ComponentProps , useId } from 'react' ;
22
33import { MediaPreview } from './MediaUploadPreview' ;
44
@@ -46,44 +46,43 @@ export type Props = {
4646 */
4747 multiple ?: boolean ;
4848 /**
49- * initial preview urls for edit mode (e.g., existing uploaded image urls)
49+ * Array of preview URLs to display existing media
5050 */
51- initialPreviewUrls ?: string [ ] ;
51+ previewUrls ?: string [ ] ;
5252 /**
53- * initial files for edit mode (if available).
53+ * Array of preview File objects for new uploads
5454 */
55- initialFiles ?: File [ ] ;
55+ previewFiles ?: File [ ] | null ;
56+ /**
57+ * Callback function called when files are selected, removed, or reset
58+ */
59+ onFileChange ?: ( files : File [ ] | null , previewUrls : string [ ] ) => void ;
5660} & Omit < ComponentProps < 'input' > , 'id' > ;
5761
5862const GB = 1024 * 1024 * 1024 ;
5963
6064export function MediaUpload ( {
6165 topAffix,
62- onFileUpload,
6366 id,
6467 label = '파일을 업로드해주세요. (jpg, jpeg, png)' ,
6568 description = '* 파일은 5GB까지 업로드 가능합니다.' ,
6669 maxSize = 5 ,
6770 acceptedFormats = [ 'image/*' ] ,
6871 multiple = false ,
69- initialPreviewUrls,
70- initialFiles,
72+ previewFiles = [ ] ,
73+ previewUrls = [ ] ,
74+ onFileChange,
7175 ...props
7276} : Props ) {
7377 const generatedId = useId ( ) ;
7478 const inputId = id || generatedId ;
75-
76- const [ selectedFiles , setSelectedFiles ] = useState < File [ ] > ( initialFiles || [ ] ) ;
77- const [ previewUrls , setPreviewUrls ] = useState < string [ ] > ( initialPreviewUrls || [ ] ) ;
78- const isSelected = selectedFiles . length > 0 ;
79+ const isSelected = previewUrls . length > 0 ;
7980
8081 const handleReset = ( ) => {
8182 previewUrls . forEach ( ( url ) => {
8283 if ( url . startsWith ( 'blob:' ) ) URL . revokeObjectURL ( url ) ;
8384 } ) ;
84- setSelectedFiles ( [ ] ) ;
85- setPreviewUrls ( [ ] ) ;
86- onFileUpload ?.( null ) ;
85+ onFileChange ?.( null , [ ] ) ;
8786 } ;
8887
8988 const handleFileChange = ( event : React . ChangeEvent < HTMLInputElement > ) => {
@@ -97,23 +96,18 @@ export function MediaUpload({
9796 }
9897
9998 const validatedFiles = multiple ? files : [ files [ 0 ] ] ;
100- setSelectedFiles ( validatedFiles ) ;
10199 const urls = validatedFiles . map ( ( file ) => URL . createObjectURL ( file ) ) ;
102- setPreviewUrls ( urls ) ;
103- onFileUpload ?.( validatedFiles ) ;
100+ onFileChange ?.( validatedFiles , urls ) ;
104101 } ;
105102
106103 const handleRemoveFile = ( index : number ) => {
107104 const urlToRemove = previewUrls [ index ] ;
108- if ( urlToRemove ?. startsWith ( 'blob:' ) ) {
109- URL . revokeObjectURL ( urlToRemove ) ;
110- }
111- const newFiles = selectedFiles . filter ( ( _ , i ) => i !== index ) ;
105+ if ( urlToRemove ?. startsWith ( 'blob:' ) ) URL . revokeObjectURL ( urlToRemove ) ;
106+
107+ const newFiles = previewFiles ?. filter ( ( _ , i ) => i !== index ) ?? null ;
112108 const newUrls = previewUrls . filter ( ( _ , i ) => i !== index ) ;
113109
114- setSelectedFiles ( newFiles ) ;
115- setPreviewUrls ( newUrls ) ;
116- onFileUpload ?.( newFiles . length > 0 ? newFiles : null ) ;
110+ onFileChange ?.( newFiles , newUrls ) ;
117111 } ;
118112
119113 return (
@@ -126,7 +120,7 @@ export function MediaUpload({
126120 < UploadBox id = { inputId } label = { label } description = { description } />
127121 ) : (
128122 < MediaPreview
129- files = { selectedFiles }
123+ files = { previewFiles }
130124 previewUrls = { previewUrls }
131125 onRemoveFile = { handleRemoveFile }
132126 multiple = { multiple }
@@ -178,7 +172,7 @@ function RefreshButton({ handleReset, isSelected }: RefreshButtonProp) {
178172 < Flex
179173 as = "button"
180174 onClick = { ( e ) => {
181- e . stopPropagation ( ) ;
175+ e . preventDefault ( ) ;
182176 if ( isSelected ) handleReset ( ) ;
183177 } }
184178 alignItems = "center"
0 commit comments