Prechádzať zdrojové kódy

wip update dialog api

Steven Silvester 7 rokov pred
rodič
commit
c1542724b6
1 zmenil súbory, kde vykonal 50 pridanie a 17 odobranie
  1. 50 17
      packages/apputils/src/dialog.ts

+ 50 - 17
packages/apputils/src/dialog.ts

@@ -34,7 +34,7 @@ import {
  * @returns A promise that resolves with whether the dialog was accepted.
  */
 export
-function showDialog(options: Dialog.IOptions={}): Promise<Dialog.IButton> {
+function showDialog<T>(options: Dialog.IOptions<T>={}): Promise<Dialog.IResult<T>> {
   let dialog = new Dialog(options);
   return dialog.launch().then(result => {
     dialog.dispose();
@@ -47,13 +47,13 @@ function showDialog(options: Dialog.IOptions={}): Promise<Dialog.IButton> {
  * A modal dialog widget.
  */
 export
-class Dialog extends Widget {
+class Dialog<T> extends Widget {
   /**
    * Create a dialog panel instance.
    *
    * @param options - The dialog setup options.
    */
-  constructor(options: Dialog.IOptions={}) {
+  constructor(options: Dialog.IOptions<T>={}) {
     super();
     this.addClass('jp-Dialog');
     options = Private.handleOptions(options);
@@ -65,9 +65,6 @@ class Dialog extends Widget {
     this._buttonNodes = toArray(map(this._buttons, button => {
       return renderer.createButtonNode(button);
     }));
-    this._primary = (
-      options.primaryElement || this._buttonNodes[this._defaultButton]
-    );
 
     let layout = this.layout = new PanelLayout();
     let content = new Panel();
@@ -80,6 +77,15 @@ class Dialog extends Widget {
     content.addWidget(header);
     content.addWidget(body);
     content.addWidget(footer);
+
+    if (typeof options.primaryElement === 'string') {
+      let els = body.node.querySelectorAll(options.primaryElement) as HTMLElement[];
+      this._primary = (els && els[0]) || this._buttonNodes[this._defaultButton];
+    } else {
+      this._primary = (
+        options.primaryElement || this._buttonNodes[this._defaultButton]
+      );
+    }
   }
 
   /**
@@ -100,12 +106,12 @@ class Dialog extends Widget {
    *
    * @returns a promise that resolves with the button that was selected.
    */
-  launch(): Promise<Dialog.IButton> {
+  launch(): Promise<Dialog.IResult<T>> {
     // Return the existing dialog if already open.
     if (this._promise) {
       return this._promise.promise;
     }
-    this._promise = new PromiseDelegate<Dialog.IButton>();
+    this._promise = new PromiseDelegate<Dialog.IResult<T>>();
     let promise = Promise.all(Private.launchQueue);
     Private.launchQueue.push(this._promise.promise);
     return promise.then(() => {
@@ -131,7 +137,7 @@ class Dialog extends Widget {
     if (index === undefined) {
       index = this._defaultButton;
     }
-    this._resolve(this._buttons[index]);
+    this._resolve({ ...this._buttons[index], value: null });
   }
 
   /**
@@ -144,7 +150,7 @@ class Dialog extends Widget {
     if (!this._promise) {
       return;
     }
-    this._resolve(Dialog.cancelButton());
+    this._resolve({ ...Dialog.cancelButton(), value: null });
   }
 
   /**
@@ -281,7 +287,7 @@ class Dialog extends Widget {
   /**
    * Resolve a button item.
    */
-  private _resolve(item: Dialog.IButton): void {
+  private _resolve(item: Dialog.IResult<T>): void {
     // Prevent loopback.
     let promise = this._promise;
     this._promise = null;
@@ -310,7 +316,7 @@ namespace Dialog {
    * The options used to create a dialog.
    */
   export
-  interface IOptions {
+  interface IOptions<T> {
     /**
      * The top level text for the dialog.  Defaults to an empty string.
      */
@@ -321,10 +327,14 @@ namespace Dialog {
      * Defaults to an empty string.
      *
      * #### Notes
+     * If a widget is given as the body, it will be disposed after the
+     * dialog is resolved.  If the widget has a `getValue()` method,
+     * the method will be called prior to disposal and the value
+     * will be provided as part of the dialog result.
      * A string argument will be used as raw `textContent`.
      * All `input` and `select` nodes will be wrapped and styled.
      */
-    body?: BodyType;
+    body?: BodyType<T>;
 
     /**
      * The host element for the dialog. Defaults to `document.body`.
@@ -343,9 +353,10 @@ namespace Dialog {
 
     /**
      * The primary element that should take focus in the dialog.
-     * Defaults to the default button's element.
+     * Defaults to the default button's element.  Can be given as
+     * as selector string.
      */
-    primaryElement?: HTMLElement;
+    primaryElement?: HTMLElement | string;
 
     /**
      * An optional renderer for dialog items.  Defaults to a shared
@@ -405,13 +416,35 @@ namespace Dialog {
    * The header input types.
    */
   export
-  type HeaderType = HTMLElement | string;
+  type HeaderType = VirtualElement | string;
+
+  /**
+   * The result of a dialog.
+   */
+  export
+  interface IResult<T> extends IButton {
+    /**
+     * The value retrieved from `.getValue()` if given on the widget.
+     */
+    value: T;
+  }
+
+  /**
+   * A widget used as a dialog body.
+   */
+  export
+  interface IBodyWidget<T> extends Widget {
+    /**
+     * Get the serialized value of the widget.
+     */
+    getValue(): T;
+  }
 
   /**
    * The body input types.
    */
   export
-  type BodyType = Widget | HTMLElement | string;
+  type BodyType<T> = Widget | IBodyWidget<T> | VirtualElement | string;
 
   /**
    * Create an accept button.