소스 검색

Merge pull request #5670 from gnestor/vdom-events

Add event handling support to vdom-extension
Ian Rose 6 년 전
부모
커밋
6b3c87cab1

+ 4 - 2
dev_mode/package.json

@@ -81,6 +81,7 @@
     "@jupyterlab/tooltip": "^1.0.0-alpha.3",
     "@jupyterlab/tooltip-extension": "^1.0.0-alpha.3",
     "@jupyterlab/ui-components": "^1.0.0-alpha.3",
+    "@jupyterlab/vdom": "^1.0.0-alpha.3",
     "@jupyterlab/vdom-extension": "^1.0.0-alpha.3",
     "@jupyterlab/vega5-extension": "^1.0.0-alpha.3",
     "@phosphor/algorithm": "^1.1.2",
@@ -172,13 +173,13 @@
       "@jupyterlab/terminal-extension": "",
       "@jupyterlab/theme-dark-extension": "",
       "@jupyterlab/theme-light-extension": "",
-      "@jupyterlab/tooltip-extension": ""
+      "@jupyterlab/tooltip-extension": "",
+      "@jupyterlab/vdom-extension": ""
     },
     "mimeExtensions": {
       "@jupyterlab/javascript-extension": "",
       "@jupyterlab/json-extension": "",
       "@jupyterlab/pdf-extension": "",
-      "@jupyterlab/vdom-extension": "",
       "@jupyterlab/vega5-extension": ""
     },
     "name": "JupyterLab",
@@ -304,6 +305,7 @@
       "@jupyterlab/tooltip": "../packages/tooltip",
       "@jupyterlab/tooltip-extension": "../packages/tooltip-extension",
       "@jupyterlab/ui-components": "../packages/ui-components",
+      "@jupyterlab/vdom": "../packages/vdom",
       "@jupyterlab/vdom-extension": "../packages/vdom-extension",
       "@jupyterlab/vega5-extension": "../packages/vega5-extension"
     }

+ 2 - 2
jupyterlab/staging/package.json

@@ -172,13 +172,13 @@
       "@jupyterlab/terminal-extension": "",
       "@jupyterlab/theme-dark-extension": "",
       "@jupyterlab/theme-light-extension": "",
-      "@jupyterlab/tooltip-extension": ""
+      "@jupyterlab/tooltip-extension": "",
+      "@jupyterlab/vdom-extension": ""
     },
     "mimeExtensions": {
       "@jupyterlab/javascript-extension": "",
       "@jupyterlab/json-extension": "",
       "@jupyterlab/pdf-extension": "",
-      "@jupyterlab/vdom-extension": "",
       "@jupyterlab/vega4-extension": ""
     },
     "name": "JupyterLab",

+ 1 - 0
packages/metapackage/package.json

@@ -99,6 +99,7 @@
     "@jupyterlab/tooltip": "^1.0.0-alpha.3",
     "@jupyterlab/tooltip-extension": "^1.0.0-alpha.3",
     "@jupyterlab/ui-components": "^1.0.0-alpha.3",
+    "@jupyterlab/vdom": "^1.0.0-alpha.3",
     "@jupyterlab/vdom-extension": "^1.0.0-alpha.3",
     "@jupyterlab/vega5-extension": "^1.0.0-alpha.3"
   },

+ 3 - 0
packages/metapackage/tsconfig.json

@@ -213,6 +213,9 @@
     {
       "path": "../ui-components"
     },
+    {
+      "path": "../vdom"
+    },
     {
       "path": "../vdom-extension"
     },

+ 1 - 1
packages/vdom-extension/README.md

@@ -61,7 +61,7 @@ VDOM({
 Using the [vdom Python library](https://github.com/nteract/vdom):
 
 ```python
-from vdom.helpers import h1, p, img, div, b
+from vdom import h1, p, img, div, b
 
 div(
     h1('Our Incredibly Declarative Example'),

+ 7 - 9
packages/vdom-extension/package.json

@@ -30,16 +30,14 @@
     "watch": "tsc -b --watch"
   },
   "dependencies": {
-    "@jupyterlab/rendermime-interfaces": "^1.3.0-alpha.3",
-    "@nteract/transform-vdom": "^1.1.1",
-    "@phosphor/messaging": "^1.2.2",
-    "@phosphor/widgets": "^1.6.0",
-    "react": "~16.8.4",
-    "react-dom": "~16.8.4"
+    "@jupyterlab/application": "^1.0.0-alpha.3",
+    "@jupyterlab/apputils": "^1.0.0-alpha.3",
+    "@jupyterlab/docregistry": "^1.0.0-alpha.3",
+    "@jupyterlab/notebook": "^1.0.0-alpha.4",
+    "@jupyterlab/rendermime": "^1.0.0-alpha.3",
+    "@jupyterlab/vdom": "^1.0.0-alpha.3"
   },
   "devDependencies": {
-    "@types/react": "~16.8.8",
-    "@types/react-dom": "~16.8.2",
     "rimraf": "~2.6.2",
     "typedoc": "^0.14.2",
     "typescript": "~3.3.1"
@@ -49,6 +47,6 @@
   },
   "gitHead": "31f68f6d1717b58c344a5fb4f4baf3b123b7c75c",
   "jupyterlab": {
-    "mimeExtension": true
+    "extension": true
   }
 }

+ 116 - 0
packages/vdom-extension/src/index.ts

@@ -0,0 +1,116 @@
+// Copyright (c) Jupyter Development Team.
+// Distributed under the terms of the Modified BSD License.
+
+import {
+  JupyterFrontEnd,
+  JupyterFrontEndPlugin,
+  ILayoutRestorer
+} from '@jupyterlab/application';
+
+import { InstanceTracker } from '@jupyterlab/apputils';
+
+import { MimeDocumentFactory, MimeDocument } from '@jupyterlab/docregistry';
+
+import { INotebookTracker } from '@jupyterlab/notebook';
+
+import { IRenderMimeRegistry } from '@jupyterlab/rendermime';
+
+import { RenderedVDOM, IVDOMTracker } from '@jupyterlab/vdom';
+
+/**
+ * The CSS class for a VDOM icon.
+ */
+const CSS_ICON_CLASS = 'jp-MaterialIcon jp-VDOMIcon';
+
+/**
+ * The MIME type for VDOM.
+ */
+export const MIME_TYPE = 'application/vdom.v1+json';
+
+/**
+ * The name of the factory that creates VDOM widgets.
+ */
+const FACTORY_NAME = 'VDOM';
+
+const plugin: JupyterFrontEndPlugin<IVDOMTracker> = {
+  id: '@jupyterlab/vdom-extension:factory',
+  requires: [IRenderMimeRegistry, INotebookTracker, ILayoutRestorer],
+  provides: IVDOMTracker,
+  autoStart: true,
+  activate: (
+    app: JupyterFrontEnd,
+    rendermime: IRenderMimeRegistry,
+    notebooks: INotebookTracker,
+    restorer: ILayoutRestorer
+  ) => {
+    const tracker = new InstanceTracker<MimeDocument>({
+      namespace: 'vdom-widget'
+    });
+
+    // Add a renderer factory to application rendermime registry.
+    rendermime.addFactory(
+      {
+        safe: false,
+        mimeTypes: [MIME_TYPE],
+        createRenderer: options => new RenderedVDOM(options)
+      },
+      0
+    );
+
+    notebooks.widgetAdded.connect((sender, panel) => {
+      // Get the notebook's context and rendermime;
+      const { context, rendermime } = panel;
+
+      // Add the renderer factory to the notebook's rendermime registry;
+      rendermime.addFactory(
+        {
+          safe: false,
+          mimeTypes: [MIME_TYPE],
+          createRenderer: options => new RenderedVDOM(options, context)
+        },
+        0
+      );
+    });
+
+    app.docRegistry.addFileType({
+      name: 'vdom',
+      mimeTypes: [MIME_TYPE],
+      extensions: ['.vdom', '.vdom.json'],
+      iconClass: CSS_ICON_CLASS
+    });
+
+    const factory = new MimeDocumentFactory({
+      renderTimeout: 1000,
+      dataType: 'json',
+      rendermime,
+      name: FACTORY_NAME,
+      primaryFileType: app.docRegistry.getFileType('vdom'),
+      fileTypes: ['vdom', 'json'],
+      defaultFor: ['vdom']
+    });
+
+    factory.widgetCreated.connect((sender, widget) => {
+      widget.context.pathChanged.connect(() => {
+        tracker.save(widget);
+      });
+      tracker.add(widget);
+    });
+
+    // Add widget factory to document registry.
+    app.docRegistry.addWidgetFactory(factory);
+
+    // Handle state restoration.
+    restorer.restore(tracker, {
+      command: 'docmanager:open',
+      args: widget => ({
+        path: widget.context.path,
+        factory: FACTORY_NAME
+      }),
+      name: widget => widget.context.path
+    });
+
+    return tracker;
+  }
+};
+
+export default plugin;

+ 0 - 101
packages/vdom-extension/src/index.tsx

@@ -1,101 +0,0 @@
-// Copyright (c) Jupyter Development Team.
-// Distributed under the terms of the Modified BSD License.
-
-import { Message } from '@phosphor/messaging';
-
-import { Widget } from '@phosphor/widgets';
-
-import { IRenderMime } from '@jupyterlab/rendermime-interfaces';
-
-import * as React from 'react';
-
-import * as ReactDOM from 'react-dom';
-
-import VDOM from '@nteract/transform-vdom';
-
-import '../style/index.css';
-
-/**
- * The CSS class to add to the VDOM Widget.
- */
-const CSS_CLASS = 'jp-RenderedVDOM';
-
-/**
- * The CSS class for a VDOM icon.
- */
-const CSS_ICON_CLASS = 'jp-MaterialIcon jp-VDOMIcon';
-
-/**
- * The MIME type for VDOM.
- */
-export const MIME_TYPE = 'application/vdom.v1+json';
-
-/**
- * A renderer for declarative virtual DOM content.
- */
-export class RenderedVDOM extends Widget implements IRenderMime.IRenderer {
-  /**
-   * Create a new widget for rendering DOM.
-   */
-  constructor(options: IRenderMime.IRendererOptions) {
-    super();
-    this.addClass(CSS_CLASS);
-    this.addClass('jp-RenderedHTML');
-    this.addClass('jp-RenderedHTMLCommon');
-    this._mimeType = options.mimeType;
-  }
-
-  /**
-   * Render VDOM into this widget's node.
-   */
-  renderModel(model: IRenderMime.IMimeModel): Promise<void> {
-    const data = model.data[this._mimeType] as any;
-    return new Promise<void>(resolve => {
-      ReactDOM.render(<VDOM data={data} />, this.node, resolve);
-    });
-  }
-
-  /**
-   * Called before the widget is detached from the DOM.
-   */
-  protected onBeforeDetach(msg: Message): void {
-    // Unmount the component so it can tear down.
-    ReactDOM.unmountComponentAtNode(this.node);
-  }
-
-  private _mimeType: string;
-}
-
-/**
- * A mime renderer factory for VDOM data.
- */
-export const rendererFactory: IRenderMime.IRendererFactory = {
-  safe: true,
-  mimeTypes: [MIME_TYPE],
-  createRenderer: options => new RenderedVDOM(options)
-};
-
-const extensions: IRenderMime.IExtension | IRenderMime.IExtension[] = [
-  {
-    id: '@jupyterlab/vdom-extension:factory',
-    rendererFactory,
-    rank: 0,
-    dataType: 'json',
-    fileTypes: [
-      {
-        name: 'vdom',
-        mimeTypes: [MIME_TYPE],
-        extensions: ['.vdom', '.vdom.json'],
-        iconClass: CSS_ICON_CLASS
-      }
-    ],
-    documentWidgetFactoryOptions: {
-      name: 'VDOM',
-      primaryFileType: 'vdom',
-      fileTypes: ['vdom', 'json'],
-      defaultFor: ['vdom']
-    }
-  }
-];
-
-export default extensions;

+ 0 - 20
packages/vdom-extension/src/transform-vdom.d.ts

@@ -1,20 +0,0 @@
-// Type definitions for @nteract/transform-vdom v1.1.1
-// https://github.com/jupyterlab/jupyterlab
-// Definitions by: Grant Nestor <https://github.com/gnestor>
-
-declare module '@nteract/transform-vdom' {
-  import * as React from 'react';
-
-  interface IVDOMElement {
-    tagName: 'string';
-    attributes: Object;
-    children: Array<IVDOMElement>;
-    key?: number | string | null;
-  }
-
-  interface IVDOMProps extends React.Props<VDOM> {
-    data: IVDOMElement;
-  }
-
-  export default class VDOM extends React.Component<IVDOMProps, {}> {}
-}

+ 0 - 4
packages/vdom-extension/style/index.css

@@ -21,10 +21,6 @@
   padding: 5px;
 }
 
-/* Output styles */
-.jp-OutputArea .jp-RenderedVDOM {
-}
-
 /* Document icon */
 .jp-VDOMIcon {
   background-image: var(--jp-icon-vdom);

+ 16 - 1
packages/vdom-extension/tsconfig.json

@@ -7,7 +7,22 @@
   "include": ["src/*"],
   "references": [
     {
-      "path": "../rendermime-interfaces"
+      "path": "../application"
+    },
+    {
+      "path": "../apputils"
+    },
+    {
+      "path": "../docregistry"
+    },
+    {
+      "path": "../notebook"
+    },
+    {
+      "path": "../rendermime"
+    },
+    {
+      "path": "../vdom"
     }
   ]
 }

+ 78 - 0
packages/vdom/README.md

@@ -0,0 +1,78 @@
+# vdom-extension
+
+A JupyterLab extension for rendering VirtualDOM using React
+
+![demo](http://g.recordit.co/EIwAIBsGBh.gif)
+
+## Prerequisites
+
+- JupyterLab ^0.27.0
+
+## Usage
+
+To render VDOM output in IPython:
+
+```python
+from IPython.display import display
+
+def VDOM(data={}):
+    bundle = {}
+    bundle['application/vdom.v1+json'] = data
+    display(bundle, raw=True)
+
+VDOM({
+    'tagName': 'div',
+    'attributes': {},
+    'children': [{
+        'tagName': 'h1',
+        'attributes': {},
+        'children': 'Our Incredibly Declarative Example',
+        'key': 0
+    }, {
+        'tagName': 'p',
+        'attributes': {},
+        'children': ['Can you believe we wrote this ', {
+            'tagName': 'b',
+            'attributes': {},
+            'children': 'in Python',
+            'key': 1
+        }, '?'],
+        'key': 1
+    }, {
+        'tagName': 'img',
+        'attributes': {
+            'src': 'https://media.giphy.com/media/xUPGcguWZHRC2HyBRS/giphy.gif'
+        },
+        'key': 2
+    }, {
+        'tagName': 'p',
+        'attributes': {},
+        'children': ['What will ', {
+            'tagName': 'b',
+            'attributes': {},
+            'children': 'you',
+            'key': 1
+        }, ' create next?'],
+        'key': 3
+    }]
+})
+```
+
+Using the [vdom Python library](https://github.com/nteract/vdom):
+
+```python
+from vdom import h1, p, img, div, b
+
+div(
+    h1('Our Incredibly Declarative Example'),
+    p('Can you believe we wrote this ', b('in Python'), '?'),
+    img(src="https://media.giphy.com/media/xUPGcguWZHRC2HyBRS/giphy.gif"),
+    p('What will ', b('you'), ' create next?'),
+)
+```
+
+To render a `.vdom` or `.vdom.json` file, simply open it:
+
+## Development
+
+See the [JupyterLab Contributor Documentation](https://github.com/jupyterlab/jupyterlab/blob/master/CONTRIBUTING.md).

+ 55 - 0
packages/vdom/package.json

@@ -0,0 +1,55 @@
+{
+  "name": "@jupyterlab/vdom",
+  "version": "1.0.0-alpha.3",
+  "description": "A viewer for VDOM documents.",
+  "homepage": "https://github.com/jupyterlab/jupyterlab",
+  "bugs": {
+    "url": "https://github.com/jupyterlab/jupyterlab/issues"
+  },
+  "license": "BSD-3-Clause",
+  "author": "Project Jupyter",
+  "files": [
+    "lib/*.d.ts",
+    "lib/*.js",
+    "style/*"
+  ],
+  "main": "lib/index.js",
+  "types": "lib/index.d.ts",
+  "directories": {
+    "lib": "lib/"
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/jupyterlab/jupyterlab.git"
+  },
+  "scripts": {
+    "build": "tsc -b",
+    "clean": "rimraf lib",
+    "docs": "typedoc --options tdoptions.json --theme ../../typedoc-theme src",
+    "prepublishOnly": "npm run build",
+    "watch": "tsc -b --watch"
+  },
+  "dependencies": {
+    "@jupyterlab/apputils": "^1.0.0-alpha.3",
+    "@jupyterlab/docregistry": "^1.0.0-alpha.3",
+    "@jupyterlab/rendermime-interfaces": "^1.3.0-alpha.3",
+    "@jupyterlab/services": "^4.0.0-alpha.3",
+    "@nteract/transform-vdom": "^4.0.1",
+    "@phosphor/coreutils": "^1.3.0",
+    "@phosphor/messaging": "^1.2.2",
+    "@phosphor/widgets": "^1.6.0",
+    "react": "~16.8.4",
+    "react-dom": "~16.8.4"
+  },
+  "devDependencies": {
+    "@types/react": "~16.8.8",
+    "@types/react-dom": "~16.8.2",
+    "rimraf": "~2.6.2",
+    "typedoc": "^0.14.2",
+    "typescript": "~3.3.1"
+  },
+  "publishConfig": {
+    "access": "public"
+  },
+  "gitHead": "31f68f6d1717b58c344a5fb4f4baf3b123b7c75c"
+}

+ 126 - 0
packages/vdom/src/index.tsx

@@ -0,0 +1,126 @@
+// Copyright (c) Jupyter Development Team.
+// Distributed under the terms of the Modified BSD License.
+
+import * as React from 'react';
+
+import * as ReactDOM from 'react-dom';
+
+import { IClientSession, IInstanceTracker } from '@jupyterlab/apputils';
+
+import { DocumentRegistry, MimeDocument } from '@jupyterlab/docregistry';
+
+import { IRenderMime } from '@jupyterlab/rendermime-interfaces';
+
+import { Kernel } from '@jupyterlab/services';
+
+import VDOM, { SerializedEvent } from '@nteract/transform-vdom';
+
+import { Token } from '@phosphor/coreutils';
+
+import { Message } from '@phosphor/messaging';
+
+import { Widget } from '@phosphor/widgets';
+
+import '../style/index.css';
+
+/**
+ * The CSS class to add to the VDOM Widget.
+ */
+const CSS_CLASS = 'jp-RenderedVDOM';
+
+/**
+ * A class that tracks VDOM widgets.
+ */
+export interface IVDOMTracker extends IInstanceTracker<MimeDocument> {}
+
+/**
+ * The VDOM tracker token.
+ */
+export const IVDOMTracker = new Token<IVDOMTracker>(
+  '@jupyterlab/vdom:IVDOMTracker'
+);
+
+/**
+ * A renderer for declarative virtual DOM content.
+ */
+export class RenderedVDOM extends Widget implements IRenderMime.IRenderer {
+  /**
+   * Create a new widget for rendering DOM.
+   */
+  constructor(
+    options: IRenderMime.IRendererOptions,
+    context?: DocumentRegistry.IContext<DocumentRegistry.IModel>
+  ) {
+    super();
+    this.addClass(CSS_CLASS);
+    this.addClass('jp-RenderedHTML');
+    this.addClass('jp-RenderedHTMLCommon');
+    this._mimeType = options.mimeType;
+    if (context) {
+      this._session = context.session;
+    }
+  }
+
+  /**
+   * Dispose of the widget.
+   */
+  dispose(): void {
+    // Dispose of comm disposables
+    for (let targetName in this._comms) {
+      this._comms[targetName].dispose();
+    }
+    super.dispose();
+  }
+
+  /**
+   * Called before the widget is detached from the DOM.
+   */
+  protected onBeforeDetach(msg: Message): void {
+    // Dispose of React component(s).
+    ReactDOM.unmountComponentAtNode(this.node);
+  }
+
+  /**
+   * Render VDOM into this widget's node.
+   */
+  renderModel(model: IRenderMime.IMimeModel): Promise<void> {
+    return new Promise((resolve, reject) => {
+      const data = model.data[this._mimeType] as any;
+      ReactDOM.render(
+        <VDOM data={data} onVDOMEvent={this.handleVDOMEvent} />,
+        this.node,
+        () => {
+          resolve();
+        }
+      );
+    });
+  }
+
+  /**
+   * Handle events for VDOM element.
+   */
+  handleVDOMEvent = (targetName: string, event: SerializedEvent<any>): void => {
+    // When a VDOM element's event handler is called, send a serialized
+    // representation of the event to the registered comm channel for the
+    // kernel to handle
+    if (this._timer) {
+      window.clearTimeout(this._timer);
+    }
+    if (this._session) {
+      this._timer = window.setTimeout(() => {
+        if (!this._comms[targetName]) {
+          this._comms[targetName] = this._session.kernel.connectToComm(
+            targetName
+          );
+          this._comms[targetName].open();
+        }
+        this._comms[targetName].send(JSON.stringify(event));
+      }, 16);
+    }
+  };
+
+  private _mimeType: string;
+  private _session?: IClientSession;
+  private _comms: { [targetName: string]: Kernel.IComm } = {};
+  private _timer: number;
+}

+ 29 - 0
packages/vdom/style/index.css

@@ -0,0 +1,29 @@
+/**
+  Copyright (c) Jupyter Development Team.
+  Distributed under the terms of the Modified BSD License.
+*/
+
+/* Add CSS variables to :root */
+:root {
+  --jp-icon-vdom: url('./react.svg');
+}
+
+/* Base styles */
+.jp-RenderedVDOM {
+  width: 100%;
+  height: 100%;
+  padding: 0;
+  overflow: auto;
+}
+
+/* Document styles */
+.jp-MimeDocument .jp-RenderedVDOM {
+  padding: 5px;
+}
+
+/* Document icon */
+.jp-VDOMIcon {
+  background-image: var(--jp-icon-vdom);
+  background-size: 24px;
+  background-position: center !important;
+}

+ 35 - 0
packages/vdom/style/react.svg

@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_2_1_" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 841.9 595.3" enable-background="new 0 0 841.9 595.3" xml:space="preserve">
+<g>
+	<path fill="#61DAFB" d="M666.3,296.5c0-32.5-40.7-63.3-103.1-82.4c14.4-63.6,8-114.2-20.2-130.4c-6.5-3.8-14.1-5.6-22.4-5.6v22.3
+		c4.6,0,8.3,0.9,11.4,2.6c13.6,7.8,19.5,37.5,14.9,75.7c-1.1,9.4-2.9,19.3-5.1,29.4c-19.6-4.8-41-8.5-63.5-10.9
+		c-13.5-18.5-27.5-35.3-41.6-50c32.6-30.3,63.2-46.9,84-46.9l0-22.3c0,0,0,0,0,0c-27.5,0-63.5,19.6-99.9,53.6
+		c-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7,0,51.4,16.5,84,46.6c-14,14.7-28,31.4-41.3,49.9c-22.6,2.4-44,6.1-63.6,11
+		c-2.3-10-4-19.7-5.2-29c-4.7-38.2,1.1-67.9,14.6-75.8c3-1.8,6.9-2.6,11.5-2.6l0-22.3c0,0,0,0,0,0c-8.4,0-16,1.8-22.6,5.6
+		c-28.1,16.2-34.4,66.7-19.9,130.1c-62.2,19.2-102.7,49.9-102.7,82.3c0,32.5,40.7,63.3,103.1,82.4c-14.4,63.6-8,114.2,20.2,130.4
+		c6.5,3.8,14.1,5.6,22.5,5.6c27.5,0,63.5-19.6,99.9-53.6c36.4,33.8,72.4,53.2,99.9,53.2c8.4,0,16-1.8,22.6-5.6
+		c28.1-16.2,34.4-66.7,19.9-130.1C625.8,359.7,666.3,328.9,666.3,296.5z M536.1,229.8c-3.7,12.9-8.3,26.2-13.5,39.5
+		c-4.1-8-8.4-16-13.1-24c-4.6-8-9.5-15.8-14.4-23.4C509.3,224,523,226.6,536.1,229.8z M490.3,336.3c-7.8,13.5-15.8,26.3-24.1,38.2
+		c-14.9,1.3-30,2-45.2,2c-15.1,0-30.2-0.7-45-1.9c-8.3-11.9-16.4-24.6-24.2-38c-7.6-13.1-14.5-26.4-20.8-39.8
+		c6.2-13.4,13.2-26.8,20.7-39.9c7.8-13.5,15.8-26.3,24.1-38.2c14.9-1.3,30-2,45.2-2c15.1,0,30.2,0.7,45,1.9
+		c8.3,11.9,16.4,24.6,24.2,38c7.6,13.1,14.5,26.4,20.8,39.8C504.7,309.8,497.8,323.2,490.3,336.3z M522.6,323.3
+		c5.4,13.4,10,26.8,13.8,39.8c-13.1,3.2-26.9,5.9-41.2,8c4.9-7.7,9.8-15.6,14.4-23.7C514.2,339.4,518.5,331.3,522.6,323.3z
+		 M421.2,430c-9.3-9.6-18.6-20.3-27.8-32c9,0.4,18.2,0.7,27.5,0.7c9.4,0,18.7-0.2,27.8-0.7C439.7,409.7,430.4,420.4,421.2,430z
+		 M346.8,371.1c-14.2-2.1-27.9-4.7-41-7.9c3.7-12.9,8.3-26.2,13.5-39.5c4.1,8,8.4,16,13.1,24C337.1,355.7,341.9,363.5,346.8,371.1z
+		 M420.7,163c9.3,9.6,18.6,20.3,27.8,32c-9-0.4-18.2-0.7-27.5-0.7c-9.4,0-18.7,0.2-27.8,0.7C402.2,183.3,411.5,172.6,420.7,163z
+		 M346.7,221.9c-4.9,7.7-9.8,15.6-14.4,23.7c-4.6,8-8.9,16-13,24c-5.4-13.4-10-26.8-13.8-39.8C318.6,226.7,332.4,224,346.7,221.9z
+		 M256.2,347.1c-35.4-15.1-58.3-34.9-58.3-50.6c0-15.7,22.9-35.6,58.3-50.6c8.6-3.7,18-7,27.7-10.1c5.7,19.6,13.2,40,22.5,60.9
+		c-9.2,20.8-16.6,41.1-22.2,60.6C274.3,354.2,264.9,350.8,256.2,347.1z M310,490c-13.6-7.8-19.5-37.5-14.9-75.7
+		c1.1-9.4,2.9-19.3,5.1-29.4c19.6,4.8,41,8.5,63.5,10.9c13.5,18.5,27.5,35.3,41.6,50c-32.6,30.3-63.2,46.9-84,46.9
+		C316.8,492.6,313,491.7,310,490z M547.2,413.8c4.7,38.2-1.1,67.9-14.6,75.8c-3,1.8-6.9,2.6-11.5,2.6c-20.7,0-51.4-16.5-84-46.6
+		c14-14.7,28-31.4,41.3-49.9c22.6-2.4,44-6.1,63.6-11C544.3,394.8,546.1,404.5,547.2,413.8z M585.7,347.1c-8.6,3.7-18,7-27.7,10.1
+		c-5.7-19.6-13.2-40-22.5-60.9c9.2-20.8,16.6-41.1,22.2-60.6c9.9,3.1,19.3,6.5,28.1,10.2c35.4,15.1,58.3,34.9,58.3,50.6
+		C644,312.2,621.1,332.1,585.7,347.1z"/>
+	<polygon fill="#61DAFB" points="320.8,78.4 320.8,78.4 320.8,78.4 	"/>
+	<circle fill="#61DAFB" cx="420.9" cy="296.5" r="45.7"/>
+	<polygon fill="#61DAFB" points="520.5,78.1 520.5,78.1 520.5,78.1 	"/>
+</g>
+</svg>

+ 20 - 0
packages/vdom/tdoptions.json

@@ -0,0 +1,20 @@
+{
+  "excludeNotExported": true,
+  "mode": "file",
+  "target": "es5",
+  "module": "es5",
+  "lib": [
+    "lib.es2015.d.ts",
+    "lib.es2015.collection.d.ts",
+    "lib.es2015.promise.d.ts",
+    "lib.dom.d.ts"
+  ],
+  "out": "../../docs/api/vdom",
+  "baseUrl": ".",
+  "paths": {
+    "@jupyterlab/*": ["../packages/*"]
+  },
+  "esModuleInterop": true,
+  "jsx": "react",
+  "types": []
+}

+ 22 - 0
packages/vdom/tsconfig.json

@@ -0,0 +1,22 @@
+{
+  "extends": "../../tsconfigbase",
+  "compilerOptions": {
+    "outDir": "lib",
+    "rootDir": "src"
+  },
+  "include": ["src/*"],
+  "references": [
+    {
+      "path": "../apputils"
+    },
+    {
+      "path": "../docregistry"
+    },
+    {
+      "path": "../rendermime-interfaces"
+    },
+    {
+      "path": "../services"
+    }
+  ]
+}

+ 5 - 3
yarn.lock

@@ -568,9 +568,11 @@
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.2.tgz#54c5a964462be3d4d78af631363c18d6fa91ac26"
 
-"@nteract/transform-vdom@^1.1.1":
-  version "1.1.1"
-  resolved "https://registry.yarnpkg.com/@nteract/transform-vdom/-/transform-vdom-1.1.1.tgz#49258c58a3704c89b20cc42b5be463d7802406fa"
+"@nteract/transform-vdom@^4.0.1":
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/@nteract/transform-vdom/-/transform-vdom-4.0.1.tgz#66149021f3bc8dfee9867711623dc8aec0bfc574"
+  dependencies:
+    lodash "^4.17.4"
 
 "@phosphor/algorithm@^1.1.2":
   version "1.1.2"