@@ -129,6 +129,16 @@ export class DeepnoteInputBlockCellStatusBarItemProvider
129129 } )
130130 ) ;
131131
132+ // File input: choose file
133+ this . disposables . push (
134+ commands . registerCommand ( 'deepnote.fileInputChooseFile' , async ( cell ?: NotebookCell ) => {
135+ const activeCell = cell || this . getActiveCell ( ) ;
136+ if ( activeCell ) {
137+ await this . fileInputChooseFile ( activeCell ) ;
138+ }
139+ } )
140+ ) ;
141+
132142 // Checkbox: toggle value
133143 this . disposables . push (
134144 commands . registerCommand ( 'deepnote.checkboxToggle' , async ( cell ?: NotebookCell ) => {
@@ -268,7 +278,11 @@ export class DeepnoteInputBlockCellStatusBarItemProvider
268278 this . addDateRangeInputStatusBarItems ( items , cell , metadata ) ;
269279 break ;
270280
271- // input-text, input-textarea, input-file, and button don't have additional buttons
281+ case 'input-file' :
282+ this . addFileInputStatusBarItems ( items , cell , metadata ) ;
283+ break ;
284+
285+ // input-text, input-textarea, and button don't have additional buttons
272286 }
273287 }
274288
@@ -382,6 +396,24 @@ export class DeepnoteInputBlockCellStatusBarItemProvider
382396 } ) ;
383397 }
384398
399+ private addFileInputStatusBarItems (
400+ items : NotebookCellStatusBarItem [ ] ,
401+ cell : NotebookCell ,
402+ _metadata : Record < string , unknown >
403+ ) : void {
404+ items . push ( {
405+ text : l10n . t ( '$(folder-opened) Choose File' ) ,
406+ alignment : 1 ,
407+ priority : 80 ,
408+ tooltip : l10n . t ( 'Choose a file\nClick to browse' ) ,
409+ command : {
410+ title : l10n . t ( 'Choose File' ) ,
411+ command : 'deepnote.fileInputChooseFile' ,
412+ arguments : [ cell ]
413+ }
414+ } ) ;
415+ }
416+
385417 private addDateInputStatusBarItems (
386418 items : NotebookCellStatusBarItem [ ] ,
387419 cell : NotebookCell ,
@@ -771,6 +803,48 @@ export class DeepnoteInputBlockCellStatusBarItemProvider
771803 await this . updateCellMetadata ( cell , { deepnote_variable_value : ! currentValue } ) ;
772804 }
773805
806+ /**
807+ * Handler for file input: choose file
808+ */
809+ private async fileInputChooseFile ( cell : NotebookCell ) : Promise < void > {
810+ const metadata = cell . metadata as Record < string , unknown > | undefined ;
811+ const allowedExtensions = metadata ?. deepnote_allowed_file_extensions as string | undefined ;
812+
813+ // Parse allowed extensions if provided
814+ const filters : { [ name : string ] : string [ ] } = { } ;
815+ if ( allowedExtensions ) {
816+ // Split by comma and clean up
817+ const extensions = allowedExtensions
818+ . split ( ',' )
819+ . map ( ( ext ) => ext . trim ( ) )
820+ . filter ( ( ext ) => ext . length > 0 ) ;
821+
822+ if ( extensions . length > 0 ) {
823+ filters [ 'Allowed Files' ] = extensions ;
824+ }
825+ }
826+
827+ // Add "All Files" option
828+ filters [ 'All Files' ] = [ '*' ] ;
829+
830+ const uris = await window . showOpenDialog ( {
831+ canSelectFiles : true ,
832+ canSelectFolders : false ,
833+ canSelectMany : false ,
834+ filters : Object . keys ( filters ) . length > 1 ? filters : undefined ,
835+ openLabel : l10n . t ( 'Select File' )
836+ } ) ;
837+
838+ if ( ! uris || uris . length === 0 ) {
839+ return ;
840+ }
841+
842+ // Get the file path
843+ const filePath = uris [ 0 ] . path ;
844+
845+ await this . updateCellMetadata ( cell , { deepnote_variable_value : filePath } ) ;
846+ }
847+
774848 /**
775849 * Handler for date input: choose date
776850 */
0 commit comments