@@ -26,22 +26,26 @@ const logger = createLogger('FileUpload')
2626interface FileUploadProps {
2727 blockId : string
2828 subBlockId : string
29+ value ?: FileUploadValue | null
30+ onValueChange ?: ( value : FileUploadValue | null ) => void
2931 maxSize ?: number // in MB
3032 acceptedTypes ?: string // comma separated MIME types
3133 multiple ?: boolean // whether to allow multiple file uploads
3234 isPreview ?: boolean
33- previewValue ?: any | null
35+ previewValue ?: FileUploadValue | null
3436 disabled ?: boolean
3537}
3638
37- interface UploadedFile {
39+ export interface UploadedFile {
3840 name : string
3941 path : string
4042 key ?: string
4143 size : number
4244 type : string
4345}
4446
47+ export type FileUploadValue = UploadedFile | UploadedFile [ ]
48+
4549interface SingleFileSelectorProps {
4650 file : UploadedFile
4751 options : Array < { label : string ; value : string ; disabled ?: boolean } >
@@ -143,6 +147,8 @@ interface UploadingFile {
143147export function FileUpload ( {
144148 blockId,
145149 subBlockId,
150+ value : controlledValue ,
151+ onValueChange,
146152 maxSize = 10 , // Default 10MB
147153 acceptedTypes = '*' ,
148154 multiple = false , // Default to single file for backward compatibility
@@ -151,6 +157,7 @@ export function FileUpload({
151157 disabled = false ,
152158} : FileUploadProps ) {
153159 const [ storeValue , setStoreValue ] = useSubBlockValue ( blockId , subBlockId )
160+ const isControlled = controlledValue !== undefined
154161 const [ uploadingFiles , setUploadingFiles ] = useState < UploadingFile [ ] > ( [ ] )
155162 const [ uploadProgress , setUploadProgress ] = useState ( 0 )
156163 const [ uploadError , setUploadError ] = useState < string | null > ( null )
@@ -173,7 +180,21 @@ export function FileUpload({
173180 const uploadFileMutation = useUploadWorkspaceFile ( )
174181 const queryClient = useQueryClient ( )
175182
176- const value = isPreview ? previewValue : storeValue
183+ const value =
184+ isPreview && previewValue !== undefined
185+ ? previewValue
186+ : isControlled
187+ ? controlledValue
188+ : storeValue
189+
190+ const setValue = ( newValue : FileUploadValue | null ) => {
191+ if ( isControlled ) {
192+ onValueChange ?.( newValue )
193+ } else {
194+ setStoreValue ( newValue )
195+ }
196+ useWorkflowStore . getState ( ) . triggerUpdate ( )
197+ }
177198
178199 /**
179200 * Checks if a file's MIME type matches the accepted types
@@ -390,11 +411,9 @@ export function FileUpload({
390411
391412 const newFiles = Array . from ( uniqueFiles . values ( ) )
392413
393- setStoreValue ( newFiles )
394- useWorkflowStore . getState ( ) . triggerUpdate ( )
414+ setValue ( newFiles )
395415 } else {
396- setStoreValue ( uploadedFiles [ 0 ] || null )
397- useWorkflowStore . getState ( ) . triggerUpdate ( )
416+ setValue ( uploadedFiles [ 0 ] || null )
398417 }
399418 } catch ( error ) {
400419 logger . error (
@@ -439,12 +458,11 @@ export function FileUpload({
439458 uniqueFiles . set ( uploadedFile . path , uploadedFile )
440459 const newFiles = Array . from ( uniqueFiles . values ( ) )
441460
442- setStoreValue ( newFiles )
461+ setValue ( newFiles )
443462 } else {
444- setStoreValue ( uploadedFile )
463+ setValue ( uploadedFile )
445464 }
446465
447- useWorkflowStore . getState ( ) . triggerUpdate ( )
448466 logger . info ( `Selected workspace file: ${ selectedFile . name } ` , activeWorkflowId )
449467 }
450468
@@ -481,12 +499,10 @@ export function FileUpload({
481499 if ( multiple ) {
482500 const filesArray = Array . isArray ( value ) ? value : value ? [ value ] : [ ]
483501 const updatedFiles = filesArray . filter ( ( f ) => f . path !== file . path )
484- setStoreValue ( updatedFiles . length > 0 ? updatedFiles : null )
502+ setValue ( updatedFiles . length > 0 ? updatedFiles : null )
485503 } else {
486- setStoreValue ( null )
504+ setValue ( null )
487505 }
488-
489- useWorkflowStore . getState ( ) . triggerUpdate ( )
490506 } catch ( error ) {
491507 logger . error (
492508 error instanceof Error ? error . message : 'Failed to remove file' ,
0 commit comments