flexdesk 0.16.1 → 0.17.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 (262) hide show
  1. package/CHANGELOG.md +112 -0
  2. package/LICENSE +0 -0
  3. package/README.md +2435 -42
  4. package/THIRD_PARTY_LICENSES.md +0 -0
  5. package/canvas.js +18 -0
  6. package/charts.js +21 -0
  7. package/core.js +14 -0
  8. package/css/base.css +1834 -75
  9. package/css/flexdesk.css +3165 -159
  10. package/css/overrides.css +16 -0
  11. package/css/reset.css +0 -0
  12. package/css/tokens.css +0 -0
  13. package/dist/canvas.js +6 -239
  14. package/dist/canvas.js.map +3 -3
  15. package/dist/charts.js +707 -18
  16. package/dist/charts.js.map +4 -4
  17. package/dist/chunk-3PHCPZHT.js +0 -0
  18. package/dist/chunk-3PHCPZHT.js.map +0 -0
  19. package/dist/chunk-4A7SJC3T.js +503 -0
  20. package/dist/chunk-4A7SJC3T.js.map +7 -0
  21. package/dist/{chunk-6JSOVNID.js → chunk-CVMCZZX2.js} +635 -10
  22. package/dist/chunk-CVMCZZX2.js.map +7 -0
  23. package/dist/chunk-D3COLZZ2.js +1311 -0
  24. package/dist/chunk-D3COLZZ2.js.map +7 -0
  25. package/dist/chunk-FOOS3T5L.js +0 -0
  26. package/dist/chunk-FOOS3T5L.js.map +0 -0
  27. package/dist/{chunk-SN4LSOAR.js → chunk-GOQLR5WR.js} +452 -2
  28. package/dist/chunk-GOQLR5WR.js.map +7 -0
  29. package/dist/{chunk-FL5KFNQH.js → chunk-HNU6MM2B.js} +52 -17
  30. package/dist/chunk-HNU6MM2B.js.map +7 -0
  31. package/dist/chunk-HYJYYEPK.js +375 -0
  32. package/dist/chunk-HYJYYEPK.js.map +7 -0
  33. package/dist/chunk-JKZLNKG6.js +2041 -0
  34. package/dist/chunk-JKZLNKG6.js.map +7 -0
  35. package/dist/chunk-JYWURG5T.js +0 -0
  36. package/dist/chunk-JYWURG5T.js.map +0 -0
  37. package/dist/{chunk-FBGP5KN5.js → chunk-LWV23YVE.js} +5073 -532
  38. package/dist/chunk-LWV23YVE.js.map +7 -0
  39. package/dist/chunk-N7HC3ADV.js +30 -0
  40. package/dist/chunk-N7HC3ADV.js.map +7 -0
  41. package/dist/{chunk-RQM5Z2MU.js → chunk-RMTRWWEO.js} +633 -311
  42. package/dist/chunk-RMTRWWEO.js.map +7 -0
  43. package/dist/{chunk-NLTOY57M.js → chunk-UURZ37SD.js} +28 -48
  44. package/dist/chunk-UURZ37SD.js.map +7 -0
  45. package/dist/{chunk-B5Q53LAJ.js → chunk-UWO43BZU.js} +2 -2
  46. package/dist/chunk-UWO43BZU.js.map +7 -0
  47. package/dist/chunk-WVFGV5FT.js +0 -0
  48. package/dist/chunk-WVFGV5FT.js.map +0 -0
  49. package/dist/core.js +170 -118
  50. package/dist/core.js.map +2 -2
  51. package/dist/editor.js +156 -70
  52. package/dist/editor.js.map +2 -2
  53. package/dist/flexdesk.css +3165 -159
  54. package/dist/flow.js +2789 -306
  55. package/dist/flow.js.map +4 -4
  56. package/dist/host.js +109 -3
  57. package/dist/host.js.map +3 -3
  58. package/dist/reset.css +0 -0
  59. package/dist/tile_registry-6WZPTUZV.js +0 -0
  60. package/dist/tile_registry-6WZPTUZV.js.map +0 -0
  61. package/dist/tiles.js +657 -234
  62. package/dist/tiles.js.map +4 -4
  63. package/dist/tokens.css +0 -0
  64. package/dist/widgets.js +3290 -2124
  65. package/dist/widgets.js.map +4 -4
  66. package/dist/wm.js +1227 -347
  67. package/dist/wm.js.map +4 -4
  68. package/editor.js +20 -0
  69. package/flow.js +21 -0
  70. package/host.js +14 -0
  71. package/package.json +12 -1
  72. package/src/canvas/canvas_adapter.js +5 -0
  73. package/src/canvas/edge_router.js +0 -0
  74. package/src/canvas/graph/connector_router.js +0 -0
  75. package/src/canvas/graph/history_service.js +0 -0
  76. package/src/canvas/graph/node_platform.js +0 -0
  77. package/src/canvas/index.js +1 -0
  78. package/src/canvas/layered_layout.js +244 -0
  79. package/src/charts/chart_types.js +0 -0
  80. package/src/charts/data_series_plot_window.js +0 -0
  81. package/src/charts/downsample.js +2 -2
  82. package/src/charts/plot_config.js +53 -29
  83. package/src/charts/plot_config_editor.js +627 -0
  84. package/src/charts/plot_grid.js +449 -0
  85. package/src/charts/plot_popout_window.js +103 -317
  86. package/src/charts/plotly_wrapper.js +22 -2
  87. package/src/charts/series_transforms.js +206 -0
  88. package/src/core/event_bus.js +0 -0
  89. package/src/core/logging.js +1 -1
  90. package/src/core/settings.js +105 -19
  91. package/src/core/state_guard.js +93 -51
  92. package/src/core/state_guard_config.js +85 -74
  93. package/src/core/state_machine.js +0 -0
  94. package/src/editor/editor_pane.js +3 -3
  95. package/src/editor/monaco_editor_factory.js +124 -60
  96. package/src/editor/monaco_loader.js +103 -28
  97. package/src/editor/notebook_search.js +0 -0
  98. package/src/editor/notebook_tab_bar.js +38 -52
  99. package/src/editor/notebook_undo_manager.js +0 -0
  100. package/src/editor/split_pane_container.js +6 -3
  101. package/src/flow/canvas_editor/connections.js +90 -0
  102. package/src/flow/canvas_editor/editor.js +2351 -153
  103. package/src/flow/canvas_editor/index.js +2 -1
  104. package/src/flow/canvas_editor/layout.js +119 -12
  105. package/src/flow/canvas_editor/strings.js +80 -0
  106. package/src/flow/kit/always_before.js +0 -0
  107. package/src/flow/kit/catalogue.js +97 -3
  108. package/src/flow/kit/chip_input.js +0 -0
  109. package/src/flow/kit/dom.js +0 -0
  110. package/src/flow/kit/findings.js +0 -0
  111. package/src/flow/kit/history.js +0 -0
  112. package/src/flow/kit/index.js +3 -3
  113. package/src/flow/kit/keys.js +7 -1
  114. package/src/flow/kit/logic_graph.js +97 -15
  115. package/src/flow/kit/references.js +0 -0
  116. package/src/flow/kit/settings_panel.js +0 -0
  117. package/src/flow/kit/settings_schema.js +2 -1
  118. package/src/flow/kit/step_picker.js +0 -0
  119. package/src/flow/kit/strings.js +3 -1
  120. package/src/flow/kit/value_picker.js +0 -0
  121. package/src/flow/kit/widgets.js +86 -109
  122. package/src/flow/lanes/editor.js +136 -14
  123. package/src/flow/lanes/index.js +3 -1
  124. package/src/flow/lanes/layout.js +0 -0
  125. package/src/flow/lanes/pipeline.js +44 -2
  126. package/src/flow/lanes/preview.js +0 -0
  127. package/src/flow/lanes/strings.js +1 -0
  128. package/src/flow/outline/editor.js +0 -0
  129. package/src/flow/outline/index.js +0 -0
  130. package/src/flow/outline/mapping.js +0 -0
  131. package/src/flow/outline/menu.js +0 -0
  132. package/src/flow/outline/operations.js +0 -0
  133. package/src/flow/outline/recognise.js +0 -0
  134. package/src/flow/outline/strings.js +0 -0
  135. package/src/help/help_modal.js +168 -42
  136. package/src/help/help_registry.js +12 -1
  137. package/src/host/external_links.js +0 -0
  138. package/src/host/file_picker.js +117 -0
  139. package/src/host/host.js +10 -2
  140. package/src/host/photino_host.js +9 -0
  141. package/src/host/photino_host.md +21 -3
  142. package/src/host/pywebview_host.js +10 -0
  143. package/src/tiles/chart_tiles.js +53 -245
  144. package/src/tiles/config_schema.js +8 -0
  145. package/src/tiles/figure_tile.js +322 -0
  146. package/src/tiles/layout_persistence.js +3 -3
  147. package/src/tiles/list_tiles.js +7 -7
  148. package/src/tiles/scope_picker.js +0 -0
  149. package/src/tiles/tile_base.js +1 -1
  150. package/src/tiles/tile_config_form.js +442 -0
  151. package/src/tiles/tile_grid.js +2 -0
  152. package/src/tiles/tile_registry.js +0 -0
  153. package/src/tiling/bottom_panel_tabs.js +67 -99
  154. package/src/tiling/command_palette.js +64 -19
  155. package/src/tiling/content_registry.js +4 -1
  156. package/src/tiling/desktops.js +11 -1
  157. package/src/tiling/entity_sources.js +0 -0
  158. package/src/tiling/keymap.js +403 -128
  159. package/src/tiling/kind_taxonomy.js +78 -0
  160. package/src/tiling/landing_table.js +0 -0
  161. package/src/tiling/loading_overlay.js +0 -0
  162. package/src/tiling/nav_panel.js +59 -10
  163. package/src/tiling/page_factory.js +5 -5
  164. package/src/tiling/panel_availability.js +49 -0
  165. package/src/tiling/panel_keys.js +0 -0
  166. package/src/tiling/shell.js +114 -12
  167. package/src/tiling/tab_strip.js +0 -0
  168. package/src/tiling/tile_breadcrumb.js +0 -0
  169. package/src/tiling/tile_renderer.js +105 -9
  170. package/src/tiling/tile_tab_menu.js +0 -0
  171. package/src/tiling/tile_tree.js +0 -0
  172. package/src/tiling/wm.js +562 -30
  173. package/src/tiling/zoom.js +0 -0
  174. package/src/ui/base/component_base.js +0 -0
  175. package/src/ui/base/controller_base.js +0 -0
  176. package/src/ui/base/page_base.js +0 -0
  177. package/src/ui/components/about_dialog.js +0 -0
  178. package/src/ui/components/action_dropdown.js +30 -2
  179. package/src/ui/components/alert_log.js +0 -0
  180. package/src/ui/components/alerts_pane.js +0 -0
  181. package/src/ui/components/attribute_list_editor.js +0 -0
  182. package/src/ui/components/autocomplete_field.js +0 -0
  183. package/src/ui/components/cell_editor_host.js +293 -0
  184. package/src/ui/components/cell_editors.js +480 -0
  185. package/src/ui/components/cell_grid.js +761 -0
  186. package/src/ui/components/cell_paste.js +243 -0
  187. package/src/ui/components/cell_selection.js +220 -0
  188. package/src/ui/components/choice_controls.js +351 -0
  189. package/src/ui/components/color_field.js +211 -0
  190. package/src/ui/components/color_list_field.js +210 -0
  191. package/src/ui/components/column_fit.js +0 -0
  192. package/src/ui/components/column_groups.js +314 -0
  193. package/src/ui/components/column_order.js +142 -0
  194. package/src/ui/components/computing_status_window.js +98 -25
  195. package/src/ui/components/confirm_dialog.js +81 -38
  196. package/src/ui/components/context_menu.js +2 -2
  197. package/src/ui/components/conversation_view.js +440 -0
  198. package/src/ui/components/crosstab.js +289 -0
  199. package/src/ui/components/data_table.js +696 -71
  200. package/src/ui/components/detail_header.js +22 -11
  201. package/src/ui/components/document_outline.js +397 -0
  202. package/src/ui/components/drag_reorder.js +0 -0
  203. package/src/ui/components/fact_table.js +0 -0
  204. package/src/ui/components/fill_handle.js +322 -0
  205. package/src/ui/components/gallery_picker.js +19 -8
  206. package/src/ui/components/header_actions.js +55 -0
  207. package/src/ui/components/inline_renamer.js +0 -0
  208. package/src/ui/components/job_progress.js +51 -0
  209. package/src/ui/components/managed_window.js +27 -4
  210. package/src/ui/components/menu_bar.js +745 -0
  211. package/src/ui/components/modal.js +449 -75
  212. package/src/ui/components/notification_history.js +3 -3
  213. package/src/ui/components/progress.js +483 -0
  214. package/src/ui/components/record_list.js +0 -0
  215. package/src/ui/components/row_activation.js +0 -0
  216. package/src/ui/components/section_stack.js +298 -0
  217. package/src/ui/components/series.js +173 -0
  218. package/src/ui/components/settings_view.js +634 -0
  219. package/src/ui/components/slide_out_panel.js +43 -6
  220. package/src/ui/components/slider_field.js +275 -18
  221. package/src/ui/components/sortable_list.js +0 -0
  222. package/src/ui/components/staged_edits.js +361 -0
  223. package/src/ui/components/staged_history.js +172 -0
  224. package/src/ui/components/table_filter_chips.js +0 -0
  225. package/src/ui/components/table_state_store.js +0 -0
  226. package/src/ui/components/table_structure.js +182 -0
  227. package/src/ui/components/table_values.js +0 -0
  228. package/src/ui/components/tabs.js +497 -0
  229. package/src/ui/components/tag_input.js +215 -0
  230. package/src/ui/components/toast.js +25 -8
  231. package/src/ui/components/toggle_field.js +175 -0
  232. package/src/ui/components/tree_view.js +55 -34
  233. package/src/ui/components/tsv.js +74 -0
  234. package/src/ui/components/window_taskbar.js +0 -0
  235. package/src/ui/components/wizard.js +563 -0
  236. package/src/ui/controllers/window_chrome_controller.js +2 -2
  237. package/src/ui/notification_center.js +375 -119
  238. package/src/ui/utils/auto_scrollbars.js +0 -0
  239. package/src/ui/utils/markdown.js +709 -0
  240. package/src/ui/utils/native_context_menu.js +0 -0
  241. package/src/ui/utils/overlay_scrollbar.js +16 -12
  242. package/src/ui/utils/raf_resize_observer.js +0 -0
  243. package/src/ui/utils/scroll_lock.js +0 -0
  244. package/src/ui/utils/strip_scroll.js +55 -0
  245. package/src/ui/utils/tooltip_service.js +0 -8
  246. package/tiles.js +27 -0
  247. package/widgets.js +69 -0
  248. package/wm.js +28 -0
  249. package/dist/chunk-6JSOVNID.js.map +0 -7
  250. package/dist/chunk-B5Q53LAJ.js.map +0 -7
  251. package/dist/chunk-FBGP5KN5.js.map +0 -7
  252. package/dist/chunk-FL5KFNQH.js.map +0 -7
  253. package/dist/chunk-NLTOY57M.js.map +0 -7
  254. package/dist/chunk-NNFTETK3.js +0 -633
  255. package/dist/chunk-NNFTETK3.js.map +0 -7
  256. package/dist/chunk-O5OHMWBB.js +0 -284
  257. package/dist/chunk-O5OHMWBB.js.map +0 -7
  258. package/dist/chunk-RQM5Z2MU.js.map +0 -7
  259. package/dist/chunk-SN4LSOAR.js.map +0 -7
  260. package/dist/chunk-W6FBJLPW.js +0 -367
  261. package/dist/chunk-W6FBJLPW.js.map +0 -7
  262. package/src/ui/controllers/panel_state_machine.js +0 -634
package/dist/charts.js CHANGED
@@ -1,10 +1,15 @@
1
+ import {
2
+ createTabs
3
+ } from "./chunk-HYJYYEPK.js";
1
4
  import {
2
5
  ALL_CHART_TYPES,
3
6
  CHART_TYPES_2D,
4
7
  CHART_TYPES_3D,
5
8
  COLOR_PALETTE,
6
9
  DARK_THEME_LAYOUT,
10
+ DEFAULT_CHART_EXPORT_FILENAME,
7
11
  DEFAULT_CONFIG,
12
+ PLOT_GRID_THEME,
8
13
  PLOT_LAYOUTS,
9
14
  PlotPopoutWindow,
10
15
  applyNanHandling,
@@ -21,35 +26,49 @@ import {
21
26
  buildYAxisLayout,
22
27
  createChart,
23
28
  createChartDeferred,
29
+ deriveSeriesTraces,
24
30
  ensurePlotly,
25
31
  extendTraces,
32
+ getChartExportFilename,
26
33
  getSeriesColor,
27
34
  hasPlot,
28
35
  hexToRgba,
29
36
  is3DChart,
30
37
  lttb,
38
+ makeDefaultSeries,
31
39
  makeDefaultSubplot,
40
+ makeDefaultYAxis,
32
41
  migrateData,
33
42
  migrateSingleChart,
34
43
  openPlotPopoutWindow,
35
44
  openRawTracesWindow,
36
45
  purge,
37
46
  relayout,
47
+ renderPlotGrid,
48
+ renderSeriesTransformControls,
38
49
  resize,
50
+ resolveSeriesData,
39
51
  restyle,
52
+ setChartExportFilename,
40
53
  setPlotlySource,
41
54
  strideDownsampleShared,
42
55
  strideIndices,
43
56
  uid,
44
57
  updateChart
45
- } from "./chunk-RQM5Z2MU.js";
58
+ } from "./chunk-RMTRWWEO.js";
46
59
  import {
60
+ AutocompleteField,
47
61
  createRafResizeObserver
48
- } from "./chunk-FBGP5KN5.js";
62
+ } from "./chunk-LWV23YVE.js";
49
63
  import {
50
- ManagedWindow
51
- } from "./chunk-6JSOVNID.js";
52
- import "./chunk-FL5KFNQH.js";
64
+ ColorField,
65
+ ManagedWindow,
66
+ ToggleField,
67
+ selectBox
68
+ } from "./chunk-CVMCZZX2.js";
69
+ import "./chunk-HNU6MM2B.js";
70
+ import "./chunk-N7HC3ADV.js";
71
+ import "./chunk-WVFGV5FT.js";
53
72
  import "./chunk-JYWURG5T.js";
54
73
 
55
74
  // src/charts/data_series_plot_window.js
@@ -243,20 +262,20 @@ var DataSeriesPlotWindow = class _DataSeriesPlotWindow {
243
262
  return section;
244
263
  }
245
264
  #buildXColumnSelect() {
246
- const select = document.createElement("select");
265
+ const select2 = document.createElement("select");
247
266
  for (const header of this.headers) {
248
267
  if (!this._numericColumns.has(header)) continue;
249
268
  const opt = document.createElement("option");
250
269
  opt.value = header;
251
270
  opt.textContent = this.labelHeader(header);
252
271
  if (header === this._config.xColumn) opt.selected = true;
253
- select.appendChild(opt);
272
+ select2.appendChild(opt);
254
273
  }
255
- select.addEventListener("change", () => {
256
- this._config.xColumn = select.value;
274
+ select2.addEventListener("change", () => {
275
+ this._config.xColumn = select2.value;
257
276
  this.#onConfigChanged();
258
277
  });
259
- return select;
278
+ return select2;
260
279
  }
261
280
  #populateYColumns() {
262
281
  const list = this._yColumnsList;
@@ -313,16 +332,16 @@ var DataSeriesPlotWindow = class _DataSeriesPlotWindow {
313
332
  return getSeriesColor(index);
314
333
  }
315
334
  #buildSelect(options, value, onChange) {
316
- const select = document.createElement("select");
335
+ const select2 = document.createElement("select");
317
336
  for (const opt of options) {
318
- const el = document.createElement("option");
319
- el.value = opt;
320
- el.textContent = opt.charAt(0).toUpperCase() + opt.slice(1);
321
- if (opt === value) el.selected = true;
322
- select.appendChild(el);
337
+ const el2 = document.createElement("option");
338
+ el2.value = opt;
339
+ el2.textContent = opt.charAt(0).toUpperCase() + opt.slice(1);
340
+ if (opt === value) el2.selected = true;
341
+ select2.appendChild(el2);
323
342
  }
324
- select.addEventListener("change", () => onChange(select.value));
325
- return select;
343
+ select2.addEventListener("change", () => onChange(select2.value));
344
+ return select2;
326
345
  }
327
346
  #buildCheckbox(label, checked, onChange) {
328
347
  const wrapper = document.createElement("label");
@@ -663,13 +682,674 @@ function closeDataSeriesPlotWindow(seriesId) {
663
682
  _openPlotWindows.delete(seriesId);
664
683
  }
665
684
  }
685
+
686
+ // src/charts/plot_config_editor.js
687
+ var CHART_TYPE_OPTIONS = Object.freeze([
688
+ { group: "2D", options: CHART_TYPES_2D },
689
+ { group: "3D", options: CHART_TYPES_3D }
690
+ ]);
691
+ var SCALES = Object.freeze([{ value: "linear", label: "Linear" }, { value: "log", label: "Log" }]);
692
+ var POSITIONS = Object.freeze([{ value: "left", label: "Left" }, { value: "right", label: "Right" }]);
693
+ var DASHES = Object.freeze([
694
+ { value: "solid", label: "Solid" },
695
+ { value: "dashed", label: "Dashed" },
696
+ { value: "dotted", label: "Dotted" }
697
+ ]);
698
+ var LEGEND_POSITIONS2 = Object.freeze([
699
+ { value: "hidden", label: "Hidden" },
700
+ { value: "top", label: "Top" },
701
+ { value: "bottom", label: "Bottom" },
702
+ { value: "left", label: "Left" },
703
+ { value: "right", label: "Right" }
704
+ ]);
705
+ var INTERPOLATIONS = Object.freeze([
706
+ { value: "linear", label: "Linear" },
707
+ { value: "step", label: "Step" },
708
+ { value: "cubic", label: "Cubic spline" }
709
+ ]);
710
+ var NAN_STRATEGIES = Object.freeze([
711
+ { value: "gap", label: "Gap" },
712
+ { value: "zero", label: "Zero" },
713
+ { value: "hold", label: "Hold last value" },
714
+ { value: "interpolate", label: "Interpolate" }
715
+ ]);
716
+ var X_SOURCES = Object.freeze([{ value: "time", label: "Time" }, { value: "series", label: "Series" }]);
717
+ var OVERLAY_MODES = Object.freeze([
718
+ { value: "markers+lines", label: "Markers and lines" },
719
+ { value: "markers", label: "Markers" },
720
+ { value: "lines", label: "Lines" }
721
+ ]);
722
+ function el(tag, className, text) {
723
+ const node = document.createElement(tag);
724
+ if (className) node.className = className;
725
+ if (text != null) node.textContent = String(text);
726
+ return node;
727
+ }
728
+ function button(text, onClick, { title = null, className = "twm-btn twm-plot-config__add" } = {}) {
729
+ const b = el("button", className, text);
730
+ b.type = "button";
731
+ if (title) b.title = title;
732
+ b.addEventListener("click", () => {
733
+ if (!b.disabled) onClick();
734
+ });
735
+ return b;
736
+ }
737
+ function removeButton(title, onClick) {
738
+ const b = button("", onClick, { title, className: "twm-btn-icon twm-plot-config__remove" });
739
+ b.setAttribute("aria-label", title);
740
+ b.appendChild(el("span", "material-symbols-outlined", "close"));
741
+ return b;
742
+ }
743
+ function field(label, control) {
744
+ const single = control.matches("input, select, textarea");
745
+ const row = el(single ? "label" : "div", "twm-plot-config__field");
746
+ row.append(el("span", "twm-plot-config__label", label), control);
747
+ return row;
748
+ }
749
+ function textInput(value, onSet, { placeholder = "", label = null } = {}) {
750
+ const input = el("input", "twm-plot-config__input");
751
+ input.type = "text";
752
+ input.value = value ?? "";
753
+ input.placeholder = placeholder;
754
+ if (label) input.setAttribute("aria-label", label);
755
+ input.addEventListener("input", () => onSet(input.value));
756
+ return input;
757
+ }
758
+ function numberInput(value, onSet, { placeholder = "Auto", label = null, min = null, max = null, step = "any" } = {}) {
759
+ const input = el("input", "twm-plot-config__input twm-plot-config__input--number");
760
+ input.type = "number";
761
+ input.step = String(step);
762
+ if (min != null) input.min = String(min);
763
+ if (max != null) input.max = String(max);
764
+ input.value = value == null ? "" : String(value);
765
+ input.placeholder = placeholder;
766
+ if (label) input.setAttribute("aria-label", label);
767
+ input.addEventListener("change", () => {
768
+ const n = parseFloat(input.value);
769
+ onSet(Number.isFinite(n) ? n : null);
770
+ });
771
+ return input;
772
+ }
773
+ function select(options, value, onPick, { label = null, empty = null } = {}) {
774
+ const s = selectBox(options, value, {
775
+ label: label ?? "",
776
+ empty,
777
+ className: "twm-plot-config__input twm-plot-config__input--select"
778
+ });
779
+ s.box.addEventListener("change", () => onPick(s.valueOf()));
780
+ return s.box;
781
+ }
782
+ function makeZAxis() {
783
+ return { label: "", scale: "linear", min: null, max: null, step: null, variable: "" };
784
+ }
785
+ var editorCount = 0;
786
+ function renderPlotConfigEditor(container, config, options = {}) {
787
+ const opts = {
788
+ onChange: null,
789
+ seriesProvider: null,
790
+ overlaySources: null,
791
+ seriesTransforms: null,
792
+ extraSeriesFields: null,
793
+ logger: null,
794
+ ...options
795
+ };
796
+ const editorId = `twm-plot-config-${++editorCount}`;
797
+ let fieldCount = 0;
798
+ let active = 0;
799
+ let disposed = false;
800
+ let bodyDisposers = [];
801
+ let generation = 0;
802
+ const notify = () => {
803
+ if (!disposed) opts.onChange?.(config);
804
+ };
805
+ const track = (fn) => {
806
+ bodyDisposers.push(fn);
807
+ };
808
+ const template = () => PLOT_LAYOUTS[config.layout] || PLOT_LAYOUTS["1x1"];
809
+ const slots = () => template().slots;
810
+ function ensureSubplots() {
811
+ if (!Array.isArray(config.subplots)) config.subplots = [];
812
+ while (config.subplots.length < slots()) {
813
+ config.subplots.push(makeDefaultSubplot(config.subplots.length));
814
+ }
815
+ }
816
+ const root = el("div", "twm-plot-config");
817
+ const layoutButtons = /* @__PURE__ */ new Map();
818
+ const picker = el("div", "twm-plot-config__layouts");
819
+ picker.setAttribute("role", "group");
820
+ picker.setAttribute("aria-label", "Layout");
821
+ for (const [key, tmpl] of Object.entries(PLOT_LAYOUTS)) {
822
+ const b = button(tmpl.label, () => setLayout(key), { className: "twm-btn twm-plot-config__layout" });
823
+ layoutButtons.set(key, b);
824
+ picker.appendChild(b);
825
+ }
826
+ const syncLayoutButtons = () => {
827
+ for (const [key, b] of layoutButtons) {
828
+ const on = key === config.layout;
829
+ b.setAttribute("aria-pressed", on ? "true" : "false");
830
+ b.classList.toggle("twm-plot-config__layout--on", on);
831
+ }
832
+ };
833
+ root.appendChild(section("Layout", picker));
834
+ const tabsHost = el("div", "twm-plot-config__tabs");
835
+ const body = el("div", "twm-plot-config__body");
836
+ root.append(tabsHost, body);
837
+ container.appendChild(root);
838
+ ensureSubplots();
839
+ const tabItems = () => Array.from({ length: slots() }, (_, i) => ({ id: i, label: `Subplot ${i + 1}` }));
840
+ const tabs = createTabs(tabsHost, {
841
+ items: tabItems(),
842
+ active: 0,
843
+ compact: true,
844
+ label: "Subplots",
845
+ onSelect: (id) => {
846
+ if (id == null || id === active) return;
847
+ active = id;
848
+ renderBody();
849
+ }
850
+ });
851
+ const syncChrome = () => {
852
+ syncLayoutButtons();
853
+ tabs.update(tabItems(), active);
854
+ tabsHost.hidden = slots() < 2;
855
+ };
856
+ function setLayout(key) {
857
+ if (disposed || key === config.layout) return;
858
+ config.layout = key;
859
+ ensureSubplots();
860
+ active = Math.min(active, slots() - 1);
861
+ syncChrome();
862
+ renderBody();
863
+ notify();
864
+ }
865
+ function section(title, ...children) {
866
+ const s = el("section", "twm-plot-config__section");
867
+ s.appendChild(el("h4", "twm-plot-config__heading", title));
868
+ for (const child of children) if (child) s.appendChild(child);
869
+ return s;
870
+ }
871
+ function disposeBody() {
872
+ generation += 1;
873
+ const disposers = bodyDisposers;
874
+ bodyDisposers = [];
875
+ for (const fn of disposers) {
876
+ try {
877
+ fn();
878
+ } catch (error) {
879
+ opts.logger?.warn?.("[plot config editor] a field failed to dispose", error);
880
+ }
881
+ }
882
+ }
883
+ function seriesPicker(target, key, role, sp, placeholder) {
884
+ let alive = true;
885
+ const ac = new AutocompleteField({
886
+ fieldId: `${editorId}-field-${++fieldCount}`,
887
+ field: { placeholder, value: target[key] ?? "" },
888
+ skipNamespacePrefix: true,
889
+ logger: opts.logger,
890
+ provider: ({ value }) => opts.seriesProvider ? opts.seriesProvider({ value, role, subplot: sp }) : [],
891
+ onChange: (value) => {
892
+ if (!alive || (target[key] ?? "") === value) return;
893
+ target[key] = value;
894
+ notify();
895
+ }
896
+ });
897
+ track(() => {
898
+ alive = false;
899
+ ac.dispose();
900
+ });
901
+ const node = ac.render();
902
+ node.classList.add("twm-plot-config__picker");
903
+ return node;
904
+ }
905
+ function colorField(value, onSet, label) {
906
+ const f = new ColorField({
907
+ value: value ?? "",
908
+ label,
909
+ onChange: (v) => {
910
+ if (v !== null) {
911
+ onSet(v || null);
912
+ notify();
913
+ }
914
+ }
915
+ });
916
+ track(() => f.dispose());
917
+ return f.render();
918
+ }
919
+ function toggle(label, checked, onSet) {
920
+ const t = new ToggleField({ label, checked, compact: true, onChange: (on) => {
921
+ onSet(on);
922
+ notify();
923
+ } });
924
+ track(() => t.dispose());
925
+ return t.render();
926
+ }
927
+ function listEditor(sp, key, { addLabel, makeItem, fields }) {
928
+ if (!Array.isArray(sp[key])) sp[key] = [];
929
+ const items = sp[key];
930
+ const wrap = el("div", "twm-plot-config__list");
931
+ items.forEach((item, i) => {
932
+ const row = el("div", "twm-plot-config__row");
933
+ row.append(...fields(item), removeButton("Remove", () => {
934
+ items.splice(i, 1);
935
+ renderBody();
936
+ notify();
937
+ }));
938
+ wrap.appendChild(row);
939
+ });
940
+ wrap.appendChild(button(addLabel, () => {
941
+ items.push(makeItem());
942
+ renderBody();
943
+ notify();
944
+ }));
945
+ return wrap;
946
+ }
947
+ function normalise(sp) {
948
+ if (!sp.xAxis) sp.xAxis = { useTime: true, variable: "" };
949
+ if (!Array.isArray(sp.yAxes) || !sp.yAxes.length) sp.yAxes = [makeDefaultYAxis(0)];
950
+ for (const axis of sp.yAxes) if (!Array.isArray(axis.series)) axis.series = [];
951
+ if (is3DChart(sp.chartType) && !sp.zAxis) sp.zAxis = makeZAxis();
952
+ }
953
+ function renderBody() {
954
+ if (disposed) return;
955
+ disposeBody();
956
+ body.replaceChildren();
957
+ const sp = config.subplots[active];
958
+ if (!sp) return;
959
+ normalise(sp);
960
+ const is3D = is3DChart(sp.chartType);
961
+ let sources = null;
962
+ const overlaySources = () => sources ??= Promise.resolve().then(() => opts.overlaySources());
963
+ body.append(
964
+ section("Subplot", field("Title", textInput(
965
+ sp.displayName,
966
+ (v) => {
967
+ sp.displayName = v;
968
+ notify();
969
+ },
970
+ { placeholder: "Untitled" }
971
+ ))),
972
+ section("Display", ...displayFields(sp)),
973
+ section("X axis", ...xAxisFields(sp)),
974
+ section("Y axes", yAxesEditor(sp, is3D, overlaySources)),
975
+ is3D ? section("Z axis", ...zAxisFields(sp)) : null,
976
+ section("Reference lines", referenceLinesEditor(sp)),
977
+ section("Shaded bands", shadedBandsEditor(sp)),
978
+ transformsSection(sp)
979
+ );
980
+ }
981
+ function displayFields(sp) {
982
+ return [
983
+ field("Chart type", select(CHART_TYPE_OPTIONS, sp.chartType ?? "line", (v) => {
984
+ const was3D = is3DChart(sp.chartType);
985
+ sp.chartType = v;
986
+ const now3D = is3DChart(v);
987
+ if (now3D) sp.zAxis ??= makeZAxis();
988
+ else sp.zAxis = null;
989
+ if (was3D !== now3D) renderBody();
990
+ notify();
991
+ })),
992
+ field("Legend", select(
993
+ LEGEND_POSITIONS2,
994
+ sp.legendPosition ?? "hidden",
995
+ (v) => {
996
+ sp.legendPosition = v;
997
+ notify();
998
+ }
999
+ )),
1000
+ field("Interpolation", select(
1001
+ INTERPOLATIONS,
1002
+ sp.interpolation ?? "linear",
1003
+ (v) => {
1004
+ sp.interpolation = v;
1005
+ notify();
1006
+ }
1007
+ )),
1008
+ field("Missing values", select(
1009
+ NAN_STRATEGIES,
1010
+ sp.nanHandling ?? "gap",
1011
+ (v) => {
1012
+ sp.nanHandling = v;
1013
+ notify();
1014
+ }
1015
+ )),
1016
+ toggle("Data points", sp.showDataPoints === true, (on) => {
1017
+ sp.showDataPoints = on;
1018
+ })
1019
+ ];
1020
+ }
1021
+ function xAxisFields(sp) {
1022
+ const useTime = sp.xAxis.useTime !== false;
1023
+ const out = [field("Against", select(X_SOURCES, useTime ? "time" : "series", (v) => {
1024
+ sp.xAxis.useTime = v === "time";
1025
+ renderBody();
1026
+ notify();
1027
+ }))];
1028
+ if (!useTime) {
1029
+ out.push(
1030
+ field("Series", seriesPicker(sp.xAxis, "variable", "x", sp, "X series")),
1031
+ field("Label", textInput(
1032
+ sp.xAxis.label,
1033
+ (v) => {
1034
+ sp.xAxis.label = v;
1035
+ notify();
1036
+ },
1037
+ { placeholder: sp.xAxis.variable || "Axis title" }
1038
+ ))
1039
+ );
1040
+ }
1041
+ return out;
1042
+ }
1043
+ function zAxisFields(sp) {
1044
+ const z = sp.zAxis;
1045
+ return [
1046
+ field("Series", seriesPicker(z, "variable", "z", sp, "Z series")),
1047
+ field("Label", textInput(z.label, (v) => {
1048
+ z.label = v;
1049
+ notify();
1050
+ }, { placeholder: "Axis title" })),
1051
+ field("Scale", select(SCALES, z.scale ?? "linear", (v) => {
1052
+ z.scale = v;
1053
+ notify();
1054
+ })),
1055
+ field("Min", numberInput(z.min, (v) => {
1056
+ z.min = v;
1057
+ notify();
1058
+ })),
1059
+ field("Max", numberInput(z.max, (v) => {
1060
+ z.max = v;
1061
+ notify();
1062
+ })),
1063
+ field("Step", numberInput(z.step, (v) => {
1064
+ z.step = v;
1065
+ notify();
1066
+ }))
1067
+ ];
1068
+ }
1069
+ function yAxesEditor(sp, is3D, overlaySources) {
1070
+ const wrap = el("div", "twm-plot-config__axes");
1071
+ sp.yAxes.forEach((axis, i) => wrap.appendChild(yAxisEditor(sp, axis, i, is3D, overlaySources)));
1072
+ const add = button("Add Y axis", () => {
1073
+ sp.yAxes.push(makeDefaultYAxis(sp.yAxes.length));
1074
+ renderBody();
1075
+ notify();
1076
+ }, { title: is3D ? "A 3D chart has one Y axis" : null });
1077
+ add.disabled = is3D;
1078
+ wrap.appendChild(add);
1079
+ return wrap;
1080
+ }
1081
+ function yAxisEditor(sp, axis, index, is3D, overlaySources) {
1082
+ const group = el("fieldset", "twm-plot-config__axis");
1083
+ const legend = el("legend", "twm-plot-config__axis-title", `Y axis ${index + 1}`);
1084
+ group.appendChild(legend);
1085
+ if (sp.yAxes.length > 1) {
1086
+ legend.appendChild(removeButton("Remove Y axis", () => {
1087
+ sp.yAxes.splice(index, 1);
1088
+ renderBody();
1089
+ notify();
1090
+ }));
1091
+ }
1092
+ if (is3D && index > 0) {
1093
+ group.disabled = true;
1094
+ group.classList.add("twm-plot-config__axis--disabled");
1095
+ group.title = "A 3D chart uses the first Y axis only";
1096
+ }
1097
+ const fields = el("div", "twm-plot-config__axis-fields");
1098
+ fields.append(
1099
+ field("Label", textInput(axis.label, (v) => {
1100
+ axis.label = v;
1101
+ notify();
1102
+ }, { placeholder: "Axis title" })),
1103
+ field("Scale", select(SCALES, axis.scale ?? "linear", (v) => {
1104
+ axis.scale = v;
1105
+ notify();
1106
+ })),
1107
+ field("Position", select(POSITIONS, axis.position ?? "left", (v) => {
1108
+ axis.position = v;
1109
+ notify();
1110
+ })),
1111
+ field("Min", numberInput(axis.min, (v) => {
1112
+ axis.min = v;
1113
+ notify();
1114
+ })),
1115
+ field("Max", numberInput(axis.max, (v) => {
1116
+ axis.max = v;
1117
+ notify();
1118
+ })),
1119
+ field("Step", numberInput(axis.step, (v) => {
1120
+ axis.step = v;
1121
+ notify();
1122
+ }))
1123
+ );
1124
+ group.appendChild(fields);
1125
+ const list = el("div", "twm-plot-config__series-list");
1126
+ if (!axis.series.length) list.appendChild(el("div", "twm-plot-config__empty", "No series."));
1127
+ for (const s of axis.series) list.appendChild(seriesRow(sp, axis, s, overlaySources));
1128
+ group.appendChild(list);
1129
+ group.appendChild(button("Add series", () => {
1130
+ const count = sp.yAxes.reduce((n, a) => n + (a.series?.length ?? 0), 0);
1131
+ axis.series.push(makeDefaultSeries(count));
1132
+ renderBody();
1133
+ notify();
1134
+ }));
1135
+ return group;
1136
+ }
1137
+ function seriesRow(sp, axis, s, overlaySources) {
1138
+ const row = el("div", "twm-plot-config__series");
1139
+ const main = el("div", "twm-plot-config__series-main");
1140
+ main.append(
1141
+ seriesPicker(s, "variable", "series", sp, "Series"),
1142
+ textInput(s.label, (v) => {
1143
+ s.label = v;
1144
+ notify();
1145
+ }, { placeholder: "Legend label", label: "Legend label" }),
1146
+ colorField(s.color, (v) => {
1147
+ if (v) s.color = v;
1148
+ else delete s.color;
1149
+ }, "Colour"),
1150
+ numberInput(
1151
+ s.lineWidth ?? 2,
1152
+ (v) => {
1153
+ s.lineWidth = v ?? 2;
1154
+ notify();
1155
+ },
1156
+ { placeholder: "2", label: "Line width", min: 1, max: 10, step: 1 }
1157
+ ),
1158
+ select(DASHES, s.lineStyle ?? "solid", (v) => {
1159
+ s.lineStyle = v;
1160
+ notify();
1161
+ }, { label: "Dash" }),
1162
+ textInput(
1163
+ s.stackGroup,
1164
+ (v) => {
1165
+ s.stackGroup = v || null;
1166
+ notify();
1167
+ },
1168
+ { placeholder: "Stack group", label: "Stack group" }
1169
+ ),
1170
+ removeButton("Remove series", () => {
1171
+ const i = axis.series.indexOf(s);
1172
+ if (i >= 0) axis.series.splice(i, 1);
1173
+ renderBody();
1174
+ notify();
1175
+ })
1176
+ );
1177
+ row.appendChild(main);
1178
+ if (opts.extraSeriesFields) {
1179
+ const extra = el("div", "twm-plot-config__series-extra");
1180
+ row.appendChild(extra);
1181
+ const handle = opts.extraSeriesFields(extra, s, { subplot: sp, axis, onChange: notify });
1182
+ if (typeof handle?.dispose === "function") track(() => handle.dispose());
1183
+ }
1184
+ if (opts.overlaySources) row.appendChild(overlayEditor(s, overlaySources));
1185
+ return row;
1186
+ }
1187
+ function overlayEditor(s, overlaySources) {
1188
+ const wrap = el("div", "twm-plot-config__overlay");
1189
+ const head = el("div", "twm-plot-config__overlay-source", "Loading overlay sources\u2026");
1190
+ const details = el("div", "twm-plot-config__overlay-fields");
1191
+ wrap.append(head, details);
1192
+ const drawDetails = () => {
1193
+ details.replaceChildren();
1194
+ const ov = s.overlay;
1195
+ if (!ov) return;
1196
+ details.append(
1197
+ field("Label", textInput(
1198
+ ov.label,
1199
+ (v) => {
1200
+ ov.label = v;
1201
+ notify();
1202
+ },
1203
+ { placeholder: `${s.label || s.variable || "Series"} (actual)` }
1204
+ )),
1205
+ field("Colour", colorField(ov.color, (v) => {
1206
+ if (v) ov.color = v;
1207
+ else delete ov.color;
1208
+ }, "Overlay colour")),
1209
+ field("Dash", select(DASHES, ov.lineStyle ?? "dashed", (v) => {
1210
+ ov.lineStyle = v;
1211
+ notify();
1212
+ })),
1213
+ field("Width", numberInput(
1214
+ ov.lineWidth ?? 2,
1215
+ (v) => {
1216
+ ov.lineWidth = v ?? 2;
1217
+ notify();
1218
+ },
1219
+ { placeholder: "2", min: 1, max: 10, step: 1 }
1220
+ )),
1221
+ field("Mode", select(OVERLAY_MODES, ov.mode ?? "markers+lines", (v) => {
1222
+ ov.mode = v;
1223
+ notify();
1224
+ }))
1225
+ );
1226
+ };
1227
+ const gen = generation;
1228
+ overlaySources().then((list) => {
1229
+ if (disposed || gen !== generation) return;
1230
+ head.replaceChildren(field("Overlay", select(Array.isArray(list) ? list : [], s.overlay?.source, (v) => {
1231
+ if (v === void 0) delete s.overlay;
1232
+ else s.overlay = { ...s.overlay ?? {}, source: v };
1233
+ drawDetails();
1234
+ notify();
1235
+ }, { empty: "None" })));
1236
+ drawDetails();
1237
+ }, () => {
1238
+ if (disposed || gen !== generation) return;
1239
+ head.textContent = "Could not load overlay sources.";
1240
+ head.classList.add("twm-plot-config__overlay-source--error");
1241
+ });
1242
+ return wrap;
1243
+ }
1244
+ function referenceLinesEditor(sp) {
1245
+ const axisOptions = sp.yAxes.map((a, i) => ({ value: a.id, label: a.label || `Y axis ${i + 1}` }));
1246
+ return listEditor(sp, "referenceLines", {
1247
+ addLabel: "Add reference line",
1248
+ makeItem: () => ({ yAxisId: sp.yAxes[0].id, value: 0, label: "", lineStyle: "dashed" }),
1249
+ fields: (line) => [
1250
+ select(
1251
+ axisOptions,
1252
+ line.yAxisId ?? sp.yAxes[0].id,
1253
+ (v) => {
1254
+ line.yAxisId = v;
1255
+ notify();
1256
+ },
1257
+ { label: "Axis" }
1258
+ ),
1259
+ numberInput(line.value, (v) => {
1260
+ line.value = v;
1261
+ notify();
1262
+ }, { placeholder: "Value", label: "Value" }),
1263
+ textInput(line.label, (v) => {
1264
+ line.label = v;
1265
+ notify();
1266
+ }, { placeholder: "Label", label: "Label" }),
1267
+ colorField(line.color, (v) => {
1268
+ if (v) line.color = v;
1269
+ else delete line.color;
1270
+ }, "Colour"),
1271
+ select(DASHES, line.lineStyle ?? "dashed", (v) => {
1272
+ line.lineStyle = v;
1273
+ notify();
1274
+ }, { label: "Dash" })
1275
+ ]
1276
+ });
1277
+ }
1278
+ function shadedBandsEditor(sp) {
1279
+ return listEditor(sp, "shadedBands", {
1280
+ addLabel: "Add shaded band",
1281
+ makeItem: () => ({ x0: null, x1: null, label: "" }),
1282
+ fields: (band) => [
1283
+ numberInput(band.x0, (v) => {
1284
+ band.x0 = v;
1285
+ notify();
1286
+ }, { placeholder: "From", label: "From" }),
1287
+ numberInput(band.x1, (v) => {
1288
+ band.x1 = v;
1289
+ notify();
1290
+ }, { placeholder: "To", label: "To" }),
1291
+ textInput(band.label, (v) => {
1292
+ band.label = v;
1293
+ notify();
1294
+ }, { placeholder: "Label", label: "Label" }),
1295
+ colorField(band.color, (v) => {
1296
+ if (v) band.color = v;
1297
+ else delete band.color;
1298
+ }, "Colour"),
1299
+ numberInput(band.opacity, (v) => {
1300
+ if (v == null) delete band.opacity;
1301
+ else band.opacity = v;
1302
+ notify();
1303
+ }, { placeholder: "Opacity", label: "Opacity", min: 0, max: 1, step: 0.05 })
1304
+ ]
1305
+ });
1306
+ }
1307
+ function transformsSection(sp) {
1308
+ if (!Object.keys(opts.seriesTransforms ?? {}).length) return null;
1309
+ const s = section("Derived series");
1310
+ const controls = renderSeriesTransformControls(s, sp, opts.seriesTransforms, { onChange: notify });
1311
+ track(() => controls.dispose());
1312
+ return s;
1313
+ }
1314
+ syncChrome();
1315
+ renderBody();
1316
+ return {
1317
+ /** Dispose every field it created and remove the editor. Later calls do nothing. */
1318
+ dispose() {
1319
+ if (disposed) return;
1320
+ disposed = true;
1321
+ disposeBody();
1322
+ tabs.destroy();
1323
+ root.remove();
1324
+ },
1325
+ /** Redraw from the config, after it was changed from outside. */
1326
+ refresh() {
1327
+ if (disposed) return;
1328
+ ensureSubplots();
1329
+ active = Math.min(active, slots() - 1);
1330
+ syncChrome();
1331
+ renderBody();
1332
+ },
1333
+ /** Bring subplot `index` to the front. */
1334
+ selectSubplot(index) {
1335
+ if (disposed || !Number.isInteger(index) || index < 0 || index >= slots()) return;
1336
+ tabs.select(index);
1337
+ },
1338
+ /** The index of the subplot in front. */
1339
+ get activeSubplot() {
1340
+ return active;
1341
+ }
1342
+ };
1343
+ }
666
1344
  export {
667
1345
  ALL_CHART_TYPES,
668
1346
  CHART_TYPES_2D,
669
1347
  CHART_TYPES_3D,
670
1348
  COLOR_PALETTE,
671
1349
  DARK_THEME_LAYOUT,
1350
+ DEFAULT_CHART_EXPORT_FILENAME,
672
1351
  DEFAULT_CONFIG,
1352
+ PLOT_GRID_THEME,
673
1353
  PLOT_LAYOUTS,
674
1354
  PlotPopoutWindow,
675
1355
  applyNanHandling,
@@ -687,14 +1367,18 @@ export {
687
1367
  closeDataSeriesPlotWindow,
688
1368
  createChart,
689
1369
  createChartDeferred,
1370
+ deriveSeriesTraces,
690
1371
  ensurePlotly,
691
1372
  extendTraces,
1373
+ getChartExportFilename,
692
1374
  getSeriesColor,
693
1375
  hasPlot,
694
1376
  hexToRgba,
695
1377
  is3DChart,
696
1378
  lttb,
1379
+ makeDefaultSeries,
697
1380
  makeDefaultSubplot,
1381
+ makeDefaultYAxis,
698
1382
  migrateData,
699
1383
  migrateSingleChart,
700
1384
  openDataSeriesPlotWindow,
@@ -702,8 +1386,13 @@ export {
702
1386
  openRawTracesWindow,
703
1387
  purge,
704
1388
  relayout,
1389
+ renderPlotConfigEditor,
1390
+ renderPlotGrid,
1391
+ renderSeriesTransformControls,
705
1392
  resize,
1393
+ resolveSeriesData,
706
1394
  restyle,
1395
+ setChartExportFilename,
707
1396
  setPlotlySource,
708
1397
  strideDownsampleShared,
709
1398
  strideIndices,