From 4576241f0883b68397d4e724e30da0386a613375 Mon Sep 17 00:00:00 2001 From: Pragya Garg Date: Tue, 10 Mar 2020 11:39:38 +0530 Subject: [PATCH 1/4] Added lazy loading to jupyterlab-plotly With this change, plotly.js will be loaded on demand. This uses dynamic imports to achieve this. Fixes #1913 --- .../src/javascript-renderer-extension.ts | 38 +++++++++++-------- .../jupyterlab-plotly/tsconfig.json | 2 +- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/packages/javascript/jupyterlab-plotly/src/javascript-renderer-extension.ts b/packages/javascript/jupyterlab-plotly/src/javascript-renderer-extension.ts index b724e5df551..1cd9606054e 100644 --- a/packages/javascript/jupyterlab-plotly/src/javascript-renderer-extension.ts +++ b/packages/javascript/jupyterlab-plotly/src/javascript-renderer-extension.ts @@ -7,8 +7,6 @@ import { Message } from '@lumino/messaging'; import { IRenderMime } from '@jupyterlab/rendermime-interfaces'; -import Plotly from 'plotly.js/dist/plotly.min'; - import '../style/index.css'; /** @@ -27,12 +25,12 @@ const CSS_ICON_CLASS = 'jp-MaterialIcon jp-PlotlyIcon'; */ export const MIME_TYPE = 'application/vnd.plotly.v1+json'; -interface IPlotlySpec { - data: Plotly.Data; - layout: Plotly.Layout; - frames?: Plotly.Frame[]; +interface PlotlyHTMLElement extends HTMLElement { + on(event: 'plotly_webglcontextlost', callback: () => void): void; } +type Frame = { [key: string]: any }; + export class RenderedPlotly extends Widget implements IRenderMime.IRenderer { /** * Create a new widget for rendering Plotly. @@ -48,8 +46,11 @@ export class RenderedPlotly extends Widget implements IRenderMime.IRenderer { this.node.appendChild(this._img_el); // Install image hover callback - this._img_el.addEventListener('mouseenter', event => { - this.createGraph(this._model); + import(/* webpackChunkName: 'plotly'*/ 'plotly.js/dist/plotly').then(Plotly => { + + this._img_el.addEventListener('mouseenter', event => { + this.createGraph(this._model, Plotly); + }) }) } @@ -74,7 +75,9 @@ export class RenderedPlotly extends Widget implements IRenderMime.IRenderer { return Promise.resolve(); } else { // Create a new graph - return this.createGraph(model); + return import(/* webpackChunkName: 'plotly'*/ 'plotly.js/dist/plotly').then(Plotly => { + this.createGraph(model, Plotly); + }) } } @@ -122,10 +125,11 @@ export class RenderedPlotly extends Widget implements IRenderMime.IRenderer { } } - private createGraph(model: IRenderMime.IMimeModel) { + private createGraph(model: IRenderMime.IMimeModel, Plotly: any) { const { data, layout, frames, config } = model.data[this._mimeType] as | any - | IPlotlySpec; + | { data: Plotly.Data; layout: Plotly.Layout; frames?: Frame[]; } + | { data: Plotly.Data; layout: Plotly.Layout; frames?: Plotly.Frame[]; } return Plotly.react(this.node, data, layout, config).then(plot => { this.showGraph(); @@ -153,7 +157,7 @@ export class RenderedPlotly extends Widget implements IRenderMime.IRenderer { } // Handle webgl context lost events - ((this.node)).on('plotly_webglcontextlost', () => { + ((this.node)).on('plotly_webglcontextlost', () => { const png_data = model.data['image/png']; if(png_data !== undefined && png_data !== null) { // We have PNG data, use it @@ -183,9 +187,11 @@ export class RenderedPlotly extends Widget implements IRenderMime.IRenderer { */ protected onUpdateRequest(msg: Message): void { if (this.isVisible && this.hasGraphElement()) { - Plotly.redraw(this.node).then(() => { - Plotly.Plots.resize(this.node); - }); + import(/* webpackChunkName: 'plotly'*/ 'plotly.js/dist/plotly').then(Plotly => { + Plotly.redraw(this.node).then(() => { + Plotly.Plots.resize(this.node); + }); + }) } } @@ -226,4 +232,4 @@ const extensions: IRenderMime.IExtension | IRenderMime.IExtension[] = [ } ]; -export default extensions; +export default extensions; \ No newline at end of file diff --git a/packages/javascript/jupyterlab-plotly/tsconfig.json b/packages/javascript/jupyterlab-plotly/tsconfig.json index 9a2060c62d5..ba5bfbdddf6 100644 --- a/packages/javascript/jupyterlab-plotly/tsconfig.json +++ b/packages/javascript/jupyterlab-plotly/tsconfig.json @@ -8,7 +8,7 @@ "noUnusedLocals": true, "esModuleInterop": true, "preserveWatchOutput": true, - "module": "commonjs", + "module": "esnext", "moduleResolution": "node", "target": "es2015", "lib": ["dom", "es2015"], From 4ced854bbe6e56ebbb604a96850ed92f5b61d4a1 Mon Sep 17 00:00:00 2001 From: Pragya Garg Date: Tue, 31 Mar 2020 12:43:24 +0530 Subject: [PATCH 2/4] Added lazy loading to plotlywidget --- packages/javascript/plotlywidget/package.json | 4 +- .../javascript/plotlywidget/src/Figure.js | 432 +++++++++--------- 2 files changed, 229 insertions(+), 207 deletions(-) diff --git a/packages/javascript/plotlywidget/package.json b/packages/javascript/plotlywidget/package.json index 7bd03cf5c71..f1bee1579c5 100644 --- a/packages/javascript/plotlywidget/package.json +++ b/packages/javascript/plotlywidget/package.json @@ -1,6 +1,6 @@ { "name": "plotlywidget", - "version": "1.5.3", + "version": "1.5.5", "description": "The plotly JupyterLab extension", "author": "The plotly.py team", "license": "MIT", @@ -23,7 +23,7 @@ ], "scripts": { "build": "webpack", - "clean": "rimraf dist/ && rimraf ../../python/plotly/plotlywidget/static'", + "clean": "rimraf dist/ && rimraf ../../python/plotly/plotlywidget/static", "test": "echo \"Error: no test specified\" && exit 1" }, "devDependencies": { diff --git a/packages/javascript/plotlywidget/src/Figure.js b/packages/javascript/plotlywidget/src/Figure.js index 25a454ec89f..8d98cddcb16 100644 --- a/packages/javascript/plotlywidget/src/Figure.js +++ b/packages/javascript/plotlywidget/src/Figure.js @@ -2,7 +2,6 @@ var widgets = require("@jupyter-widgets/base"); var _ = require("lodash"); window.PlotlyConfig = {MathJaxConfig: 'local'}; -var Plotly = require("plotly.js/dist/plotly.min"); var semver_range = "^" + require("../package.json").version; // Model @@ -709,110 +708,117 @@ var FigureView = widgets.DOMWidgetView.extend({ var initialLayout = _.cloneDeep(this.model.get("_layout")); var config = this.model.get("_config"); - Plotly.newPlot(that.el, initialTraces, initialLayout, config).then( - function () { - - // ### Send trace deltas ### - // We create an array of deltas corresponding to the new - // traces. - that._sendTraceDeltas(trace_edit_id); - - // ### Send layout delta ### - that._sendLayoutDelta(layout_edit_id); + import(/* webpackChunkName: 'plotly' */ 'plotly.js/dist/plotly').then(Plotly => { + Plotly.newPlot(that.el, initialTraces, initialLayout, config).then( + function () { - // Wire up plotly event callbacks - that.el.on("plotly_restyle", - function (update) { - that.handle_plotly_restyle(update) - }); - that.el.on("plotly_relayout", - function (update) { - that.handle_plotly_relayout(update) - }); - that.el.on("plotly_update", - function (update) { - that.handle_plotly_update(update) - }); - that.el.on("plotly_click", - function (update) { - that.handle_plotly_click(update) - }); - that.el.on("plotly_hover", - function (update) { - that.handle_plotly_hover(update) - }); - that.el.on("plotly_unhover", - function (update) { - that.handle_plotly_unhover(update) - }); - that.el.on("plotly_selected", - function (update) { - that.handle_plotly_selected(update) - }); - that.el.on("plotly_deselect", - function (update) { - that.handle_plotly_deselect(update) - }); - that.el.on("plotly_doubleclick", - function (update) { - that.handle_plotly_doubleclick(update) - }); + // ### Send trace deltas ### + // We create an array of deltas corresponding to the new + // traces. + that._sendTraceDeltas(trace_edit_id); - // Emit event indicating that the widget has finished - // rendering - var event = new CustomEvent("plotlywidget-after-render", - { "detail": {"element": that.el, 'viewID': that.viewID}}); + // ### Send layout delta ### + that._sendLayoutDelta(layout_edit_id); - // Dispatch/Trigger/Fire the event - document.dispatchEvent(event); - }); + // Wire up plotly event callbacks + that.el.on("plotly_restyle", + function (update) { + that.handle_plotly_restyle(update) + }); + that.el.on("plotly_relayout", + function (update) { + that.handle_plotly_relayout(update) + }); + that.el.on("plotly_update", + function (update) { + that.handle_plotly_update(update) + }); + that.el.on("plotly_click", + function (update) { + that.handle_plotly_click(update) + }); + that.el.on("plotly_hover", + function (update) { + that.handle_plotly_hover(update) + }); + that.el.on("plotly_unhover", + function (update) { + that.handle_plotly_unhover(update) + }); + that.el.on("plotly_selected", + function (update) { + that.handle_plotly_selected(update) + }); + that.el.on("plotly_deselect", + function (update) { + that.handle_plotly_deselect(update) + }); + that.el.on("plotly_doubleclick", + function (update) { + that.handle_plotly_doubleclick(update) + }); + + // Emit event indicating that the widget has finished + // rendering + var event = new CustomEvent("plotlywidget-after-render", + {"detail": {"element": that.el, 'viewID': that.viewID}}); + + // Dispatch/Trigger/Fire the event + document.dispatchEvent(event); + }); + }) }, /** * Respond to phosphorjs events */ processPhosphorMessage: function(msg) { - FigureView.__super__.processPhosphorMessage.apply(this, arguments); - var that = this; - switch (msg.type) { - case 'before-attach': - // Render an initial empty figure. This establishes with - // the page that the element will not be empty, avoiding - // some occasions where the dynamic sizing behavior leads - // to collapsed figure dimensions. - var axisHidden = { - showgrid: false, showline: false, tickvals: []}; - - Plotly.newPlot(that.el, [], { - xaxis: axisHidden, yaxis: axisHidden - }); + import(/* webpackChunkName: 'plotly' */ 'plotly.js/dist/plotly').then(Plotly => { + FigureView.__super__.processPhosphorMessage.apply(this, arguments); + var that = this; + switch (msg.type) { + case 'before-attach': + // Render an initial empty figure. This establishes with + // the page that the element will not be empty, avoiding + // some occasions where the dynamic sizing behavior leads + // to collapsed figure dimensions. + var axisHidden = { + showgrid: false, showline: false, tickvals: [] + }; + + Plotly.newPlot(that.el, [], { + xaxis: axisHidden, yaxis: axisHidden + }); - window.addEventListener("resize", function(){ - that.autosizeFigure(); - }); - break; - case 'after-attach': - // Rendering actual figure in the after-attach event allows - // Plotly.js to size the figure to fill the available element - this.perform_render(); - break; - case 'resize': - this.autosizeFigure(); - break - } + window.addEventListener("resize", function () { + that.autosizeFigure(); + }); + break; + case 'after-attach': + // Rendering actual figure in the after-attach event allows + // Plotly.js to size the figure to fill the available element + this.perform_render(); + break; + case 'resize': + this.autosizeFigure(); + break + } + }) }, autosizeFigure: function() { - var that = this; - var layout = that.model.get('_layout'); - if (_.isNil(layout) || - _.isNil(layout.width)) { - Plotly.Plots.resize(that.el).then(function(){ - var layout_edit_id = that.model.get( - "_last_layout_edit_id"); - that._sendLayoutDelta(layout_edit_id); - }); - } + import(/* webpackChunkName: 'plotly' */ 'plotly.js/dist/plotly').then(Plotly => { + var that = this; + var layout = that.model.get('_layout'); + if (_.isNil(layout) || + _.isNil(layout.width)) { + Plotly.Plots.resize(that.el).then(function () { + var layout_edit_id = that.model.get( + "_last_layout_edit_id"); + that._sendLayoutDelta(layout_edit_id); + }); + } + }) }, /** @@ -820,7 +826,9 @@ var FigureView = widgets.DOMWidgetView.extend({ * element when the view is destroyed */ destroy: function() { - Plotly.purge(this.el); + import(/* webpackChunkName: 'plotly' */ 'plotly.js/dist/plotly').then(Plotly => { + Plotly.purge(this.el); + }) }, /** @@ -1139,191 +1147,205 @@ var FigureView = widgets.DOMWidgetView.extend({ * Handle Plotly.addTraces request */ do_addTraces: function () { + import(/* webpackChunkName: 'plotly' */ 'plotly.js/dist/plotly').then(Plotly => { - /** @type {Py2JsAddTracesMsg} */ - var msgData = this.model.get("_py2js_addTraces"); + /** @type {Py2JsAddTracesMsg} */ + var msgData = this.model.get("_py2js_addTraces"); - if (msgData !== null) { + if (msgData !== null) { - // Save off original number of traces - var prevNumTraces = this.el.data.length; + // Save off original number of traces + var prevNumTraces = this.el.data.length; - var that = this; - Plotly.addTraces(this.el, msgData.trace_data).then(function () { + var that = this; + Plotly.addTraces(this.el, msgData.trace_data).then(function () { - // ### Send trace deltas ### - that._sendTraceDeltas(msgData.trace_edit_id); + // ### Send trace deltas ### + that._sendTraceDeltas(msgData.trace_edit_id); - // ### Send layout delta ### - var layout_edit_id = msgData.layout_edit_id; - that._sendLayoutDelta(layout_edit_id); - }); - } + // ### Send layout delta ### + var layout_edit_id = msgData.layout_edit_id; + that._sendLayoutDelta(layout_edit_id); + }); + } + }) }, /** * Handle Plotly.deleteTraces request */ do_deleteTraces: function () { + import(/* webpackChunkName: 'plotly' */ 'plotly.js/dist/plotly').then(Plotly => { - /** @type {Py2JsDeleteTracesMsg} */ - var msgData = this.model.get("_py2js_deleteTraces"); + /** @type {Py2JsDeleteTracesMsg} */ + var msgData = this.model.get("_py2js_deleteTraces"); - if (msgData !== null){ - var delete_inds = msgData.delete_inds; - var that = this; - Plotly.deleteTraces(this.el, delete_inds).then(function () { + if (msgData !== null) { + var delete_inds = msgData.delete_inds; + var that = this; + Plotly.deleteTraces(this.el, delete_inds).then(function () { - // ### Send trace deltas ### - var trace_edit_id = msgData.trace_edit_id; - that._sendTraceDeltas(trace_edit_id); + // ### Send trace deltas ### + var trace_edit_id = msgData.trace_edit_id; + that._sendTraceDeltas(trace_edit_id); - // ### Send layout delta ### - var layout_edit_id = msgData.layout_edit_id; - that._sendLayoutDelta(layout_edit_id); - }); - } + // ### Send layout delta ### + var layout_edit_id = msgData.layout_edit_id; + that._sendLayoutDelta(layout_edit_id); + }); + } + }) }, /** * Handle Plotly.moveTraces request */ do_moveTraces: function () { + import(/* webpackChunkName: 'plotly' */ 'plotly.js/dist/plotly').then(Plotly => { - /** @type {Py2JsMoveTracesMsg} */ - var msgData = this.model.get("_py2js_moveTraces"); + /** @type {Py2JsMoveTracesMsg} */ + var msgData = this.model.get("_py2js_moveTraces"); - if (msgData !== null){ - // Unpack message - var currentInds = msgData.current_trace_inds; - var newInds = msgData.new_trace_inds; + if (msgData !== null) { + // Unpack message + var currentInds = msgData.current_trace_inds; + var newInds = msgData.new_trace_inds; - // Check if the new trace indexes are actually different than - // the current indexes - var inds_equal = _.isEqual(currentInds, newInds); + // Check if the new trace indexes are actually different than + // the current indexes + var inds_equal = _.isEqual(currentInds, newInds); - if (!inds_equal) { - Plotly.moveTraces(this.el, currentInds, newInds) + if (!inds_equal) { + Plotly.moveTraces(this.el, currentInds, newInds) + } } - } + }) }, /** * Handle Plotly.restyle request */ do_restyle: function () { + import(/* webpackChunkName: 'plotly' */ 'plotly.js/dist/plotly').then(Plotly => { - /** @type {Py2JsRestyleMsg} */ - var msgData = this.model.get("_py2js_restyle"); - if (msgData !== null) { - var restyleData = msgData.restyle_data; - var traceIndexes = this.model._normalize_trace_indexes( - msgData.restyle_traces); + /** @type {Py2JsRestyleMsg} */ + var msgData = this.model.get("_py2js_restyle"); + if (msgData !== null) { + var restyleData = msgData.restyle_data; + var traceIndexes = this.model._normalize_trace_indexes( + msgData.restyle_traces); - restyleData["_doNotReportToPy"] = true; - Plotly.restyle(this.el, restyleData, traceIndexes); + restyleData["_doNotReportToPy"] = true; + Plotly.restyle(this.el, restyleData, traceIndexes); - // ### Send trace deltas ### - // We create an array of deltas corresponding to the restyled - // traces. - this._sendTraceDeltas(msgData.trace_edit_id); + // ### Send trace deltas ### + // We create an array of deltas corresponding to the restyled + // traces. + this._sendTraceDeltas(msgData.trace_edit_id); - // ### Send layout delta ### - var layout_edit_id = msgData.layout_edit_id; - this._sendLayoutDelta(layout_edit_id); - } + // ### Send layout delta ### + var layout_edit_id = msgData.layout_edit_id; + this._sendLayoutDelta(layout_edit_id); + } + }) }, /** * Handle Plotly.relayout request */ do_relayout: function () { + import(/* webpackChunkName: 'plotly' */ 'plotly.js/dist/plotly').then(Plotly => { + + /** @type {Py2JsRelayoutMsg} */ + var msgData = this.model.get("_py2js_relayout"); + if (msgData !== null) { + if (msgData.source_view_id !== this.viewID) { + var relayoutData = msgData.relayout_data; + relayoutData["_doNotReportToPy"] = true; + Plotly.relayout(this.el, msgData.relayout_data); + } - /** @type {Py2JsRelayoutMsg} */ - var msgData = this.model.get("_py2js_relayout"); - if (msgData !== null) { - if (msgData.source_view_id !== this.viewID) { - var relayoutData = msgData.relayout_data; - relayoutData["_doNotReportToPy"] = true; - Plotly.relayout(this.el, msgData.relayout_data); + // ### Send layout delta ### + var layout_edit_id = msgData.layout_edit_id; + this._sendLayoutDelta(layout_edit_id); } - - // ### Send layout delta ### - var layout_edit_id = msgData.layout_edit_id; - this._sendLayoutDelta(layout_edit_id); - } + }) }, /** * Handle Plotly.update request */ do_update: function () { + import(/* webpackChunkName: 'plotly' */ 'plotly.js/dist/plotly').then(Plotly => { - /** @type {Py2JsUpdateMsg} */ - var msgData = this.model.get("_py2js_update"); + /** @type {Py2JsUpdateMsg} */ + var msgData = this.model.get("_py2js_update"); - if (msgData !== null) { - var style = msgData.style_data || {}; - var layout = msgData.layout_data || {}; - var traceIndexes = this.model._normalize_trace_indexes( - msgData.style_traces); + if (msgData !== null) { + var style = msgData.style_data || {}; + var layout = msgData.layout_data || {}; + var traceIndexes = this.model._normalize_trace_indexes( + msgData.style_traces); - style["_doNotReportToPy"] = true; + style["_doNotReportToPy"] = true; Plotly.update(this.el, style, layout, traceIndexes); - // ### Send trace deltas ### - // We create an array of deltas corresponding to the updated - // traces. - this._sendTraceDeltas(msgData.trace_edit_id); + // ### Send trace deltas ### + // We create an array of deltas corresponding to the updated + // traces. + this._sendTraceDeltas(msgData.trace_edit_id); - // ### Send layout delta ### - var layout_edit_id = msgData.layout_edit_id; - this._sendLayoutDelta(layout_edit_id); - } + // ### Send layout delta ### + var layout_edit_id = msgData.layout_edit_id; + this._sendLayoutDelta(layout_edit_id); + } + }) }, /** * Handle Plotly.animate request */ do_animate: function() { + import(/* webpackChunkName: 'plotly' */ 'plotly.js/dist/plotly').then(Plotly => { - /** @type {Py2JsAnimateMsg} */ - var msgData = this.model.get("_py2js_animate"); + /** @type {Py2JsAnimateMsg} */ + var msgData = this.model.get("_py2js_animate"); - if (msgData !== null) { + if (msgData !== null) { - // Unpack params - // var animationData = msgData[0]; - var animationOpts = msgData.animation_opts; + // Unpack params + // var animationData = msgData[0]; + var animationOpts = msgData.animation_opts; - var styles = msgData.style_data; - var layout = msgData.layout_data; - var traceIndexes = this.model._normalize_trace_indexes( - msgData.style_traces); + var styles = msgData.style_data; + var layout = msgData.layout_data; + var traceIndexes = this.model._normalize_trace_indexes( + msgData.style_traces); - var animationData = { - data: styles, - layout: layout, - traces: traceIndexes - }; + var animationData = { + data: styles, + layout: layout, + traces: traceIndexes + }; - animationData["_doNotReportToPy"] = true; - var that = this; + animationData["_doNotReportToPy"] = true; + var that = this; - Plotly.animate(this.el, animationData, animationOpts).then( - function () { + Plotly.animate(this.el, animationData, animationOpts).then( + function () { - // ### Send trace deltas ### - // We create an array of deltas corresponding to the - // animated traces. - that._sendTraceDeltas(msgData.trace_edit_id); + // ### Send trace deltas ### + // We create an array of deltas corresponding to the + // animated traces. + that._sendTraceDeltas(msgData.trace_edit_id); - // ### Send layout delta ### - var layout_edit_id = msgData.layout_edit_id; - that._sendLayoutDelta(layout_edit_id); - }); + // ### Send layout delta ### + var layout_edit_id = msgData.layout_edit_id; + that._sendLayoutDelta(layout_edit_id); + }); - } + } + }) }, /** From 88f137f1df532367e23e1c2e1f38a824e84e6996 Mon Sep 17 00:00:00 2001 From: Pragya Garg Date: Tue, 31 Mar 2020 13:02:12 +0530 Subject: [PATCH 3/4] Updated the version --- packages/javascript/plotlywidget/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/javascript/plotlywidget/package.json b/packages/javascript/plotlywidget/package.json index 48d033c752b..ea9bc6c21b6 100644 --- a/packages/javascript/plotlywidget/package.json +++ b/packages/javascript/plotlywidget/package.json @@ -1,6 +1,6 @@ { "name": "plotlywidget", - "version": "1.5.4", + "version": "1.5.5", "description": "The plotly JupyterLab extension", "author": "The plotly.py team", "license": "MIT", From e690b1a342ba5185078ce46dd7b47350d4784c10 Mon Sep 17 00:00:00 2001 From: Pragya Garg Date: Thu, 14 May 2020 21:20:06 +0530 Subject: [PATCH 4/4] Added prefetch option to reduce loading time of lazy loaded modules --- .../jupyterlab-plotly/package-lock.json | 738 ++-- .../javascript/jupyterlab-plotly/package.json | 4 +- .../src/javascript-renderer-extension.ts | 136 +- .../javascript/jupyterlab-plotly/src/lib.d.ts | 6 +- .../javascript/plotlywidget/package-lock.json | 601 ++-- packages/javascript/plotlywidget/package.json | 4 +- .../javascript/plotlywidget/src/Figure.js | 3074 +++++++++-------- 7 files changed, 2304 insertions(+), 2259 deletions(-) diff --git a/packages/javascript/jupyterlab-plotly/package-lock.json b/packages/javascript/jupyterlab-plotly/package-lock.json index 17cdaf3edc1..58dc70b06f9 100644 --- a/packages/javascript/jupyterlab-plotly/package-lock.json +++ b/packages/javascript/jupyterlab-plotly/package-lock.json @@ -1,6 +1,6 @@ { "name": "jupyterlab-plotly", - "version": "1.5.4", + "version": "4.7.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -146,25 +146,6 @@ "@lumino/virtualdom": "1.6.1" } }, - "@mapbox/geojson-area": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@mapbox/geojson-area/-/geojson-area-0.2.2.tgz", - "integrity": "sha1-GNeBSqNr8j+7zDefjiaiKSfevxA=", - "requires": { - "wgs84": "0.0.0" - } - }, - "@mapbox/geojson-rewind": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@mapbox/geojson-rewind/-/geojson-rewind-0.4.0.tgz", - "integrity": "sha512-b+1uPWBERW4Pet/969BNu61ZPDyH2ilIxBjJDFzxyS9TyszF9UrTQyYIl/G38clux3rtpAGGFSGTCSF/qR6UjA==", - "requires": { - "@mapbox/geojson-area": "0.2.2", - "concat-stream": "1.6.2", - "minimist": "1.2.0", - "sharkdown": "0.1.1" - } - }, "@mapbox/geojson-types": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@mapbox/geojson-types/-/geojson-types-1.0.2.tgz", @@ -175,11 +156,6 @@ "resolved": "https://registry.npmjs.org/@mapbox/jsonlint-lines-primitives/-/jsonlint-lines-primitives-2.0.2.tgz", "integrity": "sha1-zlblOfg1UrWNENZy6k1vya3HsjQ=" }, - "@mapbox/mapbox-gl-supported": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@mapbox/mapbox-gl-supported/-/mapbox-gl-supported-1.4.1.tgz", - "integrity": "sha512-yyKza9S6z3ELKuf6w5n6VNUB0Osu6Z93RXPfMHLIlNWohu3KqxewLOq4lMXseYJ92GwkRAxd207Pr/Z98cwmvw==" - }, "@mapbox/point-geometry": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/@mapbox/point-geometry/-/point-geometry-0.1.0.tgz", @@ -375,11 +351,6 @@ "color-convert": "1.9.3" } }, - "ansicolors": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.2.1.tgz", - "integrity": "sha1-vgiVmQl7dKXJxKhKDNvNtivYeu8=" - }, "arr-flatten": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", @@ -576,15 +547,6 @@ "element-size": "1.1.1" } }, - "cardinal": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-0.4.4.tgz", - "integrity": "sha1-ylu2iltRG5D+k7ms6km97lwyv+I=", - "requires": { - "ansicolors": "0.2.1", - "redeyed": "0.4.4" - } - }, "cdt2d": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/cdt2d/-/cdt2d-1.0.0.tgz", @@ -1269,11 +1231,6 @@ "es6-symbol": "3.1.3" } }, - "es6-promise": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", - "integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=" - }, "es6-symbol": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", @@ -1362,14 +1319,6 @@ "object-keys": "1.1.1" } }, - "fast-isnumeric": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/fast-isnumeric/-/fast-isnumeric-1.1.3.tgz", - "integrity": "sha512-MdojHkfLx8pjRNZyGjOhX4HxNPaf0l5R/v5rGZ1bGXCnRPyQIUAe4I1H7QtrlUwuuiDHKdpQTjT3lmueVH2otw==", - "requires": { - "is-string-blank": "1.0.1" - } - }, "fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", @@ -1520,26 +1469,6 @@ "resolved": "https://registry.npmjs.org/get-canvas-context/-/get-canvas-context-1.0.2.tgz", "integrity": "sha1-1ue1C8TkyGNXzTnyJkeoS3NgHpM=" }, - "gl-axes3d": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/gl-axes3d/-/gl-axes3d-1.5.2.tgz", - "integrity": "sha512-47Cfh5KhUVRFtYXgufR4lGY5cyXH7SPgAlS1FlvTGK84spIYFCBMlOGUN3AdavGLGUOcXS4ml+tMM61cY6M3gg==", - "requires": { - "bit-twiddle": "1.0.2", - "dup": "1.0.0", - "extract-frustum-planes": "1.0.0", - "gl-buffer": "2.1.2", - "gl-mat4": "1.2.0", - "gl-shader": "4.2.1", - "gl-state": "1.0.0", - "gl-vao": "1.3.0", - "gl-vec4": "1.0.1", - "glslify": "7.0.0", - "robust-orientation": "1.1.3", - "split-polygon": "1.0.0", - "vectorize-text": "3.2.1" - } - }, "gl-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/gl-buffer/-/gl-buffer-2.1.2.tgz", @@ -1550,58 +1479,11 @@ "typedarray-pool": "1.2.0" } }, - "gl-cone3d": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/gl-cone3d/-/gl-cone3d-1.5.1.tgz", - "integrity": "sha512-R8m2lPfVN5ip/IPzykvMNgUUGWTkp9rMuCrVknKIkhjH+gaQeGfwF3+WrB0kwq3FRWvlYWcfdvabv37sZ2rKYA==", - "requires": { - "colormap": "2.3.1", - "gl-buffer": "2.1.2", - "gl-mat4": "1.2.0", - "gl-shader": "4.2.1", - "gl-texture2d": "2.1.0", - "gl-vao": "1.3.0", - "gl-vec3": "1.1.3", - "glsl-inverse": "1.0.0", - "glsl-out-of-range": "1.0.4", - "glsl-specular-cook-torrance": "2.0.1", - "glslify": "7.0.0", - "ndarray": "1.0.19" - } - }, "gl-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/gl-constants/-/gl-constants-1.0.0.tgz", "integrity": "sha1-WXpQTjZHUP9QJTqjX43qevSl0jM=" }, - "gl-contour2d": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/gl-contour2d/-/gl-contour2d-1.1.6.tgz", - "integrity": "sha512-n8nEFb4VRYooBo3+hbAgiXGELVn7PtYyVbj/hWmTNtrkxFK39Yr8LUczcT2uOOyzqq7sO3FH8+J8PSMFh+z+5A==", - "requires": { - "binary-search-bounds": "2.0.4", - "cdt2d": "1.0.0", - "clean-pslg": "1.1.2", - "gl-buffer": "2.1.2", - "gl-shader": "4.2.1", - "glslify": "7.0.0", - "iota-array": "1.0.0", - "ndarray": "1.0.19", - "surface-nets": "1.0.2" - } - }, - "gl-error3d": { - "version": "1.0.15", - "resolved": "https://registry.npmjs.org/gl-error3d/-/gl-error3d-1.0.15.tgz", - "integrity": "sha512-7mB1zU22Vzdvq0KzzYRzE0xvCRF9nHd1+9ElUqkvt0GMH0gVIpxKk+m3hNPM/iQHmNupcXaE1cBcOQE2agN3uA==", - "requires": { - "gl-buffer": "2.1.2", - "gl-shader": "4.2.1", - "gl-vao": "1.3.0", - "glsl-out-of-range": "1.0.4", - "glslify": "7.0.0" - } - }, "gl-fbo": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/gl-fbo/-/gl-fbo-2.0.5.tgz", @@ -1621,23 +1503,10 @@ "sprintf-js": "1.1.2" } }, - "gl-heatmap2d": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/gl-heatmap2d/-/gl-heatmap2d-1.0.5.tgz", - "integrity": "sha512-nki9GIh0g4OXKNIrlnAT/gy/uXxkwrFKgI+XwRcUO6nLBM1WbI2hl8EPykNFXCqsyd08HJQbXKiqaHPW7cNpJg==", - "requires": { - "binary-search-bounds": "2.0.4", - "gl-buffer": "2.1.2", - "gl-shader": "4.2.1", - "glslify": "7.0.0", - "iota-array": "1.0.0", - "typedarray-pool": "1.2.0" - } - }, "gl-line3d": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/gl-line3d/-/gl-line3d-1.1.11.tgz", - "integrity": "sha512-EitFKPEEYdn/ivFOxJ8khSi0BzNum4sXZFLq6SQq21MX5YPCYb0o+XzjpWNuU32BoXORBC78B1JTiQqnTaWhWQ==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/gl-line3d/-/gl-line3d-1.2.1.tgz", + "integrity": "sha512-eeb0+RI2ZBRqMYJK85SgsRiJK7c4aiOjcnirxv0830A3jmOc99snY3AbPcV8KvKmW0Yaf3KA4e+qNCbHiTOTnA==", "requires": { "binary-search-bounds": "2.0.4", "gl-buffer": "2.1.2", @@ -1645,7 +1514,6 @@ "gl-texture2d": "2.1.0", "gl-vao": "1.3.0", "glsl-out-of-range": "1.0.4", - "glsl-read-float": "1.1.0", "glslify": "7.0.0", "ndarray": "1.0.19" } @@ -1665,11 +1533,6 @@ "resolved": "https://registry.npmjs.org/gl-mat4/-/gl-mat4-1.2.0.tgz", "integrity": "sha512-sT5C0pwB1/e9G9AvAoLsoaJtbMGjfd/jfxo8jMCKqYYEnjZuFvqV5rehqar0538EmssjdDeiEWnKyBSTw7quoA==" }, - "gl-matrix": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-3.1.0.tgz", - "integrity": "sha512-526NA+3EA+ztAQi0IZpSWiM0fyQXIp7IbRvfJ4wS/TjjQD0uv0fVybXwwqqSOlq33UckivI0yMDlVtboWm3k7A==" - }, "gl-matrix-invert": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/gl-matrix-invert/-/gl-matrix-invert-1.0.0.tgz", @@ -1681,9 +1544,9 @@ } }, "gl-mesh3d": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/gl-mesh3d/-/gl-mesh3d-2.2.0.tgz", - "integrity": "sha512-wO6EKjBUo/k7ZLGsMACWGETjmjfsGwwoDWEKjDbjyjo1qPvgkTQQB9Y8p+OKGjE6GeihsfQuoqGBUTu9tiAOmg==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/gl-mesh3d/-/gl-mesh3d-2.3.1.tgz", + "integrity": "sha512-pXECamyGgu4/9HeAQSE5OEUuLBGS1aq9V4BCsTcxsND4fNLaajEkYKUz/WY2QSYElqKdsMBVsldGiKRKwlybqA==", "requires": { "barycentric": "1.0.1", "colormap": "2.3.1", @@ -1703,51 +1566,83 @@ } }, "gl-plot2d": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/gl-plot2d/-/gl-plot2d-1.4.2.tgz", - "integrity": "sha512-YLFiu/vgDCYZ/Qnz0wn0gV60IYCtImSnx0OTMsZ5fP1XZAhFztrRb2fJfnjfEVe15yZ+G+9zJ36RlWmJsNQYjQ==", + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/gl-plot2d/-/gl-plot2d-1.4.4.tgz", + "integrity": "sha512-0UhKiiqeampLtydv6NMNrKEilc0Ui5oaJtvHLbLZ5u/1ttT1XjOY5Yk8LzfqozA/No4a9omxjSKnH+tvSn+rQQ==", "requires": { "binary-search-bounds": "2.0.4", "gl-buffer": "2.1.2", - "gl-select-static": "2.0.4", + "gl-select-static": "2.0.6", "gl-shader": "4.2.1", "glsl-inverse": "1.0.0", "glslify": "7.0.0", - "text-cache": "4.2.1" + "text-cache": "4.2.2" + }, + "dependencies": { + "text-cache": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/text-cache/-/text-cache-4.2.2.tgz", + "integrity": "sha512-zky+UDYiX0a/aPw/YTBD+EzKMlCTu1chFuCMZeAkgoRiceySdROu1V2kJXhCbtEdBhiOviYnAdGiSYl58HW0ZQ==", + "requires": { + "vectorize-text": "3.2.1" + } + } } }, "gl-plot3d": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/gl-plot3d/-/gl-plot3d-2.4.0.tgz", - "integrity": "sha512-ZPs7gvWaCqK99GXoB0XJTMTLpChB/CiDUt3MthIawVlFhknSJLNPAJSbUU3f4pWzKCbbGtVARQr/i6XdM3MnKA==", + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/gl-plot3d/-/gl-plot3d-2.4.5.tgz", + "integrity": "sha512-cKAqMXFRHTCFxH8r1/ACdk5hyfnA9djfiAM8zVQrqu0qLEttUu0i1fq0pr+d5m0HPuNcK8wEc4F3VjL2hrDcGQ==", "requires": { "3d-view": "2.0.0", "a-big-triangle": "1.0.3", - "gl-axes3d": "1.5.2", + "gl-axes3d": "1.5.3", "gl-fbo": "2.0.5", "gl-mat4": "1.2.0", - "gl-select-static": "2.0.4", + "gl-select-static": "2.0.6", "gl-shader": "4.2.1", - "gl-spikes3d": "1.0.9", + "gl-spikes3d": "1.0.10", "glslify": "7.0.0", "has-passive-events": "1.0.0", - "is-mobile": "2.1.0", + "is-mobile": "2.2.1", "mouse-change": "1.4.0", "mouse-event-offset": "3.0.2", "mouse-wheel": "1.2.0", "ndarray": "1.0.19", "right-now": "1.0.0" - } - }, - "gl-pointcloud2d": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/gl-pointcloud2d/-/gl-pointcloud2d-1.0.2.tgz", - "integrity": "sha512-KDfuJLg1dFWNPo6eJYgwUpNdVcIdK5y29ZiYpzzP0qh3eg0bSLMq8ZkaqvPmSJsFksUryT73IRunsuxJtTJkvA==", - "requires": { - "gl-buffer": "2.1.2", - "gl-shader": "4.2.1", - "glslify": "7.0.0", - "typedarray-pool": "1.2.0" + }, + "dependencies": { + "gl-axes3d": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/gl-axes3d/-/gl-axes3d-1.5.3.tgz", + "integrity": "sha512-KRYbguKQcDQ6PcB9g1pgqB8Ly4TY1DQODpPKiDTasyWJ8PxQk0t2Q7XoQQijNqvsguITCpVVCzNb5GVtIWiVlQ==", + "requires": { + "bit-twiddle": "1.0.2", + "dup": "1.0.0", + "extract-frustum-planes": "1.0.0", + "gl-buffer": "2.1.2", + "gl-mat4": "1.2.0", + "gl-shader": "4.2.1", + "gl-state": "1.0.0", + "gl-vao": "1.3.0", + "gl-vec4": "1.0.1", + "glslify": "7.0.0", + "robust-orientation": "1.1.3", + "split-polygon": "1.0.0", + "vectorize-text": "3.2.1" + } + }, + "gl-spikes3d": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/gl-spikes3d/-/gl-spikes3d-1.0.10.tgz", + "integrity": "sha512-lT3xroowOFxMvlhT5Mof76B2TE02l5zt/NIWljhczV2FFHgIVhA4jMrd5dIv1so1RXMBDJIKu0uJI3QKliDVLg==", + "requires": { + "gl-buffer": "2.1.2", + "gl-shader": "4.2.1", + "gl-vao": "1.3.0", + "glslify": "7.0.0" + } + } } }, "gl-quat": { @@ -1760,36 +1655,10 @@ "gl-vec4": "1.0.1" } }, - "gl-scatter3d": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/gl-scatter3d/-/gl-scatter3d-1.2.2.tgz", - "integrity": "sha512-oZh3WQ0bVXnpASpZmYmiEp7eUiD0oU6J4G5C9KUOhUo5d2gucvZEILAtfWmzCT3zsOltoROn4jGuuP2tlLN88Q==", - "requires": { - "gl-buffer": "2.1.2", - "gl-mat4": "1.2.0", - "gl-shader": "4.2.1", - "gl-vao": "1.3.0", - "glsl-out-of-range": "1.0.4", - "glslify": "7.0.0", - "is-string-blank": "1.0.1", - "typedarray-pool": "1.2.0", - "vectorize-text": "3.2.1" - } - }, - "gl-select-box": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/gl-select-box/-/gl-select-box-1.0.3.tgz", - "integrity": "sha512-sQb18g1aZ6PJAsvsC8nNYhuhc2TYXNbzVbI0bP9AH9770NjrDnd7TC8HHcfu8nJXGPG69HjqR6EzS+QSqiXPSA==", - "requires": { - "gl-buffer": "2.1.2", - "gl-shader": "4.2.1", - "glslify": "7.0.0" - } - }, "gl-select-static": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/gl-select-static/-/gl-select-static-2.0.4.tgz", - "integrity": "sha512-4Kqx5VjeT8nmV+j6fry3UBFNL2B7ktQU4o508QGVPKWCILlV44rTDq3mnBFThup8rMIH9kJQx6xWsg9jTmfeMw==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/gl-select-static/-/gl-select-static-2.0.6.tgz", + "integrity": "sha512-p4DmBG1DMo/47/fV3oqPcU6uTqHy0eI1vATH1fm8OVDqlzWnLv3786tdEunZWG6Br7DUdH6NgWhuy4gAlt+TAQ==", "requires": { "bit-twiddle": "1.0.2", "cwise": "1.0.10", @@ -1812,17 +1681,6 @@ "resolved": "https://registry.npmjs.org/gl-spikes2d/-/gl-spikes2d-1.0.2.tgz", "integrity": "sha512-QVeOZsi9nQuJJl7NB3132CCv5KA10BWxAY2QgJNsKqbLsG53B/TrGJpjIAohnJftdZ4fT6b3ZojWgeaXk8bOOA==" }, - "gl-spikes3d": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/gl-spikes3d/-/gl-spikes3d-1.0.9.tgz", - "integrity": "sha512-laMxydgGdnE8kvd1YD9cNWrx0uSmrPj1Oi02cHhnxWIklut97w3F7mZKnmLMEyUkxpRLkEeQ7YkYy7Y+aUEblw==", - "requires": { - "gl-buffer": "2.1.2", - "gl-shader": "4.2.1", - "gl-vao": "1.3.0", - "glslify": "7.0.0" - } - }, "gl-state": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/gl-state/-/gl-state-1.0.0.tgz", @@ -1831,24 +1689,10 @@ "uniq": "1.0.1" } }, - "gl-streamtube3d": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/gl-streamtube3d/-/gl-streamtube3d-1.4.0.tgz", - "integrity": "sha512-WgRtdB77uFCN1lBZ6ogz7VTK4J8WwW5DGHvyB3LaBSZF3t5lf/KWeXPgm+xnNINlOy4JqJIgny+CtzwTHAk3Ew==", - "requires": { - "gl-cone3d": "1.5.1", - "gl-vec3": "1.1.3", - "gl-vec4": "1.0.1", - "glsl-inverse": "1.0.0", - "glsl-out-of-range": "1.0.4", - "glsl-specular-cook-torrance": "2.0.1", - "glslify": "7.0.0" - } - }, "gl-surface3d": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/gl-surface3d/-/gl-surface3d-1.4.6.tgz", - "integrity": "sha512-aItWQTNUX3JJc6i2FbXX82ljPZgDV3kXzkzANcBGoAnKwRpJw12WcMKKTL4sOCs9BW+3sx6BhR0P5+2zh5Scfw==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/gl-surface3d/-/gl-surface3d-1.5.2.tgz", + "integrity": "sha512-rWSQwEQDkB0T5CDEDFJwJc4VgwwJaAyFRSJ92NJlrTSwDlsEsWdzG9+APx6FWJMwkOpIoZGWqv+csswK2kMMLQ==", "requires": { "binary-search-bounds": "2.0.4", "bit-twiddle": "1.0.2", @@ -1968,11 +1812,6 @@ "resolved": "https://registry.npmjs.org/glsl-out-of-range/-/glsl-out-of-range-1.0.4.tgz", "integrity": "sha512-fCcDu2LCQ39VBvfe1FbhuazXEf0CqMZI9OYXrYlL6uUARG48CTAbL04+tZBtVM0zo1Ljx4OLu2AxNquq++lxWQ==" }, - "glsl-read-float": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/glsl-read-float/-/glsl-read-float-1.1.0.tgz", - "integrity": "sha1-37CIsBYtz8xW/E7d0vhuGMrDLyY=" - }, "glsl-resolve": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/glsl-resolve/-/glsl-resolve-0.0.1.tgz", @@ -2371,9 +2210,9 @@ "integrity": "sha1-HXK8ZtP+Iur2Fw3ajPEJQySM/HY=" }, "is-mobile": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-mobile/-/is-mobile-2.1.0.tgz", - "integrity": "sha512-M5OhlZwh+aTlmRUvDg0Wq3uWVNa+w4DyZ2SjbrS+BhSLu9Po+JXHendC305ZEu+Hh7lywb19Zu4kYXu3L1Oo8A==" + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-mobile/-/is-mobile-2.2.1.tgz", + "integrity": "sha512-6zELsfVFr326eq2CI53yvqq6YBanOxKBybwDT+MbMS2laBnK6Ez8m5XHSuTQQbnKRfpDzCod1CMWW5q3wZYMvA==" }, "is-obj": { "version": "1.0.1", @@ -2500,43 +2339,6 @@ } } }, - "mapbox-gl": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mapbox-gl/-/mapbox-gl-1.3.2.tgz", - "integrity": "sha512-6Ro7GbTMWxcbc836m6rbBNkesgTncbE1yXWeuHlr89esSqaItKr0+ntOu8rZie3fv+GtitkbODysXzIGCA7G+w==", - "requires": { - "@mapbox/geojson-rewind": "0.4.0", - "@mapbox/geojson-types": "1.0.2", - "@mapbox/jsonlint-lines-primitives": "2.0.2", - "@mapbox/mapbox-gl-supported": "1.4.1", - "@mapbox/point-geometry": "0.1.0", - "@mapbox/tiny-sdf": "1.1.1", - "@mapbox/unitbezier": "0.0.0", - "@mapbox/vector-tile": "1.3.1", - "@mapbox/whoots-js": "3.1.0", - "csscolorparser": "1.0.3", - "earcut": "2.2.1", - "geojson-vt": "3.2.1", - "gl-matrix": "3.1.0", - "grid-index": "1.1.0", - "minimist": "0.0.8", - "murmurhash-js": "1.0.0", - "pbf": "3.2.1", - "potpack": "1.0.1", - "quickselect": "2.0.0", - "rw": "1.3.3", - "supercluster": "6.0.2", - "tinyqueue": "2.0.3", - "vt-pbf": "3.1.1" - }, - "dependencies": { - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" - } - } - }, "marching-simplex-table": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/marching-simplex-table/-/marching-simplex-table-1.0.0.tgz", @@ -3028,9 +2830,9 @@ } }, "plotly.js": { - "version": "1.52.1", - "resolved": "https://registry.npmjs.org/plotly.js/-/plotly.js-1.52.1.tgz", - "integrity": "sha512-GLNwAu20zwRZrfjrSRUZHXyDulDRh1yfPBV5SLqy5AdGefb6CK2QCBbMcGlhV2P14oJwQ8vd1wqTZVZE9xQ9Rw==", + "version": "1.54.1", + "resolved": "https://registry.npmjs.org/plotly.js/-/plotly.js-1.54.1.tgz", + "integrity": "sha512-1tlsEQkUgX2BaQr3Eu+5drki3eyor5EhpolFRteuQouRFX9mrg9Pms39Lak29lbAx4W3ZQoCZm8DcKkQCOe9YQ==", "requires": { "@plotly/d3-sankey": "0.7.2", "@plotly/d3-sankey-circular": "0.33.1", @@ -3048,41 +2850,43 @@ "d3-hierarchy": "1.1.9", "d3-interpolate": "1.4.0", "delaunay-triangulate": "1.1.6", - "es6-promise": "3.3.1", - "fast-isnumeric": "1.1.3", - "gl-cone3d": "1.5.1", - "gl-contour2d": "1.1.6", - "gl-error3d": "1.0.15", - "gl-heatmap2d": "1.0.5", - "gl-line3d": "1.1.11", + "es6-promise": "4.2.8", + "fast-isnumeric": "1.1.4", + "gl-cone3d": "1.5.2", + "gl-contour2d": "1.1.7", + "gl-error3d": "1.0.16", + "gl-heatmap2d": "1.0.6", + "gl-line3d": "1.2.1", "gl-mat4": "1.2.0", - "gl-mesh3d": "2.2.0", - "gl-plot2d": "1.4.2", - "gl-plot3d": "2.4.0", - "gl-pointcloud2d": "1.0.2", - "gl-scatter3d": "1.2.2", - "gl-select-box": "1.0.3", + "gl-mesh3d": "2.3.1", + "gl-plot2d": "1.4.4", + "gl-plot3d": "2.4.5", + "gl-pointcloud2d": "1.0.3", + "gl-scatter3d": "1.2.3", + "gl-select-box": "1.0.4", "gl-spikes2d": "1.0.2", - "gl-streamtube3d": "1.4.0", - "gl-surface3d": "1.4.6", + "gl-streamtube3d": "1.4.1", + "gl-surface3d": "1.5.2", "gl-text": "1.1.8", "glslify": "7.0.0", "has-hover": "1.0.1", "has-passive-events": "1.0.0", - "mapbox-gl": "1.3.2", + "is-mobile": "2.2.1", + "mapbox-gl": "1.10.0", "matrix-camera-controller": "2.1.3", "mouse-change": "1.4.0", "mouse-event-offset": "3.0.2", "mouse-wheel": "1.2.0", - "ndarray": "1.0.19", + "ndarray": "1.0.18", "ndarray-fill": "1.0.2", "ndarray-homography": "1.0.0", + "parse-svg-path": "0.1.2", "point-cluster": "3.1.8", "polybooljs": "1.2.0", - "regl": "1.3.13", + "regl": "1.3.11", "regl-error2d": "2.0.8", "regl-line2d": "3.0.15", - "regl-scatter2d": "3.1.7", + "regl-scatter2d": "3.1.8", "regl-splom": "1.0.8", "right-now": "1.0.0", "robust-orientation": "1.1.3", @@ -3091,9 +2895,290 @@ "superscript-text": "1.0.0", "svg-path-sdf": "1.1.3", "tinycolor2": "1.4.1", - "topojson-client": "2.1.0", + "to-px": "1.0.1", + "topojson-client": "3.1.0", "webgl-context": "2.2.0", "world-calendars": "1.0.3" + }, + "dependencies": { + "@mapbox/geojson-rewind": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@mapbox/geojson-rewind/-/geojson-rewind-0.5.0.tgz", + "integrity": "sha512-73l/qJQgj/T/zO1JXVfuVvvKDgikD/7D/rHAD28S9BG1OTstgmftrmqfCx4U+zQAmtsB6HcDA3a7ymdnJZAQgg==", + "requires": { + "concat-stream": "2.0.0", + "minimist": "1.2.5" + } + }, + "@mapbox/mapbox-gl-supported": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@mapbox/mapbox-gl-supported/-/mapbox-gl-supported-1.5.0.tgz", + "integrity": "sha512-/PT1P6DNf7vjEEiPkVIRJkvibbqWtqnyGaBz3nfRdcxclNSnSdaLU5tfAgcD7I8Yt5i+L19s406YLl1koLnLbg==" + }, + "concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "requires": { + "buffer-from": "1.1.1", + "inherits": "2.0.3", + "readable-stream": "3.6.0", + "typedarray": "0.0.6" + } + }, + "earcut": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/earcut/-/earcut-2.2.2.tgz", + "integrity": "sha512-eZoZPPJcUHnfRZ0PjLvx2qBordSiO8ofC3vt+qACLM95u+4DovnbYNpQtJh0DNsWj8RnxrQytD4WA8gj5cRIaQ==" + }, + "es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" + }, + "fast-isnumeric": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/fast-isnumeric/-/fast-isnumeric-1.1.4.tgz", + "integrity": "sha512-1mM8qOr2LYz8zGaUdmiqRDiuue00Dxjgcb1NQR7TnhLVh6sQyngP9xvLo7Sl7LZpP/sk5eb+bcyWXw530NTBZw==", + "requires": { + "is-string-blank": "1.0.1" + } + }, + "gl-cone3d": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/gl-cone3d/-/gl-cone3d-1.5.2.tgz", + "integrity": "sha512-1JNeHH4sUtUmDA4ZK7Om8/kShwb8IZVAsnxaaB7IPRJsNGciLj1sTpODrJGeMl41RNkex5kXD2SQFrzyEAR2Rw==", + "requires": { + "colormap": "2.3.1", + "gl-buffer": "2.1.2", + "gl-mat4": "1.2.0", + "gl-shader": "4.2.1", + "gl-texture2d": "2.1.0", + "gl-vao": "1.3.0", + "gl-vec3": "1.1.3", + "glsl-inverse": "1.0.0", + "glsl-out-of-range": "1.0.4", + "glsl-specular-cook-torrance": "2.0.1", + "glslify": "7.0.0", + "ndarray": "1.0.18" + } + }, + "gl-contour2d": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/gl-contour2d/-/gl-contour2d-1.1.7.tgz", + "integrity": "sha512-GdebvJ9DtT3pJDpoE+eU2q+Wo9S3MijPpPz5arZbhK85w2bARmpFpVfPaDlZqWkB644W3BlH8TVyvAo1KE4Bhw==", + "requires": { + "binary-search-bounds": "2.0.4", + "cdt2d": "1.0.0", + "clean-pslg": "1.1.2", + "gl-buffer": "2.1.2", + "gl-shader": "4.2.1", + "glslify": "7.0.0", + "iota-array": "1.0.0", + "ndarray": "1.0.18", + "surface-nets": "1.0.2" + } + }, + "gl-error3d": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/gl-error3d/-/gl-error3d-1.0.16.tgz", + "integrity": "sha512-TGJewnKSp7ZnqGgG3XCF9ldrDbxZrO+OWlx6oIet4OdOM//n8xJ5isArnIV/sdPJnFbhfoLxWrW9f5fxHFRQ1A==", + "requires": { + "gl-buffer": "2.1.2", + "gl-shader": "4.2.1", + "gl-vao": "1.3.0", + "glsl-out-of-range": "1.0.4", + "glslify": "7.0.0" + } + }, + "gl-heatmap2d": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/gl-heatmap2d/-/gl-heatmap2d-1.0.6.tgz", + "integrity": "sha512-+agzSv4R5vsaH+AGYVz5RVzBK10amqAa+Bwj205F13JjNSGS91M1L9Yb8zssCv2FIjpP+1Mp73cFBYrQFfS1Jg==", + "requires": { + "binary-search-bounds": "2.0.4", + "gl-buffer": "2.1.2", + "gl-shader": "4.2.1", + "glslify": "7.0.0", + "iota-array": "1.0.0", + "typedarray-pool": "1.2.0" + } + }, + "gl-matrix": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-3.3.0.tgz", + "integrity": "sha512-COb7LDz+SXaHtl/h4LeaFcNdJdAQSDeVqjiIihSXNrkWObZLhDI4hIkZC11Aeqp7bcE72clzB0BnDXr2SmslRA==" + }, + "gl-pointcloud2d": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/gl-pointcloud2d/-/gl-pointcloud2d-1.0.3.tgz", + "integrity": "sha512-OS2e1irvJXVRpg/GziXj10xrFJm9kkRfFoB6BLUvkjCQV7ZRNNcs2CD+YSK1r0gvMwTg2T3lfLM3UPwNtz+4Xw==", + "requires": { + "gl-buffer": "2.1.2", + "gl-shader": "4.2.1", + "glslify": "7.0.0", + "typedarray-pool": "1.2.0" + } + }, + "gl-scatter3d": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/gl-scatter3d/-/gl-scatter3d-1.2.3.tgz", + "integrity": "sha512-nXqPlT1w5Qt51dTksj+DUqrZqwWAEWg0PocsKcoDnVNv0X8sGA+LBZ0Y+zrA+KNXUL0PPCX9WR9cF2uJAZl1Sw==", + "requires": { + "gl-buffer": "2.1.2", + "gl-mat4": "1.2.0", + "gl-shader": "4.2.1", + "gl-vao": "1.3.0", + "glsl-out-of-range": "1.0.4", + "glslify": "7.0.0", + "is-string-blank": "1.0.1", + "typedarray-pool": "1.2.0", + "vectorize-text": "3.2.1" + } + }, + "gl-select-box": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/gl-select-box/-/gl-select-box-1.0.4.tgz", + "integrity": "sha512-mKsCnglraSKyBbQiGq0Ila0WF+m6Tr+EWT2yfaMn/Sh9aMHq5Wt0F/l6Cf/Ed3CdERq5jHWAY5yxLviZteYu2w==", + "requires": { + "gl-buffer": "2.1.2", + "gl-shader": "4.2.1", + "glslify": "7.0.0" + } + }, + "gl-streamtube3d": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/gl-streamtube3d/-/gl-streamtube3d-1.4.1.tgz", + "integrity": "sha512-rH02v00kgwgdpkXVo7KsSoPp38bIAYR9TE1iONjcQ4cQAlDhrGRauqT/P5sUaOIzs17A2DxWGcXM+EpNQs9pUA==", + "requires": { + "gl-cone3d": "1.5.2", + "gl-vec3": "1.1.3", + "gl-vec4": "1.0.1", + "glsl-inverse": "1.0.0", + "glsl-out-of-range": "1.0.4", + "glsl-specular-cook-torrance": "2.0.1", + "glslify": "7.0.0" + } + }, + "mapbox-gl": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/mapbox-gl/-/mapbox-gl-1.10.0.tgz", + "integrity": "sha512-SrJXcR9s5yEsPuW2kKKumA1KqYW9RrL8j7ZcIh6glRQ/x3lwNMfwz/UEJAJcVNgeX+fiwzuBoDIdeGB/vSkZLQ==", + "requires": { + "@mapbox/geojson-rewind": "0.5.0", + "@mapbox/geojson-types": "1.0.2", + "@mapbox/jsonlint-lines-primitives": "2.0.2", + "@mapbox/mapbox-gl-supported": "1.5.0", + "@mapbox/point-geometry": "0.1.0", + "@mapbox/tiny-sdf": "1.1.1", + "@mapbox/unitbezier": "0.0.0", + "@mapbox/vector-tile": "1.3.1", + "@mapbox/whoots-js": "3.1.0", + "csscolorparser": "1.0.3", + "earcut": "2.2.2", + "geojson-vt": "3.2.1", + "gl-matrix": "3.3.0", + "grid-index": "1.1.0", + "minimist": "1.2.5", + "murmurhash-js": "1.0.0", + "pbf": "3.2.1", + "potpack": "1.0.1", + "quickselect": "2.0.0", + "rw": "1.3.3", + "supercluster": "7.0.0", + "tinyqueue": "2.0.3", + "vt-pbf": "3.1.1" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, + "ndarray": { + "version": "1.0.18", + "resolved": "https://registry.npmjs.org/ndarray/-/ndarray-1.0.18.tgz", + "integrity": "sha1-tg06cyJOxVXQ+qeXEeUCRI/T95M=", + "requires": { + "iota-array": "1.0.0", + "is-buffer": "1.1.6" + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "2.0.3", + "string_decoder": "1.3.0", + "util-deprecate": "1.0.2" + } + }, + "regl": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/regl/-/regl-1.3.11.tgz", + "integrity": "sha512-tmt6CRhRqbcsYDWNwv+iG7GGOXdgoOBC7lKzoPMgnzpt3WKBQ3c8i7AxgbvTRZzty29hrW92fAJeZkPFQehfWA==" + }, + "regl-scatter2d": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/regl-scatter2d/-/regl-scatter2d-3.1.8.tgz", + "integrity": "sha512-Z9MYAUx9t8e3MsiHBbJAEstbIqauXxzcL9DmuKXQuRWfCMF2DBytYJtE0FpbQU6639wEMAJ54SEIlISWF8sQ2g==", + "requires": { + "array-range": "1.0.1", + "array-rearrange": "2.2.2", + "clamp": "1.0.1", + "color-id": "1.1.0", + "color-normalize": "1.5.0", + "color-rgba": "2.1.1", + "flatten-vertex-data": "1.0.2", + "glslify": "7.0.0", + "image-palette": "2.1.0", + "is-iexplorer": "1.0.0", + "object-assign": "4.1.1", + "parse-rect": "1.2.0", + "pick-by-alias": "1.2.0", + "point-cluster": "3.1.8", + "to-float32": "1.0.1", + "update-diff": "1.1.0" + } + }, + "safe-buffer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "requires": { + "safe-buffer": "5.2.0" + } + }, + "supercluster": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/supercluster/-/supercluster-7.0.0.tgz", + "integrity": "sha512-8VuHI8ynylYQj7Qf6PBMWy1PdgsnBiIxujOgc9Z83QvJ8ualIYWNx2iMKyKeC4DZI5ntD9tz/CIwwZvIelixsA==", + "requires": { + "kdbush": "3.0.0" + } + }, + "to-px": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-px/-/to-px-1.0.1.tgz", + "integrity": "sha1-W7rtXl1PdkRbzJA8KTojB90yRkY=", + "requires": { + "parse-unit": "1.0.1" + } + }, + "topojson-client": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/topojson-client/-/topojson-client-3.1.0.tgz", + "integrity": "sha512-605uxS6bcYxGXw9qi62XyrV6Q3xwbndjachmNxu8HWTtVPxZfEJN9fd/SZS1Q54Sn2y0TMyMxFj/cJINqGHrKw==", + "requires": { + "commander": "2.1.0" + } + } } }, "point-cluster": { @@ -3282,21 +3367,6 @@ "string_decoder": "0.10.31" } }, - "redeyed": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-0.4.4.tgz", - "integrity": "sha1-N+mQpvKyGyoRwuakj9QTVpjLqX8=", - "requires": { - "esprima": "1.0.4" - }, - "dependencies": { - "esprima": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz", - "integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0=" - } - } - }, "reduce-simplicial-complex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/reduce-simplicial-complex/-/reduce-simplicial-complex-1.0.0.tgz", @@ -3609,23 +3679,6 @@ "resolved": "https://registry.npmjs.org/shallow-copy/-/shallow-copy-0.0.1.tgz", "integrity": "sha1-QV9CcC1z2BAzApLMXuhurhoRoXA=" }, - "sharkdown": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/sharkdown/-/sharkdown-0.1.1.tgz", - "integrity": "sha512-exwooSpmo5s45lrexgz6Q0rFQM574wYIX3iDZ7RLLqOb7IAoQZu9nxlZODU972g19sR69OIpKP2cpHTzU+PHIg==", - "requires": { - "cardinal": "0.4.4", - "minimist": "0.0.5", - "split": "0.2.10" - }, - "dependencies": { - "minimist": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.5.tgz", - "integrity": "sha1-16oye87PUY+RBqxrjwA/o7zqhWY=" - } - } - }, "signum": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/signum/-/signum-0.0.0.tgz", @@ -3745,14 +3798,6 @@ "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", "dev": true }, - "split": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/split/-/split-0.2.10.tgz", - "integrity": "sha1-Zwl8YB1pfOE2j0GPBs0gHPBSGlc=", - "requires": { - "through": "2.3.8" - } - }, "split-polygon": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/split-polygon/-/split-polygon-1.0.0.tgz", @@ -3959,14 +4004,6 @@ "resolved": "https://registry.npmjs.org/strongly-connected-components/-/strongly-connected-components-1.0.1.tgz", "integrity": "sha1-CSDitN9nyOrulsa2I0/inoc9upk=" }, - "supercluster": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/supercluster/-/supercluster-6.0.2.tgz", - "integrity": "sha512-aa0v2HURjBTOpbcknilcfxGDuArM8khklKSmZ/T8ZXL0BuRwb5aRw95lz+2bmWpFvCXDX/+FzqHxmg0TIaJErw==", - "requires": { - "kdbush": "3.0.0" - } - }, "superscript-text": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/superscript-text/-/superscript-text-1.0.0.tgz", @@ -4083,14 +4120,6 @@ } } }, - "text-cache": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/text-cache/-/text-cache-4.2.1.tgz", - "integrity": "sha512-G52NFRYXEW9BL4E3kBPquefXql9OT3sNT4J16gcpl3/a8y/YioDOR2Iwga5rNs9tY7rH2xv6rF8fAYrbINn6Kg==", - "requires": { - "vectorize-text": "3.2.1" - } - }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -4150,14 +4179,6 @@ "to-array-buffer": "3.2.0" } }, - "topojson-client": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/topojson-client/-/topojson-client-2.1.0.tgz", - "integrity": "sha1-/59784mRGF4LQoTCsGroNPDqxsg=", - "requires": { - "commander": "2.1.0" - } - }, "triangulate-hypercube": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/triangulate-hypercube/-/triangulate-hypercube-1.0.1.tgz", @@ -4477,11 +4498,6 @@ "get-canvas-context": "1.0.2" } }, - "wgs84": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/wgs84/-/wgs84-0.0.0.tgz", - "integrity": "sha1-NP3FVZF7blfPKigu0ENxDASc3HY=" - }, "window-size": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", diff --git a/packages/javascript/jupyterlab-plotly/package.json b/packages/javascript/jupyterlab-plotly/package.json index b8980557dcf..2ae021f2db6 100644 --- a/packages/javascript/jupyterlab-plotly/package.json +++ b/packages/javascript/jupyterlab-plotly/package.json @@ -1,6 +1,6 @@ { "name": "jupyterlab-plotly", - "version": "1.5.4", + "version": "4.7.1", "description": "The plotly JupyterLab extension", "author": "The plotly.py team", "license": "MIT", @@ -31,7 +31,7 @@ "typescript": "~3.7.0" }, "dependencies": { - "plotly.js": "^1.52.1", + "plotly.js": "^1.54.1", "@types/plotly.js": "1.44.28", "@jupyterlab/rendermime-interfaces": "^1.3.0 || ^2.0.0", "@lumino/messaging": "^1.2.3", diff --git a/packages/javascript/jupyterlab-plotly/src/javascript-renderer-extension.ts b/packages/javascript/jupyterlab-plotly/src/javascript-renderer-extension.ts index 1cd9606054e..bd0a3f26773 100644 --- a/packages/javascript/jupyterlab-plotly/src/javascript-renderer-extension.ts +++ b/packages/javascript/jupyterlab-plotly/src/javascript-renderer-extension.ts @@ -1,32 +1,32 @@ // Copyright (c) Jupyter Development Team. // Distributed under the terms of the Modified BSD License. -import { Widget } from '@lumino/widgets'; +import { Widget } from "@lumino/widgets"; -import { Message } from '@lumino/messaging'; +import { Message } from "@lumino/messaging"; -import { IRenderMime } from '@jupyterlab/rendermime-interfaces'; +import { IRenderMime } from "@jupyterlab/rendermime-interfaces"; -import '../style/index.css'; +import "../style/index.css"; /** * The CSS class to add to the Plotly Widget. */ -const CSS_CLASS = 'jp-RenderedPlotly'; +const CSS_CLASS = "jp-RenderedPlotly"; /** * The CSS class for a Plotly icon. */ -const CSS_ICON_CLASS = 'jp-MaterialIcon jp-PlotlyIcon'; +const CSS_ICON_CLASS = "jp-MaterialIcon jp-PlotlyIcon"; /** * The MIME type for Plotly. * The version of this follows the major version of Plotly. */ -export const MIME_TYPE = 'application/vnd.plotly.v1+json'; +export const MIME_TYPE = "application/vnd.plotly.v1+json"; interface PlotlyHTMLElement extends HTMLElement { - on(event: 'plotly_webglcontextlost', callback: () => void): void; + on(event: "plotly_webglcontextlost", callback: () => void): void; } type Frame = { [key: string]: any }; @@ -41,24 +41,24 @@ export class RenderedPlotly extends Widget implements IRenderMime.IRenderer { this._mimeType = options.mimeType; // Create image element - this._img_el = (document.createElement("img")); - this._img_el.className = 'plot-img'; + this._img_el = document.createElement("img"); + this._img_el.className = "plot-img"; this.node.appendChild(this._img_el); // Install image hover callback - import(/* webpackChunkName: 'plotly'*/ 'plotly.js/dist/plotly').then(Plotly => { - - this._img_el.addEventListener('mouseenter', event => { - this.createGraph(this._model, Plotly); - }) - }) + import(/* webpackChunkName: 'plotly'*/ /* webpackPrefetch: true */ "plotly.js/dist/plotly").then( + (Plotly) => { + this._img_el.addEventListener("mouseenter", (event) => { + this.createGraph(this._model, Plotly); + }); + } + ); } /** * Render Plotly into this widget's node. */ renderModel(model: IRenderMime.IMimeModel): Promise { - if (this.hasGraphElement()) { // We already have a graph, don't overwrite it return Promise.resolve(); @@ -68,23 +68,25 @@ export class RenderedPlotly extends Widget implements IRenderMime.IRenderer { this._model = model; // Check for PNG data in mime bundle - const png_data = model.data['image/png']; - if(png_data !== undefined && png_data !== null) { + const png_data = model.data["image/png"]; + if (png_data !== undefined && png_data !== null) { // We have PNG data, use it this.updateImage(png_data); return Promise.resolve(); } else { // Create a new graph - return import(/* webpackChunkName: 'plotly'*/ 'plotly.js/dist/plotly').then(Plotly => { + return import( + /* webpackChunkName: 'plotly'*/ /* webpackPrefetch: true */ "plotly.js/dist/plotly" + ).then((Plotly) => { this.createGraph(model, Plotly); - }) + }); } } private hasGraphElement() { // Check for the presence of the .plot-container element that plotly.js // places at the top of the figure structure - return this.node.querySelector('.plot-container') !== null + return this.node.querySelector(".plot-container") !== null; } private updateImage(png_data: string) { @@ -95,43 +97,43 @@ export class RenderedPlotly extends Widget implements IRenderMime.IRenderer { private hideGraph() { // Hide the graph if there is one - let el = this.node.querySelector('.plot-container'); + let el = this.node.querySelector(".plot-container"); if (el !== null && el !== undefined) { - el.style.display = "none" + el.style.display = "none"; } } private showGraph() { // Show the graph if there is one - let el = this.node.querySelector('.plot-container'); + let el = this.node.querySelector(".plot-container"); if (el !== null && el !== undefined) { - el.style.display = "block" + el.style.display = "block"; } } private hideImage() { // Hide the image element - let el = this.node.querySelector('.plot-img'); + let el = this.node.querySelector(".plot-img"); if (el !== null && el !== undefined) { - el.style.display = "none" + el.style.display = "none"; } } private showImage() { // Show the image element - let el = this.node.querySelector('.plot-img'); + let el = this.node.querySelector(".plot-img"); if (el !== null && el !== undefined) { - el.style.display = "block" + el.style.display = "block"; } } private createGraph(model: IRenderMime.IMimeModel, Plotly: any) { const { data, layout, frames, config } = model.data[this._mimeType] as | any - | { data: Plotly.Data; layout: Plotly.Layout; frames?: Frame[]; } - | { data: Plotly.Data; layout: Plotly.Layout; frames?: Plotly.Frame[]; } + | { data: Plotly.Data; layout: Plotly.Layout; frames?: Frame[] } + | { data: Plotly.Data; layout: Plotly.Layout; frames?: Plotly.Frame[] }; - return Plotly.react(this.node, data, layout, config).then(plot => { + return Plotly.react(this.node, data, layout, config).then((plot: any) => { this.showGraph(); this.hideImage(); this.update(); @@ -140,31 +142,31 @@ export class RenderedPlotly extends Widget implements IRenderMime.IRenderer { } if (this.node.offsetWidth > 0 && this.node.offsetHeight > 0) { Plotly.toImage(plot, { - format: 'png', + format: "png", width: this.node.offsetWidth, - height: this.node.offsetHeight + height: this.node.offsetHeight, }).then((url: string) => { - const imageData = url.split(',')[1]; - if (model.data['image/png'] !== imageData) { + const imageData = url.split(",")[1]; + if (model.data["image/png"] !== imageData) { model.setData({ data: { ...model.data, - 'image/png': imageData - } + "image/png": imageData, + }, }); } }); } // Handle webgl context lost events - ((this.node)).on('plotly_webglcontextlost', () => { - const png_data = model.data['image/png']; - if(png_data !== undefined && png_data !== null) { - // We have PNG data, use it - this.updateImage(png_data); - return Promise.resolve(); - } - }); + (this.node).on("plotly_webglcontextlost", () => { + const png_data = model.data["image/png"]; + if (png_data !== undefined && png_data !== null) { + // We have PNG data, use it + this.updateImage(png_data); + return Promise.resolve(); + } + }); }); } @@ -187,17 +189,19 @@ export class RenderedPlotly extends Widget implements IRenderMime.IRenderer { */ protected onUpdateRequest(msg: Message): void { if (this.isVisible && this.hasGraphElement()) { - import(/* webpackChunkName: 'plotly'*/ 'plotly.js/dist/plotly').then(Plotly => { - Plotly.redraw(this.node).then(() => { - Plotly.Plots.resize(this.node); - }); - }) + import(/* webpackChunkName: 'plotly'*/ /* webpackPrefetch: true */ "plotly.js/dist/plotly").then( + (Plotly) => { + Plotly.redraw(this.node).then(() => { + Plotly.Plots.resize(this.node); + }); + } + ); } } private _mimeType: string; private _img_el: HTMLImageElement; - private _model: IRenderMime.IMimeModel + private _model: IRenderMime.IMimeModel; } /** @@ -206,30 +210,30 @@ export class RenderedPlotly extends Widget implements IRenderMime.IRenderer { export const rendererFactory: IRenderMime.IRendererFactory = { safe: true, mimeTypes: [MIME_TYPE], - createRenderer: options => new RenderedPlotly(options) + createRenderer: (options) => new RenderedPlotly(options), }; const extensions: IRenderMime.IExtension | IRenderMime.IExtension[] = [ { - id: '@jupyterlab/plotly-extension:factory', + id: "@jupyterlab/plotly-extension:factory", rendererFactory, rank: 0, - dataType: 'json', + dataType: "json", fileTypes: [ { - name: 'plotly', + name: "plotly", mimeTypes: [MIME_TYPE], - extensions: ['.plotly', '.plotly.json'], - iconClass: CSS_ICON_CLASS - } + extensions: [".plotly", ".plotly.json"], + iconClass: CSS_ICON_CLASS, + }, ], documentWidgetFactoryOptions: { - name: 'Plotly', - primaryFileType: 'plotly', - fileTypes: ['plotly', 'json'], - defaultFor: ['plotly'] - } - } + name: "Plotly", + primaryFileType: "plotly", + fileTypes: ["plotly", "json"], + defaultFor: ["plotly"], + }, + }, ]; export default extensions; \ No newline at end of file diff --git a/packages/javascript/jupyterlab-plotly/src/lib.d.ts b/packages/javascript/jupyterlab-plotly/src/lib.d.ts index 35baebccc96..878636a6970 100644 --- a/packages/javascript/jupyterlab-plotly/src/lib.d.ts +++ b/packages/javascript/jupyterlab-plotly/src/lib.d.ts @@ -1,10 +1,10 @@ -declare module 'plotly.js/dist/plotly.min' { - export * from 'plotly.js'; +declare module "plotly.js/dist/plotly" { + export * from "plotly.js"; export type Frame = { [key: string]: any }; export function addFrames(root: Plotly.Root, frames: Frame[]): Promise; export function animate(root: Plotly.Root): void; export interface PlotlyHTMLElement extends HTMLElement { - on(event: 'plotly_webglcontextlost', callback: () => void): void; + on(event: "plotly_webglcontextlost", callback: () => void): void; } } diff --git a/packages/javascript/plotlywidget/package-lock.json b/packages/javascript/plotlywidget/package-lock.json index f08778735f1..f857017d648 100644 --- a/packages/javascript/plotlywidget/package-lock.json +++ b/packages/javascript/plotlywidget/package-lock.json @@ -1,6 +1,6 @@ { "name": "plotlywidget", - "version": "1.5.4", + "version": "4.7.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -93,23 +93,54 @@ "ws": "7.0.1" } }, - "@mapbox/geojson-area": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@mapbox/geojson-area/-/geojson-area-0.2.2.tgz", - "integrity": "sha1-GNeBSqNr8j+7zDefjiaiKSfevxA=", - "requires": { - "wgs84": "0.0.0" - } - }, "@mapbox/geojson-rewind": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@mapbox/geojson-rewind/-/geojson-rewind-0.4.0.tgz", - "integrity": "sha512-b+1uPWBERW4Pet/969BNu61ZPDyH2ilIxBjJDFzxyS9TyszF9UrTQyYIl/G38clux3rtpAGGFSGTCSF/qR6UjA==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@mapbox/geojson-rewind/-/geojson-rewind-0.5.0.tgz", + "integrity": "sha512-73l/qJQgj/T/zO1JXVfuVvvKDgikD/7D/rHAD28S9BG1OTstgmftrmqfCx4U+zQAmtsB6HcDA3a7ymdnJZAQgg==", "requires": { - "@mapbox/geojson-area": "0.2.2", - "concat-stream": "1.6.2", - "minimist": "1.2.0", - "sharkdown": "0.1.1" + "concat-stream": "2.0.0", + "minimist": "1.2.5" + }, + "dependencies": { + "concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "requires": { + "buffer-from": "1.1.1", + "inherits": "2.0.3", + "readable-stream": "3.6.0", + "typedarray": "0.0.6" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "2.0.3", + "string_decoder": "1.3.0", + "util-deprecate": "1.0.2" + } + }, + "safe-buffer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "requires": { + "safe-buffer": "5.2.0" + } + } } }, "@mapbox/geojson-types": { @@ -123,9 +154,9 @@ "integrity": "sha1-zlblOfg1UrWNENZy6k1vya3HsjQ=" }, "@mapbox/mapbox-gl-supported": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@mapbox/mapbox-gl-supported/-/mapbox-gl-supported-1.4.1.tgz", - "integrity": "sha512-yyKza9S6z3ELKuf6w5n6VNUB0Osu6Z93RXPfMHLIlNWohu3KqxewLOq4lMXseYJ92GwkRAxd207Pr/Z98cwmvw==" + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@mapbox/mapbox-gl-supported/-/mapbox-gl-supported-1.5.0.tgz", + "integrity": "sha512-/PT1P6DNf7vjEEiPkVIRJkvibbqWtqnyGaBz3nfRdcxclNSnSdaLU5tfAgcD7I8Yt5i+L19s406YLl1koLnLbg==" }, "@mapbox/point-geometry": { "version": "0.1.0", @@ -373,7 +404,8 @@ "acorn": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.4.1.tgz", - "integrity": "sha512-XLmq3H/BVvW6/GbxKryGxWORz1ebilSsUDlyC27bXhWGWAZWkGwS6FLHjOlwFXNFoWFQEO/Df4u0YYd0K3BQgQ==" + "integrity": "sha512-XLmq3H/BVvW6/GbxKryGxWORz1ebilSsUDlyC27bXhWGWAZWkGwS6FLHjOlwFXNFoWFQEO/Df4u0YYd0K3BQgQ==", + "dev": true }, "acorn-dynamic-import": { "version": "2.0.2", @@ -393,9 +425,9 @@ } }, "acorn-jsx": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz", - "integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==" + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.2.0.tgz", + "integrity": "sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ==" }, "add-line-numbers": { "version": "1.0.1", @@ -495,11 +527,6 @@ "color-convert": "1.9.3" } }, - "ansicolors": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.2.1.tgz", - "integrity": "sha1-vgiVmQl7dKXJxKhKDNvNtivYeu8=" - }, "anymatch": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", @@ -719,7 +746,7 @@ "resolved": "https://registry.npmjs.org/boundary-cells/-/boundary-cells-2.0.1.tgz", "integrity": "sha1-6QWo0UGc9Hyza+Pb9SXbXiTeAEI=", "requires": { - "tape": "4.13.0" + "tape": "4.13.2" } }, "box-intersect": { @@ -832,20 +859,20 @@ "resolved": "https://registry.npmjs.org/buble/-/buble-0.19.8.tgz", "integrity": "sha512-IoGZzrUTY5fKXVkgGHw3QeXFMUNBFv+9l8a4QJKG1JhG3nCMHTdEX1DCOg8568E2Q9qvAQIiSokv6Jsgx8p2cA==", "requires": { - "acorn": "6.4.0", + "acorn": "6.4.1", "acorn-dynamic-import": "4.0.0", - "acorn-jsx": "5.1.0", + "acorn-jsx": "5.2.0", "chalk": "2.4.2", - "magic-string": "0.25.6", + "magic-string": "0.25.7", "minimist": "1.2.0", "os-homedir": "2.0.0", - "regexpu-core": "4.6.0" + "regexpu-core": "4.7.0" }, "dependencies": { "acorn": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.0.tgz", - "integrity": "sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw==" + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", + "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==" }, "acorn-dynamic-import": { "version": "4.0.0", @@ -917,15 +944,6 @@ "element-size": "1.1.1" } }, - "cardinal": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-0.4.4.tgz", - "integrity": "sha1-ylu2iltRG5D+k7ms6km97lwyv+I=", - "requires": { - "ansicolors": "0.2.1", - "redeyed": "0.4.4" - } - }, "cdt2d": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/cdt2d/-/cdt2d-1.0.0.tgz", @@ -1449,9 +1467,9 @@ "integrity": "sha512-ii0/r5f4sjKNTfh84Di+DpztYwqKhEyUlKoPrzUFfeSkWxjW49xU2QzO9qrPrNkpdI0XJkfzvmTu8V2Zylln6A==" }, "d3-color": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.4.0.tgz", - "integrity": "sha512-TzNPeJy2+iEepfiL92LAAB7fvnp/dV2YwANPVHdDWmYMm23qIJBYww3qT8I8C1wXrmrg4UWs7BKc2tKIgyjzHg==" + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.4.1.tgz", + "integrity": "sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q==" }, "d3-dispatch": { "version": "1.0.6", @@ -1479,7 +1497,7 @@ "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.4.0.tgz", "integrity": "sha512-V9znK0zc3jOPV4VD2zZn0sDhZU3WAE2bmlxdIwwQPPzPjvyLkd8B3JUVdS1IDUFDkWZ72c9qnv1GK2ZagTZ8EA==", "requires": { - "d3-color": "1.4.0" + "d3-color": "1.4.1" } }, "d3-path": { @@ -1524,7 +1542,7 @@ "is-arguments": "1.0.4", "is-date-object": "1.0.2", "is-regex": "1.0.5", - "object-is": "1.0.2", + "object-is": "1.1.2", "object-keys": "1.1.1", "regexp.prototype.flags": "1.3.0" } @@ -1767,9 +1785,9 @@ } }, "es-abstract": { - "version": "1.17.4", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz", - "integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==", + "version": "1.17.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz", + "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==", "requires": { "es-to-primitive": "1.2.1", "function-bind": "1.1.1", @@ -1780,8 +1798,8 @@ "object-inspect": "1.7.0", "object-keys": "1.1.1", "object.assign": "4.1.0", - "string.prototype.trimleft": "2.1.1", - "string.prototype.trimright": "2.1.1" + "string.prototype.trimleft": "2.1.2", + "string.prototype.trimright": "2.1.2" } }, "es-to-primitive": { @@ -1828,9 +1846,9 @@ } }, "es6-promise": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", - "integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=" + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" }, "es6-set": { "version": "0.1.5", @@ -2016,14 +2034,26 @@ "integrity": "sha1-l9VwP/BWTIw8aDjKxF+ee8UsnvU=" }, "falafel": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/falafel/-/falafel-2.1.0.tgz", - "integrity": "sha1-lrsXdh2rqU9G0AFzizzt86Z/4Gw=", + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/falafel/-/falafel-2.2.4.tgz", + "integrity": "sha512-0HXjo8XASWRmsS0X1EkhwEMZaD3Qvp7FfURwjLKjG1ghfRm/MGZl2r4cWUTv41KdNghTw4OUMmVtdGQp3+H+uQ==", "requires": { - "acorn": "5.4.1", + "acorn": "7.1.1", "foreach": "2.0.5", - "isarray": "0.0.1", + "isarray": "2.0.5", "object-keys": "1.1.1" + }, + "dependencies": { + "acorn": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.1.tgz", + "integrity": "sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==" + }, + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + } } }, "fast-deep-equal": { @@ -2033,9 +2063,9 @@ "dev": true }, "fast-isnumeric": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/fast-isnumeric/-/fast-isnumeric-1.1.3.tgz", - "integrity": "sha512-MdojHkfLx8pjRNZyGjOhX4HxNPaf0l5R/v5rGZ1bGXCnRPyQIUAe4I1H7QtrlUwuuiDHKdpQTjT3lmueVH2otw==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/fast-isnumeric/-/fast-isnumeric-1.1.4.tgz", + "integrity": "sha512-1mM8qOr2LYz8zGaUdmiqRDiuue00Dxjgcb1NQR7TnhLVh6sQyngP9xvLo7Sl7LZpP/sk5eb+bcyWXw530NTBZw==", "requires": { "is-string-blank": "1.0.1" } @@ -3155,9 +3185,9 @@ "dev": true }, "gl-axes3d": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/gl-axes3d/-/gl-axes3d-1.5.2.tgz", - "integrity": "sha512-47Cfh5KhUVRFtYXgufR4lGY5cyXH7SPgAlS1FlvTGK84spIYFCBMlOGUN3AdavGLGUOcXS4ml+tMM61cY6M3gg==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/gl-axes3d/-/gl-axes3d-1.5.3.tgz", + "integrity": "sha512-KRYbguKQcDQ6PcB9g1pgqB8Ly4TY1DQODpPKiDTasyWJ8PxQk0t2Q7XoQQijNqvsguITCpVVCzNb5GVtIWiVlQ==", "requires": { "bit-twiddle": "1.0.2", "dup": "1.0.0", @@ -3179,15 +3209,15 @@ "resolved": "https://registry.npmjs.org/gl-buffer/-/gl-buffer-2.1.2.tgz", "integrity": "sha1-LbjZwaVSf7oM25EonCBuiCuInNs=", "requires": { - "ndarray": "1.0.19", + "ndarray": "1.0.18", "ndarray-ops": "1.2.2", "typedarray-pool": "1.2.0" } }, "gl-cone3d": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/gl-cone3d/-/gl-cone3d-1.5.1.tgz", - "integrity": "sha512-R8m2lPfVN5ip/IPzykvMNgUUGWTkp9rMuCrVknKIkhjH+gaQeGfwF3+WrB0kwq3FRWvlYWcfdvabv37sZ2rKYA==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/gl-cone3d/-/gl-cone3d-1.5.2.tgz", + "integrity": "sha512-1JNeHH4sUtUmDA4ZK7Om8/kShwb8IZVAsnxaaB7IPRJsNGciLj1sTpODrJGeMl41RNkex5kXD2SQFrzyEAR2Rw==", "requires": { "colormap": "2.3.1", "gl-buffer": "2.1.2", @@ -3200,7 +3230,7 @@ "glsl-out-of-range": "1.0.4", "glsl-specular-cook-torrance": "2.0.1", "glslify": "7.0.0", - "ndarray": "1.0.19" + "ndarray": "1.0.18" } }, "gl-constants": { @@ -3209,9 +3239,9 @@ "integrity": "sha1-WXpQTjZHUP9QJTqjX43qevSl0jM=" }, "gl-contour2d": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/gl-contour2d/-/gl-contour2d-1.1.6.tgz", - "integrity": "sha512-n8nEFb4VRYooBo3+hbAgiXGELVn7PtYyVbj/hWmTNtrkxFK39Yr8LUczcT2uOOyzqq7sO3FH8+J8PSMFh+z+5A==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/gl-contour2d/-/gl-contour2d-1.1.7.tgz", + "integrity": "sha512-GdebvJ9DtT3pJDpoE+eU2q+Wo9S3MijPpPz5arZbhK85w2bARmpFpVfPaDlZqWkB644W3BlH8TVyvAo1KE4Bhw==", "requires": { "binary-search-bounds": "2.0.4", "cdt2d": "1.0.0", @@ -3220,14 +3250,14 @@ "gl-shader": "4.2.1", "glslify": "7.0.0", "iota-array": "1.0.0", - "ndarray": "1.0.19", + "ndarray": "1.0.18", "surface-nets": "1.0.2" } }, "gl-error3d": { - "version": "1.0.15", - "resolved": "https://registry.npmjs.org/gl-error3d/-/gl-error3d-1.0.15.tgz", - "integrity": "sha512-7mB1zU22Vzdvq0KzzYRzE0xvCRF9nHd1+9ElUqkvt0GMH0gVIpxKk+m3hNPM/iQHmNupcXaE1cBcOQE2agN3uA==", + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/gl-error3d/-/gl-error3d-1.0.16.tgz", + "integrity": "sha512-TGJewnKSp7ZnqGgG3XCF9ldrDbxZrO+OWlx6oIet4OdOM//n8xJ5isArnIV/sdPJnFbhfoLxWrW9f5fxHFRQ1A==", "requires": { "gl-buffer": "2.1.2", "gl-shader": "4.2.1", @@ -3256,9 +3286,9 @@ } }, "gl-heatmap2d": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/gl-heatmap2d/-/gl-heatmap2d-1.0.5.tgz", - "integrity": "sha512-nki9GIh0g4OXKNIrlnAT/gy/uXxkwrFKgI+XwRcUO6nLBM1WbI2hl8EPykNFXCqsyd08HJQbXKiqaHPW7cNpJg==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/gl-heatmap2d/-/gl-heatmap2d-1.0.6.tgz", + "integrity": "sha512-+agzSv4R5vsaH+AGYVz5RVzBK10amqAa+Bwj205F13JjNSGS91M1L9Yb8zssCv2FIjpP+1Mp73cFBYrQFfS1Jg==", "requires": { "binary-search-bounds": "2.0.4", "gl-buffer": "2.1.2", @@ -3269,9 +3299,9 @@ } }, "gl-line3d": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/gl-line3d/-/gl-line3d-1.1.11.tgz", - "integrity": "sha512-EitFKPEEYdn/ivFOxJ8khSi0BzNum4sXZFLq6SQq21MX5YPCYb0o+XzjpWNuU32BoXORBC78B1JTiQqnTaWhWQ==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/gl-line3d/-/gl-line3d-1.2.1.tgz", + "integrity": "sha512-eeb0+RI2ZBRqMYJK85SgsRiJK7c4aiOjcnirxv0830A3jmOc99snY3AbPcV8KvKmW0Yaf3KA4e+qNCbHiTOTnA==", "requires": { "binary-search-bounds": "2.0.4", "gl-buffer": "2.1.2", @@ -3279,9 +3309,8 @@ "gl-texture2d": "2.1.0", "gl-vao": "1.3.0", "glsl-out-of-range": "1.0.4", - "glsl-read-float": "1.1.0", "glslify": "7.0.0", - "ndarray": "1.0.19" + "ndarray": "1.0.18" } }, "gl-mat2": { @@ -3300,9 +3329,9 @@ "integrity": "sha512-sT5C0pwB1/e9G9AvAoLsoaJtbMGjfd/jfxo8jMCKqYYEnjZuFvqV5rehqar0538EmssjdDeiEWnKyBSTw7quoA==" }, "gl-matrix": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-3.2.1.tgz", - "integrity": "sha512-YYVO8jUSf6+SakL4AJmx9Jc7zAZhkJQ+WhdtX3VQe5PJdCOX6/ybY4x1vk+h94ePnjRn6uml68+QxTAJneUpvA==" + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-3.3.0.tgz", + "integrity": "sha512-COb7LDz+SXaHtl/h4LeaFcNdJdAQSDeVqjiIihSXNrkWObZLhDI4hIkZC11Aeqp7bcE72clzB0BnDXr2SmslRA==" }, "gl-matrix-invert": { "version": "1.0.0", @@ -3315,9 +3344,9 @@ } }, "gl-mesh3d": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/gl-mesh3d/-/gl-mesh3d-2.3.0.tgz", - "integrity": "sha512-iKx3v0xB/6Kej+GpMHhxzW6ziqiIjp6WOyAbuXvBRN9P5iIgzifgBYnDd1mYmCLWGmf85MCki/FvD223BOYFxg==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/gl-mesh3d/-/gl-mesh3d-2.3.1.tgz", + "integrity": "sha512-pXECamyGgu4/9HeAQSE5OEUuLBGS1aq9V4BCsTcxsND4fNLaajEkYKUz/WY2QSYElqKdsMBVsldGiKRKwlybqA==", "requires": { "barycentric": "1.0.1", "colormap": "2.3.1", @@ -3329,7 +3358,7 @@ "glsl-out-of-range": "1.0.4", "glsl-specular-cook-torrance": "2.0.1", "glslify": "7.0.0", - "ndarray": "1.0.19", + "ndarray": "1.0.18", "normals": "1.1.0", "polytope-closest-point": "1.0.0", "simplicial-complex-contour": "1.0.2", @@ -3337,46 +3366,46 @@ } }, "gl-plot2d": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/gl-plot2d/-/gl-plot2d-1.4.3.tgz", - "integrity": "sha512-Ei6WC/SzQ7/qld8MMv7sWrFSdkq8/n7Xmdvj7sbwUkgsJirfknKfeq4DCwaMn9vD2rHOLmdT0NMW+HPrLKSeWQ==", + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/gl-plot2d/-/gl-plot2d-1.4.4.tgz", + "integrity": "sha512-0UhKiiqeampLtydv6NMNrKEilc0Ui5oaJtvHLbLZ5u/1ttT1XjOY5Yk8LzfqozA/No4a9omxjSKnH+tvSn+rQQ==", "requires": { "binary-search-bounds": "2.0.4", "gl-buffer": "2.1.2", - "gl-select-static": "2.0.5", + "gl-select-static": "2.0.6", "gl-shader": "4.2.1", "glsl-inverse": "1.0.0", "glslify": "7.0.0", - "text-cache": "4.2.1" + "text-cache": "4.2.2" } }, "gl-plot3d": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/gl-plot3d/-/gl-plot3d-2.4.4.tgz", - "integrity": "sha512-R/V4hSrE2sFD+Xls7D6qCOlWCRmqtUff0sKbeFJdI91HfFzPJPiy9Pqa/Jh2UsvdmwkkSQPNDcBvLd6TvhRC/g==", + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/gl-plot3d/-/gl-plot3d-2.4.5.tgz", + "integrity": "sha512-cKAqMXFRHTCFxH8r1/ACdk5hyfnA9djfiAM8zVQrqu0qLEttUu0i1fq0pr+d5m0HPuNcK8wEc4F3VjL2hrDcGQ==", "requires": { "3d-view": "2.0.0", "a-big-triangle": "1.0.3", - "gl-axes3d": "1.5.2", + "gl-axes3d": "1.5.3", "gl-fbo": "2.0.5", "gl-mat4": "1.2.0", - "gl-select-static": "2.0.5", + "gl-select-static": "2.0.6", "gl-shader": "4.2.1", - "gl-spikes3d": "1.0.9", + "gl-spikes3d": "1.0.10", "glslify": "7.0.0", "has-passive-events": "1.0.0", "is-mobile": "2.2.1", "mouse-change": "1.4.0", "mouse-event-offset": "3.0.2", "mouse-wheel": "1.2.0", - "ndarray": "1.0.19", + "ndarray": "1.0.18", "right-now": "1.0.0" } }, "gl-pointcloud2d": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/gl-pointcloud2d/-/gl-pointcloud2d-1.0.2.tgz", - "integrity": "sha512-KDfuJLg1dFWNPo6eJYgwUpNdVcIdK5y29ZiYpzzP0qh3eg0bSLMq8ZkaqvPmSJsFksUryT73IRunsuxJtTJkvA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/gl-pointcloud2d/-/gl-pointcloud2d-1.0.3.tgz", + "integrity": "sha512-OS2e1irvJXVRpg/GziXj10xrFJm9kkRfFoB6BLUvkjCQV7ZRNNcs2CD+YSK1r0gvMwTg2T3lfLM3UPwNtz+4Xw==", "requires": { "gl-buffer": "2.1.2", "gl-shader": "4.2.1", @@ -3395,9 +3424,9 @@ } }, "gl-scatter3d": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/gl-scatter3d/-/gl-scatter3d-1.2.2.tgz", - "integrity": "sha512-oZh3WQ0bVXnpASpZmYmiEp7eUiD0oU6J4G5C9KUOhUo5d2gucvZEILAtfWmzCT3zsOltoROn4jGuuP2tlLN88Q==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/gl-scatter3d/-/gl-scatter3d-1.2.3.tgz", + "integrity": "sha512-nXqPlT1w5Qt51dTksj+DUqrZqwWAEWg0PocsKcoDnVNv0X8sGA+LBZ0Y+zrA+KNXUL0PPCX9WR9cF2uJAZl1Sw==", "requires": { "gl-buffer": "2.1.2", "gl-mat4": "1.2.0", @@ -3411,9 +3440,9 @@ } }, "gl-select-box": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/gl-select-box/-/gl-select-box-1.0.3.tgz", - "integrity": "sha512-sQb18g1aZ6PJAsvsC8nNYhuhc2TYXNbzVbI0bP9AH9770NjrDnd7TC8HHcfu8nJXGPG69HjqR6EzS+QSqiXPSA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/gl-select-box/-/gl-select-box-1.0.4.tgz", + "integrity": "sha512-mKsCnglraSKyBbQiGq0Ila0WF+m6Tr+EWT2yfaMn/Sh9aMHq5Wt0F/l6Cf/Ed3CdERq5jHWAY5yxLviZteYu2w==", "requires": { "gl-buffer": "2.1.2", "gl-shader": "4.2.1", @@ -3421,14 +3450,14 @@ } }, "gl-select-static": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/gl-select-static/-/gl-select-static-2.0.5.tgz", - "integrity": "sha512-8H1M9ipHNsrVh8UjUmTv1xhhYjYzMnawAnw3n715Dh4DDoW32F3oBi80ev5qbJtQlvHrNkhHKuoMCJKBjfIt4g==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/gl-select-static/-/gl-select-static-2.0.6.tgz", + "integrity": "sha512-p4DmBG1DMo/47/fV3oqPcU6uTqHy0eI1vATH1fm8OVDqlzWnLv3786tdEunZWG6Br7DUdH6NgWhuy4gAlt+TAQ==", "requires": { "bit-twiddle": "1.0.2", "cwise": "1.0.10", "gl-fbo": "2.0.5", - "ndarray": "1.0.19", + "ndarray": "1.0.18", "typedarray-pool": "1.2.0" } }, @@ -3447,9 +3476,9 @@ "integrity": "sha512-QVeOZsi9nQuJJl7NB3132CCv5KA10BWxAY2QgJNsKqbLsG53B/TrGJpjIAohnJftdZ4fT6b3ZojWgeaXk8bOOA==" }, "gl-spikes3d": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/gl-spikes3d/-/gl-spikes3d-1.0.9.tgz", - "integrity": "sha512-laMxydgGdnE8kvd1YD9cNWrx0uSmrPj1Oi02cHhnxWIklut97w3F7mZKnmLMEyUkxpRLkEeQ7YkYy7Y+aUEblw==", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/gl-spikes3d/-/gl-spikes3d-1.0.10.tgz", + "integrity": "sha512-lT3xroowOFxMvlhT5Mof76B2TE02l5zt/NIWljhczV2FFHgIVhA4jMrd5dIv1so1RXMBDJIKu0uJI3QKliDVLg==", "requires": { "gl-buffer": "2.1.2", "gl-shader": "4.2.1", @@ -3466,11 +3495,11 @@ } }, "gl-streamtube3d": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/gl-streamtube3d/-/gl-streamtube3d-1.4.0.tgz", - "integrity": "sha512-WgRtdB77uFCN1lBZ6ogz7VTK4J8WwW5DGHvyB3LaBSZF3t5lf/KWeXPgm+xnNINlOy4JqJIgny+CtzwTHAk3Ew==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/gl-streamtube3d/-/gl-streamtube3d-1.4.1.tgz", + "integrity": "sha512-rH02v00kgwgdpkXVo7KsSoPp38bIAYR9TE1iONjcQ4cQAlDhrGRauqT/P5sUaOIzs17A2DxWGcXM+EpNQs9pUA==", "requires": { - "gl-cone3d": "1.5.1", + "gl-cone3d": "1.5.2", "gl-vec3": "1.1.3", "gl-vec4": "1.0.1", "glsl-inverse": "1.0.0", @@ -3480,9 +3509,9 @@ } }, "gl-surface3d": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/gl-surface3d/-/gl-surface3d-1.4.6.tgz", - "integrity": "sha512-aItWQTNUX3JJc6i2FbXX82ljPZgDV3kXzkzANcBGoAnKwRpJw12WcMKKTL4sOCs9BW+3sx6BhR0P5+2zh5Scfw==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/gl-surface3d/-/gl-surface3d-1.5.2.tgz", + "integrity": "sha512-rWSQwEQDkB0T5CDEDFJwJc4VgwwJaAyFRSJ92NJlrTSwDlsEsWdzG9+APx6FWJMwkOpIoZGWqv+csswK2kMMLQ==", "requires": { "binary-search-bounds": "2.0.4", "bit-twiddle": "1.0.2", @@ -3496,7 +3525,7 @@ "glsl-out-of-range": "1.0.4", "glsl-specular-beckmann": "1.1.2", "glslify": "7.0.0", - "ndarray": "1.0.19", + "ndarray": "1.0.18", "ndarray-gradient": "1.0.0", "ndarray-ops": "1.2.2", "ndarray-pack": "1.2.1", @@ -3518,14 +3547,14 @@ "flatten-vertex-data": "1.0.2", "font-atlas": "2.1.0", "font-measure": "1.2.2", - "gl-util": "3.1.2", + "gl-util": "3.1.3", "is-plain-obj": "1.1.0", "object-assign": "4.1.1", "parse-rect": "1.2.0", "parse-unit": "1.0.1", "pick-by-alias": "1.2.0", - "regl": "1.3.13", - "to-px": "1.1.0", + "regl": "1.3.11", + "to-px": "1.0.1", "typedarray-pool": "1.2.0" }, "dependencies": { @@ -3577,15 +3606,15 @@ "resolved": "https://registry.npmjs.org/gl-texture2d/-/gl-texture2d-2.1.0.tgz", "integrity": "sha1-/2gk5+fDGoum/c2+nlxpXX4hh8c=", "requires": { - "ndarray": "1.0.19", + "ndarray": "1.0.18", "ndarray-ops": "1.2.2", "typedarray-pool": "1.2.0" } }, "gl-util": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/gl-util/-/gl-util-3.1.2.tgz", - "integrity": "sha512-8czWhGTGp/H4S35X1UxGbFlJ1hjtTFhm2mc85GcymEi1CDf633WJgtkCddEiSjIa4BnNxBrqOIhj6jlF6naPqw==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/gl-util/-/gl-util-3.1.3.tgz", + "integrity": "sha512-dvRTggw5MSkJnCbh74jZzSoTOGnVYK+Bt+Ckqm39CVcl6+zSsxqWk4lr5NKhkqXHL6qvZAU9h17ZF8mIskY9mA==", "requires": { "is-browser": "2.1.0", "is-firefox": "1.0.3", @@ -3664,11 +3693,6 @@ "resolved": "https://registry.npmjs.org/glsl-out-of-range/-/glsl-out-of-range-1.0.4.tgz", "integrity": "sha512-fCcDu2LCQ39VBvfe1FbhuazXEf0CqMZI9OYXrYlL6uUARG48CTAbL04+tZBtVM0zo1Ljx4OLu2AxNquq++lxWQ==" }, - "glsl-read-float": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/glsl-read-float/-/glsl-read-float-1.1.0.tgz", - "integrity": "sha1-37CIsBYtz8xW/E7d0vhuGMrDLyY=" - }, "glsl-resolve": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/glsl-resolve/-/glsl-resolve-0.0.1.tgz", @@ -3782,7 +3806,7 @@ "bl": "1.2.1", "concat-stream": "1.6.2", "duplexify": "3.7.1", - "falafel": "2.1.0", + "falafel": "2.2.4", "from2": "2.3.0", "glsl-resolve": "0.0.1", "glsl-token-whitespace-trim": "1.0.0", @@ -3791,7 +3815,7 @@ "minimist": "1.2.0", "resolve": "1.4.0", "stack-trace": "0.0.9", - "static-eval": "2.0.3", + "static-eval": "2.0.5", "through2": "2.0.5", "xtend": "4.0.1" }, @@ -4429,9 +4453,9 @@ } }, "magic-string": { - "version": "0.25.6", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.6.tgz", - "integrity": "sha512-3a5LOMSGoCTH5rbqobC2HuDNRtE2glHZ8J7pK+QZYppyWA36yuNpsX994rIY2nCuyP7CZYy7lQq/X2jygiZ89g==", + "version": "0.25.7", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", + "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==", "requires": { "sourcemap-codec": "1.4.8" } @@ -4455,14 +4479,14 @@ } }, "mapbox-gl": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mapbox-gl/-/mapbox-gl-1.3.2.tgz", - "integrity": "sha512-6Ro7GbTMWxcbc836m6rbBNkesgTncbE1yXWeuHlr89esSqaItKr0+ntOu8rZie3fv+GtitkbODysXzIGCA7G+w==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/mapbox-gl/-/mapbox-gl-1.10.0.tgz", + "integrity": "sha512-SrJXcR9s5yEsPuW2kKKumA1KqYW9RrL8j7ZcIh6glRQ/x3lwNMfwz/UEJAJcVNgeX+fiwzuBoDIdeGB/vSkZLQ==", "requires": { - "@mapbox/geojson-rewind": "0.4.0", + "@mapbox/geojson-rewind": "0.5.0", "@mapbox/geojson-types": "1.0.2", "@mapbox/jsonlint-lines-primitives": "2.0.2", - "@mapbox/mapbox-gl-supported": "1.4.1", + "@mapbox/mapbox-gl-supported": "1.5.0", "@mapbox/point-geometry": "0.1.0", "@mapbox/tiny-sdf": "1.1.1", "@mapbox/unitbezier": "0.0.0", @@ -4471,23 +4495,23 @@ "csscolorparser": "1.0.3", "earcut": "2.2.2", "geojson-vt": "3.2.1", - "gl-matrix": "3.2.1", + "gl-matrix": "3.3.0", "grid-index": "1.1.0", - "minimist": "0.0.8", + "minimist": "1.2.5", "murmurhash-js": "1.0.0", "pbf": "3.2.1", "potpack": "1.0.1", "quickselect": "2.0.0", "rw": "1.3.3", - "supercluster": "6.0.2", + "supercluster": "7.0.0", "tinyqueue": "2.0.3", "vt-pbf": "3.1.1" }, "dependencies": { "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" } } }, @@ -4741,7 +4765,7 @@ "requires": { "right-now": "1.0.0", "signum": "1.0.0", - "to-px": "1.1.0" + "to-px": "1.0.1" }, "dependencies": { "signum": { @@ -4822,9 +4846,9 @@ "optional": true }, "ndarray": { - "version": "1.0.19", - "resolved": "https://registry.npmjs.org/ndarray/-/ndarray-1.0.19.tgz", - "integrity": "sha512-B4JHA4vdyZU30ELBw3g7/p9bZupyew5a7tX1Y/gGeF2hafrPaQZhgrGQfsvgfYbgdFZjYwuEcnaobeM/WMW+HQ==", + "version": "1.0.18", + "resolved": "https://registry.npmjs.org/ndarray/-/ndarray-1.0.18.tgz", + "integrity": "sha1-tg06cyJOxVXQ+qeXEeUCRI/T95M=", "requires": { "iota-array": "1.0.0", "is-buffer": "1.1.6" @@ -4883,7 +4907,7 @@ "integrity": "sha1-jK6+qqJNXs9w/4YCBjeXfajuWFo=", "requires": { "cwise-compiler": "1.1.3", - "ndarray": "1.0.19" + "ndarray": "1.0.18" } }, "ndarray-scratch": { @@ -4891,7 +4915,7 @@ "resolved": "https://registry.npmjs.org/ndarray-scratch/-/ndarray-scratch-1.2.0.tgz", "integrity": "sha1-YwRjbWLrqT20cnrBPGkzQdulDgE=", "requires": { - "ndarray": "1.0.19", + "ndarray": "1.0.18", "ndarray-ops": "1.2.2", "typedarray-pool": "1.2.0" } @@ -5064,9 +5088,13 @@ "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==" }, "object-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.0.2.tgz", - "integrity": "sha512-Epah+btZd5wrrfjkJZq1AOB9O6OxUQto45hzFd7lXGrpHPGE0W1k+426yrZV+k6NJOzLNNW/nVsmZdIWsAqoOQ==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.2.tgz", + "integrity": "sha512-5lHCz+0uufF6wZ7CRFWJN3hp8Jqblpgve06U5CMQ3f//6iDjPr2PEo9MWCjEssDsa+UZEL4PkFpr+BMop6aKzQ==", + "requires": { + "define-properties": "1.1.3", + "es-abstract": "1.17.5" + } }, "object-keys": { "version": "1.1.1", @@ -5375,9 +5403,9 @@ } }, "plotly.js": { - "version": "1.52.2", - "resolved": "https://registry.npmjs.org/plotly.js/-/plotly.js-1.52.2.tgz", - "integrity": "sha512-EZHr2ekxVNjucmNhku+JiLFoLV1wH6gW15T/6SFqtHFMvJZY4HeZogtRUPTLijXBPfusMWxxIKEDTzlMOLXajQ==", + "version": "1.54.1", + "resolved": "https://registry.npmjs.org/plotly.js/-/plotly.js-1.54.1.tgz", + "integrity": "sha512-1tlsEQkUgX2BaQr3Eu+5drki3eyor5EhpolFRteuQouRFX9mrg9Pms39Lak29lbAx4W3ZQoCZm8DcKkQCOe9YQ==", "requires": { "@plotly/d3-sankey": "0.7.2", "@plotly/d3-sankey-circular": "0.33.1", @@ -5395,42 +5423,43 @@ "d3-hierarchy": "1.1.9", "d3-interpolate": "1.4.0", "delaunay-triangulate": "1.1.6", - "es6-promise": "3.3.1", - "fast-isnumeric": "1.1.3", - "gl-cone3d": "1.5.1", - "gl-contour2d": "1.1.6", - "gl-error3d": "1.0.15", - "gl-heatmap2d": "1.0.5", - "gl-line3d": "1.1.11", + "es6-promise": "4.2.8", + "fast-isnumeric": "1.1.4", + "gl-cone3d": "1.5.2", + "gl-contour2d": "1.1.7", + "gl-error3d": "1.0.16", + "gl-heatmap2d": "1.0.6", + "gl-line3d": "1.2.1", "gl-mat4": "1.2.0", - "gl-mesh3d": "2.3.0", - "gl-plot2d": "1.4.3", - "gl-plot3d": "2.4.4", - "gl-pointcloud2d": "1.0.2", - "gl-scatter3d": "1.2.2", - "gl-select-box": "1.0.3", + "gl-mesh3d": "2.3.1", + "gl-plot2d": "1.4.4", + "gl-plot3d": "2.4.5", + "gl-pointcloud2d": "1.0.3", + "gl-scatter3d": "1.2.3", + "gl-select-box": "1.0.4", "gl-spikes2d": "1.0.2", - "gl-streamtube3d": "1.4.0", - "gl-surface3d": "1.4.6", + "gl-streamtube3d": "1.4.1", + "gl-surface3d": "1.5.2", "gl-text": "1.1.8", "glslify": "7.0.0", "has-hover": "1.0.1", "has-passive-events": "1.0.0", "is-mobile": "2.2.1", - "mapbox-gl": "1.3.2", + "mapbox-gl": "1.10.0", "matrix-camera-controller": "2.1.3", "mouse-change": "1.4.0", "mouse-event-offset": "3.0.2", "mouse-wheel": "1.2.0", - "ndarray": "1.0.19", + "ndarray": "1.0.18", "ndarray-fill": "1.0.2", "ndarray-homography": "1.0.0", + "parse-svg-path": "0.1.2", "point-cluster": "3.1.8", "polybooljs": "1.2.0", - "regl": "1.3.13", + "regl": "1.3.11", "regl-error2d": "2.0.8", "regl-line2d": "3.0.15", - "regl-scatter2d": "3.1.7", + "regl-scatter2d": "3.1.8", "regl-splom": "1.0.8", "right-now": "1.0.0", "robust-orientation": "1.1.3", @@ -5439,7 +5468,8 @@ "superscript-text": "1.0.0", "svg-path-sdf": "1.1.3", "tinycolor2": "1.4.1", - "topojson-client": "2.1.0", + "to-px": "1.0.1", + "topojson-client": "3.1.0", "webgl-context": "2.2.0", "world-calendars": "1.0.3" } @@ -5815,21 +5845,6 @@ } } }, - "redeyed": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-0.4.4.tgz", - "integrity": "sha1-N+mQpvKyGyoRwuakj9QTVpjLqX8=", - "requires": { - "esprima": "1.0.4" - }, - "dependencies": { - "esprima": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz", - "integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0=" - } - } - }, "reduce-simplicial-complex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/reduce-simplicial-complex/-/reduce-simplicial-complex-1.0.0.tgz", @@ -5846,9 +5861,9 @@ "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==" }, "regenerate-unicode-properties": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz", - "integrity": "sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz", + "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==", "requires": { "regenerate": "1.4.0" } @@ -5873,20 +5888,20 @@ "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", "requires": { "define-properties": "1.1.3", - "es-abstract": "1.17.4" + "es-abstract": "1.17.5" } }, "regexpu-core": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.6.0.tgz", - "integrity": "sha512-YlVaefl8P5BnFYOITTNzDvan1ulLOiXJzCNZxduTIosN17b87h3bvG9yHMoHaRuo88H4mQ06Aodj5VtYGGGiTg==", + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.0.tgz", + "integrity": "sha512-TQ4KXRnIn6tz6tjnrXEkD/sshygKH/j5KzK86X8MkeHyZ8qst/LZ89j3X4/8HEIfHANTFIP/AbXakeRhWIl5YQ==", "requires": { "regenerate": "1.4.0", - "regenerate-unicode-properties": "8.1.0", + "regenerate-unicode-properties": "8.2.0", "regjsgen": "0.5.1", - "regjsparser": "0.6.3", + "regjsparser": "0.6.4", "unicode-match-property-ecmascript": "1.0.4", - "unicode-match-property-value-ecmascript": "1.1.0" + "unicode-match-property-value-ecmascript": "1.2.0" } }, "regjsgen": { @@ -5895,17 +5910,17 @@ "integrity": "sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg==" }, "regjsparser": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.3.tgz", - "integrity": "sha512-8uZvYbnfAtEm9Ab8NTb3hdLwL4g/LQzEYP7Xs27T96abJCCE2d6r3cPZPQEsLKy0vRSGVNG+/zVGtLr86HQduA==", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.4.tgz", + "integrity": "sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw==", "requires": { "jsesc": "0.5.0" } }, "regl": { - "version": "1.3.13", - "resolved": "https://registry.npmjs.org/regl/-/regl-1.3.13.tgz", - "integrity": "sha512-TTiCabJbbUykCL4otjqOvKqDFJhvJOT7xB51JxcDeSHGrEJl1zz4RthPcoOogqfuR3ECN4Te790DfHCXzli5WQ==" + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/regl/-/regl-1.3.11.tgz", + "integrity": "sha512-tmt6CRhRqbcsYDWNwv+iG7GGOXdgoOBC7lKzoPMgnzpt3WKBQ3c8i7AxgbvTRZzty29hrW92fAJeZkPFQehfWA==" }, "regl-error2d": { "version": "2.0.8", @@ -5985,9 +6000,9 @@ } }, "regl-scatter2d": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/regl-scatter2d/-/regl-scatter2d-3.1.7.tgz", - "integrity": "sha512-FWw1hMsQrV3Y0zMU8YOytGjwSBuV3V58t8GR/mhlSL2S04jXLK1m2eAa/rDP3SpvMDkdVEr744PPDeHwsZVUhA==", + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/regl-scatter2d/-/regl-scatter2d-3.1.8.tgz", + "integrity": "sha512-Z9MYAUx9t8e3MsiHBbJAEstbIqauXxzcL9DmuKXQuRWfCMF2DBytYJtE0FpbQU6639wEMAJ54SEIlISWF8sQ2g==", "requires": { "array-range": "1.0.1", "array-rearrange": "2.2.2", @@ -6023,7 +6038,7 @@ "pick-by-alias": "1.2.0", "point-cluster": "3.1.8", "raf": "3.4.1", - "regl-scatter2d": "3.1.7" + "regl-scatter2d": "3.1.8" } }, "remove-trailing-separator": { @@ -6261,23 +6276,6 @@ "resolved": "https://registry.npmjs.org/shallow-copy/-/shallow-copy-0.0.1.tgz", "integrity": "sha1-QV9CcC1z2BAzApLMXuhurhoRoXA=" }, - "sharkdown": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/sharkdown/-/sharkdown-0.1.1.tgz", - "integrity": "sha512-exwooSpmo5s45lrexgz6Q0rFQM574wYIX3iDZ7RLLqOb7IAoQZu9nxlZODU972g19sR69OIpKP2cpHTzU+PHIg==", - "requires": { - "cardinal": "0.4.4", - "minimist": "0.0.5", - "split": "0.2.10" - }, - "dependencies": { - "minimist": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.5.tgz", - "integrity": "sha1-16oye87PUY+RBqxrjwA/o7zqhWY=" - } - } - }, "shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", @@ -6328,7 +6326,7 @@ "integrity": "sha1-iQqsrChDZTQBEFRc8mKaJuBL+dE=", "requires": { "marching-simplex-table": "1.0.0", - "ndarray": "1.0.19", + "ndarray": "1.0.18", "ndarray-sort": "1.0.1", "typedarray-pool": "1.2.0" } @@ -6423,14 +6421,6 @@ "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", "dev": true }, - "split": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/split/-/split-0.2.10.tgz", - "integrity": "sha1-Zwl8YB1pfOE2j0GPBs0gHPBSGlc=", - "requires": { - "through": "2.3.8" - } - }, "split-polygon": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/split-polygon/-/split-polygon-1.0.0.tgz", @@ -6451,9 +6441,9 @@ "integrity": "sha1-qPbq7KkGdMMz58Q5U/J1tFFRBpU=" }, "static-eval": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.0.3.tgz", - "integrity": "sha512-zsxDGucfAh8T339sSKgpFbvg15Fms2IVaJGC+jqp0bVsxhcpM+iMeAI8weNo8dmf4OblgifTBUoyk1vGVtYw2w==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.0.5.tgz", + "integrity": "sha512-nNbV6LbGtMBgv7e9LFkt5JV8RVlRsyJrphfAt9tOtBBW/SfnzZDf2KnS72an8e434A+9e/BmJuTxeGPvrAK7KA==", "requires": { "escodegen": "1.14.1" } @@ -6466,7 +6456,7 @@ "concat-stream": "1.6.2", "duplexer2": "0.0.2", "escodegen": "1.3.3", - "falafel": "2.1.0", + "falafel": "2.2.4", "has": "1.0.3", "object-inspect": "0.4.0", "quote-stream": "0.0.0", @@ -6725,26 +6715,46 @@ "integrity": "sha512-MjGFEeqixw47dAMFMtgUro/I0+wNqZB5GKXGt1fFr24u3TzDXCPu7J9Buppzoe3r/LqkSDLDDJzE15RGWDGAVw==", "requires": { "define-properties": "1.1.3", - "es-abstract": "1.17.4", + "es-abstract": "1.17.5", "function-bind": "1.1.1" } }, + "string.prototype.trimend": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", + "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", + "requires": { + "define-properties": "1.1.3", + "es-abstract": "1.17.5" + } + }, "string.prototype.trimleft": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz", - "integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz", + "integrity": "sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==", "requires": { "define-properties": "1.1.3", - "function-bind": "1.1.1" + "es-abstract": "1.17.5", + "string.prototype.trimstart": "1.0.1" } }, "string.prototype.trimright": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz", - "integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz", + "integrity": "sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg==", "requires": { "define-properties": "1.1.3", - "function-bind": "1.1.1" + "es-abstract": "1.17.5", + "string.prototype.trimend": "1.0.1" + } + }, + "string.prototype.trimstart": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", + "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", + "requires": { + "define-properties": "1.1.3", + "es-abstract": "1.17.5" } }, "string_decoder": { @@ -6779,9 +6789,9 @@ "integrity": "sha1-CSDitN9nyOrulsa2I0/inoc9upk=" }, "supercluster": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/supercluster/-/supercluster-6.0.2.tgz", - "integrity": "sha512-aa0v2HURjBTOpbcknilcfxGDuArM8khklKSmZ/T8ZXL0BuRwb5aRw95lz+2bmWpFvCXDX/+FzqHxmg0TIaJErw==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/supercluster/-/supercluster-7.0.0.tgz", + "integrity": "sha512-8VuHI8ynylYQj7Qf6PBMWy1PdgsnBiIxujOgc9Z83QvJ8ualIYWNx2iMKyKeC4DZI5ntD9tz/CIwwZvIelixsA==", "requires": { "kdbush": "3.0.0" } @@ -6854,9 +6864,9 @@ "dev": true }, "tape": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/tape/-/tape-4.13.0.tgz", - "integrity": "sha512-J/hvA+GJnuWJ0Sj8Z0dmu3JgMNU+MmusvkCT7+SN4/2TklW18FNCp/UuHIEhPZwHfy4sXfKYgC7kypKg4umbOw==", + "version": "4.13.2", + "resolved": "https://registry.npmjs.org/tape/-/tape-4.13.2.tgz", + "integrity": "sha512-waWwC/OqYVE9TS6r1IynlP2sEdk4Lfo6jazlgkuNkPTHIbuG2BTABIaKdlQWwPeB6Oo4ksZ1j33Yt0NTOAlYMQ==", "requires": { "deep-equal": "1.1.1", "defined": "1.0.0", @@ -6869,7 +6879,7 @@ "is-regex": "1.0.5", "minimist": "1.2.0", "object-inspect": "1.7.0", - "resolve": "1.14.2", + "resolve": "1.15.1", "resumer": "0.0.0", "string.prototype.trim": "1.2.1", "through": "2.3.8" @@ -6899,9 +6909,9 @@ "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" }, "resolve": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.14.2.tgz", - "integrity": "sha512-EjlOBLBO1kxsUxsKjLt7TAECyKW6fOh1VRkykQkKGzcBbjjPIxBqGh0jf7GJ3k/f5mxMqW3htMD3WdTUVtW8HQ==", + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", + "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", "requires": { "path-parse": "1.0.6" } @@ -6909,9 +6919,9 @@ } }, "text-cache": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/text-cache/-/text-cache-4.2.1.tgz", - "integrity": "sha512-G52NFRYXEW9BL4E3kBPquefXql9OT3sNT4J16gcpl3/a8y/YioDOR2Iwga5rNs9tY7rH2xv6rF8fAYrbINn6Kg==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/text-cache/-/text-cache-4.2.2.tgz", + "integrity": "sha512-zky+UDYiX0a/aPw/YTBD+EzKMlCTu1chFuCMZeAkgoRiceySdROu1V2kJXhCbtEdBhiOviYnAdGiSYl58HW0ZQ==", "requires": { "vectorize-text": "3.2.1" } @@ -6971,9 +6981,9 @@ "integrity": "sha512-nOy2WSwae3xhZbc+05xiCuU3ZPPmH0L4Rg4Q1qiOGFSuNSCTB9nVJaGgGl3ZScxAclX/L8hJuDHJGDAzbfuKCQ==" }, "to-px": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/to-px/-/to-px-1.1.0.tgz", - "integrity": "sha512-bfg3GLYrGoEzrGoE05TAL/Uw+H/qrf2ptr9V3W7U0lkjjyYnIfgxmVLUfhQ1hZpIQwin81uxhDjvUkDYsC0xWw==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-px/-/to-px-1.0.1.tgz", + "integrity": "sha1-W7rtXl1PdkRbzJA8KTojB90yRkY=", "requires": { "parse-unit": "1.0.1" } @@ -6991,9 +7001,9 @@ } }, "topojson-client": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/topojson-client/-/topojson-client-2.1.0.tgz", - "integrity": "sha1-/59784mRGF4LQoTCsGroNPDqxsg=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/topojson-client/-/topojson-client-3.1.0.tgz", + "integrity": "sha512-605uxS6bcYxGXw9qi62XyrV6Q3xwbndjachmNxu8HWTtVPxZfEJN9fd/SZS1Q54Sn2y0TMyMxFj/cJINqGHrKw==", "requires": { "commander": "2.1.0" } @@ -7123,18 +7133,18 @@ "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", "requires": { "unicode-canonical-property-names-ecmascript": "1.0.4", - "unicode-property-aliases-ecmascript": "1.0.5" + "unicode-property-aliases-ecmascript": "1.1.0" } }, "unicode-match-property-value-ecmascript": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz", - "integrity": "sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g==" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz", + "integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ==" }, "unicode-property-aliases-ecmascript": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz", - "integrity": "sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw==" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz", + "integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==" }, "union-find": { "version": "1.0.2", @@ -7356,7 +7366,7 @@ "requires": { "cdt2d": "1.0.0", "clean-pslg": "1.1.2", - "ndarray": "1.0.19", + "ndarray": "1.0.18", "planar-graph-to-polyline": "1.0.5", "simplify-planar-graph": "2.0.1", "surface-nets": "1.0.2", @@ -7538,11 +7548,6 @@ } } }, - "wgs84": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/wgs84/-/wgs84-0.0.0.tgz", - "integrity": "sha1-NP3FVZF7blfPKigu0ENxDASc3HY=" - }, "which": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", diff --git a/packages/javascript/plotlywidget/package.json b/packages/javascript/plotlywidget/package.json index ea9bc6c21b6..9d13b9cb4db 100644 --- a/packages/javascript/plotlywidget/package.json +++ b/packages/javascript/plotlywidget/package.json @@ -1,6 +1,6 @@ { "name": "plotlywidget", - "version": "1.5.5", + "version": "4.7.1", "description": "The plotly JupyterLab extension", "author": "The plotly.py team", "license": "MIT", @@ -33,7 +33,7 @@ "typescript": "~3.1.1" }, "dependencies": { - "plotly.js": "^1.52.2", + "plotly.js": "^1.54.1", "@jupyter-widgets/base": "^2.0.0 || ^3.0.0", "lodash": "^4.17.4" }, diff --git a/packages/javascript/plotlywidget/src/Figure.js b/packages/javascript/plotlywidget/src/Figure.js index 8d98cddcb16..3e6c1bd3bf5 100644 --- a/packages/javascript/plotlywidget/src/Figure.js +++ b/packages/javascript/plotlywidget/src/Figure.js @@ -1,7 +1,7 @@ var widgets = require("@jupyter-widgets/base"); var _ = require("lodash"); -window.PlotlyConfig = {MathJaxConfig: 'local'}; +window.PlotlyConfig = { MathJaxConfig: "local" }; var semver_range = "^" + require("../package.json").version; // Model @@ -14,397 +14,396 @@ var semver_range = "^" + require("../package.json").version; * even before the widget is first displayed in the Notebook * @type {widgets.DOMWidgetModel} */ -var FigureModel = widgets.DOMWidgetModel.extend({ - +var FigureModel = widgets.DOMWidgetModel.extend( + { defaults: _.extend(widgets.DOMWidgetModel.prototype.defaults(), { - // Model metadata - // -------------- - _model_name: "FigureModel", - _view_name: "FigureView", - _model_module: "plotlywidget", - _view_module: "plotlywidget", - _view_module_version: semver_range, - _model_module_version: semver_range, - - // Data and Layout - // --------------- - // The _data and _layout properties are synchronized with the - // Python side on initialization only. After initialization, these - // properties are kept in sync through the use of the _py2js_* - // messages - _data: [], - _layout: {}, - _config: {}, - - // Python -> JS messages - // --------------------- - // Messages are implemented using trait properties. This is done so - // that we can take advantage of ipywidget's binary serialization - // protocol. - // - // Messages are sent by the Python side by assigning the message - // contents to the appropriate _py2js_* property, and then immediately - // setting it to None. Messages are received by the JavaScript - // side by registering property change callbacks in the initialize - // methods for FigureModel and FigureView. e.g. (where this is a - // FigureModel): - // - // this.on('change:_py2js_addTraces', this.do_addTraces, this); - // - // Message handling methods, do_addTraces, are responsible for - // performing the appropriate action if the message contents are - // not null - - /** - * @typedef {null|Object} Py2JsAddTracesMsg - * @property {Array.} trace_data - * Array of traces to append to the end of the figure's current traces - * @property {Number} trace_edit_id - * Edit ID to use when returning trace deltas using - * the _js2py_traceDeltas message. - * @property {Number} layout_edit_id - * Edit ID to use when returning layout deltas using - * the _js2py_layoutDelta message. - */ - _py2js_addTraces: null, - - /** - * @typedef {null|Object} Py2JsDeleteTracesMsg - * @property {Array.} delete_inds - * Array of indexes of traces to be deleted, in ascending order - * @property {Number} trace_edit_id - * Edit ID to use when returning trace deltas using - * the _js2py_traceDeltas message. - * @property {Number} layout_edit_id - * Edit ID to use when returning layout deltas using - * the _js2py_layoutDelta message. - */ - _py2js_deleteTraces: null, - - /** - * @typedef {null|Object} Py2JsMoveTracesMsg - * @property {Array.} current_trace_inds - * Array of the current indexes of traces to be moved - * @property {Array.} new_trace_inds - * Array of the new indexes that traces should be moved to. - */ - _py2js_moveTraces: null, - - - /** - * @typedef {null|Object} Py2JsRestyleMsg - * @property {Object} restyle_data - * Restyle data as accepted by Plotly.restyle - * @property {null|Array.} restyle_traces - * Array of indexes of the traces that the resytle operation applies - * to, or null to apply the operation to all traces - * @property {Number} trace_edit_id - * Edit ID to use when returning trace deltas using - * the _js2py_traceDeltas message - * @property {Number} layout_edit_id - * Edit ID to use when returning layout deltas using - * the _js2py_layoutDelta message - * @property {null|String} source_view_id - * view_id of the FigureView that triggered the original restyle - * event (e.g. by clicking the legend), or null if the restyle was - * triggered from Python - */ - _py2js_restyle: null, - - /** - * @typedef {null|Object} Py2JsRelayoutMsg - * @property {Object} relayout_data - * Relayout data as accepted by Plotly.relayout - * @property {Number} layout_edit_id - * Edit ID to use when returning layout deltas using - * the _js2py_layoutDelta message - * @property {null|String} source_view_id - * view_id of the FigureView that triggered the original relayout - * event (e.g. by clicking the zoom button), or null if the - * relayout was triggered from Python - */ - _py2js_relayout: null, - - /** - * @typedef {null|Object} Py2JsUpdateMsg - * @property {Object} style_data - * Style data as accepted by Plotly.update - * @property {Object} layout_data - * Layout data as accepted by Plotly.update - * @property {Array.} style_traces - * Array of indexes of the traces that the update operation applies - * to, or null to apply the operation to all traces - * @property {Number} trace_edit_id - * Edit ID to use when returning trace deltas using - * the _js2py_traceDeltas message - * @property {Number} layout_edit_id - * Edit ID to use when returning layout deltas using - * the _js2py_layoutDelta message - * @property {null|String} source_view_id - * view_id of the FigureView that triggered the original update - * event (e.g. by clicking a button), or null if the update was - * triggered from Python - */ - _py2js_update: null, - - /** - * @typedef {null|Object} Py2JsAnimateMsg - * @property {Object} style_data - * Style data as accepted by Plotly.animate - * @property {Object} layout_data - * Layout data as accepted by Plotly.animate - * @property {Array.} style_traces - * Array of indexes of the traces that the animate operation applies - * to, or null to apply the operation to all traces - * @property {Object} animation_opts - * Animation options as accepted by Plotly.animate - * @property {Number} trace_edit_id - * Edit ID to use when returning trace deltas using - * the _js2py_traceDeltas message - * @property {Number} layout_edit_id - * Edit ID to use when returning layout deltas using - * the _js2py_layoutDelta message - * @property {null|String} source_view_id - * view_id of the FigureView that triggered the original animate - * event (e.g. by clicking a button), or null if the update was - * triggered from Python - */ - _py2js_animate: null, - - /** - * @typedef {null|Object} Py2JsRemoveLayoutPropsMsg - * @property {Array.>} remove_props - * Array of property paths to remove. Each propery path is an - * array of property names or array indexes that locate a property - * inside the _layout object - */ - _py2js_removeLayoutProps: null, - - /** - * @typedef {null|Object} Py2JsRemoveTracePropsMsg - * @property {Number} remove_trace - * The index of the trace from which to remove properties - * @property {Array.>} remove_props - * Array of property paths to remove. Each propery path is an - * array of property names or array indexes that locate a property - * inside the _data[remove_trace] object - */ - _py2js_removeTraceProps: null, - - - // JS -> Python messages - // --------------------- - // Messages are sent by the JavaScript side by assigning the - // message contents to the appropriate _js2py_* property and then - // calling the `touch` method on the view that triggered the - // change. e.g. (where this is a FigureView): - // - // this.model.set('_js2py_restyle', data); - // this.touch(); - // - // The Python side is responsible for setting the property to None - // after receiving the message. - // - // Message trigger logic is described in the corresponding - // handle_plotly_* methods of FigureView - - /** - * @typedef {null|Object} Js2PyRestyleMsg - * @property {Object} style_data - * Style data that was passed to Plotly.restyle - * @property {Array.} style_traces - * Array of indexes of the traces that the restyle operation - * was applied to, or null if applied to all traces - * @property {String} source_view_id - * view_id of the FigureView that triggered the original restyle - * event (e.g. by clicking the legend) - */ - _js2py_restyle: null, - - /** - * @typedef {null|Object} Js2PyRelayoutMsg - * @property {Object} relayout_data - * Relayout data that was passed to Plotly.relayout - * @property {String} source_view_id - * view_id of the FigureView that triggered the original relayout - * event (e.g. by clicking the zoom button) - */ - _js2py_relayout: null, - - /** - * @typedef {null|Object} Js2PyUpdateMsg - * @property {Object} style_data - * Style data that was passed to Plotly.update - * @property {Object} layout_data - * Layout data that was passed to Plotly.update - * @property {Array.} style_traces - * Array of indexes of the traces that the update operation applied - * to, or null if applied to all traces - * @property {String} source_view_id - * view_id of the FigureView that triggered the original relayout - * event (e.g. by clicking the zoom button) - */ - _js2py_update: null, - - /** - * @typedef {null|Object} Js2PyLayoutDeltaMsg - * @property {Object} layout_delta - * The layout delta object that contains all of the properties of - * _fullLayout that are not identical to those in the - * FigureModel's _layout property - * @property {Number} layout_edit_id - * Edit ID of message that triggered the creation of layout delta - */ - _js2py_layoutDelta: null, - - /** - * @typedef {null|Object} Js2PyTraceDeltasMsg - * @property {Array.} trace_deltas - * Array of trace delta objects. Each trace delta contains the - * trace's uid along with all of the properties of _fullData that - * are not identical to those in the FigureModel's _data property - * @property {Number} trace_edit_id - * Edit ID of message that triggered the creation of trace deltas - */ - _js2py_traceDeltas: null, - - - /** - * Object representing a collection of points for use in click, hover, - * and selection events - * @typedef {Object} Points - * @property {Array.} trace_indexes - * Array of the trace index for each point - * @property {Array.} point_indexes - * Array of the index of each point in its own trace - * @property {null|Array.} xs - * Array of the x coordinate of each point (for cartesian trace types) - * or null (for non-cartesian trace types) - * @property {null|Array.} ys - * Array of the y coordinate of each point (for cartesian trace types) - * or null (for non-cartesian trace types - * @property {null|Array.} zs - * Array of the z coordinate of each point (for 3D cartesian - * trace types) - * or null (for non-3D-cartesian trace types) - */ - - /** - * Object representing the state of the input devices during a - * plotly event - * @typedef {Object} InputDeviceState - * @property {boolean} alt - true if alt key pressed, - * false otherwise - * @property {boolean} ctrl - true if ctrl key pressed, - * false otherwise - * @property {boolean} meta - true if meta key pressed, - * false otherwise - * @property {boolean} shift - true if shift key pressed, - * false otherwise - * - * @property {boolean} button - * Indicates which button was pressed on the mouse to trigger the - * event. - * 0: Main button pressed, usually the left button or the - * un-initialized state - * 1: Auxiliary button pressed, usually the wheel button or - * the middle button (if present) - * 2: Secondary button pressed, usually the right button - * 3: Fourth button, typically the Browser Back button - * 4: Fifth button, typically the Browser Forward button - * - * @property {boolean} buttons - * Indicates which buttons were pressed on the mouse when the event - * is triggered. - * 0 : No button or un-initialized - * 1 : Primary button (usually left) - * 2 : Secondary button (usually right) - * 4 : Auxilary button (usually middle or mouse wheel button) - * 8 : 4th button (typically the "Browser Back" button) - * 16 : 5th button (typically the "Browser Forward" button) - * - * Combinations of buttons are represented by the sum of the codes - * above. e.g. a value of 7 indicates buttons 1 (primary), - * 2 (secondary), and 4 (auxilary) were pressed during the event - */ - - /** - * @typedef {Object} BoxSelectorState - * @property {Array.} xrange - * Two element array containing the x-range of the box selection - * @property {Array.} yrange - * Two element array containing the y-range of the box selection - */ - - /** - * @typedef {Object} LassoSelectorState - * @property {Array.} xs - * Array of the x-coordinates of the lasso selection region - * @property {Array.} ys - * Array of the y-coordinates of the lasso selection region - */ - - /** - * Object representing the state of the selection tool during a - * plotly_select event - * @typedef {Object} Selector - * @property {String} type - * Selection type. One of: 'box', or 'lasso' - * @property {BoxSelectorState|LassoSelectorState} selector_state - */ - - /** - * @typedef {null|Object} Js2PyPointsCallbackMsg - * @property {string} event_type - * Name of the triggering event. One of 'plotly_click', - * 'plotly_hover', 'plotly_unhover', or 'plotly_selected' - * @property {null|Points} points - * Points object for event - * @property {null|InputDeviceState} device_state - * InputDeviceState object for event - * @property {null|Selector} selector - * State of the selection tool for 'plotly_selected' events, null - * for other event types - */ - _js2py_pointsCallback: null, - - // Message tracking - // ---------------- - /** - * @type {Number} - * layout_edit_id of the last layout modification operation - * requested by the Python side - */ - _last_layout_edit_id: 0, - - /** - * @type {Number} - * trace_edit_id of the last trace modification operation - * requested by the Python side - */ - _last_trace_edit_id: 0 + // Model metadata + // -------------- + _model_name: "FigureModel", + _view_name: "FigureView", + _model_module: "plotlywidget", + _view_module: "plotlywidget", + _view_module_version: semver_range, + _model_module_version: semver_range, + + // Data and Layout + // --------------- + // The _data and _layout properties are synchronized with the + // Python side on initialization only. After initialization, these + // properties are kept in sync through the use of the _py2js_* + // messages + _data: [], + _layout: {}, + _config: {}, + + // Python -> JS messages + // --------------------- + // Messages are implemented using trait properties. This is done so + // that we can take advantage of ipywidget's binary serialization + // protocol. + // + // Messages are sent by the Python side by assigning the message + // contents to the appropriate _py2js_* property, and then immediately + // setting it to None. Messages are received by the JavaScript + // side by registering property change callbacks in the initialize + // methods for FigureModel and FigureView. e.g. (where this is a + // FigureModel): + // + // this.on('change:_py2js_addTraces', this.do_addTraces, this); + // + // Message handling methods, do_addTraces, are responsible for + // performing the appropriate action if the message contents are + // not null + + /** + * @typedef {null|Object} Py2JsAddTracesMsg + * @property {Array.} trace_data + * Array of traces to append to the end of the figure's current traces + * @property {Number} trace_edit_id + * Edit ID to use when returning trace deltas using + * the _js2py_traceDeltas message. + * @property {Number} layout_edit_id + * Edit ID to use when returning layout deltas using + * the _js2py_layoutDelta message. + */ + _py2js_addTraces: null, + + /** + * @typedef {null|Object} Py2JsDeleteTracesMsg + * @property {Array.} delete_inds + * Array of indexes of traces to be deleted, in ascending order + * @property {Number} trace_edit_id + * Edit ID to use when returning trace deltas using + * the _js2py_traceDeltas message. + * @property {Number} layout_edit_id + * Edit ID to use when returning layout deltas using + * the _js2py_layoutDelta message. + */ + _py2js_deleteTraces: null, + + /** + * @typedef {null|Object} Py2JsMoveTracesMsg + * @property {Array.} current_trace_inds + * Array of the current indexes of traces to be moved + * @property {Array.} new_trace_inds + * Array of the new indexes that traces should be moved to. + */ + _py2js_moveTraces: null, + + /** + * @typedef {null|Object} Py2JsRestyleMsg + * @property {Object} restyle_data + * Restyle data as accepted by Plotly.restyle + * @property {null|Array.} restyle_traces + * Array of indexes of the traces that the resytle operation applies + * to, or null to apply the operation to all traces + * @property {Number} trace_edit_id + * Edit ID to use when returning trace deltas using + * the _js2py_traceDeltas message + * @property {Number} layout_edit_id + * Edit ID to use when returning layout deltas using + * the _js2py_layoutDelta message + * @property {null|String} source_view_id + * view_id of the FigureView that triggered the original restyle + * event (e.g. by clicking the legend), or null if the restyle was + * triggered from Python + */ + _py2js_restyle: null, + + /** + * @typedef {null|Object} Py2JsRelayoutMsg + * @property {Object} relayout_data + * Relayout data as accepted by Plotly.relayout + * @property {Number} layout_edit_id + * Edit ID to use when returning layout deltas using + * the _js2py_layoutDelta message + * @property {null|String} source_view_id + * view_id of the FigureView that triggered the original relayout + * event (e.g. by clicking the zoom button), or null if the + * relayout was triggered from Python + */ + _py2js_relayout: null, + + /** + * @typedef {null|Object} Py2JsUpdateMsg + * @property {Object} style_data + * Style data as accepted by Plotly.update + * @property {Object} layout_data + * Layout data as accepted by Plotly.update + * @property {Array.} style_traces + * Array of indexes of the traces that the update operation applies + * to, or null to apply the operation to all traces + * @property {Number} trace_edit_id + * Edit ID to use when returning trace deltas using + * the _js2py_traceDeltas message + * @property {Number} layout_edit_id + * Edit ID to use when returning layout deltas using + * the _js2py_layoutDelta message + * @property {null|String} source_view_id + * view_id of the FigureView that triggered the original update + * event (e.g. by clicking a button), or null if the update was + * triggered from Python + */ + _py2js_update: null, + + /** + * @typedef {null|Object} Py2JsAnimateMsg + * @property {Object} style_data + * Style data as accepted by Plotly.animate + * @property {Object} layout_data + * Layout data as accepted by Plotly.animate + * @property {Array.} style_traces + * Array of indexes of the traces that the animate operation applies + * to, or null to apply the operation to all traces + * @property {Object} animation_opts + * Animation options as accepted by Plotly.animate + * @property {Number} trace_edit_id + * Edit ID to use when returning trace deltas using + * the _js2py_traceDeltas message + * @property {Number} layout_edit_id + * Edit ID to use when returning layout deltas using + * the _js2py_layoutDelta message + * @property {null|String} source_view_id + * view_id of the FigureView that triggered the original animate + * event (e.g. by clicking a button), or null if the update was + * triggered from Python + */ + _py2js_animate: null, + + /** + * @typedef {null|Object} Py2JsRemoveLayoutPropsMsg + * @property {Array.>} remove_props + * Array of property paths to remove. Each propery path is an + * array of property names or array indexes that locate a property + * inside the _layout object + */ + _py2js_removeLayoutProps: null, + + /** + * @typedef {null|Object} Py2JsRemoveTracePropsMsg + * @property {Number} remove_trace + * The index of the trace from which to remove properties + * @property {Array.>} remove_props + * Array of property paths to remove. Each propery path is an + * array of property names or array indexes that locate a property + * inside the _data[remove_trace] object + */ + _py2js_removeTraceProps: null, + + // JS -> Python messages + // --------------------- + // Messages are sent by the JavaScript side by assigning the + // message contents to the appropriate _js2py_* property and then + // calling the `touch` method on the view that triggered the + // change. e.g. (where this is a FigureView): + // + // this.model.set('_js2py_restyle', data); + // this.touch(); + // + // The Python side is responsible for setting the property to None + // after receiving the message. + // + // Message trigger logic is described in the corresponding + // handle_plotly_* methods of FigureView + + /** + * @typedef {null|Object} Js2PyRestyleMsg + * @property {Object} style_data + * Style data that was passed to Plotly.restyle + * @property {Array.} style_traces + * Array of indexes of the traces that the restyle operation + * was applied to, or null if applied to all traces + * @property {String} source_view_id + * view_id of the FigureView that triggered the original restyle + * event (e.g. by clicking the legend) + */ + _js2py_restyle: null, + + /** + * @typedef {null|Object} Js2PyRelayoutMsg + * @property {Object} relayout_data + * Relayout data that was passed to Plotly.relayout + * @property {String} source_view_id + * view_id of the FigureView that triggered the original relayout + * event (e.g. by clicking the zoom button) + */ + _js2py_relayout: null, + + /** + * @typedef {null|Object} Js2PyUpdateMsg + * @property {Object} style_data + * Style data that was passed to Plotly.update + * @property {Object} layout_data + * Layout data that was passed to Plotly.update + * @property {Array.} style_traces + * Array of indexes of the traces that the update operation applied + * to, or null if applied to all traces + * @property {String} source_view_id + * view_id of the FigureView that triggered the original relayout + * event (e.g. by clicking the zoom button) + */ + _js2py_update: null, + + /** + * @typedef {null|Object} Js2PyLayoutDeltaMsg + * @property {Object} layout_delta + * The layout delta object that contains all of the properties of + * _fullLayout that are not identical to those in the + * FigureModel's _layout property + * @property {Number} layout_edit_id + * Edit ID of message that triggered the creation of layout delta + */ + _js2py_layoutDelta: null, + + /** + * @typedef {null|Object} Js2PyTraceDeltasMsg + * @property {Array.} trace_deltas + * Array of trace delta objects. Each trace delta contains the + * trace's uid along with all of the properties of _fullData that + * are not identical to those in the FigureModel's _data property + * @property {Number} trace_edit_id + * Edit ID of message that triggered the creation of trace deltas + */ + _js2py_traceDeltas: null, + + /** + * Object representing a collection of points for use in click, hover, + * and selection events + * @typedef {Object} Points + * @property {Array.} trace_indexes + * Array of the trace index for each point + * @property {Array.} point_indexes + * Array of the index of each point in its own trace + * @property {null|Array.} xs + * Array of the x coordinate of each point (for cartesian trace types) + * or null (for non-cartesian trace types) + * @property {null|Array.} ys + * Array of the y coordinate of each point (for cartesian trace types) + * or null (for non-cartesian trace types + * @property {null|Array.} zs + * Array of the z coordinate of each point (for 3D cartesian + * trace types) + * or null (for non-3D-cartesian trace types) + */ + + /** + * Object representing the state of the input devices during a + * plotly event + * @typedef {Object} InputDeviceState + * @property {boolean} alt - true if alt key pressed, + * false otherwise + * @property {boolean} ctrl - true if ctrl key pressed, + * false otherwise + * @property {boolean} meta - true if meta key pressed, + * false otherwise + * @property {boolean} shift - true if shift key pressed, + * false otherwise + * + * @property {boolean} button + * Indicates which button was pressed on the mouse to trigger the + * event. + * 0: Main button pressed, usually the left button or the + * un-initialized state + * 1: Auxiliary button pressed, usually the wheel button or + * the middle button (if present) + * 2: Secondary button pressed, usually the right button + * 3: Fourth button, typically the Browser Back button + * 4: Fifth button, typically the Browser Forward button + * + * @property {boolean} buttons + * Indicates which buttons were pressed on the mouse when the event + * is triggered. + * 0 : No button or un-initialized + * 1 : Primary button (usually left) + * 2 : Secondary button (usually right) + * 4 : Auxilary button (usually middle or mouse wheel button) + * 8 : 4th button (typically the "Browser Back" button) + * 16 : 5th button (typically the "Browser Forward" button) + * + * Combinations of buttons are represented by the sum of the codes + * above. e.g. a value of 7 indicates buttons 1 (primary), + * 2 (secondary), and 4 (auxilary) were pressed during the event + */ + + /** + * @typedef {Object} BoxSelectorState + * @property {Array.} xrange + * Two element array containing the x-range of the box selection + * @property {Array.} yrange + * Two element array containing the y-range of the box selection + */ + + /** + * @typedef {Object} LassoSelectorState + * @property {Array.} xs + * Array of the x-coordinates of the lasso selection region + * @property {Array.} ys + * Array of the y-coordinates of the lasso selection region + */ + + /** + * Object representing the state of the selection tool during a + * plotly_select event + * @typedef {Object} Selector + * @property {String} type + * Selection type. One of: 'box', or 'lasso' + * @property {BoxSelectorState|LassoSelectorState} selector_state + */ + + /** + * @typedef {null|Object} Js2PyPointsCallbackMsg + * @property {string} event_type + * Name of the triggering event. One of 'plotly_click', + * 'plotly_hover', 'plotly_unhover', or 'plotly_selected' + * @property {null|Points} points + * Points object for event + * @property {null|InputDeviceState} device_state + * InputDeviceState object for event + * @property {null|Selector} selector + * State of the selection tool for 'plotly_selected' events, null + * for other event types + */ + _js2py_pointsCallback: null, + + // Message tracking + // ---------------- + /** + * @type {Number} + * layout_edit_id of the last layout modification operation + * requested by the Python side + */ + _last_layout_edit_id: 0, + + /** + * @type {Number} + * trace_edit_id of the last trace modification operation + * requested by the Python side + */ + _last_trace_edit_id: 0, }), /** * Initialize FigureModel. Called when the Python FigureWidget is first * constructed */ - initialize: function() { - FigureModel.__super__.initialize.apply(this, arguments); - - this.on("change:_data", this.do_data, this); - this.on("change:_layout", this.do_layout, this); - this.on("change:_py2js_addTraces", this.do_addTraces, this); - this.on("change:_py2js_deleteTraces", this.do_deleteTraces, this); - this.on("change:_py2js_moveTraces", this.do_moveTraces, this); - this.on("change:_py2js_restyle", this.do_restyle, this); - this.on("change:_py2js_relayout", this.do_relayout, this); - this.on("change:_py2js_update", this.do_update, this); - this.on("change:_py2js_animate", this.do_animate, this); - this.on("change:_py2js_removeLayoutProps", - this.do_removeLayoutProps, this); - this.on("change:_py2js_removeTraceProps", - this.do_removeTraceProps, this); + initialize: function () { + FigureModel.__super__.initialize.apply(this, arguments); + + this.on("change:_data", this.do_data, this); + this.on("change:_layout", this.do_layout, this); + this.on("change:_py2js_addTraces", this.do_addTraces, this); + this.on("change:_py2js_deleteTraces", this.do_deleteTraces, this); + this.on("change:_py2js_moveTraces", this.do_moveTraces, this); + this.on("change:_py2js_restyle", this.do_restyle, this); + this.on("change:_py2js_relayout", this.do_relayout, this); + this.on("change:_py2js_update", this.do_update, this); + this.on("change:_py2js_animate", this.do_animate, this); + this.on( + "change:_py2js_removeLayoutProps", + this.do_removeLayoutProps, + this + ); + this.on("change:_py2js_removeTraceProps", this.do_removeTraceProps, this); }, /** @@ -421,15 +420,15 @@ var FigureModel = widgets.DOMWidgetModel.extend({ * @private */ _normalize_trace_indexes: function (trace_indexes) { - if (trace_indexes === null || trace_indexes === undefined) { - var numTraces = this.get("_data").length; - trace_indexes = _.range(numTraces); - } - if (!Array.isArray(trace_indexes)) { - // Make sure idx is an array - trace_indexes = [trace_indexes]; - } - return trace_indexes + if (trace_indexes === null || trace_indexes === undefined) { + var numTraces = this.get("_data").length; + trace_indexes = _.range(numTraces); + } + if (!Array.isArray(trace_indexes)) { + // Make sure idx is an array + trace_indexes = [trace_indexes]; + } + return trace_indexes; }, /** @@ -437,211 +436,239 @@ var FigureModel = widgets.DOMWidgetModel.extend({ * * This should only happed on FigureModel initialization */ - do_data: function () { - - }, + do_data: function () {}, /** * Log changes to the _layout trait * * This should only happed on FigureModel initialization */ - do_layout: function () { - - }, + do_layout: function () {}, /** * Handle addTraces message */ do_addTraces: function () { - // add trace to plot - /** @type {Py2JsAddTracesMsg} */ - var msgData = this.get("_py2js_addTraces"); - - if (msgData !== null) { - var currentTraces = this.get("_data"); - var newTraces = msgData.trace_data; - _.forEach(newTraces, function (newTrace) { - currentTraces.push(newTrace); - }) - } + // add trace to plot + /** @type {Py2JsAddTracesMsg} */ + var msgData = this.get("_py2js_addTraces"); + + if (msgData !== null) { + var currentTraces = this.get("_data"); + var newTraces = msgData.trace_data; + _.forEach(newTraces, function (newTrace) { + currentTraces.push(newTrace); + }); + } }, /** * Handle deleteTraces message */ do_deleteTraces: function () { - // remove traces from plot - - /** @type {Py2JsDeleteTracesMsg} */ - var msgData = this.get("_py2js_deleteTraces"); - - if (msgData !== null) { - var delete_inds = msgData.delete_inds; - var tracesData = this.get("_data"); - - // Remove del inds in reverse order so indexes remain valid - // throughout loop - delete_inds.slice().reverse().forEach(function (del_ind) { - tracesData.splice(del_ind, 1); - }); - } + // remove traces from plot + + /** @type {Py2JsDeleteTracesMsg} */ + var msgData = this.get("_py2js_deleteTraces"); + + if (msgData !== null) { + var delete_inds = msgData.delete_inds; + var tracesData = this.get("_data"); + + // Remove del inds in reverse order so indexes remain valid + // throughout loop + delete_inds + .slice() + .reverse() + .forEach(function (del_ind) { + tracesData.splice(del_ind, 1); + }); + } }, /** * Handle moveTraces message */ do_moveTraces: function () { + /** @type {Py2JsMoveTracesMsg} */ + var msgData = this.get("_py2js_moveTraces"); - /** @type {Py2JsMoveTracesMsg} */ - var msgData = this.get("_py2js_moveTraces"); + if (msgData !== null) { + var tracesData = this.get("_data"); + var currentInds = msgData.current_trace_inds; + var newInds = msgData.new_trace_inds; - if (msgData !== null) { - var tracesData = this.get("_data"); - var currentInds = msgData.current_trace_inds; - var newInds = msgData.new_trace_inds; - - performMoveTracesLike(tracesData, currentInds, newInds); - } + performMoveTracesLike(tracesData, currentInds, newInds); + } }, /** * Handle restyle message */ do_restyle: function () { - - /** @type {Py2JsRestyleMsg} */ - var msgData = this.get("_py2js_restyle"); - if (msgData !== null) { - var restyleData = msgData.restyle_data; - var restyleTraces = this._normalize_trace_indexes( - msgData.restyle_traces); - performRestyleLike(this.get("_data"), restyleData, restyleTraces); - } + /** @type {Py2JsRestyleMsg} */ + var msgData = this.get("_py2js_restyle"); + if (msgData !== null) { + var restyleData = msgData.restyle_data; + var restyleTraces = this._normalize_trace_indexes( + msgData.restyle_traces + ); + performRestyleLike(this.get("_data"), restyleData, restyleTraces); + } }, /** * Handle relayout message */ do_relayout: function () { + /** @type {Py2JsRelayoutMsg} */ + var msgData = this.get("_py2js_relayout"); - /** @type {Py2JsRelayoutMsg} */ - var msgData = this.get("_py2js_relayout"); - - if (msgData !== null) { - performRelayoutLike(this.get("_layout"), msgData.relayout_data); - } + if (msgData !== null) { + performRelayoutLike(this.get("_layout"), msgData.relayout_data); + } }, /** * Handle update message */ - do_update: function() { - - /** @type {Py2JsUpdateMsg} */ - var msgData = this.get("_py2js_update"); - - if (msgData !== null) { - var style = msgData.style_data; - var layout = msgData.layout_data; - var styleTraces = this._normalize_trace_indexes( - msgData.style_traces); - performRestyleLike(this.get("_data"), style, styleTraces); - performRelayoutLike(this.get("_layout"), layout); - } + do_update: function () { + /** @type {Py2JsUpdateMsg} */ + var msgData = this.get("_py2js_update"); + + if (msgData !== null) { + var style = msgData.style_data; + var layout = msgData.layout_data; + var styleTraces = this._normalize_trace_indexes(msgData.style_traces); + performRestyleLike(this.get("_data"), style, styleTraces); + performRelayoutLike(this.get("_layout"), layout); + } }, /** * Handle animate message */ do_animate: function () { - - /** @type {Py2JsAnimateMsg} */ - var msgData = this.get("_py2js_animate"); - if (msgData !== null) { - - var styles = msgData.style_data; - var layout = msgData.layout_data; - var trace_indexes = this._normalize_trace_indexes( - msgData.style_traces); - - for (var i = 0; i < styles.length; i++) { - var style = styles[i]; - var trace_index = trace_indexes[i]; - var trace = this.get("_data")[trace_index]; - performRelayoutLike(trace, style); - } - - performRelayoutLike(this.get("_layout"), layout); + /** @type {Py2JsAnimateMsg} */ + var msgData = this.get("_py2js_animate"); + if (msgData !== null) { + var styles = msgData.style_data; + var layout = msgData.layout_data; + var trace_indexes = this._normalize_trace_indexes(msgData.style_traces); + + for (var i = 0; i < styles.length; i++) { + var style = styles[i]; + var trace_index = trace_indexes[i]; + var trace = this.get("_data")[trace_index]; + performRelayoutLike(trace, style); } + + performRelayoutLike(this.get("_layout"), layout); + } }, /** * Handle removeLayoutProps message */ do_removeLayoutProps: function () { - /** @type {Py2JsRemoveLayoutPropsMsg} */ - var msgData = this.get("_py2js_removeLayoutProps"); - - if (msgData !== null) { - var keyPaths = msgData.remove_props; - var layout = this.get("_layout"); - performRemoveProps(layout, keyPaths); - } + /** @type {Py2JsRemoveLayoutPropsMsg} */ + var msgData = this.get("_py2js_removeLayoutProps"); + + if (msgData !== null) { + var keyPaths = msgData.remove_props; + var layout = this.get("_layout"); + performRemoveProps(layout, keyPaths); + } }, /** * Handle removeTraceProps message */ do_removeTraceProps: function () { - /** @type {Py2JsRemoveTracePropsMsg} */ - var msgData = this.get("_py2js_removeTraceProps"); - if (msgData !== null) { - var keyPaths = msgData.remove_props; - var traceIndex = msgData.remove_trace; - var trace = this.get("_data")[traceIndex]; - - performRemoveProps(trace, keyPaths); - } - } -}, { - serializers: _.extend({ - _data: { deserialize: py2js_deserializer, - serialize: js2py_serializer}, - _layout: { deserialize: py2js_deserializer, - serialize: js2py_serializer}, - _py2js_addTraces: { deserialize: py2js_deserializer, - serialize: js2py_serializer}, - _py2js_deleteTraces: { deserialize: py2js_deserializer, - serialize: js2py_serializer}, - _py2js_moveTraces: { deserialize: py2js_deserializer, - serialize: js2py_serializer}, - _py2js_restyle: { deserialize: py2js_deserializer, - serialize: js2py_serializer}, - _py2js_relayout: { deserialize: py2js_deserializer, - serialize: js2py_serializer}, - _py2js_update: { deserialize: py2js_deserializer, - serialize: js2py_serializer}, - _py2js_animate: { deserialize: py2js_deserializer, - serialize: js2py_serializer}, - _py2js_removeLayoutProps: { deserialize: py2js_deserializer, - serialize: js2py_serializer}, - _py2js_removeTraceProps: { deserialize: py2js_deserializer, - serialize: js2py_serializer}, - _js2py_restyle: { deserialize: py2js_deserializer, - serialize: js2py_serializer}, - _js2py_relayout: { deserialize: py2js_deserializer, - serialize: js2py_serializer}, - _js2py_update: { deserialize: py2js_deserializer, - serialize: js2py_serializer}, - _js2py_layoutDelta: { deserialize: py2js_deserializer, - serialize: js2py_serializer}, - _js2py_traceDeltas: { deserialize: py2js_deserializer, - serialize: js2py_serializer}, - _js2py_pointsCallback: { deserialize: py2js_deserializer, - serialize: js2py_serializer} - }, widgets.DOMWidgetModel.serializers) -}); + /** @type {Py2JsRemoveTracePropsMsg} */ + var msgData = this.get("_py2js_removeTraceProps"); + if (msgData !== null) { + var keyPaths = msgData.remove_props; + var traceIndex = msgData.remove_trace; + var trace = this.get("_data")[traceIndex]; + + performRemoveProps(trace, keyPaths); + } + }, + }, + { + serializers: _.extend( + { + _data: { deserialize: py2js_deserializer, serialize: js2py_serializer }, + _layout: { + deserialize: py2js_deserializer, + serialize: js2py_serializer, + }, + _py2js_addTraces: { + deserialize: py2js_deserializer, + serialize: js2py_serializer, + }, + _py2js_deleteTraces: { + deserialize: py2js_deserializer, + serialize: js2py_serializer, + }, + _py2js_moveTraces: { + deserialize: py2js_deserializer, + serialize: js2py_serializer, + }, + _py2js_restyle: { + deserialize: py2js_deserializer, + serialize: js2py_serializer, + }, + _py2js_relayout: { + deserialize: py2js_deserializer, + serialize: js2py_serializer, + }, + _py2js_update: { + deserialize: py2js_deserializer, + serialize: js2py_serializer, + }, + _py2js_animate: { + deserialize: py2js_deserializer, + serialize: js2py_serializer, + }, + _py2js_removeLayoutProps: { + deserialize: py2js_deserializer, + serialize: js2py_serializer, + }, + _py2js_removeTraceProps: { + deserialize: py2js_deserializer, + serialize: js2py_serializer, + }, + _js2py_restyle: { + deserialize: py2js_deserializer, + serialize: js2py_serializer, + }, + _js2py_relayout: { + deserialize: py2js_deserializer, + serialize: js2py_serializer, + }, + _js2py_update: { + deserialize: py2js_deserializer, + serialize: js2py_serializer, + }, + _js2py_layoutDelta: { + deserialize: py2js_deserializer, + serialize: js2py_serializer, + }, + _js2py_traceDeltas: { + deserialize: py2js_deserializer, + serialize: js2py_serializer, + }, + _js2py_pointsCallback: { + deserialize: py2js_deserializer, + serialize: js2py_serializer, + }, + }, + widgets.DOMWidgetModel.serializers + ), + } +); // View // ==== @@ -655,751 +682,747 @@ var FigureModel = widgets.DOMWidgetModel.extend({ * @type {widgets.DOMWidgetView} */ var FigureView = widgets.DOMWidgetView.extend({ + /** + * The perform_render method is called by processPhosphorMessage + * after the widget's DOM element has been attached to the notebook + * output cell. This happens after the initialize of the + * FigureModel, and it won't happen at all if the Python FigureWidget + * is never displayed in a notebook output cell + */ + perform_render: function () { + var that = this; + + // Wire up message property callbacks + // ---------------------------------- + // Python -> JS event properties + this.model.on("change:_py2js_addTraces", this.do_addTraces, this); + this.model.on("change:_py2js_deleteTraces", this.do_deleteTraces, this); + this.model.on("change:_py2js_moveTraces", this.do_moveTraces, this); + this.model.on("change:_py2js_restyle", this.do_restyle, this); + this.model.on("change:_py2js_relayout", this.do_relayout, this); + this.model.on("change:_py2js_update", this.do_update, this); + this.model.on("change:_py2js_animate", this.do_animate, this); + + // MathJax configuration + // --------------------- + if (window.MathJax) { + MathJax.Hub.Config({ SVG: { font: "STIX-Web" } }); + } - /** - * The perform_render method is called by processPhosphorMessage - * after the widget's DOM element has been attached to the notebook - * output cell. This happens after the initialize of the - * FigureModel, and it won't happen at all if the Python FigureWidget - * is never displayed in a notebook output cell - */ - perform_render: function() { - - var that = this; - - // Wire up message property callbacks - // ---------------------------------- - // Python -> JS event properties - this.model.on("change:_py2js_addTraces", - this.do_addTraces, this); - this.model.on("change:_py2js_deleteTraces", - this.do_deleteTraces, this); - this.model.on("change:_py2js_moveTraces", - this.do_moveTraces, this); - this.model.on("change:_py2js_restyle", - this.do_restyle, this); - this.model.on("change:_py2js_relayout", - this.do_relayout, this); - this.model.on("change:_py2js_update", - this.do_update, this); - this.model.on("change:_py2js_animate", - this.do_animate, this); - - // MathJax configuration - // --------------------- - if (window.MathJax) { - MathJax.Hub.Config({SVG: {font: "STIX-Web"}}); - } - - // Get message ids - // --------------------- - var layout_edit_id = this.model.get("_last_layout_edit_id"); - var trace_edit_id = this.model.get("_last_trace_edit_id"); - - // Set view UID - // ------------ - this.viewID = randstr(); - - // Initialize Plotly.js figure - // --------------------------- - // We must clone the model's data and layout properties so that - // the model is not directly mutated by the Plotly.js library. - var initialTraces = _.cloneDeep(this.model.get("_data")); - var initialLayout = _.cloneDeep(this.model.get("_layout")); - var config = this.model.get("_config"); - - import(/* webpackChunkName: 'plotly' */ 'plotly.js/dist/plotly').then(Plotly => { - Plotly.newPlot(that.el, initialTraces, initialLayout, config).then( - function () { - - // ### Send trace deltas ### - // We create an array of deltas corresponding to the new - // traces. - that._sendTraceDeltas(trace_edit_id); - - // ### Send layout delta ### - that._sendLayoutDelta(layout_edit_id); - - // Wire up plotly event callbacks - that.el.on("plotly_restyle", - function (update) { - that.handle_plotly_restyle(update) - }); - that.el.on("plotly_relayout", - function (update) { - that.handle_plotly_relayout(update) - }); - that.el.on("plotly_update", - function (update) { - that.handle_plotly_update(update) - }); - that.el.on("plotly_click", - function (update) { - that.handle_plotly_click(update) - }); - that.el.on("plotly_hover", - function (update) { - that.handle_plotly_hover(update) - }); - that.el.on("plotly_unhover", - function (update) { - that.handle_plotly_unhover(update) - }); - that.el.on("plotly_selected", - function (update) { - that.handle_plotly_selected(update) - }); - that.el.on("plotly_deselect", - function (update) { - that.handle_plotly_deselect(update) - }); - that.el.on("plotly_doubleclick", - function (update) { - that.handle_plotly_doubleclick(update) - }); - - // Emit event indicating that the widget has finished - // rendering - var event = new CustomEvent("plotlywidget-after-render", - {"detail": {"element": that.el, 'viewID': that.viewID}}); - - // Dispatch/Trigger/Fire the event - document.dispatchEvent(event); - }); - }) - }, - - /** - * Respond to phosphorjs events - */ - processPhosphorMessage: function(msg) { - import(/* webpackChunkName: 'plotly' */ 'plotly.js/dist/plotly').then(Plotly => { - FigureView.__super__.processPhosphorMessage.apply(this, arguments); - var that = this; - switch (msg.type) { - case 'before-attach': - // Render an initial empty figure. This establishes with - // the page that the element will not be empty, avoiding - // some occasions where the dynamic sizing behavior leads - // to collapsed figure dimensions. - var axisHidden = { - showgrid: false, showline: false, tickvals: [] - }; - - Plotly.newPlot(that.el, [], { - xaxis: axisHidden, yaxis: axisHidden - }); - - window.addEventListener("resize", function () { - that.autosizeFigure(); - }); - break; - case 'after-attach': - // Rendering actual figure in the after-attach event allows - // Plotly.js to size the figure to fill the available element - this.perform_render(); - break; - case 'resize': - this.autosizeFigure(); - break - } - }) - }, - - autosizeFigure: function() { - import(/* webpackChunkName: 'plotly' */ 'plotly.js/dist/plotly').then(Plotly => { - var that = this; - var layout = that.model.get('_layout'); - if (_.isNil(layout) || - _.isNil(layout.width)) { - Plotly.Plots.resize(that.el).then(function () { - var layout_edit_id = that.model.get( - "_last_layout_edit_id"); - that._sendLayoutDelta(layout_edit_id); - }); - } - }) - }, - - /** - * Purge Plotly.js data structures from the notebook output display - * element when the view is destroyed - */ - destroy: function() { - import(/* webpackChunkName: 'plotly' */ 'plotly.js/dist/plotly').then(Plotly => { - Plotly.purge(this.el); - }) - }, - - /** - * Return the figure's _fullData array merged with its data array - * - * The merge ensures that for any properties that el._fullData and - * el.data have in common, we return the version from el.data - * - * Named colorscales are one example of why this is needed. The el.data - * array will hold named colorscale strings (e.g. 'Viridis'), while the - * el._fullData array will hold the actual colorscale array. e.g. - * - * el.data[0].marker.colorscale == 'Viridis' but - * el._fullData[0].marker.colorscale = [[..., ...], ...] - * - * Performing the merge allows our FigureModel to retain the 'Viridis' - * string, rather than having it overridded by the colorscale array. - * - */ - getFullData: function () { - return _.mergeWith({}, this.el._fullData, this.el.data, - fullMergeCustomizer) - }, - - /** - * Return the figure's _fullLayout object merged with its layout object - * - * See getFullData documentation for discussion of why the merge is - * necessary - */ - getFullLayout: function () { - return _.mergeWith({}, this.el._fullLayout, this.el.layout, - fullMergeCustomizer); - }, - - /** - * Build Points data structure from data supplied by the plotly_click, - * plotly_hover, or plotly_select events - * @param {Object} data - * @returns {null|Points} - */ - buildPointsObject: function (data) { - - var pointsObject; - if (data.hasOwnProperty("points")) { - // Most cartesian plots - var pointObjects = data["points"]; - var numPoints = pointObjects.length; - pointsObject = { - "trace_indexes": new Array(numPoints), - "point_indexes": new Array(numPoints), - "xs": new Array(numPoints), - "ys": new Array(numPoints)}; - - - for (var p = 0; p < numPoints; p++) { - pointsObject["trace_indexes"][p] = - pointObjects[p]["curveNumber"]; - pointsObject["point_indexes"][p] = - pointObjects[p]["pointNumber"]; - pointsObject["xs"][p] = - pointObjects[p]["x"]; - pointsObject["ys"][p] = - pointObjects[p]["y"]; - } - - // Add z if present - var hasZ = pointObjects[0] !== - undefined && pointObjects[0].hasOwnProperty("z"); - if (hasZ) { - pointsObject["zs"] = new Array(numPoints); - for (p = 0; p < numPoints; p++) { - pointsObject["zs"][p] = pointObjects[p]["z"]; - } - } + // Get message ids + // --------------------- + var layout_edit_id = this.model.get("_last_layout_edit_id"); + var trace_edit_id = this.model.get("_last_trace_edit_id"); + + // Set view UID + // ------------ + this.viewID = randstr(); + + // Initialize Plotly.js figure + // --------------------------- + // We must clone the model's data and layout properties so that + // the model is not directly mutated by the Plotly.js library. + var initialTraces = _.cloneDeep(this.model.get("_data")); + var initialLayout = _.cloneDeep(this.model.get("_layout")); + var config = this.model.get("_config"); + + import(/* webpackChunkName: 'plotly' */ /* webpackPrefetch: true */ "plotly.js/dist/plotly").then( + (Plotly) => { + Plotly.newPlot(that.el, initialTraces, initialLayout, config).then( + function () { + // ### Send trace deltas ### + // We create an array of deltas corresponding to the new + // traces. + that._sendTraceDeltas(trace_edit_id); + + // ### Send layout delta ### + that._sendLayoutDelta(layout_edit_id); + + // Wire up plotly event callbacks + that.el.on("plotly_restyle", function (update) { + that.handle_plotly_restyle(update); + }); + that.el.on("plotly_relayout", function (update) { + that.handle_plotly_relayout(update); + }); + that.el.on("plotly_update", function (update) { + that.handle_plotly_update(update); + }); + that.el.on("plotly_click", function (update) { + that.handle_plotly_click(update); + }); + that.el.on("plotly_hover", function (update) { + that.handle_plotly_hover(update); + }); + that.el.on("plotly_unhover", function (update) { + that.handle_plotly_unhover(update); + }); + that.el.on("plotly_selected", function (update) { + that.handle_plotly_selected(update); + }); + that.el.on("plotly_deselect", function (update) { + that.handle_plotly_deselect(update); + }); + that.el.on("plotly_doubleclick", function (update) { + that.handle_plotly_doubleclick(update); + }); - return pointsObject - } else { - return null - } - }, + // Emit event indicating that the widget has finished + // rendering + var event = new CustomEvent("plotlywidget-after-render", { + detail: { element: that.el, viewID: that.viewID }, + }); - /** - * Build InputDeviceState data structure from data supplied by the - * plotly_click, plotly_hover, or plotly_select events - * @param {Object} data - * @returns {null|InputDeviceState} - */ - buildInputDeviceStateObject: function (data) { - var event = data["event"]; - if (event === undefined) { - return null; - } else { - /** @type {InputDeviceState} */ - var inputDeviceState = { - // Keyboard modifiers - "alt": event["altKey"], - "ctrl": event["ctrlKey"], - "meta": event["metaKey"], - "shift": event["shiftKey"], - - // Mouse buttons - "button": event["button"], - "buttons": event["buttons"] + // Dispatch/Trigger/Fire the event + document.dispatchEvent(event); + } + ); + } + ); + }, + + /** + * Respond to phosphorjs events + */ + processPhosphorMessage: function (msg) { + import(/* webpackChunkName: 'plotly' */ /* webpackPrefetch: true */ "plotly.js/dist/plotly").then( + (Plotly) => { + FigureView.__super__.processPhosphorMessage.apply(this, arguments); + var that = this; + switch (msg.type) { + case "before-attach": + // Render an initial empty figure. This establishes with + // the page that the element will not be empty, avoiding + // some occasions where the dynamic sizing behavior leads + // to collapsed figure dimensions. + var axisHidden = { + showgrid: false, + showline: false, + tickvals: [], }; - return inputDeviceState - } - }, - /** - * Build Selector data structure from data supplied by the - * plotly_select event - * @param data - * @returns {null|Selector} - */ - buildSelectorObject: function(data) { - - var selectorObject; + Plotly.newPlot(that.el, [], { + xaxis: axisHidden, + yaxis: axisHidden, + }); - if (data.hasOwnProperty("range")) { - // Box selection - selectorObject = { - type: "box", - selector_state: { - xrange: data["range"]["x"], - yrange: data["range"]["y"] - } - }; - } else if (data.hasOwnProperty("lassoPoints")) { - // Lasso selection - selectorObject = { - type: "lasso", - selector_state: { - xs: data["lassoPoints"]["x"], - ys: data["lassoPoints"]["y"] - } - }; - } else { - selectorObject = null; + window.addEventListener("resize", function () { + that.autosizeFigure(); + }); + break; + case "after-attach": + // Rendering actual figure in the after-attach event allows + // Plotly.js to size the figure to fill the available element + this.perform_render(); + break; + case "resize": + this.autosizeFigure(); + break; } - return selectorObject - }, - - /** - * Handle ploty_restyle events emitted by the Plotly.js library - * @param data - */ - handle_plotly_restyle: function (data) { + } + ); + }, - if (data === null || data === undefined) { - // No data to report to the Python side - return + autosizeFigure: function () { + import(/* webpackChunkName: 'plotly' */ /* webpackPrefetch: true */ "plotly.js/dist/plotly").then( + (Plotly) => { + var that = this; + var layout = that.model.get("_layout"); + if (_.isNil(layout) || _.isNil(layout.width)) { + Plotly.Plots.resize(that.el).then(function () { + var layout_edit_id = that.model.get("_last_layout_edit_id"); + that._sendLayoutDelta(layout_edit_id); + }); } - - if (data[0] && data[0].hasOwnProperty("_doNotReportToPy")) { - // Restyle originated on the Python side - return + } + ); + }, + + /** + * Purge Plotly.js data structures from the notebook output display + * element when the view is destroyed + */ + destroy: function () { + import(/* webpackChunkName: 'plotly' */ /* webpackPrefetch: true */ "plotly.js/dist/plotly").then( + (Plotly) => { + Plotly.purge(this.el); + } + ); + }, + + /** + * Return the figure's _fullData array merged with its data array + * + * The merge ensures that for any properties that el._fullData and + * el.data have in common, we return the version from el.data + * + * Named colorscales are one example of why this is needed. The el.data + * array will hold named colorscale strings (e.g. 'Viridis'), while the + * el._fullData array will hold the actual colorscale array. e.g. + * + * el.data[0].marker.colorscale == 'Viridis' but + * el._fullData[0].marker.colorscale = [[..., ...], ...] + * + * Performing the merge allows our FigureModel to retain the 'Viridis' + * string, rather than having it overridded by the colorscale array. + * + */ + getFullData: function () { + return _.mergeWith( + {}, + this.el._fullData, + this.el.data, + fullMergeCustomizer + ); + }, + + /** + * Return the figure's _fullLayout object merged with its layout object + * + * See getFullData documentation for discussion of why the merge is + * necessary + */ + getFullLayout: function () { + return _.mergeWith( + {}, + this.el._fullLayout, + this.el.layout, + fullMergeCustomizer + ); + }, + + /** + * Build Points data structure from data supplied by the plotly_click, + * plotly_hover, or plotly_select events + * @param {Object} data + * @returns {null|Points} + */ + buildPointsObject: function (data) { + var pointsObject; + if (data.hasOwnProperty("points")) { + // Most cartesian plots + var pointObjects = data["points"]; + var numPoints = pointObjects.length; + pointsObject = { + trace_indexes: new Array(numPoints), + point_indexes: new Array(numPoints), + xs: new Array(numPoints), + ys: new Array(numPoints), + }; + + for (var p = 0; p < numPoints; p++) { + pointsObject["trace_indexes"][p] = pointObjects[p]["curveNumber"]; + pointsObject["point_indexes"][p] = pointObjects[p]["pointNumber"]; + pointsObject["xs"][p] = pointObjects[p]["x"]; + pointsObject["ys"][p] = pointObjects[p]["y"]; + } + + // Add z if present + var hasZ = + pointObjects[0] !== undefined && pointObjects[0].hasOwnProperty("z"); + if (hasZ) { + pointsObject["zs"] = new Array(numPoints); + for (p = 0; p < numPoints; p++) { + pointsObject["zs"][p] = pointObjects[p]["z"]; } + } - // Unpack data - var styleData = data[0]; - var styleTraces = data[1]; - - // Construct restyle message to send to the Python side - /** @type {Js2PyRestyleMsg} */ - var restyleMsg = { - style_data: styleData, - style_traces: styleTraces, - source_view_id: this.viewID - }; - - this.model.set("_js2py_restyle", restyleMsg); - this.touch(); - }, - - /** - * Handle plotly_relayout events emitted by the Plotly.js library - * @param data - */ - handle_plotly_relayout: function (data) { + return pointsObject; + } else { + return null; + } + }, + + /** + * Build InputDeviceState data structure from data supplied by the + * plotly_click, plotly_hover, or plotly_select events + * @param {Object} data + * @returns {null|InputDeviceState} + */ + buildInputDeviceStateObject: function (data) { + var event = data["event"]; + if (event === undefined) { + return null; + } else { + /** @type {InputDeviceState} */ + var inputDeviceState = { + // Keyboard modifiers + alt: event["altKey"], + ctrl: event["ctrlKey"], + meta: event["metaKey"], + shift: event["shiftKey"], + + // Mouse buttons + button: event["button"], + buttons: event["buttons"], + }; + return inputDeviceState; + } + }, + + /** + * Build Selector data structure from data supplied by the + * plotly_select event + * @param data + * @returns {null|Selector} + */ + buildSelectorObject: function (data) { + var selectorObject; + + if (data.hasOwnProperty("range")) { + // Box selection + selectorObject = { + type: "box", + selector_state: { + xrange: data["range"]["x"], + yrange: data["range"]["y"], + }, + }; + } else if (data.hasOwnProperty("lassoPoints")) { + // Lasso selection + selectorObject = { + type: "lasso", + selector_state: { + xs: data["lassoPoints"]["x"], + ys: data["lassoPoints"]["y"], + }, + }; + } else { + selectorObject = null; + } + return selectorObject; + }, + + /** + * Handle ploty_restyle events emitted by the Plotly.js library + * @param data + */ + handle_plotly_restyle: function (data) { + if (data === null || data === undefined) { + // No data to report to the Python side + return; + } - if (data === null || data === undefined) { - // No data to report to the Python side - return - } + if (data[0] && data[0].hasOwnProperty("_doNotReportToPy")) { + // Restyle originated on the Python side + return; + } - if (data.hasOwnProperty("_doNotReportToPy")) { - // Relayout originated on the Python side - return - } + // Unpack data + var styleData = data[0]; + var styleTraces = data[1]; - /** @type {Js2PyRelayoutMsg} */ - var relayoutMsg = { - relayout_data: data, - source_view_id: this.viewID - }; + // Construct restyle message to send to the Python side + /** @type {Js2PyRestyleMsg} */ + var restyleMsg = { + style_data: styleData, + style_traces: styleTraces, + source_view_id: this.viewID, + }; - this.model.set("_js2py_relayout", relayoutMsg); - this.touch(); - }, + this.model.set("_js2py_restyle", restyleMsg); + this.touch(); + }, + + /** + * Handle plotly_relayout events emitted by the Plotly.js library + * @param data + */ + handle_plotly_relayout: function (data) { + if (data === null || data === undefined) { + // No data to report to the Python side + return; + } - /** - * Handle plotly_update events emitted by the Plotly.js library - * @param data - */ - handle_plotly_update: function (data) { + if (data.hasOwnProperty("_doNotReportToPy")) { + // Relayout originated on the Python side + return; + } - if (data === null || data === undefined) { - // No data to report to the Python side - return - } + /** @type {Js2PyRelayoutMsg} */ + var relayoutMsg = { + relayout_data: data, + source_view_id: this.viewID, + }; - if (data["data"] && - data["data"][0].hasOwnProperty("_doNotReportToPy")) { - // Update originated on the Python side - return - } + this.model.set("_js2py_relayout", relayoutMsg); + this.touch(); + }, + + /** + * Handle plotly_update events emitted by the Plotly.js library + * @param data + */ + handle_plotly_update: function (data) { + if (data === null || data === undefined) { + // No data to report to the Python side + return; + } - /** @type {Js2PyUpdateMsg} */ - var updateMsg = { - style_data: data["data"][0], - style_traces: data["data"][1], - layout_data: data["layout"], - source_view_id: this.viewID - }; - - // Log message - this.model.set("_js2py_update", updateMsg); - this.touch(); - }, + if (data["data"] && data["data"][0].hasOwnProperty("_doNotReportToPy")) { + // Update originated on the Python side + return; + } - /** - * Handle plotly_click events emitted by the Plotly.js library - * @param data - */ - handle_plotly_click: function (data) { - this._send_points_callback_message(data, "plotly_click"); - }, + /** @type {Js2PyUpdateMsg} */ + var updateMsg = { + style_data: data["data"][0], + style_traces: data["data"][1], + layout_data: data["layout"], + source_view_id: this.viewID, + }; - /** - * Handle plotly_hover events emitted by the Plotly.js library - * @param data - */ - handle_plotly_hover: function (data) { - this._send_points_callback_message(data, "plotly_hover"); - }, + // Log message + this.model.set("_js2py_update", updateMsg); + this.touch(); + }, + + /** + * Handle plotly_click events emitted by the Plotly.js library + * @param data + */ + handle_plotly_click: function (data) { + this._send_points_callback_message(data, "plotly_click"); + }, + + /** + * Handle plotly_hover events emitted by the Plotly.js library + * @param data + */ + handle_plotly_hover: function (data) { + this._send_points_callback_message(data, "plotly_hover"); + }, + + /** + * Handle plotly_unhover events emitted by the Plotly.js library + * @param data + */ + handle_plotly_unhover: function (data) { + this._send_points_callback_message(data, "plotly_unhover"); + }, + + /** + * Handle plotly_selected events emitted by the Plotly.js library + * @param data + */ + handle_plotly_selected: function (data) { + this._send_points_callback_message(data, "plotly_selected"); + }, + + /** + * Handle plotly_deselect events emitted by the Plotly.js library + * @param data + */ + handle_plotly_deselect: function (data) { + data = { + points: [], + }; + this._send_points_callback_message(data, "plotly_deselect"); + }, + + /** + * Build and send a points callback message to the Python side + * + * @param {Object} data + * data object as provided by the plotly_click, plotly_hover, + * plotly_unhover, or plotly_selected events + * @param {String} event_type + * Name of the triggering event. One of 'plotly_click', + * 'plotly_hover', 'plotly_unhover', or 'plotly_selected' + * @private + */ + _send_points_callback_message: function (data, event_type) { + if (data === null || data === undefined) { + // No data to report to the Python side + return; + } - /** - * Handle plotly_unhover events emitted by the Plotly.js library - * @param data - */ - handle_plotly_unhover: function (data) { - this._send_points_callback_message(data, "plotly_unhover"); - }, + /** @type {Js2PyPointsCallbackMsg} */ + var pointsMsg = { + event_type: event_type, + points: this.buildPointsObject(data), + device_state: this.buildInputDeviceStateObject(data), + selector: this.buildSelectorObject(data), + }; - /** - * Handle plotly_selected events emitted by the Plotly.js library - * @param data - */ - handle_plotly_selected: function (data) { - this._send_points_callback_message(data, "plotly_selected"); - }, + if (pointsMsg["points"] !== null && pointsMsg["points"] !== undefined) { + this.model.set("_js2py_pointsCallback", pointsMsg); + this.touch(); + } + }, + + /** + * Stub for future handling of plotly_doubleclick + * @param data + */ + handle_plotly_doubleclick: function (data) {}, + + /** + * Handle Plotly.addTraces request + */ + do_addTraces: function () { + import(/* webpackChunkName: 'plotly' */ /* webpackPrefetch: true */ "plotly.js/dist/plotly").then( + (Plotly) => { + /** @type {Py2JsAddTracesMsg} */ + var msgData = this.model.get("_py2js_addTraces"); - /** - * Handle plotly_deselect events emitted by the Plotly.js library - * @param data - */ - handle_plotly_deselect: function (data) { - data = { - points : [] + if (msgData !== null) { + // Save off original number of traces + var prevNumTraces = this.el.data.length; + + var that = this; + Plotly.addTraces(this.el, msgData.trace_data).then(function () { + // ### Send trace deltas ### + that._sendTraceDeltas(msgData.trace_edit_id); + + // ### Send layout delta ### + var layout_edit_id = msgData.layout_edit_id; + that._sendLayoutDelta(layout_edit_id); + }); } - this._send_points_callback_message(data, "plotly_deselect"); - }, + } + ); + }, + + /** + * Handle Plotly.deleteTraces request + */ + do_deleteTraces: function () { + import(/* webpackChunkName: 'plotly' */ /* webpackPrefetch: true */ "plotly.js/dist/plotly").then( + (Plotly) => { + /** @type {Py2JsDeleteTracesMsg} */ + var msgData = this.model.get("_py2js_deleteTraces"); - /** - * Build and send a points callback message to the Python side - * - * @param {Object} data - * data object as provided by the plotly_click, plotly_hover, - * plotly_unhover, or plotly_selected events - * @param {String} event_type - * Name of the triggering event. One of 'plotly_click', - * 'plotly_hover', 'plotly_unhover', or 'plotly_selected' - * @private - */ - _send_points_callback_message: function (data, event_type) { - if (data === null || data === undefined) { - // No data to report to the Python side - return; + if (msgData !== null) { + var delete_inds = msgData.delete_inds; + var that = this; + Plotly.deleteTraces(this.el, delete_inds).then(function () { + // ### Send trace deltas ### + var trace_edit_id = msgData.trace_edit_id; + that._sendTraceDeltas(trace_edit_id); + + // ### Send layout delta ### + var layout_edit_id = msgData.layout_edit_id; + that._sendLayoutDelta(layout_edit_id); + }); } + } + ); + }, + + /** + * Handle Plotly.moveTraces request + */ + do_moveTraces: function () { + import(/* webpackChunkName: 'plotly' */ /* webpackPrefetch: true */ "plotly.js/dist/plotly").then( + (Plotly) => { + /** @type {Py2JsMoveTracesMsg} */ + var msgData = this.model.get("_py2js_moveTraces"); - /** @type {Js2PyPointsCallbackMsg} */ - var pointsMsg = { - event_type: event_type, - points: this.buildPointsObject(data), - device_state: this.buildInputDeviceStateObject(data), - selector: this.buildSelectorObject(data) - }; + if (msgData !== null) { + // Unpack message + var currentInds = msgData.current_trace_inds; + var newInds = msgData.new_trace_inds; - if (pointsMsg["points"] !== null && - pointsMsg["points"] !== undefined) { + // Check if the new trace indexes are actually different than + // the current indexes + var inds_equal = _.isEqual(currentInds, newInds); - this.model.set("_js2py_pointsCallback", pointsMsg); - this.touch(); + if (!inds_equal) { + Plotly.moveTraces(this.el, currentInds, newInds); + } } - }, - - /** - * Stub for future handling of plotly_doubleclick - * @param data - */ - handle_plotly_doubleclick: function (data) {}, - - - /** - * Handle Plotly.addTraces request - */ - do_addTraces: function () { - import(/* webpackChunkName: 'plotly' */ 'plotly.js/dist/plotly').then(Plotly => { - - /** @type {Py2JsAddTracesMsg} */ - var msgData = this.model.get("_py2js_addTraces"); - - if (msgData !== null) { - - // Save off original number of traces - var prevNumTraces = this.el.data.length; - - var that = this; - Plotly.addTraces(this.el, msgData.trace_data).then(function () { - - // ### Send trace deltas ### - that._sendTraceDeltas(msgData.trace_edit_id); - - // ### Send layout delta ### - var layout_edit_id = msgData.layout_edit_id; - that._sendLayoutDelta(layout_edit_id); - }); - } - }) - }, - - /** - * Handle Plotly.deleteTraces request - */ - do_deleteTraces: function () { - import(/* webpackChunkName: 'plotly' */ 'plotly.js/dist/plotly').then(Plotly => { - - /** @type {Py2JsDeleteTracesMsg} */ - var msgData = this.model.get("_py2js_deleteTraces"); - - if (msgData !== null) { - var delete_inds = msgData.delete_inds; - var that = this; - Plotly.deleteTraces(this.el, delete_inds).then(function () { - - // ### Send trace deltas ### - var trace_edit_id = msgData.trace_edit_id; - that._sendTraceDeltas(trace_edit_id); - - // ### Send layout delta ### - var layout_edit_id = msgData.layout_edit_id; - that._sendLayoutDelta(layout_edit_id); - }); - } - }) - }, - - /** - * Handle Plotly.moveTraces request - */ - do_moveTraces: function () { - import(/* webpackChunkName: 'plotly' */ 'plotly.js/dist/plotly').then(Plotly => { - - /** @type {Py2JsMoveTracesMsg} */ - var msgData = this.model.get("_py2js_moveTraces"); - - if (msgData !== null) { - // Unpack message - var currentInds = msgData.current_trace_inds; - var newInds = msgData.new_trace_inds; - - // Check if the new trace indexes are actually different than - // the current indexes - var inds_equal = _.isEqual(currentInds, newInds); - - if (!inds_equal) { - Plotly.moveTraces(this.el, currentInds, newInds) - } - } - }) - }, - - /** - * Handle Plotly.restyle request - */ - do_restyle: function () { - import(/* webpackChunkName: 'plotly' */ 'plotly.js/dist/plotly').then(Plotly => { - - /** @type {Py2JsRestyleMsg} */ - var msgData = this.model.get("_py2js_restyle"); - if (msgData !== null) { - var restyleData = msgData.restyle_data; - var traceIndexes = this.model._normalize_trace_indexes( - msgData.restyle_traces); - - restyleData["_doNotReportToPy"] = true; - Plotly.restyle(this.el, restyleData, traceIndexes); - - // ### Send trace deltas ### - // We create an array of deltas corresponding to the restyled - // traces. - this._sendTraceDeltas(msgData.trace_edit_id); - - // ### Send layout delta ### - var layout_edit_id = msgData.layout_edit_id; - this._sendLayoutDelta(layout_edit_id); - } - }) - }, - - /** - * Handle Plotly.relayout request - */ - do_relayout: function () { - import(/* webpackChunkName: 'plotly' */ 'plotly.js/dist/plotly').then(Plotly => { - - /** @type {Py2JsRelayoutMsg} */ - var msgData = this.model.get("_py2js_relayout"); - if (msgData !== null) { - if (msgData.source_view_id !== this.viewID) { - var relayoutData = msgData.relayout_data; - relayoutData["_doNotReportToPy"] = true; - Plotly.relayout(this.el, msgData.relayout_data); - } - - // ### Send layout delta ### - var layout_edit_id = msgData.layout_edit_id; - this._sendLayoutDelta(layout_edit_id); - } - }) - }, - - /** - * Handle Plotly.update request - */ - do_update: function () { - import(/* webpackChunkName: 'plotly' */ 'plotly.js/dist/plotly').then(Plotly => { - - /** @type {Py2JsUpdateMsg} */ - var msgData = this.model.get("_py2js_update"); - - if (msgData !== null) { - var style = msgData.style_data || {}; - var layout = msgData.layout_data || {}; - var traceIndexes = this.model._normalize_trace_indexes( - msgData.style_traces); - - style["_doNotReportToPy"] = true; - Plotly.update(this.el, style, layout, traceIndexes); - - // ### Send trace deltas ### - // We create an array of deltas corresponding to the updated - // traces. - this._sendTraceDeltas(msgData.trace_edit_id); - - // ### Send layout delta ### - var layout_edit_id = msgData.layout_edit_id; - this._sendLayoutDelta(layout_edit_id); - } - }) - }, - - /** - * Handle Plotly.animate request - */ - do_animate: function() { - import(/* webpackChunkName: 'plotly' */ 'plotly.js/dist/plotly').then(Plotly => { - - /** @type {Py2JsAnimateMsg} */ - var msgData = this.model.get("_py2js_animate"); - - if (msgData !== null) { - - // Unpack params - // var animationData = msgData[0]; - var animationOpts = msgData.animation_opts; - - var styles = msgData.style_data; - var layout = msgData.layout_data; - var traceIndexes = this.model._normalize_trace_indexes( - msgData.style_traces); - - var animationData = { - data: styles, - layout: layout, - traces: traceIndexes - }; - - animationData["_doNotReportToPy"] = true; - var that = this; - - Plotly.animate(this.el, animationData, animationOpts).then( - function () { - - // ### Send trace deltas ### - // We create an array of deltas corresponding to the - // animated traces. - that._sendTraceDeltas(msgData.trace_edit_id); + } + ); + }, + + /** + * Handle Plotly.restyle request + */ + do_restyle: function () { + import(/* webpackChunkName: 'plotly' */ /* webpackPrefetch: true */ "plotly.js/dist/plotly").then( + (Plotly) => { + /** @type {Py2JsRestyleMsg} */ + var msgData = this.model.get("_py2js_restyle"); + if (msgData !== null) { + var restyleData = msgData.restyle_data; + var traceIndexes = this.model._normalize_trace_indexes( + msgData.restyle_traces + ); + + restyleData["_doNotReportToPy"] = true; + Plotly.restyle(this.el, restyleData, traceIndexes); + + // ### Send trace deltas ### + // We create an array of deltas corresponding to the restyled + // traces. + this._sendTraceDeltas(msgData.trace_edit_id); + + // ### Send layout delta ### + var layout_edit_id = msgData.layout_edit_id; + this._sendLayoutDelta(layout_edit_id); + } + } + ); + }, + + /** + * Handle Plotly.relayout request + */ + do_relayout: function () { + import(/* webpackChunkName: 'plotly' */ /* webpackPrefetch: true */ "plotly.js/dist/plotly").then( + (Plotly) => { + /** @type {Py2JsRelayoutMsg} */ + var msgData = this.model.get("_py2js_relayout"); + if (msgData !== null) { + if (msgData.source_view_id !== this.viewID) { + var relayoutData = msgData.relayout_data; + relayoutData["_doNotReportToPy"] = true; + Plotly.relayout(this.el, msgData.relayout_data); + } + + // ### Send layout delta ### + var layout_edit_id = msgData.layout_edit_id; + this._sendLayoutDelta(layout_edit_id); + } + } + ); + }, + + /** + * Handle Plotly.update request + */ + do_update: function () { + import(/* webpackChunkName: 'plotly' */ /* webpackPrefetch: true */ "plotly.js/dist/plotly").then( + (Plotly) => { + /** @type {Py2JsUpdateMsg} */ + var msgData = this.model.get("_py2js_update"); - // ### Send layout delta ### - var layout_edit_id = msgData.layout_edit_id; - that._sendLayoutDelta(layout_edit_id); - }); + if (msgData !== null) { + var style = msgData.style_data || {}; + var layout = msgData.layout_data || {}; + var traceIndexes = this.model._normalize_trace_indexes( + msgData.style_traces + ); + + style["_doNotReportToPy"] = true; + Plotly.update(this.el, style, layout, traceIndexes); + + // ### Send trace deltas ### + // We create an array of deltas corresponding to the updated + // traces. + this._sendTraceDeltas(msgData.trace_edit_id); + + // ### Send layout delta ### + var layout_edit_id = msgData.layout_edit_id; + this._sendLayoutDelta(layout_edit_id); + } + } + ); + }, + + /** + * Handle Plotly.animate request + */ + do_animate: function () { + import(/* webpackChunkName: 'plotly' */ /* webpackPrefetch: true */ "plotly.js/dist/plotly").then( + (Plotly) => { + /** @type {Py2JsAnimateMsg} */ + var msgData = this.model.get("_py2js_animate"); + if (msgData !== null) { + // Unpack params + // var animationData = msgData[0]; + var animationOpts = msgData.animation_opts; + + var styles = msgData.style_data; + var layout = msgData.layout_data; + var traceIndexes = this.model._normalize_trace_indexes( + msgData.style_traces + ); + + var animationData = { + data: styles, + layout: layout, + traces: traceIndexes, + }; + + animationData["_doNotReportToPy"] = true; + var that = this; + + Plotly.animate(this.el, animationData, animationOpts).then( + function () { + // ### Send trace deltas ### + // We create an array of deltas corresponding to the + // animated traces. + that._sendTraceDeltas(msgData.trace_edit_id); + + // ### Send layout delta ### + var layout_edit_id = msgData.layout_edit_id; + that._sendLayoutDelta(layout_edit_id); } - }) - }, - - /** - * Construct layout delta object and send layoutDelta message to the - * Python side - * - * @param layout_edit_id - * Edit ID of message that triggered the creation of the layout delta - * @private - */ - _sendLayoutDelta: function(layout_edit_id) { - // ### Handle layout delta ### - var layout_delta = createDeltaObject( - this.getFullLayout(), - this.model.get("_layout")); - - /** @type{Js2PyLayoutDeltaMsg} */ - var layoutDeltaMsg = { - layout_delta: layout_delta, - layout_edit_id: layout_edit_id}; - - this.model.set("_js2py_layoutDelta", layoutDeltaMsg); - this.touch(); - }, - - /** - * Construct trace deltas array for the requested trace indexes and - * send traceDeltas message to the Python side - * Array of indexes of traces for which to compute deltas - * @param trace_edit_id - * Edit ID of message that triggered the creation of trace deltas - * @private - */ - _sendTraceDeltas: function (trace_edit_id) { - - var trace_data = this.model.get("_data"); - var traceIndexes = _.range(trace_data.length); - var trace_deltas = new Array(traceIndexes.length); - - var fullData = this.getFullData(); - for (var i = 0; i < traceIndexes.length; i++) { - var traceInd = traceIndexes[i]; - trace_deltas[i] = createDeltaObject( - fullData[traceInd], trace_data[traceInd]); + ); } + } + ); + }, + + /** + * Construct layout delta object and send layoutDelta message to the + * Python side + * + * @param layout_edit_id + * Edit ID of message that triggered the creation of the layout delta + * @private + */ + _sendLayoutDelta: function (layout_edit_id) { + // ### Handle layout delta ### + var layout_delta = createDeltaObject( + this.getFullLayout(), + this.model.get("_layout") + ); + + /** @type{Js2PyLayoutDeltaMsg} */ + var layoutDeltaMsg = { + layout_delta: layout_delta, + layout_edit_id: layout_edit_id, + }; - /** @type{Js2PyTraceDeltasMsg} */ - var traceDeltasMsg = { - trace_deltas: trace_deltas, - trace_edit_id: trace_edit_id}; - - this.model.set("_js2py_traceDeltas", traceDeltasMsg); - this.touch(); + this.model.set("_js2py_layoutDelta", layoutDeltaMsg); + this.touch(); + }, + + /** + * Construct trace deltas array for the requested trace indexes and + * send traceDeltas message to the Python side + * Array of indexes of traces for which to compute deltas + * @param trace_edit_id + * Edit ID of message that triggered the creation of trace deltas + * @private + */ + _sendTraceDeltas: function (trace_edit_id) { + var trace_data = this.model.get("_data"); + var traceIndexes = _.range(trace_data.length); + var trace_deltas = new Array(traceIndexes.length); + + var fullData = this.getFullData(); + for (var i = 0; i < traceIndexes.length; i++) { + var traceInd = traceIndexes[i]; + trace_deltas[i] = createDeltaObject( + fullData[traceInd], + trace_data[traceInd] + ); } + + /** @type{Js2PyTraceDeltasMsg} */ + var traceDeltasMsg = { + trace_deltas: trace_deltas, + trace_edit_id: trace_edit_id, + }; + + this.model.set("_js2py_traceDeltas", traceDeltasMsg); + this.touch(); + }, }); // Serialization @@ -1408,122 +1431,124 @@ var FigureView = widgets.DOMWidgetView.extend({ * constructors */ var numpy_dtype_to_typedarray_type = { - int8: Int8Array, - int16: Int16Array, - int32: Int32Array, - uint8: Uint8Array, - uint16: Uint16Array, - uint32: Uint32Array, - float32: Float32Array, - float64: Float64Array + int8: Int8Array, + int16: Int16Array, + int32: Int32Array, + uint8: Uint8Array, + uint16: Uint16Array, + uint32: Uint32Array, + float32: Float32Array, + float64: Float64Array, }; function serializeTypedArray(v) { - var numpyType; - if (v instanceof Int8Array) { - numpyType = 'int8'; - } else if (v instanceof Int16Array) { - numpyType = 'int16'; - } else if (v instanceof Int32Array) { - numpyType = 'int32'; - } else if (v instanceof Uint8Array) { - numpyType = 'uint8'; - } else if (v instanceof Uint16Array) { - numpyType = 'uint16'; - } else if (v instanceof Uint32Array) { - numpyType = 'uint32'; - } else if (v instanceof Float32Array) { - numpyType = 'float32'; - } else if (v instanceof Float64Array) { - numpyType = 'float64'; - } else { - // Don't understand it, return as is - return v; - } - var res = { - dtype: numpyType, - shape: [v.length], - value: v.buffer - }; - return res + var numpyType; + if (v instanceof Int8Array) { + numpyType = "int8"; + } else if (v instanceof Int16Array) { + numpyType = "int16"; + } else if (v instanceof Int32Array) { + numpyType = "int32"; + } else if (v instanceof Uint8Array) { + numpyType = "uint8"; + } else if (v instanceof Uint16Array) { + numpyType = "uint16"; + } else if (v instanceof Uint32Array) { + numpyType = "uint32"; + } else if (v instanceof Float32Array) { + numpyType = "float32"; + } else if (v instanceof Float64Array) { + numpyType = "float64"; + } else { + // Don't understand it, return as is + return v; + } + var res = { + dtype: numpyType, + shape: [v.length], + value: v.buffer, + }; + return res; } /** * ipywidget JavaScript -> Python serializer */ function js2py_serializer(v, widgetManager) { - var res; - - if (_.isTypedArray(v)) { - res = serializeTypedArray(v); - } else if (Array.isArray(v)) { - // Serialize array elements recursively - res = new Array(v.length); - for (var i = 0; i < v.length; i++) { - res[i] = js2py_serializer(v[i]); - } - } else if (_.isPlainObject(v)) { - // Serialize object properties recursively - res = {}; - for (var p in v) { - if (v.hasOwnProperty(p)) { - res[p] = js2py_serializer(v[p]); - } - } - } else if (v === undefined) { - // Translate undefined into '_undefined_' sentinal string. The - // Python _js_to_py deserializer will convert this into an - // Undefined object - res = "_undefined_"; - } else { - // Primitive value to transfer directly - res = v; + var res; + + if (_.isTypedArray(v)) { + res = serializeTypedArray(v); + } else if (Array.isArray(v)) { + // Serialize array elements recursively + res = new Array(v.length); + for (var i = 0; i < v.length; i++) { + res[i] = js2py_serializer(v[i]); } - return res + } else if (_.isPlainObject(v)) { + // Serialize object properties recursively + res = {}; + for (var p in v) { + if (v.hasOwnProperty(p)) { + res[p] = js2py_serializer(v[p]); + } + } + } else if (v === undefined) { + // Translate undefined into '_undefined_' sentinal string. The + // Python _js_to_py deserializer will convert this into an + // Undefined object + res = "_undefined_"; + } else { + // Primitive value to transfer directly + res = v; + } + return res; } /** * ipywidget Python -> Javascript deserializer */ function py2js_deserializer(v, widgetManager) { - var res; + var res; - if (Array.isArray(v)) { - // Deserialize array elements recursively - res = new Array(v.length); - for (var i = 0; i < v.length; i++) { - res[i] = py2js_deserializer(v[i]); - } - } else if (_.isPlainObject(v)) { - if ((_.has(v, 'value') || _.has(v, 'buffer')) && - _.has(v, 'dtype') && - _.has(v, 'shape')) { - // Deserialize special buffer/dtype/shape objects into typed arrays - // These objects correspond to numpy arrays on the Python side - // - // Note plotly.py<=3.1.1 called the buffer object `buffer` - // This was renamed `value` in 3.2 to work around a naming conflict - // when saving widget state to a notebook. - var typedarray_type = numpy_dtype_to_typedarray_type[v.dtype]; - var buffer = _.has(v, 'value')? v.value.buffer: v.buffer.buffer; - res = new typedarray_type(buffer); - } else { - // Deserialize object properties recursively - res = {}; - for (var p in v) { - if (v.hasOwnProperty(p)) { - res[p] = py2js_deserializer(v[p]); - } - } - } - } else if (v === "_undefined_") { - // Convert the _undefined_ sentinal into undefined - res = undefined; + if (Array.isArray(v)) { + // Deserialize array elements recursively + res = new Array(v.length); + for (var i = 0; i < v.length; i++) { + res[i] = py2js_deserializer(v[i]); + } + } else if (_.isPlainObject(v)) { + if ( + (_.has(v, "value") || _.has(v, "buffer")) && + _.has(v, "dtype") && + _.has(v, "shape") + ) { + // Deserialize special buffer/dtype/shape objects into typed arrays + // These objects correspond to numpy arrays on the Python side + // + // Note plotly.py<=3.1.1 called the buffer object `buffer` + // This was renamed `value` in 3.2 to work around a naming conflict + // when saving widget state to a notebook. + var typedarray_type = numpy_dtype_to_typedarray_type[v.dtype]; + var buffer = _.has(v, "value") ? v.value.buffer : v.buffer.buffer; + res = new typedarray_type(buffer); } else { - // Accept primitive value directly - res = v; + // Deserialize object properties recursively + res = {}; + for (var p in v) { + if (v.hasOwnProperty(p)) { + res[p] = py2js_deserializer(v[p]); + } + } } - return res + } else if (v === "_undefined_") { + // Convert the _undefined_ sentinal into undefined + res = undefined; + } else { + // Accept primitive value directly + res = v; + } + return res; } /** @@ -1533,8 +1558,10 @@ function py2js_deserializer(v, widgetManager) { * @returns {boolean} */ function isTypedArray(potentialTypedArray) { - return ArrayBuffer.isView(potentialTypedArray) && - !(potentialTypedArray instanceof DataView); + return ( + ArrayBuffer.isView(potentialTypedArray) && + !(potentialTypedArray instanceof DataView) + ); } /** @@ -1546,13 +1573,13 @@ function isTypedArray(potentialTypedArray) { * See: https://lodash.com/docs/latest#mergeWith */ function fullMergeCustomizer(objValue, srcValue, key) { - if (key[0] === '_') { - // Don't recurse into private properties - return null - } else if (isTypedArray(srcValue)) { - // Return typed arrays directly, don't recurse inside - return srcValue - } + if (key[0] === "_") { + // Don't recurse into private properties + return null; + } else if (isTypedArray(srcValue)) { + // Return typed arrays directly, don't recurse inside + return srcValue; + } } /** @@ -1578,22 +1605,22 @@ function fullMergeCustomizer(objValue, srcValue, key) { * */ function performRelayoutLike(parentObj, relayoutData) { - // Perform a relayout style operation on a given parent object - for (var rawKey in relayoutData) { - if (!relayoutData.hasOwnProperty(rawKey)) { - continue - } + // Perform a relayout style operation on a given parent object + for (var rawKey in relayoutData) { + if (!relayoutData.hasOwnProperty(rawKey)) { + continue; + } - // Extract value for this key - var relayoutVal = relayoutData[rawKey]; + // Extract value for this key + var relayoutVal = relayoutData[rawKey]; - // Set property value - if (relayoutVal === null) { - _.unset(parentObj, rawKey); - } else { - _.set(parentObj, rawKey, relayoutVal); - } + // Set property value + if (relayoutVal === null) { + _.unset(parentObj, rawKey); + } else { + _.set(parentObj, rawKey, relayoutVal); } + } } /** @@ -1621,34 +1648,35 @@ function performRelayoutLike(parentObj, relayoutData) { * */ function performRestyleLike(parentArray, restyleData, restyleTraces) { - // Loop over the properties of restyleData - for (var rawKey in restyleData) { - if (!restyleData.hasOwnProperty(rawKey)) { continue } - - // Extract value for property and normalize into a value list - var valArray = restyleData[rawKey]; - if (!Array.isArray(valArray)) { - valArray = [valArray] - } - - // Loop over the indexes of the traces being restyled - for (var i = 0; i < restyleTraces.length; i++) { - - // Get trace object - var traceInd = restyleTraces[i]; - var trace = parentArray[traceInd]; + // Loop over the properties of restyleData + for (var rawKey in restyleData) { + if (!restyleData.hasOwnProperty(rawKey)) { + continue; + } - // Extract value for this trace - var singleVal = valArray[i % valArray.length]; + // Extract value for property and normalize into a value list + var valArray = restyleData[rawKey]; + if (!Array.isArray(valArray)) { + valArray = [valArray]; + } - // Set property value - if (singleVal === null) { - _.unset(trace, rawKey); - } else if (singleVal !== undefined){ - _.set(trace, rawKey, singleVal); - } - } + // Loop over the indexes of the traces being restyled + for (var i = 0; i < restyleTraces.length; i++) { + // Get trace object + var traceInd = restyleTraces[i]; + var trace = parentArray[traceInd]; + + // Extract value for this trace + var singleVal = valArray[i % valArray.length]; + + // Set property value + if (singleVal === null) { + _.unset(trace, rawKey); + } else if (singleVal !== undefined) { + _.set(trace, rawKey, singleVal); + } } + } } /** @@ -1671,28 +1699,28 @@ function performRestyleLike(parentArray, restyleData, restyleTraces) { * d -> [{foo: 1}, {foo: 0}, {foo: 2}] */ function performMoveTracesLike(parentArray, currentInds, newInds) { - - // ### Remove by currentInds in reverse order ### - var movingTracesData = []; - for (var ci = currentInds.length - 1; ci >= 0; ci--) { - // Insert moving parentArray at beginning of the list - movingTracesData.splice(0, 0, parentArray[currentInds[ci]]); - parentArray.splice(currentInds[ci], 1); - } - - // ### Sort newInds and movingTracesData by newInds ### - var newIndexSortedArrays = _(newInds).zip(movingTracesData) - .sortBy(0) - .unzip() - .value(); - - newInds = newIndexSortedArrays[0]; - movingTracesData = newIndexSortedArrays[1]; - - // ### Insert by newInds in forward order ### - for (var ni = 0; ni < newInds.length; ni++) { - parentArray.splice(newInds[ni], 0, movingTracesData[ni]); - } + // ### Remove by currentInds in reverse order ### + var movingTracesData = []; + for (var ci = currentInds.length - 1; ci >= 0; ci--) { + // Insert moving parentArray at beginning of the list + movingTracesData.splice(0, 0, parentArray[currentInds[ci]]); + parentArray.splice(currentInds[ci], 1); + } + + // ### Sort newInds and movingTracesData by newInds ### + var newIndexSortedArrays = _(newInds) + .zip(movingTracesData) + .sortBy(0) + .unzip() + .value(); + + newInds = newIndexSortedArrays[0]; + movingTracesData = newIndexSortedArrays[1]; + + // ### Insert by newInds in forward order ### + for (var ni = 0; ni < newInds.length; ni++) { + parentArray.splice(newInds[ni], 0, movingTracesData[ni]); + } } /** @@ -1715,14 +1743,12 @@ function performMoveTracesLike(parentArray, currentInds, newInds) { * */ function performRemoveProps(parentObj, keyPaths) { - - for(var i=0; i < keyPaths.length; i++) { - var keyPath = keyPaths[i]; - _.unset(parentObj, keyPath); - } + for (var i = 0; i < keyPaths.length; i++) { + var keyPath = keyPaths[i]; + _.unset(parentObj, keyPath); + } } - /** * Return object that contains all properties in fullObj that are not * identical to the corresponding properties in removeObj @@ -1752,125 +1778,119 @@ function performRemoveProps(parentObj, keyPaths) { * */ function createDeltaObject(fullObj, removeObj) { - - // Initialize result as object or array - var res; - if(Array.isArray(fullObj)) { - res = new Array(fullObj.length); - } else { - res = {}; - } - - // Initialize removeObj to empty object if not specified - if (removeObj === null || removeObj === undefined) { - removeObj = {}; - } - - // Iterate over object properties or array indices - for (var p in fullObj) { - if (p[0] !== "_" && // Don't consider private properties - fullObj.hasOwnProperty(p) && // Exclude parent properties - fullObj[p] !== null // Exclude cases where fullObj doesn't - // have the property - ) { - // Compute object equality - var props_equal; - props_equal = _.isEqual(fullObj[p], removeObj[p]); - - // Perform recursive comparison if props are not equal - if (!props_equal || p === "uid") { // Let uids through - - // property has non-null value in fullObj that doesn't - // match the value in removeObj - var fullVal = fullObj[p]; - if (removeObj.hasOwnProperty(p) && - typeof fullVal === "object") { - // Recurse over object properties - if(Array.isArray(fullVal)) { - - if (fullVal.length > 0 && - typeof(fullVal[0]) === "object") { - // We have an object array - res[p] = new Array(fullVal.length); - for (var i = 0; i < fullVal.length; i++) { - if (!Array.isArray(removeObj[p]) || - removeObj[p].length <= i) { - - res[p][i] = fullVal[i] - } else { - res[p][i] = createDeltaObject(fullVal[i], - removeObj[p][i]); - } - } - } else { - // We have a primitive array or typed array - res[p] = fullVal; - } - } else { // object - var full_obj = createDeltaObject(fullVal, - removeObj[p]); - if (Object.keys(full_obj).length > 0) { - // new object is not empty - res[p] = full_obj; - } - } - } else if (typeof fullVal === "object" && - !Array.isArray(fullVal)) { - // Return 'clone' of fullVal - // We don't use a standard clone method so that we keep - // the special case handling of this method - res[p] = createDeltaObject(fullVal, {}); - - } else if (fullVal !== undefined && - typeof fullVal !== 'function') { - // No recursion necessary, Just keep value from fullObj. - // But skip values with function type - res[p] = fullVal; + // Initialize result as object or array + var res; + if (Array.isArray(fullObj)) { + res = new Array(fullObj.length); + } else { + res = {}; + } + + // Initialize removeObj to empty object if not specified + if (removeObj === null || removeObj === undefined) { + removeObj = {}; + } + + // Iterate over object properties or array indices + for (var p in fullObj) { + if ( + p[0] !== "_" && // Don't consider private properties + fullObj.hasOwnProperty(p) && // Exclude parent properties + fullObj[p] !== null // Exclude cases where fullObj doesn't + // have the property + ) { + // Compute object equality + var props_equal; + props_equal = _.isEqual(fullObj[p], removeObj[p]); + + // Perform recursive comparison if props are not equal + if (!props_equal || p === "uid") { + // Let uids through + + // property has non-null value in fullObj that doesn't + // match the value in removeObj + var fullVal = fullObj[p]; + if (removeObj.hasOwnProperty(p) && typeof fullVal === "object") { + // Recurse over object properties + if (Array.isArray(fullVal)) { + if (fullVal.length > 0 && typeof fullVal[0] === "object") { + // We have an object array + res[p] = new Array(fullVal.length); + for (var i = 0; i < fullVal.length; i++) { + if (!Array.isArray(removeObj[p]) || removeObj[p].length <= i) { + res[p][i] = fullVal[i]; + } else { + res[p][i] = createDeltaObject(fullVal[i], removeObj[p][i]); } + } + } else { + // We have a primitive array or typed array + res[p] = fullVal; } + } else { + // object + var full_obj = createDeltaObject(fullVal, removeObj[p]); + if (Object.keys(full_obj).length > 0) { + // new object is not empty + res[p] = full_obj; + } + } + } else if (typeof fullVal === "object" && !Array.isArray(fullVal)) { + // Return 'clone' of fullVal + // We don't use a standard clone method so that we keep + // the special case handling of this method + res[p] = createDeltaObject(fullVal, {}); + } else if (fullVal !== undefined && typeof fullVal !== "function") { + // No recursion necessary, Just keep value from fullObj. + // But skip values with function type + res[p] = fullVal; } + } } - return res + } + return res; } function randstr(existing, bits, base, _recursion) { - if(!base) base = 16; - if(bits === undefined) bits = 24; - if(bits <= 0) return '0'; - - var digits = Math.log(Math.pow(2, bits)) / Math.log(base); - var res = ''; - var i, b, x; - - for(i = 2; digits === Infinity; i *= 2) { - digits = Math.log(Math.pow(2, bits / i)) / Math.log(base) * i; - } - - var rem = digits - Math.floor(digits); - - for(i = 0; i < Math.floor(digits); i++) { - x = Math.floor(Math.random() * base).toString(base); - res = x + res; - } - - if(rem) { - b = Math.pow(base, rem); - x = Math.floor(Math.random() * b).toString(base); - res = x + res; + if (!base) base = 16; + if (bits === undefined) bits = 24; + if (bits <= 0) return "0"; + + var digits = Math.log(Math.pow(2, bits)) / Math.log(base); + var res = ""; + var i, b, x; + + for (i = 2; digits === Infinity; i *= 2) { + digits = (Math.log(Math.pow(2, bits / i)) / Math.log(base)) * i; + } + + var rem = digits - Math.floor(digits); + + for (i = 0; i < Math.floor(digits); i++) { + x = Math.floor(Math.random() * base).toString(base); + res = x + res; + } + + if (rem) { + b = Math.pow(base, rem); + x = Math.floor(Math.random() * b).toString(base); + res = x + res; + } + + var parsed = parseInt(res, base); + if ( + (existing && existing[res]) || + (parsed !== Infinity && parsed >= Math.pow(2, bits)) + ) { + if (_recursion > 10) { + lib.warn("randstr failed uniqueness"); + return res; } - - var parsed = parseInt(res, base); - if((existing && existing[res]) || - (parsed !== Infinity && parsed >= Math.pow(2, bits))) { - if(_recursion > 10) { - lib.warn('randstr failed uniqueness'); - return res; - } - return randstr(existing, bits, base, (_recursion || 0) + 1); - } else return res; + return randstr(existing, bits, base, (_recursion || 0) + 1); + } else return res; } module.exports = { - FigureView : FigureView, - FigureModel: FigureModel + FigureView: FigureView, + FigureModel: FigureModel, };