@datalayer/jupyter-react 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (297) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +56 -0
  3. package/lib/examples/Example.d.ts +1 -0
  4. package/lib/examples/Example.js +8 -0
  5. package/lib/examples/Example.js.map +1 -0
  6. package/lib/examples/MuiSetup.d.ts +5 -0
  7. package/lib/examples/MuiSetup.js +13 -0
  8. package/lib/examples/MuiSetup.js.map +1 -0
  9. package/lib/examples/bootstrap/All.bootstrap.d.ts +1 -0
  10. package/lib/examples/bootstrap/All.bootstrap.js +84 -0
  11. package/lib/examples/bootstrap/All.bootstrap.js.map +1 -0
  12. package/lib/examples/bootstrap/Cell.bootstrap.d.ts +1 -0
  13. package/lib/examples/bootstrap/Cell.bootstrap.js +12 -0
  14. package/lib/examples/bootstrap/Cell.bootstrap.js.map +1 -0
  15. package/lib/examples/bootstrap/FileBrowser.bootstrap.d.ts +1 -0
  16. package/lib/examples/bootstrap/FileBrowser.bootstrap.js +10 -0
  17. package/lib/examples/bootstrap/FileBrowser.bootstrap.js.map +1 -0
  18. package/lib/examples/bootstrap/Gallery.bootstrap.d.ts +1 -0
  19. package/lib/examples/bootstrap/Gallery.bootstrap.js +18 -0
  20. package/lib/examples/bootstrap/Gallery.bootstrap.js.map +1 -0
  21. package/lib/examples/bootstrap/IPyWidgets.bootstrap.d.ts +1 -0
  22. package/lib/examples/bootstrap/IPyWidgets.bootstrap.js +12 -0
  23. package/lib/examples/bootstrap/IPyWidgets.bootstrap.js.map +1 -0
  24. package/lib/examples/bootstrap/Lumino.bootstrap.d.ts +1 -0
  25. package/lib/examples/bootstrap/Lumino.bootstrap.js +11 -0
  26. package/lib/examples/bootstrap/Lumino.bootstrap.js.map +1 -0
  27. package/lib/examples/bootstrap/Notebook.bootstrap.d.ts +1 -0
  28. package/lib/examples/bootstrap/Notebook.bootstrap.js +22 -0
  29. package/lib/examples/bootstrap/Notebook.bootstrap.js.map +1 -0
  30. package/lib/examples/bootstrap/NotebookCustom.bootstrap.d.ts +1 -0
  31. package/lib/examples/bootstrap/NotebookCustom.bootstrap.js +7 -0
  32. package/lib/examples/bootstrap/NotebookCustom.bootstrap.js.map +1 -0
  33. package/lib/examples/bootstrap/Outputs.bootstrap.d.ts +1 -0
  34. package/lib/examples/bootstrap/Outputs.bootstrap.js +154 -0
  35. package/lib/examples/bootstrap/Outputs.bootstrap.js.map +1 -0
  36. package/lib/examples/bootstrap/Terminal.bootstrap.d.ts +1 -0
  37. package/lib/examples/bootstrap/Terminal.bootstrap.js +13 -0
  38. package/lib/examples/bootstrap/Terminal.bootstrap.js.map +1 -0
  39. package/lib/examples/controls/CellControl.d.ts +3 -0
  40. package/lib/examples/controls/CellControl.js +15 -0
  41. package/lib/examples/controls/CellControl.js.map +1 -0
  42. package/lib/examples/controls/CommandsControl.d.ts +3 -0
  43. package/lib/examples/controls/CommandsControl.js +12 -0
  44. package/lib/examples/controls/CommandsControl.js.map +1 -0
  45. package/lib/examples/controls/ConsoleControl.d.ts +3 -0
  46. package/lib/examples/controls/ConsoleControl.js +12 -0
  47. package/lib/examples/controls/ConsoleControl.js.map +1 -0
  48. package/lib/examples/controls/DialogControl.d.ts +2 -0
  49. package/lib/examples/controls/DialogControl.js +7 -0
  50. package/lib/examples/controls/DialogControl.js.map +1 -0
  51. package/lib/examples/controls/FileBrowserControl.d.ts +3 -0
  52. package/lib/examples/controls/FileBrowserControl.js +12 -0
  53. package/lib/examples/controls/FileBrowserControl.js.map +1 -0
  54. package/lib/examples/controls/InitControl.d.ts +2 -0
  55. package/lib/examples/controls/InitControl.js +7 -0
  56. package/lib/examples/controls/InitControl.js.map +1 -0
  57. package/lib/examples/controls/NotebookControl.d.ts +3 -0
  58. package/lib/examples/controls/NotebookControl.js +16 -0
  59. package/lib/examples/controls/NotebookControl.js.map +1 -0
  60. package/lib/examples/controls/OutputControl.d.ts +3 -0
  61. package/lib/examples/controls/OutputControl.js +7 -0
  62. package/lib/examples/controls/OutputControl.js.map +1 -0
  63. package/lib/examples/controls/SettingsControl.d.ts +3 -0
  64. package/lib/examples/controls/SettingsControl.js +12 -0
  65. package/lib/examples/controls/SettingsControl.js.map +1 -0
  66. package/lib/examples/controls/SimpleControl.d.ts +2 -0
  67. package/lib/examples/controls/SimpleControl.js +7 -0
  68. package/lib/examples/controls/SimpleControl.js.map +1 -0
  69. package/lib/examples/controls/TerminalControl.d.ts +3 -0
  70. package/lib/examples/controls/TerminalControl.js +22 -0
  71. package/lib/examples/controls/TerminalControl.js.map +1 -0
  72. package/lib/examples/examples/cell/CellExample.d.ts +2 -0
  73. package/lib/examples/examples/cell/CellExample.js +42 -0
  74. package/lib/examples/examples/cell/CellExample.js.map +1 -0
  75. package/lib/examples/examples/gallery/GalleryExample.d.ts +2 -0
  76. package/lib/examples/examples/gallery/GalleryExample.js +154 -0
  77. package/lib/examples/examples/gallery/GalleryExample.js.map +1 -0
  78. package/lib/examples/examples/ipywidgets/IpyWidgetsExample.d.ts +4 -0
  79. package/lib/examples/examples/ipywidgets/IpyWidgetsExample.js +156 -0
  80. package/lib/examples/examples/ipywidgets/IpyWidgetsExample.js.map +1 -0
  81. package/lib/examples/examples/lumino/LuminoAdapter.css +34 -0
  82. package/lib/examples/examples/lumino/LuminoAdapter.d.ts +9 -0
  83. package/lib/examples/examples/lumino/LuminoAdapter.js +70 -0
  84. package/lib/examples/examples/lumino/LuminoAdapter.js.map +1 -0
  85. package/lib/examples/examples/lumino/LuminoExample.d.ts +2 -0
  86. package/lib/examples/examples/lumino/LuminoExample.js +10 -0
  87. package/lib/examples/examples/lumino/LuminoExample.js.map +1 -0
  88. package/lib/examples/examples/notebook/NotebookCustomHeader.d.ts +2 -0
  89. package/lib/examples/examples/notebook/NotebookCustomHeader.js +39 -0
  90. package/lib/examples/examples/notebook/NotebookCustomHeader.js.map +1 -0
  91. package/lib/examples/examples/notebook/NotebookExample.d.ts +1 -0
  92. package/lib/examples/examples/notebook/NotebookExample.js +24 -0
  93. package/lib/examples/examples/notebook/NotebookExample.js.map +1 -0
  94. package/lib/examples/theme/Layers.d.ts +2 -0
  95. package/lib/examples/theme/Layers.js +15 -0
  96. package/lib/examples/theme/Layers.js.map +1 -0
  97. package/lib/examples/theme/Layers.svg +14 -0
  98. package/lib/examples/theme/muiLightTheme.d.ts +8 -0
  99. package/lib/examples/theme/muiLightTheme.js +169 -0
  100. package/lib/examples/theme/muiLightTheme.js.map +1 -0
  101. package/lib/examples/theme/vintage.project.json +172 -0
  102. package/lib/examples/theme/westeros.project.json +168 -0
  103. package/lib/examples/theme/wonderland.project.json +168 -0
  104. package/lib/index.d.ts +31 -0
  105. package/lib/index.js +45 -0
  106. package/lib/index.js.map +1 -0
  107. package/lib/ipywidgets/IPyWidgetsAttached.d.ts +8 -0
  108. package/lib/ipywidgets/IPyWidgetsAttached.js +15 -0
  109. package/lib/ipywidgets/IPyWidgetsAttached.js.map +1 -0
  110. package/lib/ipywidgets/IPyWidgetsClassicManager.d.ts +18 -0
  111. package/lib/ipywidgets/IPyWidgetsClassicManager.js +76 -0
  112. package/lib/ipywidgets/IPyWidgetsClassicManager.js.map +1 -0
  113. package/lib/ipywidgets/IPyWidgetsJupyterLabPlugin.d.ts +15 -0
  114. package/lib/ipywidgets/IPyWidgetsJupyterLabPlugin.js +178 -0
  115. package/lib/ipywidgets/IPyWidgetsJupyterLabPlugin.js.map +1 -0
  116. package/lib/ipywidgets/IpyWidgetsComponent.d.ts +4 -0
  117. package/lib/ipywidgets/IpyWidgetsComponent.js +9 -0
  118. package/lib/ipywidgets/IpyWidgetsComponent.js.map +1 -0
  119. package/lib/ipywidgets/IpyWidgetsManager.d.ts +11 -0
  120. package/lib/ipywidgets/IpyWidgetsManager.js +71 -0
  121. package/lib/ipywidgets/IpyWidgetsManager.js.map +1 -0
  122. package/lib/ipywidgets/plotly/Figure.d.ts +587 -0
  123. package/lib/ipywidgets/plotly/Figure.js +1697 -0
  124. package/lib/ipywidgets/plotly/Figure.js.map +1 -0
  125. package/lib/ipywidgets/plotly/index.d.ts +2 -0
  126. package/lib/ipywidgets/plotly/index.js +4 -0
  127. package/lib/ipywidgets/plotly/index.js.map +1 -0
  128. package/lib/ipywidgets/plotly/jupyterlab-plugin.d.ts +5 -0
  129. package/lib/ipywidgets/plotly/jupyterlab-plugin.js +12 -0
  130. package/lib/ipywidgets/plotly/jupyterlab-plugin.js.map +1 -0
  131. package/lib/ipywidgets/plotly/version.d.ts +8 -0
  132. package/lib/ipywidgets/plotly/version.js +16 -0
  133. package/lib/ipywidgets/plotly/version.js.map +1 -0
  134. package/lib/jupyter/AuthError.d.ts +7 -0
  135. package/lib/jupyter/AuthError.js +8 -0
  136. package/lib/jupyter/AuthError.js.map +1 -0
  137. package/lib/jupyter/Handlers.d.ts +8 -0
  138. package/lib/jupyter/Handlers.js +50 -0
  139. package/lib/jupyter/Handlers.js.map +1 -0
  140. package/lib/jupyter/Jupyter.d.ts +23 -0
  141. package/lib/jupyter/Jupyter.js +35 -0
  142. package/lib/jupyter/Jupyter.js.map +1 -0
  143. package/lib/jupyter/JupyterConfig.d.ts +37 -0
  144. package/lib/jupyter/JupyterConfig.js +59 -0
  145. package/lib/jupyter/JupyterConfig.js.map +1 -0
  146. package/lib/jupyter/JupyterContext.d.ts +35 -0
  147. package/lib/jupyter/JupyterContext.js +64 -0
  148. package/lib/jupyter/JupyterContext.js.map +1 -0
  149. package/lib/lumino/LuminoAttached.d.ts +9 -0
  150. package/lib/lumino/LuminoAttached.js +23 -0
  151. package/lib/lumino/LuminoAttached.js.map +1 -0
  152. package/lib/lumino/LuminoDetached.d.ts +9 -0
  153. package/lib/lumino/LuminoDetached.js +13 -0
  154. package/lib/lumino/LuminoDetached.js.map +1 -0
  155. package/lib/lumino/LuminoObservable.d.ts +6 -0
  156. package/lib/lumino/LuminoObservable.js +16 -0
  157. package/lib/lumino/LuminoObservable.js.map +1 -0
  158. package/lib/lumino/LuminoReactPortal.d.ts +180 -0
  159. package/lib/lumino/LuminoReactPortal.js +195 -0
  160. package/lib/lumino/LuminoReactPortal.js.map +1 -0
  161. package/lib/lumino/LuminoRedux.d.ts +8 -0
  162. package/lib/lumino/LuminoRedux.js +2 -0
  163. package/lib/lumino/LuminoRedux.js.map +1 -0
  164. package/lib/services/Services.d.ts +17 -0
  165. package/lib/services/Services.js +41 -0
  166. package/lib/services/Services.js.map +1 -0
  167. package/lib/services/kernel/Kernel.d.ts +18 -0
  168. package/lib/services/kernel/Kernel.js +95 -0
  169. package/lib/services/kernel/Kernel.js.map +1 -0
  170. package/lib/services/kernel/KernelModel.d.ts +18 -0
  171. package/lib/services/kernel/KernelModel.js +52 -0
  172. package/lib/services/kernel/KernelModel.js.map +1 -0
  173. package/lib/state/AllState.d.ts +8 -0
  174. package/lib/state/AllState.js +24 -0
  175. package/lib/state/AllState.js.map +1 -0
  176. package/lib/state/InjectableStore.d.ts +9 -0
  177. package/lib/state/InjectableStore.js +27 -0
  178. package/lib/state/InjectableStore.js.map +1 -0
  179. package/lib/state/init/Init.d.ts +3 -0
  180. package/lib/state/init/Init.js +12 -0
  181. package/lib/state/init/Init.js.map +1 -0
  182. package/lib/state/init/InitRedux.d.ts +21 -0
  183. package/lib/state/init/InitRedux.js +50 -0
  184. package/lib/state/init/InitRedux.js.map +1 -0
  185. package/lib/widgets/cell/CellAdapter.css +16 -0
  186. package/lib/widgets/cell/CellAdapter.d.ts +18 -0
  187. package/lib/widgets/cell/CellAdapter.js +160 -0
  188. package/lib/widgets/cell/CellAdapter.js.map +1 -0
  189. package/lib/widgets/cell/CellLumino.d.ts +9 -0
  190. package/lib/widgets/cell/CellLumino.js +48 -0
  191. package/lib/widgets/cell/CellLumino.js.map +1 -0
  192. package/lib/widgets/cell/CellState.d.ts +22 -0
  193. package/lib/widgets/cell/CellState.js +79 -0
  194. package/lib/widgets/cell/CellState.js.map +1 -0
  195. package/lib/widgets/commands/CommandsAdapter.css +3 -0
  196. package/lib/widgets/commands/CommandsAdapter.d.ts +9 -0
  197. package/lib/widgets/commands/CommandsAdapter.js +36 -0
  198. package/lib/widgets/commands/CommandsAdapter.js.map +1 -0
  199. package/lib/widgets/commands/CommandsLumino.d.ts +2 -0
  200. package/lib/widgets/commands/CommandsLumino.js +9 -0
  201. package/lib/widgets/commands/CommandsLumino.js.map +1 -0
  202. package/lib/widgets/commands/CommandsState.d.ts +19 -0
  203. package/lib/widgets/commands/CommandsState.js +50 -0
  204. package/lib/widgets/commands/CommandsState.js.map +1 -0
  205. package/lib/widgets/console/ConsoleAdapter.css +4 -0
  206. package/lib/widgets/console/ConsoleAdapter.d.ts +11 -0
  207. package/lib/widgets/console/ConsoleAdapter.js +82 -0
  208. package/lib/widgets/console/ConsoleAdapter.js.map +1 -0
  209. package/lib/widgets/console/ConsoleLumino.d.ts +2 -0
  210. package/lib/widgets/console/ConsoleLumino.js +9 -0
  211. package/lib/widgets/console/ConsoleLumino.js.map +1 -0
  212. package/lib/widgets/console/ConsoleState.d.ts +19 -0
  213. package/lib/widgets/console/ConsoleState.js +50 -0
  214. package/lib/widgets/console/ConsoleState.js.map +1 -0
  215. package/lib/widgets/dialog/DialogAdapter.css +0 -0
  216. package/lib/widgets/dialog/DialogAdapter.d.ts +10 -0
  217. package/lib/widgets/dialog/DialogAdapter.js +19 -0
  218. package/lib/widgets/dialog/DialogAdapter.js.map +1 -0
  219. package/lib/widgets/dialog/DialogLumino.d.ts +2 -0
  220. package/lib/widgets/dialog/DialogLumino.js +13 -0
  221. package/lib/widgets/dialog/DialogLumino.js.map +1 -0
  222. package/lib/widgets/editor/CodeMirrorEditor.d.ts +7 -0
  223. package/lib/widgets/editor/CodeMirrorEditor.js +62 -0
  224. package/lib/widgets/editor/CodeMirrorEditor.js.map +1 -0
  225. package/lib/widgets/filebrowser/FileBrowser.d.ts +2 -0
  226. package/lib/widgets/filebrowser/FileBrowser.js +60 -0
  227. package/lib/widgets/filebrowser/FileBrowser.js.map +1 -0
  228. package/lib/widgets/filebrowser/FileBrowserAdapter.css +8 -0
  229. package/lib/widgets/filebrowser/FileBrowserAdapter.d.ts +13 -0
  230. package/lib/widgets/filebrowser/FileBrowserAdapter.js +267 -0
  231. package/lib/widgets/filebrowser/FileBrowserAdapter.js.map +1 -0
  232. package/lib/widgets/filebrowser/FileBrowserLumino.d.ts +2 -0
  233. package/lib/widgets/filebrowser/FileBrowserLumino.js +9 -0
  234. package/lib/widgets/filebrowser/FileBrowserLumino.js.map +1 -0
  235. package/lib/widgets/filebrowser/FileBrowserState.d.ts +19 -0
  236. package/lib/widgets/filebrowser/FileBrowserState.js +50 -0
  237. package/lib/widgets/filebrowser/FileBrowserState.js.map +1 -0
  238. package/lib/widgets/notebook/NotebookAdapter.css +27 -0
  239. package/lib/widgets/notebook/NotebookAdapter.d.ts +26 -0
  240. package/lib/widgets/notebook/NotebookAdapter.js +187 -0
  241. package/lib/widgets/notebook/NotebookAdapter.js.map +1 -0
  242. package/lib/widgets/notebook/NotebookCommands.d.ts +7 -0
  243. package/lib/widgets/notebook/NotebookCommands.js +349 -0
  244. package/lib/widgets/notebook/NotebookCommands.js.map +1 -0
  245. package/lib/widgets/notebook/NotebookLumino.d.ts +19 -0
  246. package/lib/widgets/notebook/NotebookLumino.js +75 -0
  247. package/lib/widgets/notebook/NotebookLumino.js.map +1 -0
  248. package/lib/widgets/notebook/NotebookState.d.ts +43 -0
  249. package/lib/widgets/notebook/NotebookState.js +114 -0
  250. package/lib/widgets/notebook/NotebookState.js.map +1 -0
  251. package/lib/widgets/notebook/NotebookToolbar.d.ts +2 -0
  252. package/lib/widgets/notebook/NotebookToolbar.js +24 -0
  253. package/lib/widgets/notebook/NotebookToolbar.js.map +1 -0
  254. package/lib/widgets/notebook/extension/CellSidebar.d.ts +7 -0
  255. package/lib/widgets/notebook/extension/CellSidebar.js +23 -0
  256. package/lib/widgets/notebook/extension/CellSidebar.js.map +1 -0
  257. package/lib/widgets/notebook/extension/CellSidebarDefault.d.ts +2 -0
  258. package/lib/widgets/notebook/extension/CellSidebarDefault.js +47 -0
  259. package/lib/widgets/notebook/extension/CellSidebarDefault.js.map +1 -0
  260. package/lib/widgets/notebook/extension/ContentFactoryWithSidebar.d.ts +14 -0
  261. package/lib/widgets/notebook/extension/ContentFactoryWithSidebar.js +20 -0
  262. package/lib/widgets/notebook/extension/ContentFactoryWithSidebar.js.map +1 -0
  263. package/lib/widgets/notebook/extension/NotebookInputPrompt.d.ts +21 -0
  264. package/lib/widgets/notebook/extension/NotebookInputPrompt.js +67 -0
  265. package/lib/widgets/notebook/extension/NotebookInputPrompt.js.map +1 -0
  266. package/lib/widgets/outputs/OutputAdapter.css +0 -0
  267. package/lib/widgets/outputs/OutputAdapter.d.ts +21 -0
  268. package/lib/widgets/outputs/OutputAdapter.js +75 -0
  269. package/lib/widgets/outputs/OutputAdapter.js.map +1 -0
  270. package/lib/widgets/outputs/OutputLumino.d.ts +16 -0
  271. package/lib/widgets/outputs/OutputLumino.js +56 -0
  272. package/lib/widgets/outputs/OutputLumino.js.map +1 -0
  273. package/lib/widgets/outputs/OutputState.d.ts +19 -0
  274. package/lib/widgets/outputs/OutputState.js +50 -0
  275. package/lib/widgets/outputs/OutputState.js.map +1 -0
  276. package/lib/widgets/settings/SettingsAdapter.css +0 -0
  277. package/lib/widgets/settings/SettingsAdapter.d.ts +10 -0
  278. package/lib/widgets/settings/SettingsAdapter.js +16 -0
  279. package/lib/widgets/settings/SettingsAdapter.js.map +1 -0
  280. package/lib/widgets/settings/SettingsLumino.d.ts +2 -0
  281. package/lib/widgets/settings/SettingsLumino.js +11 -0
  282. package/lib/widgets/settings/SettingsLumino.js.map +1 -0
  283. package/lib/widgets/settings/SettingsState.d.ts +19 -0
  284. package/lib/widgets/settings/SettingsState.js +50 -0
  285. package/lib/widgets/settings/SettingsState.js.map +1 -0
  286. package/lib/widgets/terminal/TerminalAdapter.css +3 -0
  287. package/lib/widgets/terminal/TerminalAdapter.d.ts +13 -0
  288. package/lib/widgets/terminal/TerminalAdapter.js +28 -0
  289. package/lib/widgets/terminal/TerminalAdapter.js.map +1 -0
  290. package/lib/widgets/terminal/TerminalLumino.d.ts +2 -0
  291. package/lib/widgets/terminal/TerminalLumino.js +17 -0
  292. package/lib/widgets/terminal/TerminalLumino.js.map +1 -0
  293. package/lib/widgets/terminal/TerminalState.d.ts +17 -0
  294. package/lib/widgets/terminal/TerminalState.js +45 -0
  295. package/lib/widgets/terminal/TerminalState.js.map +1 -0
  296. package/package.json +163 -0
  297. package/style/index.css +3 -0
@@ -0,0 +1,1697 @@
1
+ import { DOMWidgetModel, DOMWidgetView, } from "@jupyter-widgets/base";
2
+ import _ from "lodash";
3
+ import Plotly from "plotly.js";
4
+ import { MODULE_NAME, MODULE_VERSION } from "./version";
5
+ // @ts-ignore
6
+ window.PlotlyConfig = { MathJaxConfig: "local" };
7
+ const semver_range = "^" + MODULE_VERSION;
8
+ // Model
9
+ // =====
10
+ /**
11
+ * A FigureModel holds a mirror copy of the state of a FigureWidget on
12
+ * the Python side. There is a one-to-one relationship between JavaScript
13
+ * FigureModels and Python FigureWidgets. The JavaScript FigureModel is
14
+ * initialized as soon as a Python FigureWidget initialized, this happens
15
+ * even before the widget is first displayed in the Notebook
16
+ * @type {widgets.DOMWidgetModel}
17
+ */
18
+ export class FigureModel extends DOMWidgetModel {
19
+ defaults() {
20
+ return Object.assign(Object.assign({}, super.defaults()), {
21
+ // Model metadata
22
+ // --------------
23
+ _model_name: FigureModel.model_name, _model_module: FigureModel.model_module, _model_module_version: FigureModel.model_module_version, _view_name: FigureModel.view_name, _view_module: FigureModel.view_module, _view_module_version: FigureModel.view_module_version,
24
+ // Data and Layout
25
+ // ---------------
26
+ // The _data and _layout properties are synchronized with the
27
+ // Python side on initialization only. After initialization, these
28
+ // properties are kept in sync through the use of the _py2js_*
29
+ // messages
30
+ _data: [], _layout: {}, _config: {},
31
+ // Python -> JS messages
32
+ // ---------------------
33
+ // Messages are implemented using trait properties. This is done so
34
+ // that we can take advantage of ipywidget's binary serialization
35
+ // protocol.
36
+ //
37
+ // Messages are sent by the Python side by assigning the message
38
+ // contents to the appropriate _py2js_* property, and then immediately
39
+ // setting it to None. Messages are received by the JavaScript
40
+ // side by registering property change callbacks in the initialize
41
+ // methods for FigureModel and FigureView. e.g. (where this is a
42
+ // FigureModel):
43
+ //
44
+ // this.on('change:_py2js_addTraces', this.do_addTraces, this);
45
+ //
46
+ // Message handling methods, do_addTraces, are responsible for
47
+ // performing the appropriate action if the message contents are
48
+ // not null
49
+ /**
50
+ * @typedef {null|Object} Py2JsAddTracesMsg
51
+ * @property {Array.<Object>} trace_data
52
+ * Array of traces to append to the end of the figure's current traces
53
+ * @property {Number} trace_edit_id
54
+ * Edit ID to use when returning trace deltas using
55
+ * the _js2py_traceDeltas message.
56
+ * @property {Number} layout_edit_id
57
+ * Edit ID to use when returning layout deltas using
58
+ * the _js2py_layoutDelta message.
59
+ */
60
+ _py2js_addTraces: null,
61
+ /**
62
+ * @typedef {null|Object} Py2JsDeleteTracesMsg
63
+ * @property {Array.<Number>} delete_inds
64
+ * Array of indexes of traces to be deleted, in ascending order
65
+ * @property {Number} trace_edit_id
66
+ * Edit ID to use when returning trace deltas using
67
+ * the _js2py_traceDeltas message.
68
+ * @property {Number} layout_edit_id
69
+ * Edit ID to use when returning layout deltas using
70
+ * the _js2py_layoutDelta message.
71
+ */
72
+ _py2js_deleteTraces: null,
73
+ /**
74
+ * @typedef {null|Object} Py2JsMoveTracesMsg
75
+ * @property {Array.<Number>} current_trace_inds
76
+ * Array of the current indexes of traces to be moved
77
+ * @property {Array.<Number>} new_trace_inds
78
+ * Array of the new indexes that traces should be moved to.
79
+ */
80
+ _py2js_moveTraces: null,
81
+ /**
82
+ * @typedef {null|Object} Py2JsRestyleMsg
83
+ * @property {Object} restyle_data
84
+ * Restyle data as accepted by Plotly.restyle
85
+ * @property {null|Array.<Number>} restyle_traces
86
+ * Array of indexes of the traces that the resytle operation applies
87
+ * to, or null to apply the operation to all traces
88
+ * @property {Number} trace_edit_id
89
+ * Edit ID to use when returning trace deltas using
90
+ * the _js2py_traceDeltas message
91
+ * @property {Number} layout_edit_id
92
+ * Edit ID to use when returning layout deltas using
93
+ * the _js2py_layoutDelta message
94
+ * @property {null|String} source_view_id
95
+ * view_id of the FigureView that triggered the original restyle
96
+ * event (e.g. by clicking the legend), or null if the restyle was
97
+ * triggered from Python
98
+ */
99
+ _py2js_restyle: null,
100
+ /**
101
+ * @typedef {null|Object} Py2JsRelayoutMsg
102
+ * @property {Object} relayout_data
103
+ * Relayout data as accepted by Plotly.relayout
104
+ * @property {Number} layout_edit_id
105
+ * Edit ID to use when returning layout deltas using
106
+ * the _js2py_layoutDelta message
107
+ * @property {null|String} source_view_id
108
+ * view_id of the FigureView that triggered the original relayout
109
+ * event (e.g. by clicking the zoom button), or null if the
110
+ * relayout was triggered from Python
111
+ */
112
+ _py2js_relayout: null,
113
+ /**
114
+ * @typedef {null|Object} Py2JsUpdateMsg
115
+ * @property {Object} style_data
116
+ * Style data as accepted by Plotly.update
117
+ * @property {Object} layout_data
118
+ * Layout data as accepted by Plotly.update
119
+ * @property {Array.<Number>} style_traces
120
+ * Array of indexes of the traces that the update operation applies
121
+ * to, or null to apply the operation to all traces
122
+ * @property {Number} trace_edit_id
123
+ * Edit ID to use when returning trace deltas using
124
+ * the _js2py_traceDeltas message
125
+ * @property {Number} layout_edit_id
126
+ * Edit ID to use when returning layout deltas using
127
+ * the _js2py_layoutDelta message
128
+ * @property {null|String} source_view_id
129
+ * view_id of the FigureView that triggered the original update
130
+ * event (e.g. by clicking a button), or null if the update was
131
+ * triggered from Python
132
+ */
133
+ _py2js_update: null,
134
+ /**
135
+ * @typedef {null|Object} Py2JsAnimateMsg
136
+ * @property {Object} style_data
137
+ * Style data as accepted by Plotly.animate
138
+ * @property {Object} layout_data
139
+ * Layout data as accepted by Plotly.animate
140
+ * @property {Array.<Number>} style_traces
141
+ * Array of indexes of the traces that the animate operation applies
142
+ * to, or null to apply the operation to all traces
143
+ * @property {Object} animation_opts
144
+ * Animation options as accepted by Plotly.animate
145
+ * @property {Number} trace_edit_id
146
+ * Edit ID to use when returning trace deltas using
147
+ * the _js2py_traceDeltas message
148
+ * @property {Number} layout_edit_id
149
+ * Edit ID to use when returning layout deltas using
150
+ * the _js2py_layoutDelta message
151
+ * @property {null|String} source_view_id
152
+ * view_id of the FigureView that triggered the original animate
153
+ * event (e.g. by clicking a button), or null if the update was
154
+ * triggered from Python
155
+ */
156
+ _py2js_animate: null,
157
+ /**
158
+ * @typedef {null|Object} Py2JsRemoveLayoutPropsMsg
159
+ * @property {Array.<Array.<String|Number>>} remove_props
160
+ * Array of property paths to remove. Each propery path is an
161
+ * array of property names or array indexes that locate a property
162
+ * inside the _layout object
163
+ */
164
+ _py2js_removeLayoutProps: null,
165
+ /**
166
+ * @typedef {null|Object} Py2JsRemoveTracePropsMsg
167
+ * @property {Number} remove_trace
168
+ * The index of the trace from which to remove properties
169
+ * @property {Array.<Array.<String|Number>>} remove_props
170
+ * Array of property paths to remove. Each propery path is an
171
+ * array of property names or array indexes that locate a property
172
+ * inside the _data[remove_trace] object
173
+ */
174
+ _py2js_removeTraceProps: null,
175
+ // JS -> Python messages
176
+ // ---------------------
177
+ // Messages are sent by the JavaScript side by assigning the
178
+ // message contents to the appropriate _js2py_* property and then
179
+ // calling the `touch` method on the view that triggered the
180
+ // change. e.g. (where this is a FigureView):
181
+ //
182
+ // this.model.set('_js2py_restyle', data);
183
+ // this.touch();
184
+ //
185
+ // The Python side is responsible for setting the property to None
186
+ // after receiving the message.
187
+ //
188
+ // Message trigger logic is described in the corresponding
189
+ // handle_plotly_* methods of FigureView
190
+ /**
191
+ * @typedef {null|Object} Js2PyRestyleMsg
192
+ * @property {Object} style_data
193
+ * Style data that was passed to Plotly.restyle
194
+ * @property {Array.<Number>} style_traces
195
+ * Array of indexes of the traces that the restyle operation
196
+ * was applied to, or null if applied to all traces
197
+ * @property {String} source_view_id
198
+ * view_id of the FigureView that triggered the original restyle
199
+ * event (e.g. by clicking the legend)
200
+ */
201
+ _js2py_restyle: null,
202
+ /**
203
+ * @typedef {null|Object} Js2PyRelayoutMsg
204
+ * @property {Object} relayout_data
205
+ * Relayout data that was passed to Plotly.relayout
206
+ * @property {String} source_view_id
207
+ * view_id of the FigureView that triggered the original relayout
208
+ * event (e.g. by clicking the zoom button)
209
+ */
210
+ _js2py_relayout: null,
211
+ /**
212
+ * @typedef {null|Object} Js2PyUpdateMsg
213
+ * @property {Object} style_data
214
+ * Style data that was passed to Plotly.update
215
+ * @property {Object} layout_data
216
+ * Layout data that was passed to Plotly.update
217
+ * @property {Array.<Number>} style_traces
218
+ * Array of indexes of the traces that the update operation applied
219
+ * to, or null if applied to all traces
220
+ * @property {String} source_view_id
221
+ * view_id of the FigureView that triggered the original relayout
222
+ * event (e.g. by clicking the zoom button)
223
+ */
224
+ _js2py_update: null,
225
+ /**
226
+ * @typedef {null|Object} Js2PyLayoutDeltaMsg
227
+ * @property {Object} layout_delta
228
+ * The layout delta object that contains all of the properties of
229
+ * _fullLayout that are not identical to those in the
230
+ * FigureModel's _layout property
231
+ * @property {Number} layout_edit_id
232
+ * Edit ID of message that triggered the creation of layout delta
233
+ */
234
+ _js2py_layoutDelta: null,
235
+ /**
236
+ * @typedef {null|Object} Js2PyTraceDeltasMsg
237
+ * @property {Array.<Object>} trace_deltas
238
+ * Array of trace delta objects. Each trace delta contains the
239
+ * trace's uid along with all of the properties of _fullData that
240
+ * are not identical to those in the FigureModel's _data property
241
+ * @property {Number} trace_edit_id
242
+ * Edit ID of message that triggered the creation of trace deltas
243
+ */
244
+ _js2py_traceDeltas: null,
245
+ /**
246
+ * Object representing a collection of points for use in click, hover,
247
+ * and selection events
248
+ * @typedef {Object} Points
249
+ * @property {Array.<Number>} trace_indexes
250
+ * Array of the trace index for each point
251
+ * @property {Array.<Number>} point_indexes
252
+ * Array of the index of each point in its own trace
253
+ * @property {null|Array.<Number>} xs
254
+ * Array of the x coordinate of each point (for cartesian trace types)
255
+ * or null (for non-cartesian trace types)
256
+ * @property {null|Array.<Number>} ys
257
+ * Array of the y coordinate of each point (for cartesian trace types)
258
+ * or null (for non-cartesian trace types
259
+ * @property {null|Array.<Number>} zs
260
+ * Array of the z coordinate of each point (for 3D cartesian
261
+ * trace types)
262
+ * or null (for non-3D-cartesian trace types)
263
+ */
264
+ /**
265
+ * Object representing the state of the input devices during a
266
+ * plotly event
267
+ * @typedef {Object} InputDeviceState
268
+ * @property {boolean} alt - true if alt key pressed,
269
+ * false otherwise
270
+ * @property {boolean} ctrl - true if ctrl key pressed,
271
+ * false otherwise
272
+ * @property {boolean} meta - true if meta key pressed,
273
+ * false otherwise
274
+ * @property {boolean} shift - true if shift key pressed,
275
+ * false otherwise
276
+ *
277
+ * @property {boolean} button
278
+ * Indicates which button was pressed on the mouse to trigger the
279
+ * event.
280
+ * 0: Main button pressed, usually the left button or the
281
+ * un-initialized state
282
+ * 1: Auxiliary button pressed, usually the wheel button or
283
+ * the middle button (if present)
284
+ * 2: Secondary button pressed, usually the right button
285
+ * 3: Fourth button, typically the Browser Back button
286
+ * 4: Fifth button, typically the Browser Forward button
287
+ *
288
+ * @property {boolean} buttons
289
+ * Indicates which buttons were pressed on the mouse when the event
290
+ * is triggered.
291
+ * 0 : No button or un-initialized
292
+ * 1 : Primary button (usually left)
293
+ * 2 : Secondary button (usually right)
294
+ * 4 : Auxilary button (usually middle or mouse wheel button)
295
+ * 8 : 4th button (typically the "Browser Back" button)
296
+ * 16 : 5th button (typically the "Browser Forward" button)
297
+ *
298
+ * Combinations of buttons are represented by the sum of the codes
299
+ * above. e.g. a value of 7 indicates buttons 1 (primary),
300
+ * 2 (secondary), and 4 (auxilary) were pressed during the event
301
+ */
302
+ /**
303
+ * @typedef {Object} BoxSelectorState
304
+ * @property {Array.<Number>} xrange
305
+ * Two element array containing the x-range of the box selection
306
+ * @property {Array.<Number>} yrange
307
+ * Two element array containing the y-range of the box selection
308
+ */
309
+ /**
310
+ * @typedef {Object} LassoSelectorState
311
+ * @property {Array.<Number>} xs
312
+ * Array of the x-coordinates of the lasso selection region
313
+ * @property {Array.<Number>} ys
314
+ * Array of the y-coordinates of the lasso selection region
315
+ */
316
+ /**
317
+ * Object representing the state of the selection tool during a
318
+ * plotly_select event
319
+ * @typedef {Object} Selector
320
+ * @property {String} type
321
+ * Selection type. One of: 'box', or 'lasso'
322
+ * @property {BoxSelectorState|LassoSelectorState} selector_state
323
+ */
324
+ /**
325
+ * @typedef {null|Object} Js2PyPointsCallbackMsg
326
+ * @property {string} event_type
327
+ * Name of the triggering event. One of 'plotly_click',
328
+ * 'plotly_hover', 'plotly_unhover', or 'plotly_selected'
329
+ * @property {null|Points} points
330
+ * Points object for event
331
+ * @property {null|InputDeviceState} device_state
332
+ * InputDeviceState object for event
333
+ * @property {null|Selector} selector
334
+ * State of the selection tool for 'plotly_selected' events, null
335
+ * for other event types
336
+ */
337
+ _js2py_pointsCallback: null,
338
+ // Message tracking
339
+ // ----------------
340
+ /**
341
+ * @type {Number}
342
+ * layout_edit_id of the last layout modification operation
343
+ * requested by the Python side
344
+ */
345
+ _last_layout_edit_id: 0,
346
+ /**
347
+ * @type {Number}
348
+ * trace_edit_id of the last trace modification operation
349
+ * requested by the Python side
350
+ */
351
+ _last_trace_edit_id: 0 });
352
+ }
353
+ /**
354
+ * Initialize FigureModel. Called when the Python FigureWidget is first
355
+ * constructed
356
+ */
357
+ initialize() {
358
+ super.initialize.apply(this, arguments);
359
+ this.on("change:_data", this.do_data, this);
360
+ this.on("change:_layout", this.do_layout, this);
361
+ this.on("change:_py2js_addTraces", this.do_addTraces, this);
362
+ this.on("change:_py2js_deleteTraces", this.do_deleteTraces, this);
363
+ this.on("change:_py2js_moveTraces", this.do_moveTraces, this);
364
+ this.on("change:_py2js_restyle", this.do_restyle, this);
365
+ this.on("change:_py2js_relayout", this.do_relayout, this);
366
+ this.on("change:_py2js_update", this.do_update, this);
367
+ this.on("change:_py2js_animate", this.do_animate, this);
368
+ this.on("change:_py2js_removeLayoutProps", this.do_removeLayoutProps, this);
369
+ this.on("change:_py2js_removeTraceProps", this.do_removeTraceProps, this);
370
+ }
371
+ /**
372
+ * Input a trace index specification and return an Array of trace
373
+ * indexes where:
374
+ *
375
+ * - null|undefined -> Array of all traces
376
+ * - Trace index as Number -> Single element array of input index
377
+ * - Array of trace indexes -> Input array unchanged
378
+ *
379
+ * @param {undefined|null|Number|Array.<Number>} trace_indexes
380
+ * @returns {Array.<Number>}
381
+ * Array of trace indexes
382
+ * @private
383
+ */
384
+ _normalize_trace_indexes(trace_indexes) {
385
+ if (trace_indexes === null || trace_indexes === undefined) {
386
+ var numTraces = this.get("_data").length;
387
+ trace_indexes = _.range(numTraces);
388
+ }
389
+ if (!Array.isArray(trace_indexes)) {
390
+ // Make sure idx is an array
391
+ trace_indexes = [trace_indexes];
392
+ }
393
+ return trace_indexes;
394
+ }
395
+ /**
396
+ * Log changes to the _data trait
397
+ *
398
+ * This should only happed on FigureModel initialization
399
+ */
400
+ do_data() { }
401
+ /**
402
+ * Log changes to the _layout trait
403
+ *
404
+ * This should only happed on FigureModel initialization
405
+ */
406
+ do_layout() { }
407
+ /**
408
+ * Handle addTraces message
409
+ */
410
+ do_addTraces() {
411
+ // add trace to plot
412
+ /** @type {Py2JsAddTracesMsg} */
413
+ var msgData = this.get("_py2js_addTraces");
414
+ if (msgData !== null) {
415
+ var currentTraces = this.get("_data");
416
+ var newTraces = msgData.trace_data;
417
+ _.forEach(newTraces, function (newTrace) {
418
+ currentTraces.push(newTrace);
419
+ });
420
+ }
421
+ }
422
+ /**
423
+ * Handle deleteTraces message
424
+ */
425
+ do_deleteTraces() {
426
+ // remove traces from plot
427
+ /** @type {Py2JsDeleteTracesMsg} */
428
+ var msgData = this.get("_py2js_deleteTraces");
429
+ if (msgData !== null) {
430
+ var delete_inds = msgData.delete_inds;
431
+ var tracesData = this.get("_data");
432
+ // Remove del inds in reverse order so indexes remain valid
433
+ // throughout loop
434
+ delete_inds
435
+ .slice()
436
+ .reverse()
437
+ .forEach(function (del_ind) {
438
+ tracesData.splice(del_ind, 1);
439
+ });
440
+ }
441
+ }
442
+ /**
443
+ * Handle moveTraces message
444
+ */
445
+ do_moveTraces() {
446
+ /** @type {Py2JsMoveTracesMsg} */
447
+ var msgData = this.get("_py2js_moveTraces");
448
+ if (msgData !== null) {
449
+ var tracesData = this.get("_data");
450
+ var currentInds = msgData.current_trace_inds;
451
+ var newInds = msgData.new_trace_inds;
452
+ performMoveTracesLike(tracesData, currentInds, newInds);
453
+ }
454
+ }
455
+ /**
456
+ * Handle restyle message
457
+ */
458
+ do_restyle() {
459
+ /** @type {Py2JsRestyleMsg} */
460
+ var msgData = this.get("_py2js_restyle");
461
+ if (msgData !== null) {
462
+ var restyleData = msgData.restyle_data;
463
+ var restyleTraces = this._normalize_trace_indexes(msgData.restyle_traces);
464
+ performRestyleLike(this.get("_data"), restyleData, restyleTraces);
465
+ }
466
+ }
467
+ /**
468
+ * Handle relayout message
469
+ */
470
+ do_relayout() {
471
+ /** @type {Py2JsRelayoutMsg} */
472
+ var msgData = this.get("_py2js_relayout");
473
+ if (msgData !== null) {
474
+ performRelayoutLike(this.get("_layout"), msgData.relayout_data);
475
+ }
476
+ }
477
+ /**
478
+ * Handle update message
479
+ */
480
+ do_update() {
481
+ /** @type {Py2JsUpdateMsg} */
482
+ var msgData = this.get("_py2js_update");
483
+ if (msgData !== null) {
484
+ var style = msgData.style_data;
485
+ var layout = msgData.layout_data;
486
+ var styleTraces = this._normalize_trace_indexes(msgData.style_traces);
487
+ performRestyleLike(this.get("_data"), style, styleTraces);
488
+ performRelayoutLike(this.get("_layout"), layout);
489
+ }
490
+ }
491
+ /**
492
+ * Handle animate message
493
+ */
494
+ do_animate() {
495
+ /** @type {Py2JsAnimateMsg} */
496
+ var msgData = this.get("_py2js_animate");
497
+ if (msgData !== null) {
498
+ var styles = msgData.style_data;
499
+ var layout = msgData.layout_data;
500
+ var trace_indexes = this._normalize_trace_indexes(msgData.style_traces);
501
+ for (var i = 0; i < styles.length; i++) {
502
+ var style = styles[i];
503
+ var trace_index = trace_indexes[i];
504
+ var trace = this.get("_data")[trace_index];
505
+ performRelayoutLike(trace, style);
506
+ }
507
+ performRelayoutLike(this.get("_layout"), layout);
508
+ }
509
+ }
510
+ /**
511
+ * Handle removeLayoutProps message
512
+ */
513
+ do_removeLayoutProps() {
514
+ /** @type {Py2JsRemoveLayoutPropsMsg} */
515
+ var msgData = this.get("_py2js_removeLayoutProps");
516
+ if (msgData !== null) {
517
+ var keyPaths = msgData.remove_props;
518
+ var layout = this.get("_layout");
519
+ performRemoveProps(layout, keyPaths);
520
+ }
521
+ }
522
+ /**
523
+ * Handle removeTraceProps message
524
+ */
525
+ do_removeTraceProps() {
526
+ /** @type {Py2JsRemoveTracePropsMsg} */
527
+ var msgData = this.get("_py2js_removeTraceProps");
528
+ if (msgData !== null) {
529
+ var keyPaths = msgData.remove_props;
530
+ var traceIndex = msgData.remove_trace;
531
+ var trace = this.get("_data")[traceIndex];
532
+ performRemoveProps(trace, keyPaths);
533
+ }
534
+ }
535
+ }
536
+ FigureModel.serializers = Object.assign(Object.assign({}, DOMWidgetModel.serializers), { _data: { deserialize: py2js_deserializer, serialize: js2py_serializer }, _layout: {
537
+ deserialize: py2js_deserializer,
538
+ serialize: js2py_serializer,
539
+ }, _py2js_addTraces: {
540
+ deserialize: py2js_deserializer,
541
+ serialize: js2py_serializer,
542
+ }, _py2js_deleteTraces: {
543
+ deserialize: py2js_deserializer,
544
+ serialize: js2py_serializer,
545
+ }, _py2js_moveTraces: {
546
+ deserialize: py2js_deserializer,
547
+ serialize: js2py_serializer,
548
+ }, _py2js_restyle: {
549
+ deserialize: py2js_deserializer,
550
+ serialize: js2py_serializer,
551
+ }, _py2js_relayout: {
552
+ deserialize: py2js_deserializer,
553
+ serialize: js2py_serializer,
554
+ }, _py2js_update: {
555
+ deserialize: py2js_deserializer,
556
+ serialize: js2py_serializer,
557
+ }, _py2js_animate: {
558
+ deserialize: py2js_deserializer,
559
+ serialize: js2py_serializer,
560
+ }, _py2js_removeLayoutProps: {
561
+ deserialize: py2js_deserializer,
562
+ serialize: js2py_serializer,
563
+ }, _py2js_removeTraceProps: {
564
+ deserialize: py2js_deserializer,
565
+ serialize: js2py_serializer,
566
+ }, _js2py_restyle: {
567
+ deserialize: py2js_deserializer,
568
+ serialize: js2py_serializer,
569
+ }, _js2py_relayout: {
570
+ deserialize: py2js_deserializer,
571
+ serialize: js2py_serializer,
572
+ }, _js2py_update: {
573
+ deserialize: py2js_deserializer,
574
+ serialize: js2py_serializer,
575
+ }, _js2py_layoutDelta: {
576
+ deserialize: py2js_deserializer,
577
+ serialize: js2py_serializer,
578
+ }, _js2py_traceDeltas: {
579
+ deserialize: py2js_deserializer,
580
+ serialize: js2py_serializer,
581
+ }, _js2py_pointsCallback: {
582
+ deserialize: py2js_deserializer,
583
+ serialize: js2py_serializer,
584
+ } });
585
+ FigureModel.model_name = "FigureModel";
586
+ FigureModel.model_module = MODULE_NAME;
587
+ FigureModel.model_module_version = semver_range;
588
+ FigureModel.view_name = "FigureView";
589
+ FigureModel.view_module = MODULE_NAME;
590
+ FigureModel.view_module_version = semver_range;
591
+ // View
592
+ // ====
593
+ /**
594
+ * A FigureView manages the visual presentation of a single Plotly.js
595
+ * figure for a single notebook output cell. Each FigureView has a
596
+ * reference to FigureModel. Multiple views may share a single model
597
+ * instance, as is the case when a Python FigureWidget is displayed in
598
+ * multiple notebook output cells.
599
+ *
600
+ * @type {widgets.DOMWidgetView}
601
+ */
602
+ export class FigureView extends DOMWidgetView {
603
+ /**
604
+ * The perform_render method is called by processLuminoMessage
605
+ * after the widget's DOM element has been attached to the notebook
606
+ * output cell. This happens after the initialize of the
607
+ * FigureModel, and it won't happen at all if the Python FigureWidget
608
+ * is never displayed in a notebook output cell
609
+ */
610
+ perform_render() {
611
+ var that = this;
612
+ // Wire up message property callbacks
613
+ // ----------------------------------
614
+ // Python -> JS event properties
615
+ this.model.on("change:_py2js_addTraces", this.do_addTraces, this);
616
+ this.model.on("change:_py2js_deleteTraces", this.do_deleteTraces, this);
617
+ this.model.on("change:_py2js_moveTraces", this.do_moveTraces, this);
618
+ this.model.on("change:_py2js_restyle", this.do_restyle, this);
619
+ this.model.on("change:_py2js_relayout", this.do_relayout, this);
620
+ this.model.on("change:_py2js_update", this.do_update, this);
621
+ this.model.on("change:_py2js_animate", this.do_animate, this);
622
+ // MathJax configuration
623
+ // ---------------------
624
+ if (window.MathJax) {
625
+ window.MathJax.Hub.Config({ SVG: { font: "STIX-Web" } });
626
+ }
627
+ // Get message ids
628
+ // ---------------------
629
+ var layout_edit_id = this.model.get("_last_layout_edit_id");
630
+ var trace_edit_id = this.model.get("_last_trace_edit_id");
631
+ // Set view UID
632
+ // ------------
633
+ this.viewID = randstr();
634
+ // Initialize Plotly.js figure
635
+ // ---------------------------
636
+ // We must clone the model's data and layout properties so that
637
+ // the model is not directly mutated by the Plotly.js library.
638
+ var initialTraces = _.cloneDeep(this.model.get("_data"));
639
+ var initialLayout = _.cloneDeep(this.model.get("_layout"));
640
+ var config = this.model.get("_config");
641
+ Plotly.newPlot(that.el, initialTraces, initialLayout, config).then(function () {
642
+ // ### Send trace deltas ###
643
+ // We create an array of deltas corresponding to the new
644
+ // traces.
645
+ that._sendTraceDeltas(trace_edit_id);
646
+ // ### Send layout delta ###
647
+ that._sendLayoutDelta(layout_edit_id);
648
+ // Wire up plotly event callbacks
649
+ that.el.on("plotly_restyle", function (update) {
650
+ that.handle_plotly_restyle(update);
651
+ });
652
+ that.el.on("plotly_relayout", function (update) {
653
+ that.handle_plotly_relayout(update);
654
+ });
655
+ /*
656
+ (<Plotly.PlotlyHTMLElement>that.el).on("plotly_update", function (update: any) {
657
+ that.handle_plotly_update(update);
658
+ });
659
+ */
660
+ that.el.on("plotly_click", function (update) {
661
+ that.handle_plotly_click(update);
662
+ });
663
+ that.el.on("plotly_hover", function (update) {
664
+ that.handle_plotly_hover(update);
665
+ });
666
+ that.el.on("plotly_unhover", function (update) {
667
+ that.handle_plotly_unhover(update);
668
+ });
669
+ that.el.on("plotly_selected", function (update) {
670
+ that.handle_plotly_selected(update);
671
+ });
672
+ /*
673
+ (<Plotly.PlotlyHTMLElement>that.el).on("plotly_deselect", function (update: any) {
674
+ that.handle_plotly_deselect(update);
675
+ });
676
+ (<Plotly.PlotlyHTMLElement>that.el).on("plotly_doubleclick", function (update: any) {
677
+ that.handle_plotly_doubleclick(update);
678
+ });
679
+ */
680
+ // Emit event indicating that the widget has finished
681
+ // rendering
682
+ var event = new CustomEvent("plotlywidget-after-render", {
683
+ detail: { element: that.el, viewID: that.viewID },
684
+ });
685
+ // Dispatch/Trigger/Fire the event
686
+ document.dispatchEvent(event);
687
+ });
688
+ }
689
+ /**
690
+ * Respond to phosphorjs events
691
+ */
692
+ processLuminoMessage(msg) {
693
+ super.processLuminoMessage.apply(this, arguments);
694
+ var that = this;
695
+ switch (msg.type) {
696
+ case "before-attach":
697
+ // Render an initial empty figure. This establishes with
698
+ // the page that the element will not be empty, avoiding
699
+ // some occasions where the dynamic sizing behavior leads
700
+ // to collapsed figure dimensions.
701
+ var axisHidden = {
702
+ showgrid: false,
703
+ showline: false,
704
+ tickvals: [],
705
+ };
706
+ Plotly.newPlot(that.el, [], {
707
+ xaxis: axisHidden,
708
+ yaxis: axisHidden,
709
+ });
710
+ window.addEventListener("resize", function () {
711
+ that.autosizeFigure();
712
+ });
713
+ break;
714
+ case "after-attach":
715
+ // Rendering actual figure in the after-attach event allows
716
+ // Plotly.js to size the figure to fill the available element
717
+ this.perform_render();
718
+ break;
719
+ case "resize":
720
+ this.autosizeFigure();
721
+ break;
722
+ }
723
+ }
724
+ autosizeFigure() {
725
+ var that = this;
726
+ var layout = that.model.get("_layout");
727
+ if (_.isNil(layout) || _.isNil(layout.width)) {
728
+ // @ts-ignore
729
+ Plotly.Plots.resize(that.el).then(function () {
730
+ var layout_edit_id = that.model.get("_last_layout_edit_id");
731
+ that._sendLayoutDelta(layout_edit_id);
732
+ });
733
+ }
734
+ }
735
+ /**
736
+ * Purge Plotly.js data structures from the notebook output display
737
+ * element when the view is destroyed
738
+ */
739
+ destroy() {
740
+ Plotly.purge(this.el);
741
+ }
742
+ /**
743
+ * Return the figure's _fullData array merged with its data array
744
+ *
745
+ * The merge ensures that for any properties that el._fullData and
746
+ * el.data have in common, we return the version from el.data
747
+ *
748
+ * Named colorscales are one example of why this is needed. The el.data
749
+ * array will hold named colorscale strings (e.g. 'Viridis'), while the
750
+ * el._fullData array will hold the actual colorscale array. e.g.
751
+ *
752
+ * el.data[0].marker.colorscale == 'Viridis' but
753
+ * el._fullData[0].marker.colorscale = [[..., ...], ...]
754
+ *
755
+ * Performing the merge allows our FigureModel to retain the 'Viridis'
756
+ * string, rather than having it overridded by the colorscale array.
757
+ *
758
+ */
759
+ getFullData() {
760
+ return _.mergeWith({}, this.el._fullData, this.el.data, fullMergeCustomizer);
761
+ }
762
+ /**
763
+ * Return the figure's _fullLayout object merged with its layout object
764
+ *
765
+ * See getFullData documentation for discussion of why the merge is
766
+ * necessary
767
+ */
768
+ getFullLayout() {
769
+ return _.mergeWith({}, this.el._fullLayout, this.el.layout, fullMergeCustomizer);
770
+ }
771
+ /**
772
+ * Build Points data structure from data supplied by the plotly_click,
773
+ * plotly_hover, or plotly_select events
774
+ * @param {Object} data
775
+ * @returns {null|Points}
776
+ */
777
+ buildPointsObject(data) {
778
+ var pointsObject;
779
+ if (data.hasOwnProperty("points")) {
780
+ // Most cartesian plots
781
+ var pointObjects = data["points"];
782
+ var numPoints = pointObjects.length;
783
+ var hasNestedPointObjects = true;
784
+ for (let i = 0; i < numPoints; i++) {
785
+ hasNestedPointObjects =
786
+ hasNestedPointObjects &&
787
+ pointObjects[i].hasOwnProperty("pointNumbers");
788
+ if (!hasNestedPointObjects)
789
+ break;
790
+ }
791
+ var numPointNumbers = numPoints;
792
+ if (hasNestedPointObjects) {
793
+ numPointNumbers = 0;
794
+ for (let i = 0; i < numPoints; i++) {
795
+ numPointNumbers += pointObjects[i]["pointNumbers"].length;
796
+ }
797
+ }
798
+ pointsObject = {
799
+ trace_indexes: new Array(numPointNumbers),
800
+ point_indexes: new Array(numPointNumbers),
801
+ xs: new Array(numPointNumbers),
802
+ ys: new Array(numPointNumbers),
803
+ };
804
+ if (hasNestedPointObjects) {
805
+ var flatPointIndex = 0;
806
+ for (var p = 0; p < numPoints; p++) {
807
+ for (let i = 0; i < pointObjects[p]["pointNumbers"].length; i++, flatPointIndex++) {
808
+ pointsObject["point_indexes"][flatPointIndex] =
809
+ pointObjects[p]["pointNumbers"][i];
810
+ // also add xs, ys and traces so that the array doesn't get truncated later
811
+ pointsObject["xs"][flatPointIndex] = pointObjects[p]["x"];
812
+ pointsObject["ys"][flatPointIndex] = pointObjects[p]["y"];
813
+ pointsObject["trace_indexes"][flatPointIndex] =
814
+ pointObjects[p]["curveNumber"];
815
+ }
816
+ }
817
+ let single_trace = true;
818
+ for (let i = 1; i < numPointNumbers; i++) {
819
+ single_trace = single_trace && (pointsObject["trace_indexes"][i - 1] === pointsObject["trace_indexes"][i]);
820
+ if (!single_trace)
821
+ break;
822
+ }
823
+ if (single_trace) {
824
+ pointsObject["point_indexes"].sort((function (a, b) {
825
+ return a - b;
826
+ }));
827
+ }
828
+ }
829
+ else {
830
+ for (var p = 0; p < numPoints; p++) {
831
+ pointsObject["trace_indexes"][p] = pointObjects[p]["curveNumber"];
832
+ pointsObject["point_indexes"][p] = pointObjects[p]["pointNumber"];
833
+ pointsObject["xs"][p] = pointObjects[p]["x"];
834
+ pointsObject["ys"][p] = pointObjects[p]["y"];
835
+ }
836
+ }
837
+ // Add z if present
838
+ var hasZ = pointObjects[0] !== undefined && pointObjects[0].hasOwnProperty("z");
839
+ if (hasZ) {
840
+ pointsObject["zs"] = new Array(numPoints);
841
+ for (p = 0; p < numPoints; p++) {
842
+ pointsObject["zs"][p] = pointObjects[p]["z"];
843
+ }
844
+ }
845
+ return pointsObject;
846
+ }
847
+ else {
848
+ return null;
849
+ }
850
+ }
851
+ /**
852
+ * Build InputDeviceState data structure from data supplied by the
853
+ * plotly_click, plotly_hover, or plotly_select events
854
+ * @param {Object} data
855
+ * @returns {null|InputDeviceState}
856
+ */
857
+ buildInputDeviceStateObject(data) {
858
+ var event = data["event"];
859
+ if (event === undefined) {
860
+ return null;
861
+ }
862
+ else {
863
+ /** @type {InputDeviceState} */
864
+ var inputDeviceState = {
865
+ // Keyboard modifiers
866
+ alt: event["altKey"],
867
+ ctrl: event["ctrlKey"],
868
+ meta: event["metaKey"],
869
+ shift: event["shiftKey"],
870
+ // Mouse buttons
871
+ button: event["button"],
872
+ buttons: event["buttons"],
873
+ };
874
+ return inputDeviceState;
875
+ }
876
+ }
877
+ /**
878
+ * Build Selector data structure from data supplied by the
879
+ * plotly_select event
880
+ * @param data
881
+ * @returns {null|Selector}
882
+ */
883
+ buildSelectorObject(data) {
884
+ var selectorObject;
885
+ if (data.hasOwnProperty("range")) {
886
+ // Box selection
887
+ selectorObject = {
888
+ type: "box",
889
+ selector_state: {
890
+ xrange: data["range"]["x"],
891
+ yrange: data["range"]["y"],
892
+ },
893
+ };
894
+ }
895
+ else if (data.hasOwnProperty("lassoPoints")) {
896
+ // Lasso selection
897
+ selectorObject = {
898
+ type: "lasso",
899
+ selector_state: {
900
+ xs: data["lassoPoints"]["x"],
901
+ ys: data["lassoPoints"]["y"],
902
+ },
903
+ };
904
+ }
905
+ else {
906
+ selectorObject = null;
907
+ }
908
+ return selectorObject;
909
+ }
910
+ /**
911
+ * Handle ploty_restyle events emitted by the Plotly.js library
912
+ * @param data
913
+ */
914
+ handle_plotly_restyle(data) {
915
+ if (data === null || data === undefined) {
916
+ // No data to report to the Python side
917
+ return;
918
+ }
919
+ if (data[0] && data[0].hasOwnProperty("_doNotReportToPy")) {
920
+ // Restyle originated on the Python side
921
+ return;
922
+ }
923
+ // Unpack data
924
+ var styleData = data[0];
925
+ var styleTraces = data[1];
926
+ // Construct restyle message to send to the Python side
927
+ /** @type {Js2PyRestyleMsg} */
928
+ var restyleMsg = {
929
+ style_data: styleData,
930
+ style_traces: styleTraces,
931
+ source_view_id: this.viewID,
932
+ };
933
+ this.model.set("_js2py_restyle", restyleMsg);
934
+ this.touch();
935
+ }
936
+ /**
937
+ * Handle plotly_relayout events emitted by the Plotly.js library
938
+ * @param data
939
+ */
940
+ handle_plotly_relayout(data) {
941
+ if (data === null || data === undefined) {
942
+ // No data to report to the Python side
943
+ return;
944
+ }
945
+ if (data.hasOwnProperty("_doNotReportToPy")) {
946
+ // Relayout originated on the Python side
947
+ return;
948
+ }
949
+ /** @type {Js2PyRelayoutMsg} */
950
+ var relayoutMsg = {
951
+ relayout_data: data,
952
+ source_view_id: this.viewID,
953
+ };
954
+ this.model.set("_js2py_relayout", relayoutMsg);
955
+ this.touch();
956
+ }
957
+ /**
958
+ * Handle plotly_update events emitted by the Plotly.js library
959
+ * @param data
960
+ */
961
+ handle_plotly_update(data) {
962
+ if (data === null || data === undefined) {
963
+ // No data to report to the Python side
964
+ return;
965
+ }
966
+ if (data["data"] && data["data"][0].hasOwnProperty("_doNotReportToPy")) {
967
+ // Update originated on the Python side
968
+ return;
969
+ }
970
+ /** @type {Js2PyUpdateMsg} */
971
+ var updateMsg = {
972
+ style_data: data["data"][0],
973
+ style_traces: data["data"][1],
974
+ layout_data: data["layout"],
975
+ source_view_id: this.viewID,
976
+ };
977
+ // Log message
978
+ this.model.set("_js2py_update", updateMsg);
979
+ this.touch();
980
+ }
981
+ /**
982
+ * Handle plotly_click events emitted by the Plotly.js library
983
+ * @param data
984
+ */
985
+ handle_plotly_click(data) {
986
+ this._send_points_callback_message(data, "plotly_click");
987
+ }
988
+ /**
989
+ * Handle plotly_hover events emitted by the Plotly.js library
990
+ * @param data
991
+ */
992
+ handle_plotly_hover(data) {
993
+ this._send_points_callback_message(data, "plotly_hover");
994
+ }
995
+ /**
996
+ * Handle plotly_unhover events emitted by the Plotly.js library
997
+ * @param data
998
+ */
999
+ handle_plotly_unhover(data) {
1000
+ this._send_points_callback_message(data, "plotly_unhover");
1001
+ }
1002
+ /**
1003
+ * Handle plotly_selected events emitted by the Plotly.js library
1004
+ * @param data
1005
+ */
1006
+ handle_plotly_selected(data) {
1007
+ this._send_points_callback_message(data, "plotly_selected");
1008
+ }
1009
+ /**
1010
+ * Handle plotly_deselect events emitted by the Plotly.js library
1011
+ * @param data
1012
+ */
1013
+ handle_plotly_deselect(data) {
1014
+ data = {
1015
+ points: [],
1016
+ };
1017
+ this._send_points_callback_message(data, "plotly_deselect");
1018
+ }
1019
+ /**
1020
+ * Build and send a points callback message to the Python side
1021
+ *
1022
+ * @param {Object} data
1023
+ * data object as provided by the plotly_click, plotly_hover,
1024
+ * plotly_unhover, or plotly_selected events
1025
+ * @param {String} event_type
1026
+ * Name of the triggering event. One of 'plotly_click',
1027
+ * 'plotly_hover', 'plotly_unhover', or 'plotly_selected'
1028
+ * @private
1029
+ */
1030
+ _send_points_callback_message(data, event_type) {
1031
+ if (data === null || data === undefined) {
1032
+ // No data to report to the Python side
1033
+ return;
1034
+ }
1035
+ /** @type {Js2PyPointsCallbackMsg} */
1036
+ var pointsMsg = {
1037
+ event_type: event_type,
1038
+ points: this.buildPointsObject(data),
1039
+ device_state: this.buildInputDeviceStateObject(data),
1040
+ selector: this.buildSelectorObject(data),
1041
+ };
1042
+ if (pointsMsg["points"] !== null && pointsMsg["points"] !== undefined) {
1043
+ this.model.set("_js2py_pointsCallback", pointsMsg);
1044
+ this.touch();
1045
+ }
1046
+ }
1047
+ /**
1048
+ * Stub for future handling of plotly_doubleclick
1049
+ * @param data
1050
+ */
1051
+ handle_plotly_doubleclick(data) { }
1052
+ /**
1053
+ * Handle Plotly.addTraces request
1054
+ */
1055
+ do_addTraces() {
1056
+ /** @type {Py2JsAddTracesMsg} */
1057
+ var msgData = this.model.get("_py2js_addTraces");
1058
+ if (msgData !== null) {
1059
+ var that = this;
1060
+ Plotly.addTraces(this.el, msgData.trace_data).then(function () {
1061
+ // ### Send trace deltas ###
1062
+ that._sendTraceDeltas(msgData.trace_edit_id);
1063
+ // ### Send layout delta ###
1064
+ var layout_edit_id = msgData.layout_edit_id;
1065
+ that._sendLayoutDelta(layout_edit_id);
1066
+ });
1067
+ }
1068
+ }
1069
+ /**
1070
+ * Handle Plotly.deleteTraces request
1071
+ */
1072
+ do_deleteTraces() {
1073
+ /** @type {Py2JsDeleteTracesMsg} */
1074
+ var msgData = this.model.get("_py2js_deleteTraces");
1075
+ if (msgData !== null) {
1076
+ var delete_inds = msgData.delete_inds;
1077
+ var that = this;
1078
+ Plotly.deleteTraces(this.el, delete_inds).then(function () {
1079
+ // ### Send trace deltas ###
1080
+ var trace_edit_id = msgData.trace_edit_id;
1081
+ that._sendTraceDeltas(trace_edit_id);
1082
+ // ### Send layout delta ###
1083
+ var layout_edit_id = msgData.layout_edit_id;
1084
+ that._sendLayoutDelta(layout_edit_id);
1085
+ });
1086
+ }
1087
+ }
1088
+ /**
1089
+ * Handle Plotly.moveTraces request
1090
+ */
1091
+ do_moveTraces() {
1092
+ /** @type {Py2JsMoveTracesMsg} */
1093
+ var msgData = this.model.get("_py2js_moveTraces");
1094
+ if (msgData !== null) {
1095
+ // Unpack message
1096
+ var currentInds = msgData.current_trace_inds;
1097
+ var newInds = msgData.new_trace_inds;
1098
+ // Check if the new trace indexes are actually different than
1099
+ // the current indexes
1100
+ var inds_equal = _.isEqual(currentInds, newInds);
1101
+ if (!inds_equal) {
1102
+ Plotly.moveTraces(this.el, currentInds, newInds);
1103
+ }
1104
+ }
1105
+ }
1106
+ /**
1107
+ * Handle Plotly.restyle request
1108
+ */
1109
+ do_restyle() {
1110
+ /** @type {Py2JsRestyleMsg} */
1111
+ var msgData = this.model.get("_py2js_restyle");
1112
+ if (msgData !== null) {
1113
+ var restyleData = msgData.restyle_data;
1114
+ var traceIndexes = this.model._normalize_trace_indexes(msgData.restyle_traces);
1115
+ restyleData["_doNotReportToPy"] = true;
1116
+ Plotly.restyle(this.el, restyleData, traceIndexes);
1117
+ // ### Send trace deltas ###
1118
+ // We create an array of deltas corresponding to the restyled
1119
+ // traces.
1120
+ this._sendTraceDeltas(msgData.trace_edit_id);
1121
+ // ### Send layout delta ###
1122
+ var layout_edit_id = msgData.layout_edit_id;
1123
+ this._sendLayoutDelta(layout_edit_id);
1124
+ }
1125
+ }
1126
+ /**
1127
+ * Handle Plotly.relayout request
1128
+ */
1129
+ do_relayout() {
1130
+ /** @type {Py2JsRelayoutMsg} */
1131
+ var msgData = this.model.get("_py2js_relayout");
1132
+ if (msgData !== null) {
1133
+ if (msgData.source_view_id !== this.viewID) {
1134
+ var relayoutData = msgData.relayout_data;
1135
+ relayoutData["_doNotReportToPy"] = true;
1136
+ Plotly.relayout(this.el, msgData.relayout_data);
1137
+ }
1138
+ // ### Send layout delta ###
1139
+ var layout_edit_id = msgData.layout_edit_id;
1140
+ this._sendLayoutDelta(layout_edit_id);
1141
+ }
1142
+ }
1143
+ /**
1144
+ * Handle Plotly.update request
1145
+ */
1146
+ do_update() {
1147
+ /** @type {Py2JsUpdateMsg} */
1148
+ var msgData = this.model.get("_py2js_update");
1149
+ if (msgData !== null) {
1150
+ var style = msgData.style_data || {};
1151
+ var layout = msgData.layout_data || {};
1152
+ var traceIndexes = this.model._normalize_trace_indexes(msgData.style_traces);
1153
+ style["_doNotReportToPy"] = true;
1154
+ Plotly.update(this.el, style, layout, traceIndexes);
1155
+ // ### Send trace deltas ###
1156
+ // We create an array of deltas corresponding to the updated
1157
+ // traces.
1158
+ this._sendTraceDeltas(msgData.trace_edit_id);
1159
+ // ### Send layout delta ###
1160
+ var layout_edit_id = msgData.layout_edit_id;
1161
+ this._sendLayoutDelta(layout_edit_id);
1162
+ }
1163
+ }
1164
+ /**
1165
+ * Handle Plotly.animate request
1166
+ */
1167
+ do_animate() {
1168
+ /** @type {Py2JsAnimateMsg} */
1169
+ var msgData = this.model.get("_py2js_animate");
1170
+ if (msgData !== null) {
1171
+ // Unpack params
1172
+ // var animationData = msgData[0];
1173
+ var animationOpts = msgData.animation_opts;
1174
+ var styles = msgData.style_data;
1175
+ var layout = msgData.layout_data;
1176
+ var traceIndexes = this.model._normalize_trace_indexes(msgData.style_traces);
1177
+ var animationData = {
1178
+ data: styles,
1179
+ layout: layout,
1180
+ traces: traceIndexes,
1181
+ };
1182
+ animationData["_doNotReportToPy"] = true;
1183
+ var that = this;
1184
+ // @ts-ignore
1185
+ Plotly.animate(this.el, animationData, animationOpts).then(function () {
1186
+ // ### Send trace deltas ###
1187
+ // We create an array of deltas corresponding to the
1188
+ // animated traces.
1189
+ that._sendTraceDeltas(msgData.trace_edit_id);
1190
+ // ### Send layout delta ###
1191
+ var layout_edit_id = msgData.layout_edit_id;
1192
+ that._sendLayoutDelta(layout_edit_id);
1193
+ });
1194
+ }
1195
+ }
1196
+ /**
1197
+ * Construct layout delta object and send layoutDelta message to the
1198
+ * Python side
1199
+ *
1200
+ * @param layout_edit_id
1201
+ * Edit ID of message that triggered the creation of the layout delta
1202
+ * @private
1203
+ */
1204
+ _sendLayoutDelta(layout_edit_id) {
1205
+ // ### Handle layout delta ###
1206
+ var layout_delta = createDeltaObject(this.getFullLayout(), this.model.get("_layout"));
1207
+ /** @type{Js2PyLayoutDeltaMsg} */
1208
+ var layoutDeltaMsg = {
1209
+ layout_delta: layout_delta,
1210
+ layout_edit_id: layout_edit_id,
1211
+ };
1212
+ this.model.set("_js2py_layoutDelta", layoutDeltaMsg);
1213
+ this.touch();
1214
+ }
1215
+ /**
1216
+ * Construct trace deltas array for the requested trace indexes and
1217
+ * send traceDeltas message to the Python side
1218
+ * Array of indexes of traces for which to compute deltas
1219
+ * @param trace_edit_id
1220
+ * Edit ID of message that triggered the creation of trace deltas
1221
+ * @private
1222
+ */
1223
+ _sendTraceDeltas(trace_edit_id) {
1224
+ var trace_data = this.model.get("_data");
1225
+ var traceIndexes = _.range(trace_data.length);
1226
+ var trace_deltas = new Array(traceIndexes.length);
1227
+ var fullData = this.getFullData();
1228
+ for (var i = 0; i < traceIndexes.length; i++) {
1229
+ var traceInd = traceIndexes[i];
1230
+ trace_deltas[i] = createDeltaObject(fullData[traceInd], trace_data[traceInd]);
1231
+ }
1232
+ /** @type{Js2PyTraceDeltasMsg} */
1233
+ var traceDeltasMsg = {
1234
+ trace_deltas: trace_deltas,
1235
+ trace_edit_id: trace_edit_id,
1236
+ };
1237
+ this.model.set("_js2py_traceDeltas", traceDeltasMsg);
1238
+ this.touch();
1239
+ }
1240
+ }
1241
+ // Serialization
1242
+ /**
1243
+ * Create a mapping from numpy dtype strings to corresponding typed array
1244
+ * constructors
1245
+ */
1246
+ const numpy_dtype_to_typedarray_type = {
1247
+ int8: Int8Array,
1248
+ int16: Int16Array,
1249
+ int32: Int32Array,
1250
+ uint8: Uint8Array,
1251
+ uint16: Uint16Array,
1252
+ uint32: Uint32Array,
1253
+ float32: Float32Array,
1254
+ float64: Float64Array,
1255
+ };
1256
+ function serializeTypedArray(v) {
1257
+ var numpyType;
1258
+ if (v instanceof Int8Array) {
1259
+ numpyType = "int8";
1260
+ }
1261
+ else if (v instanceof Int16Array) {
1262
+ numpyType = "int16";
1263
+ }
1264
+ else if (v instanceof Int32Array) {
1265
+ numpyType = "int32";
1266
+ }
1267
+ else if (v instanceof Uint8Array) {
1268
+ numpyType = "uint8";
1269
+ }
1270
+ else if (v instanceof Uint16Array) {
1271
+ numpyType = "uint16";
1272
+ }
1273
+ else if (v instanceof Uint32Array) {
1274
+ numpyType = "uint32";
1275
+ }
1276
+ else if (v instanceof Float32Array) {
1277
+ numpyType = "float32";
1278
+ }
1279
+ else if (v instanceof Float64Array) {
1280
+ numpyType = "float64";
1281
+ }
1282
+ else {
1283
+ // Don't understand it, return as is
1284
+ return v;
1285
+ }
1286
+ var res = {
1287
+ dtype: numpyType,
1288
+ shape: [v.length],
1289
+ value: v.buffer,
1290
+ };
1291
+ return res;
1292
+ }
1293
+ /**
1294
+ * ipywidget JavaScript -> Python serializer
1295
+ */
1296
+ function js2py_serializer(v, widgetManager) {
1297
+ var res;
1298
+ if (_.isTypedArray(v)) {
1299
+ res = serializeTypedArray(v);
1300
+ }
1301
+ else if (Array.isArray(v)) {
1302
+ // Serialize array elements recursively
1303
+ res = new Array(v.length);
1304
+ for (var i = 0; i < v.length; i++) {
1305
+ res[i] = js2py_serializer(v[i]);
1306
+ }
1307
+ }
1308
+ else if (_.isPlainObject(v)) {
1309
+ // Serialize object properties recursively
1310
+ res = {};
1311
+ for (var p in v) {
1312
+ if (v.hasOwnProperty(p)) {
1313
+ res[p] = js2py_serializer(v[p]);
1314
+ }
1315
+ }
1316
+ }
1317
+ else if (v === undefined) {
1318
+ // Translate undefined into '_undefined_' sentinal string. The
1319
+ // Python _js_to_py deserializer will convert this into an
1320
+ // Undefined object
1321
+ res = "_undefined_";
1322
+ }
1323
+ else {
1324
+ // Primitive value to transfer directly
1325
+ res = v;
1326
+ }
1327
+ return res;
1328
+ }
1329
+ /**
1330
+ * ipywidget Python -> Javascript deserializer
1331
+ */
1332
+ function py2js_deserializer(v, widgetManager) {
1333
+ var res;
1334
+ if (Array.isArray(v)) {
1335
+ // Deserialize array elements recursively
1336
+ res = new Array(v.length);
1337
+ for (var i = 0; i < v.length; i++) {
1338
+ res[i] = py2js_deserializer(v[i]);
1339
+ }
1340
+ }
1341
+ else if (_.isPlainObject(v)) {
1342
+ if ((_.has(v, "value") || _.has(v, "buffer")) &&
1343
+ _.has(v, "dtype") &&
1344
+ _.has(v, "shape")) {
1345
+ // Deserialize special buffer/dtype/shape objects into typed arrays
1346
+ // These objects correspond to numpy arrays on the Python side
1347
+ //
1348
+ // Note plotly.py<=3.1.1 called the buffer object `buffer`
1349
+ // This was renamed `value` in 3.2 to work around a naming conflict
1350
+ // when saving widget state to a notebook.
1351
+ // @ts-ignore
1352
+ var typedarray_type = numpy_dtype_to_typedarray_type[v.dtype];
1353
+ var buffer = _.has(v, "value") ? v.value.buffer : v.buffer.buffer;
1354
+ res = new typedarray_type(buffer);
1355
+ }
1356
+ else {
1357
+ // Deserialize object properties recursively
1358
+ res = {};
1359
+ for (var p in v) {
1360
+ if (v.hasOwnProperty(p)) {
1361
+ res[p] = py2js_deserializer(v[p]);
1362
+ }
1363
+ }
1364
+ }
1365
+ }
1366
+ else if (v === "_undefined_") {
1367
+ // Convert the _undefined_ sentinal into undefined
1368
+ res = undefined;
1369
+ }
1370
+ else {
1371
+ // Accept primitive value directly
1372
+ res = v;
1373
+ }
1374
+ return res;
1375
+ }
1376
+ /**
1377
+ * Return whether the input value is a typed array
1378
+ * @param potentialTypedArray
1379
+ * Value to examine
1380
+ * @returns {boolean}
1381
+ */
1382
+ function isTypedArray(potentialTypedArray) {
1383
+ return (ArrayBuffer.isView(potentialTypedArray) &&
1384
+ !(potentialTypedArray instanceof DataView));
1385
+ }
1386
+ /**
1387
+ * Customizer for use with lodash's mergeWith function
1388
+ *
1389
+ * The customizer ensures that typed arrays are not converted into standard
1390
+ * arrays during the recursive merge
1391
+ *
1392
+ * See: https://lodash.com/docs/latest#mergeWith
1393
+ */
1394
+ function fullMergeCustomizer(objValue, srcValue, key) {
1395
+ if (key[0] === "_") {
1396
+ // Don't recurse into private properties
1397
+ return null;
1398
+ }
1399
+ else if (isTypedArray(srcValue)) {
1400
+ // Return typed arrays directly, don't recurse inside
1401
+ return srcValue;
1402
+ }
1403
+ }
1404
+ /**
1405
+ * Reform a Plotly.relayout like operation on an input object
1406
+ *
1407
+ * @param {Object} parentObj
1408
+ * The object that the relayout operation should be applied to
1409
+ * @param {Object} relayoutData
1410
+ * An relayout object as accepted by Plotly.relayout
1411
+ *
1412
+ * Examples:
1413
+ * var d = {foo {bar [5, 10]}};
1414
+ * performRelayoutLike(d, {'foo.bar': [0, 1]});
1415
+ * d -> {foo: {bar: [0, 1]}}
1416
+ *
1417
+ * var d = {foo {bar [5, 10]}};
1418
+ * performRelayoutLike(d, {'baz': 34});
1419
+ * d -> {foo: {bar: [5, 10]}, baz: 34}
1420
+ *
1421
+ * var d = {foo: {bar: [5, 10]};
1422
+ * performRelayoutLike(d, {'foo.baz[1]': 17});
1423
+ * d -> {foo: {bar: [5, 17]}}
1424
+ *
1425
+ */
1426
+ function performRelayoutLike(parentObj, relayoutData) {
1427
+ // Perform a relayout style operation on a given parent object
1428
+ for (var rawKey in relayoutData) {
1429
+ if (!relayoutData.hasOwnProperty(rawKey)) {
1430
+ continue;
1431
+ }
1432
+ // Extract value for this key
1433
+ var relayoutVal = relayoutData[rawKey];
1434
+ // Set property value
1435
+ if (relayoutVal === null) {
1436
+ _.unset(parentObj, rawKey);
1437
+ }
1438
+ else {
1439
+ _.set(parentObj, rawKey, relayoutVal);
1440
+ }
1441
+ }
1442
+ }
1443
+ /**
1444
+ * Perform a Plotly.restyle like operation on an input object array
1445
+ *
1446
+ * @param {Array.<Object>} parentArray
1447
+ * The object that the restyle operation should be applied to
1448
+ * @param {Object} restyleData
1449
+ * A restyle object as accepted by Plotly.restyle
1450
+ * @param {Array.<Number>} restyleTraces
1451
+ * Array of indexes of the traces that the resytle operation applies to
1452
+ *
1453
+ * Examples:
1454
+ * var d = [{foo: {bar: 1}}, {}, {}]
1455
+ * performRestyleLike(d, {'foo.bar': 2}, [0])
1456
+ * d -> [{foo: {bar: 2}}, {}, {}]
1457
+ *
1458
+ * var d = [{foo: {bar: 1}}, {}, {}]
1459
+ * performRestyleLike(d, {'foo.bar': 2}, [0, 1, 2])
1460
+ * d -> [{foo: {bar: 2}}, {foo: {bar: 2}}, {foo: {bar: 2}}]
1461
+ *
1462
+ * var d = [{foo: {bar: 1}}, {}, {}]
1463
+ * performRestyleLike(d, {'foo.bar': [2, 3, 4]}, [0, 1, 2])
1464
+ * d -> [{foo: {bar: 2}}, {foo: {bar: 3}}, {foo: {bar: 4}}]
1465
+ *
1466
+ */
1467
+ function performRestyleLike(parentArray, restyleData, restyleTraces) {
1468
+ // Loop over the properties of restyleData
1469
+ for (var rawKey in restyleData) {
1470
+ if (!restyleData.hasOwnProperty(rawKey)) {
1471
+ continue;
1472
+ }
1473
+ // Extract value for property and normalize into a value list
1474
+ var valArray = restyleData[rawKey];
1475
+ if (!Array.isArray(valArray)) {
1476
+ valArray = [valArray];
1477
+ }
1478
+ // Loop over the indexes of the traces being restyled
1479
+ for (var i = 0; i < restyleTraces.length; i++) {
1480
+ // Get trace object
1481
+ var traceInd = restyleTraces[i];
1482
+ var trace = parentArray[traceInd];
1483
+ // Extract value for this trace
1484
+ var singleVal = valArray[i % valArray.length];
1485
+ // Set property value
1486
+ if (singleVal === null) {
1487
+ _.unset(trace, rawKey);
1488
+ }
1489
+ else if (singleVal !== undefined) {
1490
+ _.set(trace, rawKey, singleVal);
1491
+ }
1492
+ }
1493
+ }
1494
+ }
1495
+ /**
1496
+ * Perform a Plotly.moveTraces like operation on an input object array
1497
+ * @param parentArray
1498
+ * The object that the moveTraces operation should be applied to
1499
+ * @param currentInds
1500
+ * Array of the current indexes of traces to be moved
1501
+ * @param newInds
1502
+ * Array of the new indexes that traces selected by currentInds should be
1503
+ * moved to.
1504
+ *
1505
+ * Examples:
1506
+ * var d = [{foo: 0}, {foo: 1}, {foo: 2}]
1507
+ * performMoveTracesLike(d, [0, 1], [2, 0])
1508
+ * d -> [{foo: 1}, {foo: 2}, {foo: 0}]
1509
+ *
1510
+ * var d = [{foo: 0}, {foo: 1}, {foo: 2}]
1511
+ * performMoveTracesLike(d, [0, 2], [1, 2])
1512
+ * d -> [{foo: 1}, {foo: 0}, {foo: 2}]
1513
+ */
1514
+ function performMoveTracesLike(parentArray, currentInds, newInds) {
1515
+ // ### Remove by currentInds in reverse order ###
1516
+ var movingTracesData = [];
1517
+ for (var ci = currentInds.length - 1; ci >= 0; ci--) {
1518
+ // Insert moving parentArray at beginning of the list
1519
+ movingTracesData.splice(0, 0, parentArray[currentInds[ci]]);
1520
+ parentArray.splice(currentInds[ci], 1);
1521
+ }
1522
+ // ### Sort newInds and movingTracesData by newInds ###
1523
+ var newIndexSortedArrays = _(newInds)
1524
+ .zip(movingTracesData)
1525
+ .sortBy(0)
1526
+ .unzip()
1527
+ .value();
1528
+ newInds = newIndexSortedArrays[0];
1529
+ movingTracesData = newIndexSortedArrays[1];
1530
+ // ### Insert by newInds in forward order ###
1531
+ for (var ni = 0; ni < newInds.length; ni++) {
1532
+ parentArray.splice(newInds[ni], 0, movingTracesData[ni]);
1533
+ }
1534
+ }
1535
+ /**
1536
+ * Remove nested properties from a parent object
1537
+ * @param {Object} parentObj
1538
+ * Parent object from which properties or nested properties should be removed
1539
+ * @param {Array.<Array.<Number|String>>} keyPaths
1540
+ * Array of key paths for properties that should be removed. Each key path
1541
+ * is an array of properties names or array indexes that reference a
1542
+ * property to be removed
1543
+ *
1544
+ * Examples:
1545
+ * var d = {foo: [{bar: 0}, {bar: 1}], baz: 32}
1546
+ * performRemoveProps(d, ['baz'])
1547
+ * d -> {foo: [{bar: 0}, {bar: 1}]}
1548
+ *
1549
+ * var d = {foo: [{bar: 0}, {bar: 1}], baz: 32}
1550
+ * performRemoveProps(d, ['foo[1].bar', 'baz'])
1551
+ * d -> {foo: [{bar: 0}, {}]}
1552
+ *
1553
+ */
1554
+ function performRemoveProps(parentObj, keyPaths) {
1555
+ for (var i = 0; i < keyPaths.length; i++) {
1556
+ var keyPath = keyPaths[i];
1557
+ _.unset(parentObj, keyPath);
1558
+ }
1559
+ }
1560
+ /**
1561
+ * Return object that contains all properties in fullObj that are not
1562
+ * identical to the corresponding properties in removeObj
1563
+ *
1564
+ * Properties of fullObj and removeObj may be objects or arrays of objects
1565
+ *
1566
+ * Returned object is a deep clone of the properties of the input objects
1567
+ *
1568
+ * @param {Object} fullObj
1569
+ * @param {Object} removeObj
1570
+ *
1571
+ * Examples:
1572
+ * var fullD = {foo: [{bar: 0}, {bar: 1}], baz: 32}
1573
+ * var removeD = {baz: 32}
1574
+ * createDeltaObject(fullD, removeD)
1575
+ * -> {foo: [{bar: 0}, {bar: 1}]}
1576
+ *
1577
+ * var fullD = {foo: [{bar: 0}, {bar: 1}], baz: 32}
1578
+ * var removeD = {baz: 45}
1579
+ * createDeltaObject(fullD, removeD)
1580
+ * -> {foo: [{bar: 0}, {bar: 1}], baz: 32}
1581
+ *
1582
+ * var fullD = {foo: [{bar: 0}, {bar: 1}], baz: 32}
1583
+ * var removeD = {foo: [{bar: 0}, {bar: 1}]}
1584
+ * createDeltaObject(fullD, removeD)
1585
+ * -> {baz: 32}
1586
+ *
1587
+ */
1588
+ function createDeltaObject(fullObj, removeObj) {
1589
+ // Initialize result as object or array
1590
+ var res;
1591
+ if (Array.isArray(fullObj)) {
1592
+ res = new Array(fullObj.length);
1593
+ }
1594
+ else {
1595
+ res = {};
1596
+ }
1597
+ // Initialize removeObj to empty object if not specified
1598
+ if (removeObj === null || removeObj === undefined) {
1599
+ removeObj = {};
1600
+ }
1601
+ // Iterate over object properties or array indices
1602
+ for (var p in fullObj) {
1603
+ if (p[0] !== "_" && // Don't consider private properties
1604
+ fullObj.hasOwnProperty(p) && // Exclude parent properties
1605
+ fullObj[p] !== null // Exclude cases where fullObj doesn't
1606
+ // have the property
1607
+ ) {
1608
+ // Compute object equality
1609
+ var props_equal;
1610
+ props_equal = _.isEqual(fullObj[p], removeObj[p]);
1611
+ // Perform recursive comparison if props are not equal
1612
+ if (!props_equal || p === "uid") {
1613
+ // Let uids through
1614
+ // property has non-null value in fullObj that doesn't
1615
+ // match the value in removeObj
1616
+ var fullVal = fullObj[p];
1617
+ if (removeObj.hasOwnProperty(p) && typeof fullVal === "object") {
1618
+ // Recurse over object properties
1619
+ if (Array.isArray(fullVal)) {
1620
+ if (fullVal.length > 0 && typeof fullVal[0] === "object") {
1621
+ // We have an object array
1622
+ res[p] = new Array(fullVal.length);
1623
+ for (var i = 0; i < fullVal.length; i++) {
1624
+ if (!Array.isArray(removeObj[p]) || removeObj[p].length <= i) {
1625
+ res[p][i] = fullVal[i];
1626
+ }
1627
+ else {
1628
+ res[p][i] = createDeltaObject(fullVal[i], removeObj[p][i]);
1629
+ }
1630
+ }
1631
+ }
1632
+ else {
1633
+ // We have a primitive array or typed array
1634
+ res[p] = fullVal;
1635
+ }
1636
+ }
1637
+ else {
1638
+ // object
1639
+ var full_obj = createDeltaObject(fullVal, removeObj[p]);
1640
+ if (Object.keys(full_obj).length > 0) {
1641
+ // new object is not empty
1642
+ res[p] = full_obj;
1643
+ }
1644
+ }
1645
+ }
1646
+ else if (typeof fullVal === "object" && !Array.isArray(fullVal)) {
1647
+ // Return 'clone' of fullVal
1648
+ // We don't use a standard clone method so that we keep
1649
+ // the special case handling of this method
1650
+ res[p] = createDeltaObject(fullVal, {});
1651
+ }
1652
+ else if (fullVal !== undefined && typeof fullVal !== "function") {
1653
+ // No recursion necessary, Just keep value from fullObj.
1654
+ // But skip values with function type
1655
+ res[p] = fullVal;
1656
+ }
1657
+ }
1658
+ }
1659
+ }
1660
+ return res;
1661
+ }
1662
+ function randstr(existing, bits, base, _recursion) {
1663
+ if (!base)
1664
+ base = 16;
1665
+ if (bits === undefined)
1666
+ bits = 24;
1667
+ if (bits <= 0)
1668
+ return "0";
1669
+ var digits = Math.log(Math.pow(2, bits)) / Math.log(base);
1670
+ var res = "";
1671
+ var i, b, x;
1672
+ for (i = 2; digits === Infinity; i *= 2) {
1673
+ digits = (Math.log(Math.pow(2, bits / i)) / Math.log(base)) * i;
1674
+ }
1675
+ var rem = digits - Math.floor(digits);
1676
+ for (i = 0; i < Math.floor(digits); i++) {
1677
+ x = Math.floor(Math.random() * base).toString(base);
1678
+ res = x + res;
1679
+ }
1680
+ if (rem) {
1681
+ b = Math.pow(base, rem);
1682
+ x = Math.floor(Math.random() * b).toString(base);
1683
+ res = x + res;
1684
+ }
1685
+ var parsed = parseInt(res, base);
1686
+ if ((existing && existing[res]) ||
1687
+ (parsed !== Infinity && parsed >= Math.pow(2, bits))) {
1688
+ if (_recursion > 10) {
1689
+ console.warn("randstr failed uniqueness");
1690
+ return res;
1691
+ }
1692
+ return randstr(existing, bits, base, (_recursion || 0) + 1);
1693
+ }
1694
+ else
1695
+ return res;
1696
+ }
1697
+ //# sourceMappingURL=Figure.js.map