@jupyterlab/filebrowser 4.1.0-alpha.2 → 4.1.0-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -19,6 +19,10 @@ export declare namespace FileDialog {
19
19
  * The application language translator.
20
20
  */
21
21
  translator?: ITranslator;
22
+ /**
23
+ * Default path to open
24
+ */
25
+ defaultPath?: string;
22
26
  }
23
27
  /**
24
28
  * Options for the open file dialog
package/lib/opendialog.js CHANGED
@@ -7,6 +7,7 @@ import { newFolderIcon, refreshIcon } from '@jupyterlab/ui-components';
7
7
  import { PanelLayout, Widget } from '@lumino/widgets';
8
8
  import { FileBrowser } from './browser';
9
9
  import { FilterFileBrowserModel } from './model';
10
+ import { PromiseDelegate } from '@lumino/coreutils';
10
11
  /**
11
12
  * The class name added to open file dialog
12
13
  */
@@ -26,9 +27,10 @@ export var FileDialog;
26
27
  *
27
28
  * @returns A promise that resolves with whether the dialog was accepted.
28
29
  */
29
- function getOpenFiles(options) {
30
+ async function getOpenFiles(options) {
30
31
  const translator = options.translator || nullTranslator;
31
32
  const trans = translator.load('jupyterlab');
33
+ const openDialog = new OpenDialog(options.manager, options.filter, translator, options.defaultPath);
32
34
  const dialogOptions = {
33
35
  title: options.title,
34
36
  buttons: [
@@ -40,8 +42,9 @@ export var FileDialog;
40
42
  focusNodeSelector: options.focusNodeSelector,
41
43
  host: options.host,
42
44
  renderer: options.renderer,
43
- body: new OpenDialog(options.manager, options.filter, translator)
45
+ body: openDialog
44
46
  };
47
+ await openDialog.ready;
45
48
  const dialog = new Dialog(dialogOptions);
46
49
  return dialog.launch();
47
50
  }
@@ -70,42 +73,51 @@ export var FileDialog;
70
73
  * Open dialog widget
71
74
  */
72
75
  class OpenDialog extends Widget {
73
- constructor(manager, filter, translator, filterDirectories) {
76
+ constructor(manager, filter, translator, defaultPath, filterDirectories) {
74
77
  super();
78
+ this._ready = new PromiseDelegate();
75
79
  translator = translator !== null && translator !== void 0 ? translator : nullTranslator;
76
80
  const trans = translator.load('jupyterlab');
77
81
  this.addClass(OPEN_DIALOG_CLASS);
78
- this._browser = Private.createFilteredFileBrowser('filtered-file-browser-dialog', manager, filter, {}, translator, filterDirectories);
79
- // Add toolbar items
80
- setToolbar(this._browser, (browser) => [
81
- {
82
- name: 'new-folder',
83
- widget: new ToolbarButton({
84
- icon: newFolderIcon,
85
- onClick: () => {
86
- void browser.createNewDirectory();
87
- },
88
- tooltip: trans.__('New Folder')
89
- })
90
- },
91
- {
92
- name: 'refresher',
93
- widget: new ToolbarButton({
94
- icon: refreshIcon,
95
- onClick: () => {
96
- browser.model.refresh().catch(reason => {
97
- console.error('Failed to refresh file browser in open dialog.', reason);
98
- });
99
- },
100
- tooltip: trans.__('Refresh File List')
101
- })
102
- }
103
- ]);
104
- // Build the sub widgets
105
- const layout = new PanelLayout();
106
- layout.addWidget(this._browser);
107
- // Set Widget content
108
- this.layout = layout;
82
+ Private.createFilteredFileBrowser('filtered-file-browser-dialog', manager, filter, {}, translator, defaultPath, filterDirectories)
83
+ .then(browser => {
84
+ this._browser = browser;
85
+ // Add toolbar items
86
+ setToolbar(this._browser, (browser) => [
87
+ {
88
+ name: 'new-folder',
89
+ widget: new ToolbarButton({
90
+ icon: newFolderIcon,
91
+ onClick: () => {
92
+ void browser.createNewDirectory();
93
+ },
94
+ tooltip: trans.__('New Folder')
95
+ })
96
+ },
97
+ {
98
+ name: 'refresher',
99
+ widget: new ToolbarButton({
100
+ icon: refreshIcon,
101
+ onClick: () => {
102
+ browser.model.refresh().catch(reason => {
103
+ console.error('Failed to refresh file browser in open dialog.', reason);
104
+ });
105
+ },
106
+ tooltip: trans.__('Refresh File List')
107
+ })
108
+ }
109
+ ]);
110
+ // Build the sub widgets
111
+ const layout = new PanelLayout();
112
+ layout.addWidget(this._browser);
113
+ // Set Widget content
114
+ this.layout = layout;
115
+ this._ready.resolve();
116
+ })
117
+ .catch(reason => {
118
+ console.error('Error while creating file browser in open dialog', reason);
119
+ this._ready.reject(void 0);
120
+ });
109
121
  }
110
122
  /**
111
123
  * Get the selected items.
@@ -132,6 +144,12 @@ class OpenDialog extends Widget {
132
144
  return selection;
133
145
  }
134
146
  }
147
+ /**
148
+ * A promise that resolves when openDialog is successfully created.
149
+ */
150
+ get ready() {
151
+ return this._ready.promise;
152
+ }
135
153
  }
136
154
  var Private;
137
155
  (function (Private) {
@@ -157,7 +175,7 @@ var Private;
157
175
  * as the initial ID passed into the factory is used for only one file browser
158
176
  * instance.
159
177
  */
160
- Private.createFilteredFileBrowser = (id, manager, filter, options = {}, translator, filterDirectories) => {
178
+ Private.createFilteredFileBrowser = async (id, manager, filter, options = {}, translator, defaultPath, filterDirectories) => {
161
179
  translator = translator || nullTranslator;
162
180
  const model = new FilterFileBrowserModel({
163
181
  manager,
@@ -167,6 +185,9 @@ var Private;
167
185
  refreshInterval: options.refreshInterval,
168
186
  filterDirectories
169
187
  });
188
+ if (defaultPath) {
189
+ await model.cd(defaultPath);
190
+ }
170
191
  const widget = new FileBrowser({
171
192
  id,
172
193
  model,
@@ -1 +1 @@
1
- {"version":3,"file":"opendialog.js","sourceRoot":"","sources":["../src/opendialog.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"opendialog.js","sourceRoot":"","sources":["../src/opendialog.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jupyterlab/filebrowser",
3
- "version": "4.1.0-alpha.2",
3
+ "version": "4.1.0-alpha.4",
4
4
  "description": "JupyterLab - FileBrowser Widget",
5
5
  "homepage": "https://github.com/jupyterlab/jupyterlab",
6
6
  "bugs": {
@@ -42,34 +42,34 @@
42
42
  "watch": "tsc -b --watch"
43
43
  },
44
44
  "dependencies": {
45
- "@jupyterlab/apputils": "^4.2.0-alpha.2",
46
- "@jupyterlab/coreutils": "^6.1.0-alpha.2",
47
- "@jupyterlab/docmanager": "^4.1.0-alpha.2",
48
- "@jupyterlab/docregistry": "^4.1.0-alpha.2",
49
- "@jupyterlab/services": "^7.1.0-alpha.2",
50
- "@jupyterlab/statedb": "^4.1.0-alpha.2",
51
- "@jupyterlab/statusbar": "^4.1.0-alpha.2",
52
- "@jupyterlab/translation": "^4.1.0-alpha.2",
53
- "@jupyterlab/ui-components": "^4.1.0-alpha.2",
45
+ "@jupyterlab/apputils": "^4.2.0-alpha.4",
46
+ "@jupyterlab/coreutils": "^6.1.0-alpha.4",
47
+ "@jupyterlab/docmanager": "^4.1.0-alpha.4",
48
+ "@jupyterlab/docregistry": "^4.1.0-alpha.4",
49
+ "@jupyterlab/services": "^7.1.0-alpha.4",
50
+ "@jupyterlab/statedb": "^4.1.0-alpha.4",
51
+ "@jupyterlab/statusbar": "^4.1.0-alpha.4",
52
+ "@jupyterlab/translation": "^4.1.0-alpha.4",
53
+ "@jupyterlab/ui-components": "^4.1.0-alpha.4",
54
54
  "@lumino/algorithm": "^2.0.1",
55
55
  "@lumino/coreutils": "^2.1.2",
56
56
  "@lumino/disposable": "^2.1.2",
57
57
  "@lumino/domutils": "^2.0.1",
58
- "@lumino/dragdrop": "^2.1.3",
58
+ "@lumino/dragdrop": "^2.1.4",
59
59
  "@lumino/messaging": "^2.0.1",
60
60
  "@lumino/polling": "^2.1.2",
61
61
  "@lumino/signaling": "^2.1.2",
62
62
  "@lumino/virtualdom": "^2.0.1",
63
- "@lumino/widgets": "^2.3.1-alpha.0",
63
+ "@lumino/widgets": "^2.3.1",
64
64
  "react": "^18.2.0"
65
65
  },
66
66
  "devDependencies": {
67
- "@jupyterlab/testing": "^4.1.0-alpha.2",
67
+ "@jupyterlab/testing": "^4.1.0-alpha.4",
68
68
  "@types/jest": "^29.2.0",
69
69
  "jest": "^29.2.0",
70
- "rimraf": "~3.0.0",
70
+ "rimraf": "~5.0.5",
71
71
  "typedoc": "~0.24.7",
72
- "typescript": "~5.0.4"
72
+ "typescript": "~5.1.6"
73
73
  },
74
74
  "publishConfig": {
75
75
  "access": "public"
package/src/browser.ts CHANGED
@@ -62,8 +62,6 @@ export class FileBrowser extends SidePanel {
62
62
  model.connectionFailure.connect(this._onConnectionFailure, this);
63
63
  this._manager = model.manager;
64
64
 
65
- // a11y
66
- this.toolbar.node.setAttribute('role', 'navigation');
67
65
  this.toolbar.node.setAttribute(
68
66
  'aria-label',
69
67
  this._trans.__('file browser')
@@ -126,6 +124,17 @@ export class FileBrowser extends SidePanel {
126
124
  }
127
125
  }
128
126
 
127
+ /**
128
+ * Whether to show the full path in the breadcrumbs
129
+ */
130
+ get showFullPath(): boolean {
131
+ return this.crumbs.fullPath;
132
+ }
133
+
134
+ set showFullPath(value: boolean) {
135
+ this.crumbs.fullPath = value;
136
+ }
137
+
129
138
  /**
130
139
  * Whether to show the file size column
131
140
  */
package/src/crumbs.ts CHANGED
@@ -15,6 +15,7 @@ import {
15
15
  folderIcon as rootIcon
16
16
  } from '@jupyterlab/ui-components';
17
17
  import { ArrayExt } from '@lumino/algorithm';
18
+ import { JSONExt } from '@lumino/coreutils';
18
19
  import { ElementExt } from '@lumino/domutils';
19
20
  import { Drag } from '@lumino/dragdrop';
20
21
  import { Message } from '@lumino/messaging';
@@ -70,6 +71,7 @@ export class BreadCrumbs extends Widget {
70
71
  this.translator = options.translator || nullTranslator;
71
72
  this._trans = this.translator.load('jupyterlab');
72
73
  this._model = options.model;
74
+ this._fullPath = options.fullPath || false;
73
75
  this.addClass(BREADCRUMB_CLASS);
74
76
  this._crumbs = Private.createCrumbs();
75
77
  this._crumbSeps = Private.createCrumbSeparators();
@@ -114,6 +116,17 @@ export class BreadCrumbs extends Widget {
114
116
  }
115
117
  }
116
118
 
119
+ /**
120
+ * Whether to show the full path in the breadcrumbs
121
+ */
122
+ get fullPath(): boolean {
123
+ return this._fullPath;
124
+ }
125
+
126
+ set fullPath(value: boolean) {
127
+ this._fullPath = value;
128
+ }
129
+
117
130
  /**
118
131
  * A message handler invoked on an `'after-attach'` message.
119
132
  */
@@ -148,12 +161,16 @@ export class BreadCrumbs extends Widget {
148
161
  // Update the breadcrumb list.
149
162
  const contents = this._model.manager.services.contents;
150
163
  const localPath = contents.localPath(this._model.path);
151
- Private.updateCrumbs(
152
- this._crumbs,
153
- this._crumbSeps,
154
- localPath,
155
- this._hasPreferred
156
- );
164
+ const state = {
165
+ path: localPath,
166
+ hasPreferred: this._hasPreferred,
167
+ fullPath: this._fullPath
168
+ };
169
+ if (this._previousState && JSONExt.deepEqual(state, this._previousState)) {
170
+ return;
171
+ }
172
+ this._previousState = state;
173
+ Private.updateCrumbs(this._crumbs, this._crumbSeps, state);
157
174
  }
158
175
 
159
176
  /**
@@ -184,12 +201,20 @@ export class BreadCrumbs extends Widget {
184
201
  node.classList.contains(BREADCRUMB_ITEM_CLASS) ||
185
202
  node.classList.contains(BREADCRUMB_ROOT_CLASS)
186
203
  ) {
187
- const index = ArrayExt.findFirstIndex(
204
+ let index = ArrayExt.findFirstIndex(
188
205
  this._crumbs,
189
206
  value => value === node
190
207
  );
208
+ let destination = BREAD_CRUMB_PATHS[index];
209
+ if (
210
+ this._fullPath &&
211
+ index < 0 &&
212
+ !node.classList.contains(BREADCRUMB_ROOT_CLASS)
213
+ ) {
214
+ destination = node.title;
215
+ }
191
216
  this._model
192
- .cd(BREAD_CRUMB_PATHS[index])
217
+ .cd(destination)
193
218
  .catch(error =>
194
219
  showErrorMessage(this._trans.__('Open Error'), error)
195
220
  );
@@ -309,6 +334,8 @@ export class BreadCrumbs extends Widget {
309
334
  private _hasPreferred: boolean;
310
335
  private _crumbs: ReadonlyArray<HTMLElement>;
311
336
  private _crumbSeps: ReadonlyArray<HTMLElement>;
337
+ private _fullPath: boolean;
338
+ private _previousState: Private.ICrumbsState | null = null;
312
339
  }
313
340
 
314
341
  /**
@@ -328,6 +355,11 @@ export namespace BreadCrumbs {
328
355
  * The application language translator.
329
356
  */
330
357
  translator?: ITranslator;
358
+
359
+ /**
360
+ * Show the full file browser path in breadcrumbs
361
+ */
362
+ fullPath?: boolean;
331
363
  }
332
364
  }
333
365
 
@@ -346,14 +378,23 @@ namespace Private {
346
378
  Preferred
347
379
  }
348
380
 
381
+ /**
382
+ * Breadcrumbs state.
383
+ */
384
+ export interface ICrumbsState {
385
+ [key: string]: string | boolean;
386
+ path: string;
387
+ hasPreferred: boolean;
388
+ fullPath: boolean;
389
+ }
390
+
349
391
  /**
350
392
  * Populate the breadcrumb node.
351
393
  */
352
394
  export function updateCrumbs(
353
395
  breadcrumbs: ReadonlyArray<HTMLElement>,
354
396
  separators: ReadonlyArray<HTMLElement>,
355
- path: string,
356
- hasPreferred: boolean
397
+ state: ICrumbsState
357
398
  ): void {
358
399
  const node = breadcrumbs[0].parentNode as HTMLElement;
359
400
 
@@ -363,33 +404,47 @@ namespace Private {
363
404
  node.removeChild(firstChild.nextSibling);
364
405
  }
365
406
 
366
- if (hasPreferred) {
407
+ if (state.hasPreferred) {
367
408
  node.appendChild(breadcrumbs[Crumb.Home]);
368
409
  node.appendChild(separators[0]);
369
410
  } else {
370
411
  node.appendChild(separators[0]);
371
412
  }
372
413
 
373
- const parts = path.split('/');
374
- if (parts.length > 2) {
414
+ const parts = state.path.split('/');
415
+ if (!state.fullPath && parts.length > 2) {
375
416
  node.appendChild(breadcrumbs[Crumb.Ellipsis]);
376
417
  const grandParent = parts.slice(0, parts.length - 2).join('/');
377
418
  breadcrumbs[Crumb.Ellipsis].title = grandParent;
378
419
  node.appendChild(separators[1]);
379
420
  }
380
421
 
381
- if (path) {
382
- if (parts.length >= 2) {
383
- breadcrumbs[Crumb.Parent].textContent = parts[parts.length - 2];
384
- node.appendChild(breadcrumbs[Crumb.Parent]);
385
- const parent = parts.slice(0, parts.length - 1).join('/');
386
- breadcrumbs[Crumb.Parent].title = parent;
387
- node.appendChild(separators[2]);
422
+ if (state.path) {
423
+ if (!state.fullPath) {
424
+ if (parts.length >= 2) {
425
+ breadcrumbs[Crumb.Parent].textContent = parts[parts.length - 2];
426
+ node.appendChild(breadcrumbs[Crumb.Parent]);
427
+ const parent = parts.slice(0, parts.length - 1).join('/');
428
+ breadcrumbs[Crumb.Parent].title = parent;
429
+ node.appendChild(separators[2]);
430
+ }
431
+ breadcrumbs[Crumb.Current].textContent = parts[parts.length - 1];
432
+ node.appendChild(breadcrumbs[Crumb.Current]);
433
+ breadcrumbs[Crumb.Current].title = state.path;
434
+ node.appendChild(separators[3]);
435
+ } else {
436
+ for (let i = 0; i < parts.length; i++) {
437
+ const elem = document.createElement('span');
438
+ elem.className = BREADCRUMB_ITEM_CLASS;
439
+ elem.textContent = parts[i];
440
+ const elemPath = `/${parts.slice(0, i + 1).join('/')}`;
441
+ elem.title = elemPath;
442
+ node.appendChild(elem);
443
+ const separator = document.createElement('span');
444
+ separator.textContent = '/';
445
+ node.appendChild(separator);
446
+ }
388
447
  }
389
- breadcrumbs[Crumb.Current].textContent = parts[parts.length - 1];
390
- node.appendChild(breadcrumbs[Crumb.Current]);
391
- breadcrumbs[Crumb.Current].title = path;
392
- node.appendChild(separators[3]);
393
448
  }
394
449
  }
395
450
 
package/src/listing.ts CHANGED
@@ -2251,6 +2251,8 @@ export namespace DirListing {
2251
2251
  const node = document.createElement('div');
2252
2252
  const header = document.createElement('div');
2253
2253
  const content = document.createElement('ul');
2254
+ // Allow the node to scroll while dragging items.
2255
+ content.setAttribute('data-lm-dragscroll', 'true');
2254
2256
  content.className = CONTENT_CLASS;
2255
2257
  header.className = HEADER_CLASS;
2256
2258
  node.appendChild(header);
package/src/opendialog.ts CHANGED
@@ -11,6 +11,7 @@ import { PanelLayout, Widget } from '@lumino/widgets';
11
11
  import { FileBrowser } from './browser';
12
12
  import { FilterFileBrowserModel } from './model';
13
13
  import { IFileBrowserFactory } from './tokens';
14
+ import { PromiseDelegate } from '@lumino/coreutils';
14
15
 
15
16
  /**
16
17
  * The class name added to open file dialog
@@ -43,6 +44,11 @@ export namespace FileDialog {
43
44
  * The application language translator.
44
45
  */
45
46
  translator?: ITranslator;
47
+
48
+ /**
49
+ * Default path to open
50
+ */
51
+ defaultPath?: string;
46
52
  }
47
53
 
48
54
  /**
@@ -70,11 +76,17 @@ export namespace FileDialog {
70
76
  *
71
77
  * @returns A promise that resolves with whether the dialog was accepted.
72
78
  */
73
- export function getOpenFiles(
79
+ export async function getOpenFiles(
74
80
  options: IFileOptions
75
81
  ): Promise<Dialog.IResult<Contents.IModel[]>> {
76
82
  const translator = options.translator || nullTranslator;
77
83
  const trans = translator.load('jupyterlab');
84
+ const openDialog = new OpenDialog(
85
+ options.manager,
86
+ options.filter,
87
+ translator,
88
+ options.defaultPath
89
+ );
78
90
  const dialogOptions: Partial<Dialog.IOptions<Contents.IModel[]>> = {
79
91
  title: options.title,
80
92
  buttons: [
@@ -86,8 +98,11 @@ export namespace FileDialog {
86
98
  focusNodeSelector: options.focusNodeSelector,
87
99
  host: options.host,
88
100
  renderer: options.renderer,
89
- body: new OpenDialog(options.manager, options.filter, translator)
101
+ body: openDialog
90
102
  };
103
+
104
+ await openDialog.ready;
105
+
91
106
  const dialog = new Dialog(dialogOptions);
92
107
  return dialog.launch();
93
108
  }
@@ -125,6 +140,7 @@ class OpenDialog
125
140
  manager: IDocumentManager,
126
141
  filter?: (value: Contents.IModel) => Partial<IScore> | null,
127
142
  translator?: ITranslator,
143
+ defaultPath?: string,
128
144
  filterDirectories?: boolean
129
145
  ) {
130
146
  super();
@@ -132,50 +148,63 @@ class OpenDialog
132
148
  const trans = translator.load('jupyterlab');
133
149
  this.addClass(OPEN_DIALOG_CLASS);
134
150
 
135
- this._browser = Private.createFilteredFileBrowser(
151
+ Private.createFilteredFileBrowser(
136
152
  'filtered-file-browser-dialog',
137
153
  manager,
138
154
  filter,
139
155
  {},
140
156
  translator,
157
+ defaultPath,
141
158
  filterDirectories
142
- );
159
+ )
160
+ .then(browser => {
161
+ this._browser = browser;
143
162
 
144
- // Add toolbar items
145
- setToolbar(this._browser, (browser: FileBrowser) => [
146
- {
147
- name: 'new-folder',
148
- widget: new ToolbarButton({
149
- icon: newFolderIcon,
150
- onClick: () => {
151
- void browser.createNewDirectory();
152
- },
153
- tooltip: trans.__('New Folder')
154
- })
155
- },
156
- {
157
- name: 'refresher',
158
- widget: new ToolbarButton({
159
- icon: refreshIcon,
160
- onClick: () => {
161
- browser.model.refresh().catch(reason => {
162
- console.error(
163
- 'Failed to refresh file browser in open dialog.',
164
- reason
165
- );
166
- });
163
+ // Add toolbar items
164
+ setToolbar(this._browser, (browser: FileBrowser) => [
165
+ {
166
+ name: 'new-folder',
167
+ widget: new ToolbarButton({
168
+ icon: newFolderIcon,
169
+ onClick: () => {
170
+ void browser.createNewDirectory();
171
+ },
172
+ tooltip: trans.__('New Folder')
173
+ })
167
174
  },
168
- tooltip: trans.__('Refresh File List')
169
- })
170
- }
171
- ]);
175
+ {
176
+ name: 'refresher',
177
+ widget: new ToolbarButton({
178
+ icon: refreshIcon,
179
+ onClick: () => {
180
+ browser.model.refresh().catch(reason => {
181
+ console.error(
182
+ 'Failed to refresh file browser in open dialog.',
183
+ reason
184
+ );
185
+ });
186
+ },
187
+ tooltip: trans.__('Refresh File List')
188
+ })
189
+ }
190
+ ]);
191
+
192
+ // Build the sub widgets
193
+ const layout = new PanelLayout();
194
+ layout.addWidget(this._browser);
172
195
 
173
- // Build the sub widgets
174
- const layout = new PanelLayout();
175
- layout.addWidget(this._browser);
196
+ // Set Widget content
197
+ this.layout = layout;
176
198
 
177
- // Set Widget content
178
- this.layout = layout;
199
+ this._ready.resolve();
200
+ })
201
+ .catch(reason => {
202
+ console.error(
203
+ 'Error while creating file browser in open dialog',
204
+ reason
205
+ );
206
+ this._ready.reject(void 0);
207
+ });
179
208
  }
180
209
 
181
210
  /**
@@ -203,6 +232,14 @@ class OpenDialog
203
232
  }
204
233
  }
205
234
 
235
+ /**
236
+ * A promise that resolves when openDialog is successfully created.
237
+ */
238
+ get ready(): Promise<void> {
239
+ return this._ready.promise;
240
+ }
241
+
242
+ private _ready: PromiseDelegate<void> = new PromiseDelegate<void>();
206
243
  private _browser: FileBrowser;
207
244
  }
208
245
 
@@ -229,14 +266,15 @@ namespace Private {
229
266
  * as the initial ID passed into the factory is used for only one file browser
230
267
  * instance.
231
268
  */
232
- export const createFilteredFileBrowser = (
269
+ export const createFilteredFileBrowser = async (
233
270
  id: string,
234
271
  manager: IDocumentManager,
235
272
  filter?: (value: Contents.IModel) => Partial<IScore> | null,
236
273
  options: IFileBrowserFactory.IOptions = {},
237
274
  translator?: ITranslator,
275
+ defaultPath?: string,
238
276
  filterDirectories?: boolean
239
- ): FileBrowser => {
277
+ ): Promise<FileBrowser> => {
240
278
  translator = translator || nullTranslator;
241
279
  const model = new FilterFileBrowserModel({
242
280
  manager,
@@ -246,6 +284,11 @@ namespace Private {
246
284
  refreshInterval: options.refreshInterval,
247
285
  filterDirectories
248
286
  });
287
+
288
+ if (defaultPath) {
289
+ await model.cd(defaultPath);
290
+ }
291
+
249
292
  const widget = new FileBrowser({
250
293
  id,
251
294
  model,