flexdesk 0.16.1 → 0.17.0
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.
- package/CHANGELOG.md +93 -0
- package/LICENSE +0 -0
- package/README.md +2217 -42
- package/THIRD_PARTY_LICENSES.md +0 -0
- package/css/base.css +1834 -75
- package/css/flexdesk.css +3146 -164
- package/css/overrides.css +16 -0
- package/css/reset.css +0 -0
- package/css/tokens.css +0 -0
- package/dist/canvas.js +6 -239
- package/dist/canvas.js.map +3 -3
- package/dist/charts.js +709 -18
- package/dist/charts.js.map +4 -4
- package/dist/chunk-3PHCPZHT.js +0 -0
- package/dist/chunk-3PHCPZHT.js.map +0 -0
- package/dist/chunk-4A7SJC3T.js +503 -0
- package/dist/chunk-4A7SJC3T.js.map +7 -0
- package/dist/{chunk-6JSOVNID.js → chunk-CVMCZZX2.js} +635 -10
- package/dist/chunk-CVMCZZX2.js.map +7 -0
- package/dist/chunk-D3COLZZ2.js +1311 -0
- package/dist/chunk-D3COLZZ2.js.map +7 -0
- package/dist/chunk-FOOS3T5L.js +0 -0
- package/dist/chunk-FOOS3T5L.js.map +0 -0
- package/dist/{chunk-SN4LSOAR.js → chunk-GOQLR5WR.js} +452 -2
- package/dist/chunk-GOQLR5WR.js.map +7 -0
- package/dist/{chunk-FL5KFNQH.js → chunk-HNU6MM2B.js} +52 -17
- package/dist/chunk-HNU6MM2B.js.map +7 -0
- package/dist/chunk-HYJYYEPK.js +375 -0
- package/dist/chunk-HYJYYEPK.js.map +7 -0
- package/dist/chunk-JKZLNKG6.js +2041 -0
- package/dist/chunk-JKZLNKG6.js.map +7 -0
- package/dist/chunk-JYWURG5T.js +0 -0
- package/dist/chunk-JYWURG5T.js.map +0 -0
- package/dist/{chunk-RQM5Z2MU.js → chunk-MCIXFNVF.js} +633 -311
- package/dist/chunk-MCIXFNVF.js.map +7 -0
- package/dist/chunk-N7HC3ADV.js +30 -0
- package/dist/chunk-N7HC3ADV.js.map +7 -0
- package/dist/{chunk-FBGP5KN5.js → chunk-Q36EPT2R.js} +3268 -203
- package/dist/chunk-Q36EPT2R.js.map +7 -0
- package/dist/chunk-QWQJUDPD.js +610 -0
- package/dist/chunk-QWQJUDPD.js.map +7 -0
- package/dist/{chunk-NLTOY57M.js → chunk-UURZ37SD.js} +28 -48
- package/dist/chunk-UURZ37SD.js.map +7 -0
- package/dist/{chunk-B5Q53LAJ.js → chunk-UWO43BZU.js} +2 -2
- package/dist/chunk-UWO43BZU.js.map +7 -0
- package/dist/chunk-WVFGV5FT.js +0 -0
- package/dist/chunk-WVFGV5FT.js.map +0 -0
- package/dist/core.js +170 -118
- package/dist/core.js.map +2 -2
- package/dist/editor.js +156 -70
- package/dist/editor.js.map +2 -2
- package/dist/flexdesk.css +3146 -164
- package/dist/flow.js +2789 -306
- package/dist/flow.js.map +4 -4
- package/dist/host.js +109 -3
- package/dist/host.js.map +3 -3
- package/dist/reset.css +0 -0
- package/dist/tile_registry-6WZPTUZV.js +0 -0
- package/dist/tile_registry-6WZPTUZV.js.map +0 -0
- package/dist/tiles.js +657 -234
- package/dist/tiles.js.map +4 -4
- package/dist/tokens.css +0 -0
- package/dist/widgets.js +3252 -2124
- package/dist/widgets.js.map +4 -4
- package/dist/wm.js +1227 -347
- package/dist/wm.js.map +4 -4
- package/package.json +3 -1
- package/src/canvas/canvas_adapter.js +5 -0
- package/src/canvas/edge_router.js +0 -0
- package/src/canvas/graph/connector_router.js +0 -0
- package/src/canvas/graph/history_service.js +0 -0
- package/src/canvas/graph/node_platform.js +0 -0
- package/src/canvas/index.js +1 -0
- package/src/canvas/layered_layout.js +244 -0
- package/src/charts/chart_types.js +0 -0
- package/src/charts/data_series_plot_window.js +0 -0
- package/src/charts/downsample.js +2 -2
- package/src/charts/plot_config.js +53 -29
- package/src/charts/plot_config_editor.js +627 -0
- package/src/charts/plot_grid.js +449 -0
- package/src/charts/plot_popout_window.js +103 -317
- package/src/charts/plotly_wrapper.js +22 -2
- package/src/charts/series_transforms.js +206 -0
- package/src/core/event_bus.js +0 -0
- package/src/core/logging.js +1 -1
- package/src/core/settings.js +105 -19
- package/src/core/state_guard.js +93 -51
- package/src/core/state_guard_config.js +85 -74
- package/src/core/state_machine.js +0 -0
- package/src/editor/editor_pane.js +3 -3
- package/src/editor/monaco_editor_factory.js +124 -60
- package/src/editor/monaco_loader.js +103 -28
- package/src/editor/notebook_search.js +0 -0
- package/src/editor/notebook_tab_bar.js +38 -52
- package/src/editor/notebook_undo_manager.js +0 -0
- package/src/editor/split_pane_container.js +6 -3
- package/src/flow/canvas_editor/connections.js +90 -0
- package/src/flow/canvas_editor/editor.js +2351 -153
- package/src/flow/canvas_editor/index.js +2 -1
- package/src/flow/canvas_editor/layout.js +119 -12
- package/src/flow/canvas_editor/strings.js +80 -0
- package/src/flow/kit/always_before.js +0 -0
- package/src/flow/kit/catalogue.js +97 -3
- package/src/flow/kit/chip_input.js +0 -0
- package/src/flow/kit/dom.js +0 -0
- package/src/flow/kit/findings.js +0 -0
- package/src/flow/kit/history.js +0 -0
- package/src/flow/kit/index.js +3 -3
- package/src/flow/kit/keys.js +7 -1
- package/src/flow/kit/logic_graph.js +97 -15
- package/src/flow/kit/references.js +0 -0
- package/src/flow/kit/settings_panel.js +0 -0
- package/src/flow/kit/settings_schema.js +2 -1
- package/src/flow/kit/step_picker.js +0 -0
- package/src/flow/kit/strings.js +3 -1
- package/src/flow/kit/value_picker.js +0 -0
- package/src/flow/kit/widgets.js +86 -109
- package/src/flow/lanes/editor.js +136 -14
- package/src/flow/lanes/index.js +3 -1
- package/src/flow/lanes/layout.js +0 -0
- package/src/flow/lanes/pipeline.js +44 -2
- package/src/flow/lanes/preview.js +0 -0
- package/src/flow/lanes/strings.js +1 -0
- package/src/flow/outline/editor.js +0 -0
- package/src/flow/outline/index.js +0 -0
- package/src/flow/outline/mapping.js +0 -0
- package/src/flow/outline/menu.js +0 -0
- package/src/flow/outline/operations.js +0 -0
- package/src/flow/outline/recognise.js +0 -0
- package/src/flow/outline/strings.js +0 -0
- package/src/help/help_modal.js +168 -42
- package/src/help/help_registry.js +12 -1
- package/src/host/external_links.js +0 -0
- package/src/host/file_picker.js +117 -0
- package/src/host/host.js +10 -2
- package/src/host/photino_host.js +9 -0
- package/src/host/photino_host.md +21 -3
- package/src/host/pywebview_host.js +10 -0
- package/src/tiles/chart_tiles.js +53 -245
- package/src/tiles/config_schema.js +8 -0
- package/src/tiles/figure_tile.js +322 -0
- package/src/tiles/layout_persistence.js +3 -3
- package/src/tiles/list_tiles.js +7 -7
- package/src/tiles/scope_picker.js +0 -0
- package/src/tiles/tile_base.js +1 -1
- package/src/tiles/tile_config_form.js +442 -0
- package/src/tiles/tile_grid.js +2 -0
- package/src/tiles/tile_registry.js +0 -0
- package/src/tiling/bottom_panel_tabs.js +67 -99
- package/src/tiling/command_palette.js +64 -19
- package/src/tiling/content_registry.js +4 -1
- package/src/tiling/desktops.js +11 -1
- package/src/tiling/entity_sources.js +0 -0
- package/src/tiling/keymap.js +403 -128
- package/src/tiling/kind_taxonomy.js +78 -0
- package/src/tiling/landing_table.js +0 -0
- package/src/tiling/loading_overlay.js +0 -0
- package/src/tiling/nav_panel.js +59 -10
- package/src/tiling/page_factory.js +5 -5
- package/src/tiling/panel_availability.js +49 -0
- package/src/tiling/panel_keys.js +0 -0
- package/src/tiling/shell.js +114 -12
- package/src/tiling/tab_strip.js +0 -0
- package/src/tiling/tile_breadcrumb.js +0 -0
- package/src/tiling/tile_renderer.js +105 -9
- package/src/tiling/tile_tab_menu.js +0 -0
- package/src/tiling/tile_tree.js +0 -0
- package/src/tiling/wm.js +562 -30
- package/src/tiling/zoom.js +0 -0
- package/src/ui/base/component_base.js +0 -0
- package/src/ui/base/controller_base.js +0 -0
- package/src/ui/base/page_base.js +0 -0
- package/src/ui/components/about_dialog.js +0 -0
- package/src/ui/components/action_dropdown.js +30 -2
- package/src/ui/components/alert_log.js +0 -0
- package/src/ui/components/alerts_pane.js +0 -0
- package/src/ui/components/attribute_list_editor.js +0 -0
- package/src/ui/components/autocomplete_field.js +0 -0
- package/src/ui/components/cell_editor_host.js +211 -0
- package/src/ui/components/cell_grid.js +648 -0
- package/src/ui/components/cell_selection.js +220 -0
- package/src/ui/components/choice_controls.js +351 -0
- package/src/ui/components/color_field.js +211 -0
- package/src/ui/components/color_list_field.js +210 -0
- package/src/ui/components/column_fit.js +0 -0
- package/src/ui/components/column_groups.js +314 -0
- package/src/ui/components/column_order.js +142 -0
- package/src/ui/components/computing_status_window.js +98 -25
- package/src/ui/components/confirm_dialog.js +81 -38
- package/src/ui/components/context_menu.js +2 -2
- package/src/ui/components/conversation_view.js +440 -0
- package/src/ui/components/crosstab.js +289 -0
- package/src/ui/components/data_table.js +601 -62
- package/src/ui/components/detail_header.js +22 -11
- package/src/ui/components/document_outline.js +397 -0
- package/src/ui/components/drag_reorder.js +0 -0
- package/src/ui/components/fact_table.js +0 -0
- package/src/ui/components/fill_handle.js +322 -0
- package/src/ui/components/gallery_picker.js +19 -8
- package/src/ui/components/header_actions.js +55 -0
- package/src/ui/components/inline_renamer.js +0 -0
- package/src/ui/components/job_progress.js +51 -0
- package/src/ui/components/managed_window.js +27 -4
- package/src/ui/components/menu_bar.js +745 -0
- package/src/ui/components/modal.js +449 -75
- package/src/ui/components/notification_history.js +3 -3
- package/src/ui/components/progress.js +483 -0
- package/src/ui/components/record_list.js +0 -0
- package/src/ui/components/row_activation.js +0 -0
- package/src/ui/components/section_stack.js +298 -0
- package/src/ui/components/series.js +173 -0
- package/src/ui/components/settings_view.js +634 -0
- package/src/ui/components/slide_out_panel.js +43 -6
- package/src/ui/components/slider_field.js +275 -18
- package/src/ui/components/sortable_list.js +0 -0
- package/src/ui/components/staged_edits.js +343 -0
- package/src/ui/components/staged_history.js +172 -0
- package/src/ui/components/table_filter_chips.js +0 -0
- package/src/ui/components/table_state_store.js +0 -0
- package/src/ui/components/table_structure.js +182 -0
- package/src/ui/components/table_values.js +0 -0
- package/src/ui/components/tabs.js +497 -0
- package/src/ui/components/tag_input.js +215 -0
- package/src/ui/components/toast.js +25 -8
- package/src/ui/components/toggle_field.js +175 -0
- package/src/ui/components/tree_view.js +55 -34
- package/src/ui/components/window_taskbar.js +0 -0
- package/src/ui/components/wizard.js +563 -0
- package/src/ui/controllers/window_chrome_controller.js +2 -2
- package/src/ui/notification_center.js +375 -119
- package/src/ui/utils/auto_scrollbars.js +0 -0
- package/src/ui/utils/markdown.js +709 -0
- package/src/ui/utils/native_context_menu.js +0 -0
- package/src/ui/utils/overlay_scrollbar.js +16 -12
- package/src/ui/utils/raf_resize_observer.js +0 -0
- package/src/ui/utils/scroll_lock.js +0 -0
- package/src/ui/utils/strip_scroll.js +55 -0
- package/src/ui/utils/tooltip_service.js +0 -8
- package/dist/chunk-6JSOVNID.js.map +0 -7
- package/dist/chunk-B5Q53LAJ.js.map +0 -7
- package/dist/chunk-FBGP5KN5.js.map +0 -7
- package/dist/chunk-FL5KFNQH.js.map +0 -7
- package/dist/chunk-NLTOY57M.js.map +0 -7
- package/dist/chunk-NNFTETK3.js +0 -633
- package/dist/chunk-NNFTETK3.js.map +0 -7
- package/dist/chunk-O5OHMWBB.js +0 -284
- package/dist/chunk-O5OHMWBB.js.map +0 -7
- package/dist/chunk-RQM5Z2MU.js.map +0 -7
- package/dist/chunk-SN4LSOAR.js.map +0 -7
- package/dist/chunk-W6FBJLPW.js +0 -367
- package/dist/chunk-W6FBJLPW.js.map +0 -7
- package/src/ui/controllers/panel_state_machine.js +0 -634
package/dist/charts.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../src/charts/data_series_plot_window.js"],
|
|
4
|
-
"sourcesContent": ["/**\n * Data Series Plot Window\n *\n * Opens a data series in a ManagedWindow with a split layout:\n * - Left: Plotly chart\n * - Right: Configuration panel (column selection, chart type, styling)\n *\n * Config is persisted in workspace metadata via savePlotConfig callback.\n */\n\nimport { ManagedWindow } from '../ui/components/managed_window.js';\nimport {\n ensurePlotly,\n purge,\n DARK_THEME_LAYOUT,\n DEFAULT_CONFIG,\n getSeriesColor,\n} from './plotly_wrapper.js';\nimport {\n buildTrace,\n buildYAxisLayout,\n buildXAxisLayout,\n buildLegendLayout,\n} from './chart_types.js';\n// The two header helpers are INJECTED, not imported.\n//\n// They used to come from ui/js/ui/utils/header_utils.js, which decides whether a\n// column is a STOCK or a FLOW by looking for `asset`, `liability`, `equity`,\n// `reserves`, `deposit`. That is stock-flow-consistent accounting, not charting,\n// and that one import was the last thing keeping this window out of @flexdesk/charts.\n//\n// The defaults below are what a chart library can honestly know about a column\n// name: whether it looks like a time axis, and nothing else.\n\n/** A column called `t`/`time`/`step`/`period` is the x-axis. Everything else is data. */\nconst defaultClassifyHeader = (header) => {\n const lower = String(header ?? '').trim().toLowerCase();\n return (lower === 't' || lower === 'time' || lower === 'step' || lower === 'period')\n ? 'time' : 'indicator';\n};\n\n/** No convention to strip, absent one being supplied. */\nconst defaultLabelHeader = (header) => header;\nimport { createRafResizeObserver } from '../ui/utils/raf_resize_observer.js';\n\nconst INTERPOLATION_MODES = ['linear', 'step', 'cubic'];\nconst CHART_TYPES = ['line', 'scatter', 'bar', 'area', 'area-stacked'];\nconst LEGEND_POSITIONS = ['top', 'bottom', 'right', 'hidden'];\nconst MAX_AUTO_COLUMNS = 3;\n\nclass DataSeriesPlotWindow {\n /**\n * @param {Object} options\n * @param {string} options.seriesId\n * @param {string} options.seriesName\n * @param {string} options.datasetName\n * @param {string[]} options.headers - Column headers from the series\n * @param {Object} options.dataHub - DataHub service for fetching data\n * @param {Object} options.services - { eventBus, logger }\n * @param {Object} [options.host] - A Host (ui/js/host/host.js). Its `dialogs`\n * capability backs Export PNG/CSV; absent => Blob download fallback.\n * @param {Function} options.getPlotConfig - (seriesId) => config | null\n * @param {Function} options.savePlotConfig - (seriesId, config) => void\n */\n constructor({ seriesId, seriesName, datasetName, headers, dataHub, services, host,\n getPlotConfig, savePlotConfig,\n classifyHeader = defaultClassifyHeader,\n labelHeader = defaultLabelHeader }) {\n this.classifyHeader = classifyHeader;\n this.labelHeader = labelHeader;\n this.seriesId = seriesId;\n this.seriesName = seriesName;\n this.datasetName = datasetName;\n this.headers = headers;\n this.dataHub = dataHub;\n this.services = services;\n this._host = host || null;\n this.getPlotConfig = getPlotConfig;\n this.savePlotConfig = savePlotConfig;\n\n this.window = null;\n this.contentEl = null;\n this.plotDiv = null;\n this._resizeObserver = null;\n this._chartCreated = false;\n this._config = null;\n this._fullData = null; // { headers, rows } with all data\n this._numericColumns = null; // Set of numeric column headers\n this._loading = false;\n }\n\n async show() {\n if (this.window?.isVisible) {\n this.window.bringToFront();\n return;\n }\n\n await ensurePlotly();\n await this.#fetchData();\n\n // Determine which columns are numeric from actual data\n this._numericColumns = new Set(this.headers.filter(h => this.#isNumericColumn(h)));\n\n // Load or create config (filter out any non-numeric columns from saved config)\n const saved = this.getPlotConfig?.(this.seriesId);\n if (saved) {\n this._config = { ...saved };\n this._config.yColumns = (saved.yColumns || []).filter(c => this._numericColumns.has(c.header));\n } else {\n this._config = DataSeriesPlotWindow.createDefaultConfig(this.headers, this._numericColumns);\n }\n\n this.#createWindow();\n this.#setupResizeObserver();\n await this.#renderPlot();\n }\n\n close() {\n if (this.window?.isVisible) {\n this.window.close();\n }\n }\n\n // \u2500\u2500 Window creation \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n #createWindow() {\n this.contentEl = this.#buildContent();\n\n const title = this.datasetName\n ? `${this.datasetName} \u00B7 ${this.seriesName}`\n : this.seriesName || 'Series Plot';\n\n this.window = new ManagedWindow({\n id: `data-series-plot-${this.seriesId}`,\n title,\n icon: 'monitoring',\n content: this.contentEl,\n minWidth: 600,\n minHeight: 400,\n defaultWidth: 900,\n defaultHeight: 550,\n canMinimize: true,\n canMaximize: true,\n canResize: true,\n canDrag: true,\n onClose: () => this.#dispose(),\n });\n\n this.window.show();\n }\n\n #buildContent() {\n const container = document.createElement('div');\n container.className = 'twm-data-series-plot-container';\n\n // Actions bar (download buttons)\n const actionsBar = document.createElement('div');\n actionsBar.className = 'twm-data-series-plot-actions';\n\n const pngBtn = document.createElement('button');\n pngBtn.className = 'twm-btn-icon twm-has-tooltip';\n pngBtn.type = 'button';\n pngBtn.setAttribute('data-tooltip', 'Download plot as PNG');\n pngBtn.innerHTML = '<span class=\"material-symbols-outlined\">image</span>';\n pngBtn.addEventListener('click', () => this.#downloadPNG());\n\n const csvBtn = document.createElement('button');\n csvBtn.className = 'twm-btn-icon twm-has-tooltip';\n csvBtn.type = 'button';\n csvBtn.setAttribute('data-tooltip', 'Download data as CSV');\n csvBtn.innerHTML = '<span class=\"material-symbols-outlined\">download</span>';\n csvBtn.addEventListener('click', () => this.#downloadCSV());\n\n actionsBar.appendChild(pngBtn);\n actionsBar.appendChild(csvBtn);\n\n // Chart area\n const chartWrap = document.createElement('div');\n chartWrap.className = 'twm-data-series-plot-body';\n\n this.plotDiv = document.createElement('div');\n this.plotDiv.className = 'twm-data-series-plot-chart';\n chartWrap.appendChild(this.plotDiv);\n\n // Config panel\n const configPanel = this.#buildConfigPanel();\n chartWrap.appendChild(configPanel);\n\n container.appendChild(actionsBar);\n container.appendChild(chartWrap);\n\n return container;\n }\n\n // \u2500\u2500 Config panel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n #buildConfigPanel() {\n const panel = document.createElement('div');\n panel.className = 'twm-data-series-plot-config';\n\n // X Column\n panel.appendChild(this.#buildSection('X Axis', this.#buildXColumnSelect()));\n\n // Y Columns\n this._yColumnsList = document.createElement('div');\n this._yColumnsList.className = 'twm-data-series-plot-config__columns';\n this.#populateYColumns();\n panel.appendChild(this.#buildSection('Y Axis', this._yColumnsList));\n\n // Chart type\n panel.appendChild(this.#buildSection('Chart Type', this.#buildSelect(\n CHART_TYPES,\n this._config.chartType,\n (val) => { this._config.chartType = val; this.#onConfigChanged(); }\n )));\n\n // Interpolation\n panel.appendChild(this.#buildSection('Interpolation', this.#buildSelect(\n INTERPOLATION_MODES,\n this._config.interpolation,\n (val) => { this._config.interpolation = val; this.#onConfigChanged(); }\n )));\n\n // Legend position\n panel.appendChild(this.#buildSection('Legend', this.#buildSelect(\n LEGEND_POSITIONS,\n this._config.legendPosition,\n (val) => { this._config.legendPosition = val; this.#onConfigChanged(); }\n )));\n\n // Show data points\n panel.appendChild(this.#buildSection('', this.#buildCheckbox(\n 'Show data points',\n this._config.showDataPoints,\n (checked) => { this._config.showDataPoints = checked; this.#onConfigChanged(); }\n )));\n\n return panel;\n }\n\n #buildSection(label, content) {\n const section = document.createElement('div');\n section.className = 'twm-data-series-plot-config__section';\n\n if (label) {\n const labelEl = document.createElement('div');\n labelEl.className = 'twm-data-series-plot-config__label';\n labelEl.textContent = label;\n section.appendChild(labelEl);\n }\n\n if (content instanceof HTMLElement) {\n section.appendChild(content);\n }\n\n return section;\n }\n\n #buildXColumnSelect() {\n const select = document.createElement('select');\n for (const header of this.headers) {\n if (!this._numericColumns.has(header)) continue;\n const opt = document.createElement('option');\n opt.value = header;\n opt.textContent = this.labelHeader(header);\n if (header === this._config.xColumn) opt.selected = true;\n select.appendChild(opt);\n }\n select.addEventListener('change', () => {\n this._config.xColumn = select.value;\n this.#onConfigChanged();\n });\n return select;\n }\n\n #populateYColumns() {\n const list = this._yColumnsList;\n list.innerHTML = '';\n\n const selectedSet = new Set(this._config.yColumns.map(c => c.header));\n\n for (const header of this.headers) {\n if (header === this._config.xColumn) continue;\n if (!this._numericColumns.has(header)) continue;\n\n const item = document.createElement('label');\n item.className = 'twm-data-series-plot-config__column-item';\n\n const cb = document.createElement('input');\n cb.type = 'checkbox';\n cb.checked = selectedSet.has(header);\n cb.addEventListener('change', () => this.#toggleYColumn(header, cb.checked));\n\n const colorSwatch = document.createElement('input');\n colorSwatch.type = 'color';\n colorSwatch.className = 'twm-data-series-plot-config__color-swatch';\n const existing = this._config.yColumns.find(c => c.header === header);\n colorSwatch.value = existing?.color || this.#nextColor(this.headers.indexOf(header));\n colorSwatch.addEventListener('input', () => this.#updateColumnColor(header, colorSwatch.value));\n\n const label = document.createElement('span');\n label.textContent = this.labelHeader(header);\n label.title = header;\n\n item.appendChild(cb);\n item.appendChild(colorSwatch);\n item.appendChild(label);\n list.appendChild(item);\n }\n }\n\n #toggleYColumn(header, checked) {\n if (checked) {\n if (!this._config.yColumns.find(c => c.header === header)) {\n const colorSwatch = this._yColumnsList.querySelector(\n `label:has(span[title=\"${header}\"]) input[type=\"color\"]`\n );\n this._config.yColumns.push({\n header,\n color: colorSwatch?.value || this.#nextColor(this.headers.indexOf(header)),\n });\n }\n } else {\n this._config.yColumns = this._config.yColumns.filter(c => c.header !== header);\n }\n this.#onConfigChanged();\n }\n\n #updateColumnColor(header, color) {\n const col = this._config.yColumns.find(c => c.header === header);\n if (col) {\n col.color = color;\n this.#onConfigChanged();\n }\n }\n\n #nextColor(index) {\n return getSeriesColor(index);\n }\n\n #buildSelect(options, value, onChange) {\n const select = document.createElement('select');\n for (const opt of options) {\n const el = document.createElement('option');\n el.value = opt;\n el.textContent = opt.charAt(0).toUpperCase() + opt.slice(1);\n if (opt === value) el.selected = true;\n select.appendChild(el);\n }\n select.addEventListener('change', () => onChange(select.value));\n return select;\n }\n\n #buildCheckbox(label, checked, onChange) {\n const wrapper = document.createElement('label');\n wrapper.className = 'twm-data-series-plot-config__column-item';\n\n const cb = document.createElement('input');\n cb.type = 'checkbox';\n cb.checked = checked;\n cb.addEventListener('change', () => onChange(cb.checked));\n\n const span = document.createElement('span');\n span.textContent = label;\n\n wrapper.appendChild(cb);\n wrapper.appendChild(span);\n return wrapper;\n }\n\n // \u2500\u2500 Data fetching \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n async #fetchData() {\n if (this._loading) return;\n this._loading = true;\n\n try {\n const response = await this.dataHub.fetchSeriesById(this.seriesId, { limit: null, offset: 0 });\n if (response?.ok) {\n this._fullData = {\n headers: response.headers || [],\n rows: response.rows || [],\n };\n } else {\n this.#notify('Plot', response?.error || 'Failed to load series data', 'error');\n }\n } catch (err) {\n this.services.logger?.warn?.('[DataSeriesPlotWindow] Fetch failed', err);\n this.#notify('Plot', 'Failed to load data', 'error');\n } finally {\n this._loading = false;\n }\n }\n\n #isNumericColumn(header) {\n if (!this._fullData) return false;\n const data = this.#extractColumnData(header);\n // Sample up to 20 non-empty values\n let numericCount = 0;\n let sampleCount = 0;\n for (const v of data) {\n if (v == null || v === '') continue;\n sampleCount++;\n if (Number.isFinite(Number(v))) numericCount++;\n if (sampleCount >= 20) break;\n }\n return sampleCount > 0 && numericCount / sampleCount >= 0.8;\n }\n\n // \u2500\u2500 Chart rendering \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n #extractColumnData(columnHeader) {\n if (!this._fullData) return [];\n\n const { headers, rows } = this._fullData;\n const idx = headers.indexOf(columnHeader);\n if (idx < 0) return [];\n\n const TIME_NAMES = new Set(['time', 'tDisp', 'year', 'date', 'timestamp']);\n const firstIsTime = TIME_NAMES.has(headers[0]);\n const colOffset = firstIsTime ? 1 : 0;\n\n return rows.map(row => {\n if (Array.isArray(row)) return row[idx];\n if (row && typeof row === 'object') {\n // Handle {tDisp, cols} format\n if (TIME_NAMES.has(columnHeader) && row.tDisp !== undefined) return row.tDisp;\n if (Array.isArray(row.cols)) return row.cols[idx - colOffset] ?? '';\n return row[columnHeader] ?? '';\n }\n return '';\n }).map(v => {\n const n = Number(v);\n return Number.isFinite(n) ? n : v;\n });\n }\n\n async #renderPlot() {\n if (!this.plotDiv || !window.Plotly || !this._fullData) return;\n\n const cfg = this._config;\n const xData = this.#extractColumnData(cfg.xColumn);\n\n if (xData.length === 0 || cfg.yColumns.length === 0) {\n // Show empty state\n if (this._chartCreated) {\n try { purge(this.plotDiv); } catch (e) { /* ignore */ }\n this._chartCreated = false;\n }\n this.plotDiv.innerHTML = '<div style=\"display:flex;align-items:center;justify-content:center;height:100%;color:#888;font-size:13px;\">Select columns to plot</div>';\n return;\n }\n\n // Clear empty state if present\n if (!this._chartCreated) {\n this.plotDiv.innerHTML = '';\n }\n\n const traces = [];\n\n for (let i = 0; i < cfg.yColumns.length; i++) {\n const col = cfg.yColumns[i];\n const yData = this.#extractColumnData(col.header);\n\n traces.push(buildTrace({\n chartType: cfg.chartType,\n x: xData,\n y: yData,\n name: this.labelHeader(col.header),\n color: col.color,\n lineWidth: 2,\n lineStyle: 'solid',\n interpolation: cfg.interpolation,\n yAxisId: 'y',\n showMarkers: cfg.showDataPoints,\n seriesIndex: i,\n }));\n }\n\n const legendAtTop = cfg.legendPosition === 'top';\n const legendAtBottom = cfg.legendPosition === 'bottom';\n\n const layout = {\n ...DARK_THEME_LAYOUT,\n autosize: true,\n margin: {\n l: 60, r: 40,\n b: legendAtBottom ? 80 : 50,\n t: legendAtTop ? 60 : 30,\n },\n };\n\n // Remove 3D scene from layout\n delete layout.scene;\n\n // X-axis\n layout.xaxis = {\n ...buildXAxisLayout({ title: this.labelHeader(cfg.xColumn) }),\n };\n\n // Unified hover\n layout.hovermode = 'x unified';\n layout.xaxis.showspikes = true;\n layout.xaxis.spikemode = 'across';\n layout.xaxis.spikethickness = 1;\n layout.xaxis.spikecolor = '#666666';\n layout.xaxis.spikedash = 'dot';\n\n // Y-axis\n layout.yaxis = buildYAxisLayout({\n axisId: 'yaxis',\n title: '',\n position: 'left',\n scaleType: 'linear',\n showGrid: true,\n });\n\n // Legend\n const legendConfig = buildLegendLayout(cfg.legendPosition);\n if (legendConfig.legend) {\n layout.legend = legendConfig.legend;\n }\n layout.showlegend = legendConfig.showlegend !== false;\n\n const plotConfig = {\n ...DEFAULT_CONFIG,\n responsive: true,\n displayModeBar: true,\n modeBarButtonsToRemove: ['lasso2d', 'select2d', 'toImage'],\n };\n\n try {\n await window.Plotly.newPlot(this.plotDiv, traces, layout, plotConfig);\n this._chartCreated = true;\n\n requestAnimationFrame(() => {\n try {\n window.Plotly.Plots.resize(this.plotDiv);\n } catch (e) { /* ignore */ }\n });\n } catch (e) {\n console.error('[DataSeriesPlotWindow] Chart render error:', e);\n }\n }\n\n // \u2500\u2500 Config change handler \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n #onConfigChanged() {\n this.#renderPlot();\n this.savePlotConfig?.(this.seriesId, { ...this._config, yColumns: [...this._config.yColumns] });\n }\n\n // \u2500\u2500 Resize observer \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n #setupResizeObserver() {\n if (!this.plotDiv) return;\n\n this._resizeObserver = createRafResizeObserver(() => {\n if (this.plotDiv && window.Plotly && this._chartCreated) {\n try {\n window.Plotly.Plots.resize(this.plotDiv);\n } catch (e) { /* ignore */ }\n }\n });\n\n this._resizeObserver.observe(this.plotDiv);\n }\n\n // \u2500\u2500 Downloads \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n async #downloadPNG() {\n if (!this.plotDiv || !window.Plotly || !this._chartCreated) {\n this.#notify('Download', 'Plot not ready', 'warn');\n return;\n }\n\n const filename = `${(this.seriesName || 'series').replace(/[^a-z0-9]/gi, '_')}.png`;\n\n try {\n const pngDataUrl = await window.Plotly.toImage(this.plotDiv, {\n format: 'png', width: 1920, height: 1080, scale: 2,\n });\n\n // null <=> no save dialog behind the capability (host.js) -> fall back.\n const dialogs = this._host?.dialogs;\n const result = dialogs\n ? await dialogs.saveFile({ data: pngDataUrl.split(',')[1], filename, kind: 'png' })\n : null;\n if (result) {\n if (result.ok) {\n this.#notify('Download', `Plot saved to ${result.path}`, 'success');\n } else if (!result.cancelled) {\n this.#notify('Download', result.error || 'Failed to save image', 'error');\n }\n } else {\n const link = document.createElement('a');\n link.href = pngDataUrl;\n link.download = filename;\n link.click();\n }\n } catch (err) {\n this.services.logger?.warn?.('[DataSeriesPlotWindow] PNG download failed', err);\n this.#notify('Download', 'Failed to generate PNG', 'error');\n }\n }\n\n async #downloadCSV() {\n if (!this._fullData || !this._fullData.rows.length) {\n this.#notify('Download', 'No data available', 'warn');\n return;\n }\n\n const cfg = this._config;\n const columns = [cfg.xColumn, ...cfg.yColumns.map(c => c.header)];\n const headers = columns.map(h => this.labelHeader(h));\n\n // Pre-extract all columns once\n const columnData = columns.map(col => this.#extractColumnData(col));\n const rowCount = this._fullData.rows.length;\n\n const lines = [headers.join(',')];\n for (let r = 0; r < rowCount; r++) {\n const vals = columnData.map(data => this.#csvEscape(data[r]));\n lines.push(vals.join(','));\n }\n const csv = lines.join('\\n');\n\n const filename = `${(this.seriesName || 'series').replace(/[^a-z0-9]/gi, '_')}_data.csv`;\n\n // null <=> no save dialog behind the capability (host.js) -> fall back.\n const dialogs = this._host?.dialogs;\n let result = null;\n if (dialogs) {\n try {\n result = await dialogs.saveFile({ data: csv, filename, kind: 'csv' });\n } catch (err) {\n this.#notify('Download', 'Failed to save file', 'error');\n return;\n }\n }\n if (result) {\n if (result.ok) {\n this.#notify('Download', `Saved to ${result.path}`, 'success');\n } else if (!result.cancelled) {\n this.#notify('Download', result.error || 'Failed to save file', 'error');\n }\n } else {\n const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });\n const url = URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = url;\n link.download = filename;\n link.click();\n URL.revokeObjectURL(url);\n }\n }\n\n #csvEscape(value) {\n if (value == null) return '';\n const str = String(value);\n if (/[\",\\n]/.test(str)) return `\"${str.replace(/\"/g, '\"\"')}\"`;\n return str;\n }\n\n // \u2500\u2500 Notifications \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n #notify(title, message, severity = 'info') {\n this.services.eventBus?.emit?.('toast:show', { title, message, type: severity });\n }\n\n // \u2500\u2500 Disposal \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n #dispose() {\n if (this._resizeObserver) {\n this._resizeObserver.disconnect();\n this._resizeObserver = null;\n }\n\n if (this.plotDiv && window.Plotly) {\n try { purge(this.plotDiv); } catch (e) { /* ignore */ }\n }\n\n _openPlotWindows.delete(this.seriesId);\n\n this.window = null;\n this.contentEl = null;\n this.plotDiv = null;\n this._yColumnsList = null;\n this._chartCreated = false;\n this._fullData = null;\n this._numericColumns = null;\n this._config = null;\n }\n\n // \u2500\u2500 Default config factory \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n static createDefaultConfig(headers, numericColumns) {\n const isNumeric = numericColumns instanceof Set ? (h) => numericColumns.has(h) : () => true;\n\n // Find best X column (time-like, must be numeric)\n let xColumn = '';\n for (const h of headers) {\n if (isNumeric(h) && this.classifyHeader(h) === 'time') {\n xColumn = h;\n break;\n }\n }\n // Fallback: first numeric column\n if (!xColumn) {\n for (const h of headers) {\n if (isNumeric(h)) { xColumn = h; break; }\n }\n }\n\n // Pick first N non-X numeric columns for Y\n const yColumns = [];\n for (const h of headers) {\n if (h === xColumn) continue;\n if (!isNumeric(h)) continue;\n if (yColumns.length >= MAX_AUTO_COLUMNS) break;\n yColumns.push({ header: h, color: getSeriesColor(yColumns.length) });\n }\n\n return {\n xColumn,\n yColumns,\n chartType: 'line',\n showDataPoints: false,\n interpolation: 'linear',\n legendPosition: 'top',\n };\n }\n}\n\n// \u2500\u2500 Singleton window management \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst _openPlotWindows = new Map();\n\nexport async function openDataSeriesPlotWindow(options) {\n const { seriesId } = options;\n let win = _openPlotWindows.get(seriesId);\n if (win?.window?.isVisible) {\n win.window.bringToFront();\n return win;\n }\n\n win = new DataSeriesPlotWindow(options);\n _openPlotWindows.set(seriesId, win);\n await win.show();\n return win;\n}\n\nexport function closeDataSeriesPlotWindow(seriesId) {\n const win = _openPlotWindows.get(seriesId);\n if (win) {\n win.close();\n _openPlotWindows.delete(seriesId);\n }\n}\n\nexport default DataSeriesPlotWindow;\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": []
|
|
3
|
+
"sources": ["../src/charts/data_series_plot_window.js", "../src/charts/plot_config_editor.js"],
|
|
4
|
+
"sourcesContent": ["/**\n * Data Series Plot Window\n *\n * Opens a data series in a ManagedWindow with a split layout:\n * - Left: Plotly chart\n * - Right: Configuration panel (column selection, chart type, styling)\n *\n * Config is persisted in workspace metadata via savePlotConfig callback.\n */\n\nimport { ManagedWindow } from '../ui/components/managed_window.js';\nimport {\n ensurePlotly,\n purge,\n DARK_THEME_LAYOUT,\n DEFAULT_CONFIG,\n getSeriesColor,\n} from './plotly_wrapper.js';\nimport {\n buildTrace,\n buildYAxisLayout,\n buildXAxisLayout,\n buildLegendLayout,\n} from './chart_types.js';\n// The two header helpers are INJECTED, not imported.\n//\n// They used to come from ui/js/ui/utils/header_utils.js, which decides whether a\n// column is a STOCK or a FLOW by looking for `asset`, `liability`, `equity`,\n// `reserves`, `deposit`. That is stock-flow-consistent accounting, not charting,\n// and that one import was the last thing keeping this window out of @flexdesk/charts.\n//\n// The defaults below are what a chart library can honestly know about a column\n// name: whether it looks like a time axis, and nothing else.\n\n/** A column called `t`/`time`/`step`/`period` is the x-axis. Everything else is data. */\nconst defaultClassifyHeader = (header) => {\n const lower = String(header ?? '').trim().toLowerCase();\n return (lower === 't' || lower === 'time' || lower === 'step' || lower === 'period')\n ? 'time' : 'indicator';\n};\n\n/** No convention to strip, absent one being supplied. */\nconst defaultLabelHeader = (header) => header;\nimport { createRafResizeObserver } from '../ui/utils/raf_resize_observer.js';\n\nconst INTERPOLATION_MODES = ['linear', 'step', 'cubic'];\nconst CHART_TYPES = ['line', 'scatter', 'bar', 'area', 'area-stacked'];\nconst LEGEND_POSITIONS = ['top', 'bottom', 'right', 'hidden'];\nconst MAX_AUTO_COLUMNS = 3;\n\nclass DataSeriesPlotWindow {\n /**\n * @param {Object} options\n * @param {string} options.seriesId\n * @param {string} options.seriesName\n * @param {string} options.datasetName\n * @param {string[]} options.headers - Column headers from the series\n * @param {Object} options.dataHub - DataHub service for fetching data\n * @param {Object} options.services - { eventBus, logger }\n * @param {Object} [options.host] - A Host (ui/js/host/host.js). Its `dialogs`\n * capability backs Export PNG/CSV; absent => Blob download fallback.\n * @param {Function} options.getPlotConfig - (seriesId) => config | null\n * @param {Function} options.savePlotConfig - (seriesId, config) => void\n */\n constructor({ seriesId, seriesName, datasetName, headers, dataHub, services, host,\n getPlotConfig, savePlotConfig,\n classifyHeader = defaultClassifyHeader,\n labelHeader = defaultLabelHeader }) {\n this.classifyHeader = classifyHeader;\n this.labelHeader = labelHeader;\n this.seriesId = seriesId;\n this.seriesName = seriesName;\n this.datasetName = datasetName;\n this.headers = headers;\n this.dataHub = dataHub;\n this.services = services;\n this._host = host || null;\n this.getPlotConfig = getPlotConfig;\n this.savePlotConfig = savePlotConfig;\n\n this.window = null;\n this.contentEl = null;\n this.plotDiv = null;\n this._resizeObserver = null;\n this._chartCreated = false;\n this._config = null;\n this._fullData = null; // { headers, rows } with all data\n this._numericColumns = null; // Set of numeric column headers\n this._loading = false;\n }\n\n async show() {\n if (this.window?.isVisible) {\n this.window.bringToFront();\n return;\n }\n\n await ensurePlotly();\n await this.#fetchData();\n\n // Determine which columns are numeric from actual data\n this._numericColumns = new Set(this.headers.filter(h => this.#isNumericColumn(h)));\n\n // Load or create config (filter out any non-numeric columns from saved config)\n const saved = this.getPlotConfig?.(this.seriesId);\n if (saved) {\n this._config = { ...saved };\n this._config.yColumns = (saved.yColumns || []).filter(c => this._numericColumns.has(c.header));\n } else {\n this._config = DataSeriesPlotWindow.createDefaultConfig(this.headers, this._numericColumns);\n }\n\n this.#createWindow();\n this.#setupResizeObserver();\n await this.#renderPlot();\n }\n\n close() {\n if (this.window?.isVisible) {\n this.window.close();\n }\n }\n\n // \u2500\u2500 Window creation \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n #createWindow() {\n this.contentEl = this.#buildContent();\n\n const title = this.datasetName\n ? `${this.datasetName} \u00B7 ${this.seriesName}`\n : this.seriesName || 'Series Plot';\n\n this.window = new ManagedWindow({\n id: `data-series-plot-${this.seriesId}`,\n title,\n icon: 'monitoring',\n content: this.contentEl,\n minWidth: 600,\n minHeight: 400,\n defaultWidth: 900,\n defaultHeight: 550,\n canMinimize: true,\n canMaximize: true,\n canResize: true,\n canDrag: true,\n onClose: () => this.#dispose(),\n });\n\n this.window.show();\n }\n\n #buildContent() {\n const container = document.createElement('div');\n container.className = 'twm-data-series-plot-container';\n\n // Actions bar (download buttons)\n const actionsBar = document.createElement('div');\n actionsBar.className = 'twm-data-series-plot-actions';\n\n const pngBtn = document.createElement('button');\n pngBtn.className = 'twm-btn-icon twm-has-tooltip';\n pngBtn.type = 'button';\n pngBtn.setAttribute('data-tooltip', 'Download plot as PNG');\n pngBtn.innerHTML = '<span class=\"material-symbols-outlined\">image</span>';\n pngBtn.addEventListener('click', () => this.#downloadPNG());\n\n const csvBtn = document.createElement('button');\n csvBtn.className = 'twm-btn-icon twm-has-tooltip';\n csvBtn.type = 'button';\n csvBtn.setAttribute('data-tooltip', 'Download data as CSV');\n csvBtn.innerHTML = '<span class=\"material-symbols-outlined\">download</span>';\n csvBtn.addEventListener('click', () => this.#downloadCSV());\n\n actionsBar.appendChild(pngBtn);\n actionsBar.appendChild(csvBtn);\n\n // Chart area\n const chartWrap = document.createElement('div');\n chartWrap.className = 'twm-data-series-plot-body';\n\n this.plotDiv = document.createElement('div');\n this.plotDiv.className = 'twm-data-series-plot-chart';\n chartWrap.appendChild(this.plotDiv);\n\n // Config panel\n const configPanel = this.#buildConfigPanel();\n chartWrap.appendChild(configPanel);\n\n container.appendChild(actionsBar);\n container.appendChild(chartWrap);\n\n return container;\n }\n\n // \u2500\u2500 Config panel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n #buildConfigPanel() {\n const panel = document.createElement('div');\n panel.className = 'twm-data-series-plot-config';\n\n // X Column\n panel.appendChild(this.#buildSection('X Axis', this.#buildXColumnSelect()));\n\n // Y Columns\n this._yColumnsList = document.createElement('div');\n this._yColumnsList.className = 'twm-data-series-plot-config__columns';\n this.#populateYColumns();\n panel.appendChild(this.#buildSection('Y Axis', this._yColumnsList));\n\n // Chart type\n panel.appendChild(this.#buildSection('Chart Type', this.#buildSelect(\n CHART_TYPES,\n this._config.chartType,\n (val) => { this._config.chartType = val; this.#onConfigChanged(); }\n )));\n\n // Interpolation\n panel.appendChild(this.#buildSection('Interpolation', this.#buildSelect(\n INTERPOLATION_MODES,\n this._config.interpolation,\n (val) => { this._config.interpolation = val; this.#onConfigChanged(); }\n )));\n\n // Legend position\n panel.appendChild(this.#buildSection('Legend', this.#buildSelect(\n LEGEND_POSITIONS,\n this._config.legendPosition,\n (val) => { this._config.legendPosition = val; this.#onConfigChanged(); }\n )));\n\n // Show data points\n panel.appendChild(this.#buildSection('', this.#buildCheckbox(\n 'Show data points',\n this._config.showDataPoints,\n (checked) => { this._config.showDataPoints = checked; this.#onConfigChanged(); }\n )));\n\n return panel;\n }\n\n #buildSection(label, content) {\n const section = document.createElement('div');\n section.className = 'twm-data-series-plot-config__section';\n\n if (label) {\n const labelEl = document.createElement('div');\n labelEl.className = 'twm-data-series-plot-config__label';\n labelEl.textContent = label;\n section.appendChild(labelEl);\n }\n\n if (content instanceof HTMLElement) {\n section.appendChild(content);\n }\n\n return section;\n }\n\n #buildXColumnSelect() {\n const select = document.createElement('select');\n for (const header of this.headers) {\n if (!this._numericColumns.has(header)) continue;\n const opt = document.createElement('option');\n opt.value = header;\n opt.textContent = this.labelHeader(header);\n if (header === this._config.xColumn) opt.selected = true;\n select.appendChild(opt);\n }\n select.addEventListener('change', () => {\n this._config.xColumn = select.value;\n this.#onConfigChanged();\n });\n return select;\n }\n\n #populateYColumns() {\n const list = this._yColumnsList;\n list.innerHTML = '';\n\n const selectedSet = new Set(this._config.yColumns.map(c => c.header));\n\n for (const header of this.headers) {\n if (header === this._config.xColumn) continue;\n if (!this._numericColumns.has(header)) continue;\n\n const item = document.createElement('label');\n item.className = 'twm-data-series-plot-config__column-item';\n\n const cb = document.createElement('input');\n cb.type = 'checkbox';\n cb.checked = selectedSet.has(header);\n cb.addEventListener('change', () => this.#toggleYColumn(header, cb.checked));\n\n const colorSwatch = document.createElement('input');\n colorSwatch.type = 'color';\n colorSwatch.className = 'twm-data-series-plot-config__color-swatch';\n const existing = this._config.yColumns.find(c => c.header === header);\n colorSwatch.value = existing?.color || this.#nextColor(this.headers.indexOf(header));\n colorSwatch.addEventListener('input', () => this.#updateColumnColor(header, colorSwatch.value));\n\n const label = document.createElement('span');\n label.textContent = this.labelHeader(header);\n label.title = header;\n\n item.appendChild(cb);\n item.appendChild(colorSwatch);\n item.appendChild(label);\n list.appendChild(item);\n }\n }\n\n #toggleYColumn(header, checked) {\n if (checked) {\n if (!this._config.yColumns.find(c => c.header === header)) {\n const colorSwatch = this._yColumnsList.querySelector(\n `label:has(span[title=\"${header}\"]) input[type=\"color\"]`\n );\n this._config.yColumns.push({\n header,\n color: colorSwatch?.value || this.#nextColor(this.headers.indexOf(header)),\n });\n }\n } else {\n this._config.yColumns = this._config.yColumns.filter(c => c.header !== header);\n }\n this.#onConfigChanged();\n }\n\n #updateColumnColor(header, color) {\n const col = this._config.yColumns.find(c => c.header === header);\n if (col) {\n col.color = color;\n this.#onConfigChanged();\n }\n }\n\n #nextColor(index) {\n return getSeriesColor(index);\n }\n\n #buildSelect(options, value, onChange) {\n const select = document.createElement('select');\n for (const opt of options) {\n const el = document.createElement('option');\n el.value = opt;\n el.textContent = opt.charAt(0).toUpperCase() + opt.slice(1);\n if (opt === value) el.selected = true;\n select.appendChild(el);\n }\n select.addEventListener('change', () => onChange(select.value));\n return select;\n }\n\n #buildCheckbox(label, checked, onChange) {\n const wrapper = document.createElement('label');\n wrapper.className = 'twm-data-series-plot-config__column-item';\n\n const cb = document.createElement('input');\n cb.type = 'checkbox';\n cb.checked = checked;\n cb.addEventListener('change', () => onChange(cb.checked));\n\n const span = document.createElement('span');\n span.textContent = label;\n\n wrapper.appendChild(cb);\n wrapper.appendChild(span);\n return wrapper;\n }\n\n // \u2500\u2500 Data fetching \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n async #fetchData() {\n if (this._loading) return;\n this._loading = true;\n\n try {\n const response = await this.dataHub.fetchSeriesById(this.seriesId, { limit: null, offset: 0 });\n if (response?.ok) {\n this._fullData = {\n headers: response.headers || [],\n rows: response.rows || [],\n };\n } else {\n this.#notify('Plot', response?.error || 'Failed to load series data', 'error');\n }\n } catch (err) {\n this.services.logger?.warn?.('[DataSeriesPlotWindow] Fetch failed', err);\n this.#notify('Plot', 'Failed to load data', 'error');\n } finally {\n this._loading = false;\n }\n }\n\n #isNumericColumn(header) {\n if (!this._fullData) return false;\n const data = this.#extractColumnData(header);\n // Sample up to 20 non-empty values\n let numericCount = 0;\n let sampleCount = 0;\n for (const v of data) {\n if (v == null || v === '') continue;\n sampleCount++;\n if (Number.isFinite(Number(v))) numericCount++;\n if (sampleCount >= 20) break;\n }\n return sampleCount > 0 && numericCount / sampleCount >= 0.8;\n }\n\n // \u2500\u2500 Chart rendering \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n #extractColumnData(columnHeader) {\n if (!this._fullData) return [];\n\n const { headers, rows } = this._fullData;\n const idx = headers.indexOf(columnHeader);\n if (idx < 0) return [];\n\n const TIME_NAMES = new Set(['time', 'tDisp', 'year', 'date', 'timestamp']);\n const firstIsTime = TIME_NAMES.has(headers[0]);\n const colOffset = firstIsTime ? 1 : 0;\n\n return rows.map(row => {\n if (Array.isArray(row)) return row[idx];\n if (row && typeof row === 'object') {\n // Handle {tDisp, cols} format\n if (TIME_NAMES.has(columnHeader) && row.tDisp !== undefined) return row.tDisp;\n if (Array.isArray(row.cols)) return row.cols[idx - colOffset] ?? '';\n return row[columnHeader] ?? '';\n }\n return '';\n }).map(v => {\n const n = Number(v);\n return Number.isFinite(n) ? n : v;\n });\n }\n\n async #renderPlot() {\n if (!this.plotDiv || !window.Plotly || !this._fullData) return;\n\n const cfg = this._config;\n const xData = this.#extractColumnData(cfg.xColumn);\n\n if (xData.length === 0 || cfg.yColumns.length === 0) {\n // Show empty state\n if (this._chartCreated) {\n try { purge(this.plotDiv); } catch (e) { /* ignore */ }\n this._chartCreated = false;\n }\n this.plotDiv.innerHTML = '<div style=\"display:flex;align-items:center;justify-content:center;height:100%;color:#888;font-size:13px;\">Select columns to plot</div>';\n return;\n }\n\n // Clear empty state if present\n if (!this._chartCreated) {\n this.plotDiv.innerHTML = '';\n }\n\n const traces = [];\n\n for (let i = 0; i < cfg.yColumns.length; i++) {\n const col = cfg.yColumns[i];\n const yData = this.#extractColumnData(col.header);\n\n traces.push(buildTrace({\n chartType: cfg.chartType,\n x: xData,\n y: yData,\n name: this.labelHeader(col.header),\n color: col.color,\n lineWidth: 2,\n lineStyle: 'solid',\n interpolation: cfg.interpolation,\n yAxisId: 'y',\n showMarkers: cfg.showDataPoints,\n seriesIndex: i,\n }));\n }\n\n const legendAtTop = cfg.legendPosition === 'top';\n const legendAtBottom = cfg.legendPosition === 'bottom';\n\n const layout = {\n ...DARK_THEME_LAYOUT,\n autosize: true,\n margin: {\n l: 60, r: 40,\n b: legendAtBottom ? 80 : 50,\n t: legendAtTop ? 60 : 30,\n },\n };\n\n // Remove 3D scene from layout\n delete layout.scene;\n\n // X-axis\n layout.xaxis = {\n ...buildXAxisLayout({ title: this.labelHeader(cfg.xColumn) }),\n };\n\n // Unified hover\n layout.hovermode = 'x unified';\n layout.xaxis.showspikes = true;\n layout.xaxis.spikemode = 'across';\n layout.xaxis.spikethickness = 1;\n layout.xaxis.spikecolor = '#666666';\n layout.xaxis.spikedash = 'dot';\n\n // Y-axis\n layout.yaxis = buildYAxisLayout({\n axisId: 'yaxis',\n title: '',\n position: 'left',\n scaleType: 'linear',\n showGrid: true,\n });\n\n // Legend\n const legendConfig = buildLegendLayout(cfg.legendPosition);\n if (legendConfig.legend) {\n layout.legend = legendConfig.legend;\n }\n layout.showlegend = legendConfig.showlegend !== false;\n\n const plotConfig = {\n ...DEFAULT_CONFIG,\n responsive: true,\n displayModeBar: true,\n modeBarButtonsToRemove: ['lasso2d', 'select2d', 'toImage'],\n };\n\n try {\n await window.Plotly.newPlot(this.plotDiv, traces, layout, plotConfig);\n this._chartCreated = true;\n\n requestAnimationFrame(() => {\n try {\n window.Plotly.Plots.resize(this.plotDiv);\n } catch (e) { /* ignore */ }\n });\n } catch (e) {\n console.error('[DataSeriesPlotWindow] Chart render error:', e);\n }\n }\n\n // \u2500\u2500 Config change handler \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n #onConfigChanged() {\n this.#renderPlot();\n this.savePlotConfig?.(this.seriesId, { ...this._config, yColumns: [...this._config.yColumns] });\n }\n\n // \u2500\u2500 Resize observer \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n #setupResizeObserver() {\n if (!this.plotDiv) return;\n\n this._resizeObserver = createRafResizeObserver(() => {\n if (this.plotDiv && window.Plotly && this._chartCreated) {\n try {\n window.Plotly.Plots.resize(this.plotDiv);\n } catch (e) { /* ignore */ }\n }\n });\n\n this._resizeObserver.observe(this.plotDiv);\n }\n\n // \u2500\u2500 Downloads \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n async #downloadPNG() {\n if (!this.plotDiv || !window.Plotly || !this._chartCreated) {\n this.#notify('Download', 'Plot not ready', 'warn');\n return;\n }\n\n const filename = `${(this.seriesName || 'series').replace(/[^a-z0-9]/gi, '_')}.png`;\n\n try {\n const pngDataUrl = await window.Plotly.toImage(this.plotDiv, {\n format: 'png', width: 1920, height: 1080, scale: 2,\n });\n\n // null <=> no save dialog behind the capability (host.js) -> fall back.\n const dialogs = this._host?.dialogs;\n const result = dialogs\n ? await dialogs.saveFile({ data: pngDataUrl.split(',')[1], filename, kind: 'png' })\n : null;\n if (result) {\n if (result.ok) {\n this.#notify('Download', `Plot saved to ${result.path}`, 'success');\n } else if (!result.cancelled) {\n this.#notify('Download', result.error || 'Failed to save image', 'error');\n }\n } else {\n const link = document.createElement('a');\n link.href = pngDataUrl;\n link.download = filename;\n link.click();\n }\n } catch (err) {\n this.services.logger?.warn?.('[DataSeriesPlotWindow] PNG download failed', err);\n this.#notify('Download', 'Failed to generate PNG', 'error');\n }\n }\n\n async #downloadCSV() {\n if (!this._fullData || !this._fullData.rows.length) {\n this.#notify('Download', 'No data available', 'warn');\n return;\n }\n\n const cfg = this._config;\n const columns = [cfg.xColumn, ...cfg.yColumns.map(c => c.header)];\n const headers = columns.map(h => this.labelHeader(h));\n\n // Pre-extract all columns once\n const columnData = columns.map(col => this.#extractColumnData(col));\n const rowCount = this._fullData.rows.length;\n\n const lines = [headers.join(',')];\n for (let r = 0; r < rowCount; r++) {\n const vals = columnData.map(data => this.#csvEscape(data[r]));\n lines.push(vals.join(','));\n }\n const csv = lines.join('\\n');\n\n const filename = `${(this.seriesName || 'series').replace(/[^a-z0-9]/gi, '_')}_data.csv`;\n\n // null <=> no save dialog behind the capability (host.js) -> fall back.\n const dialogs = this._host?.dialogs;\n let result = null;\n if (dialogs) {\n try {\n result = await dialogs.saveFile({ data: csv, filename, kind: 'csv' });\n } catch (err) {\n this.#notify('Download', 'Failed to save file', 'error');\n return;\n }\n }\n if (result) {\n if (result.ok) {\n this.#notify('Download', `Saved to ${result.path}`, 'success');\n } else if (!result.cancelled) {\n this.#notify('Download', result.error || 'Failed to save file', 'error');\n }\n } else {\n const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });\n const url = URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = url;\n link.download = filename;\n link.click();\n URL.revokeObjectURL(url);\n }\n }\n\n #csvEscape(value) {\n if (value == null) return '';\n const str = String(value);\n if (/[\",\\n]/.test(str)) return `\"${str.replace(/\"/g, '\"\"')}\"`;\n return str;\n }\n\n // \u2500\u2500 Notifications \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n #notify(title, message, severity = 'info') {\n this.services.eventBus?.emit?.('toast:show', { title, message, type: severity });\n }\n\n // \u2500\u2500 Disposal \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n #dispose() {\n if (this._resizeObserver) {\n this._resizeObserver.disconnect();\n this._resizeObserver = null;\n }\n\n if (this.plotDiv && window.Plotly) {\n try { purge(this.plotDiv); } catch (e) { /* ignore */ }\n }\n\n _openPlotWindows.delete(this.seriesId);\n\n this.window = null;\n this.contentEl = null;\n this.plotDiv = null;\n this._yColumnsList = null;\n this._chartCreated = false;\n this._fullData = null;\n this._numericColumns = null;\n this._config = null;\n }\n\n // \u2500\u2500 Default config factory \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n static createDefaultConfig(headers, numericColumns) {\n const isNumeric = numericColumns instanceof Set ? (h) => numericColumns.has(h) : () => true;\n\n // Find best X column (time-like, must be numeric)\n let xColumn = '';\n for (const h of headers) {\n if (isNumeric(h) && this.classifyHeader(h) === 'time') {\n xColumn = h;\n break;\n }\n }\n // Fallback: first numeric column\n if (!xColumn) {\n for (const h of headers) {\n if (isNumeric(h)) { xColumn = h; break; }\n }\n }\n\n // Pick first N non-X numeric columns for Y\n const yColumns = [];\n for (const h of headers) {\n if (h === xColumn) continue;\n if (!isNumeric(h)) continue;\n if (yColumns.length >= MAX_AUTO_COLUMNS) break;\n yColumns.push({ header: h, color: getSeriesColor(yColumns.length) });\n }\n\n return {\n xColumn,\n yColumns,\n chartType: 'line',\n showDataPoints: false,\n interpolation: 'linear',\n legendPosition: 'top',\n };\n }\n}\n\n// \u2500\u2500 Singleton window management \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst _openPlotWindows = new Map();\n\nexport async function openDataSeriesPlotWindow(options) {\n const { seriesId } = options;\n let win = _openPlotWindows.get(seriesId);\n if (win?.window?.isVisible) {\n win.window.bringToFront();\n return win;\n }\n\n win = new DataSeriesPlotWindow(options);\n _openPlotWindows.set(seriesId, win);\n await win.show();\n return win;\n}\n\nexport function closeDataSeriesPlotWindow(seriesId) {\n const win = _openPlotWindows.get(seriesId);\n if (win) {\n win.close();\n _openPlotWindows.delete(seriesId);\n }\n}\n\nexport default DataSeriesPlotWindow;\n", "/**\n * plot_config_editor.js \u2014 edit a plot config (plot_config.js: `{ layout, subplots }`)\n * in place.\n *\n * const editor = renderPlotConfigEditor(el, plotConfig, {\n * onChange: () => grid.update({ plotConfig }),\n * seriesProvider: ({ value, role, subplot }) => myNames(value), // or a promise\n * });\n * editor.dispose();\n *\n * It draws a layout picker, a tab per subplot slot (when the layout has more\n * than one) and, for the subplot in front: its title; its chart type, legend,\n * interpolation, NaN handling and data points; its x axis (time, or a series);\n * its y axes (label, scale, position, min, max, step) and their series (a\n * picker, label, colour, width, dash, stack group, the embedder's own fields\n * and, with `overlaySources`, an overlay source); its z axis while the chart\n * type is 3D; its reference lines and shaded bands; and the toggles of any\n * injected `seriesTransforms` (series_transforms.js).\n *\n * Every edit writes the config object it was given and then calls\n * `onChange(config)`. A layout with more slots than the config has subplots\n * gets default subplots (makeDefaultSubplot) for the new slots; a layout with\n * fewer keeps the extra subplots, unseen, so switching back restores them.\n *\n * A 3D chart type gives the subplot a z axis and uses its first y axis only:\n * while one is chosen the other y axes are shown disabled and no y axis can be\n * added. A 2D chart type removes the z axis (`zAxis: null`, as in\n * makeDefaultSubplot).\n *\n * Series names come from `seriesProvider`, through an AutocompleteField per\n * picker: it is asked `{ value, role, subplot }` (`role` is 'series', 'x' or\n * 'z') and answers AutocompleteField items (`{ label, insertText?, type? }`)\n * or a promise of them. One that throws or rejects shows no suggestions and\n * leaves what was typed as it is. Nothing here knows what a series is.\n *\n * It fits PlotPopoutWindow's `configRenderer` slot, which disposes what the\n * renderer returns when the window closes (openPlotPopoutWindow is async):\n *\n * const win = await openPlotPopoutWindow({ id, title, plotConfig, getResults, services,\n * configRenderer: (el) => renderPlotConfigEditor(el, plotConfig,\n * { onChange: () => win.updateConfig(plotConfig) }) });\n */\n\nimport { AutocompleteField } from '../ui/components/autocomplete_field.js';\nimport { ColorField } from '../ui/components/color_field.js';\nimport { ToggleField } from '../ui/components/toggle_field.js';\nimport { selectBox } from '../ui/components/choice_controls.js';\nimport { createTabs } from '../ui/components/tabs.js';\nimport { CHART_TYPES_2D, CHART_TYPES_3D, is3DChart } from './chart_types.js';\nimport { PLOT_LAYOUTS, makeDefaultSubplot, makeDefaultYAxis, makeDefaultSeries } from './plot_config.js';\nimport { renderSeriesTransformControls } from './series_transforms.js';\n\nconst CHART_TYPE_OPTIONS = Object.freeze([\n { group: '2D', options: CHART_TYPES_2D },\n { group: '3D', options: CHART_TYPES_3D },\n]);\nconst SCALES = Object.freeze([{ value: 'linear', label: 'Linear' }, { value: 'log', label: 'Log' }]);\nconst POSITIONS = Object.freeze([{ value: 'left', label: 'Left' }, { value: 'right', label: 'Right' }]);\nconst DASHES = Object.freeze([\n { value: 'solid', label: 'Solid' }, { value: 'dashed', label: 'Dashed' }, { value: 'dotted', label: 'Dotted' },\n]);\nconst LEGEND_POSITIONS = Object.freeze([\n { value: 'hidden', label: 'Hidden' }, { value: 'top', label: 'Top' }, { value: 'bottom', label: 'Bottom' },\n { value: 'left', label: 'Left' }, { value: 'right', label: 'Right' },\n]);\nconst INTERPOLATIONS = Object.freeze([\n { value: 'linear', label: 'Linear' }, { value: 'step', label: 'Step' }, { value: 'cubic', label: 'Cubic spline' },\n]);\nconst NAN_STRATEGIES = Object.freeze([\n { value: 'gap', label: 'Gap' }, { value: 'zero', label: 'Zero' },\n { value: 'hold', label: 'Hold last value' }, { value: 'interpolate', label: 'Interpolate' },\n]);\nconst X_SOURCES = Object.freeze([{ value: 'time', label: 'Time' }, { value: 'series', label: 'Series' }]);\nconst OVERLAY_MODES = Object.freeze([\n { value: 'markers+lines', label: 'Markers and lines' }, { value: 'markers', label: 'Markers' },\n { value: 'lines', label: 'Lines' },\n]);\n\nfunction el(tag, className, text) {\n const node = document.createElement(tag);\n if (className) node.className = className;\n if (text != null) node.textContent = String(text);\n return node;\n}\n\nfunction button(text, onClick, { title = null, className = 'twm-btn twm-plot-config__add' } = {}) {\n const b = el('button', className, text);\n b.type = 'button';\n if (title) b.title = title;\n b.addEventListener('click', () => { if (!b.disabled) onClick(); });\n return b;\n}\n\nfunction removeButton(title, onClick) {\n const b = button('', onClick, { title, className: 'twm-btn-icon twm-plot-config__remove' });\n b.setAttribute('aria-label', title);\n b.appendChild(el('span', 'material-symbols-outlined', 'close'));\n return b;\n}\n\n/**\n * A labelled control. A single input or select is wrapped in a `<label>`; a\n * compound one (a picker, a colour field) is not, so a click on its text does\n * not land on whichever of its inputs comes first.\n */\nfunction field(label, control) {\n const single = control.matches('input, select, textarea');\n const row = el(single ? 'label' : 'div', 'twm-plot-config__field');\n row.append(el('span', 'twm-plot-config__label', label), control);\n return row;\n}\n\nfunction textInput(value, onSet, { placeholder = '', label = null } = {}) {\n const input = el('input', 'twm-plot-config__input');\n input.type = 'text';\n input.value = value ?? '';\n input.placeholder = placeholder;\n if (label) input.setAttribute('aria-label', label);\n input.addEventListener('input', () => onSet(input.value));\n return input;\n}\n\n/** A number box: empty (or not a number) sets null. */\nfunction numberInput(value, onSet, { placeholder = 'Auto', label = null, min = null, max = null, step = 'any' } = {}) {\n const input = el('input', 'twm-plot-config__input twm-plot-config__input--number');\n input.type = 'number';\n input.step = String(step);\n if (min != null) input.min = String(min);\n if (max != null) input.max = String(max);\n input.value = value == null ? '' : String(value);\n input.placeholder = placeholder;\n if (label) input.setAttribute('aria-label', label);\n input.addEventListener('change', () => {\n const n = parseFloat(input.value);\n onSet(Number.isFinite(n) ? n : null);\n });\n return input;\n}\n\n/** A select over choice options; `onPick(value)` gets the option's own value. */\nfunction select(options, value, onPick, { label = null, empty = null } = {}) {\n const s = selectBox(options, value, {\n label: label ?? '', empty,\n className: 'twm-plot-config__input twm-plot-config__input--select',\n });\n s.box.addEventListener('change', () => onPick(s.valueOf()));\n return s.box;\n}\n\nfunction makeZAxis() {\n return { label: '', scale: 'linear', min: null, max: null, step: null, variable: '' };\n}\n\nlet editorCount = 0;\n\n/**\n * Edit `config` in place.\n *\n * @param {HTMLElement} container - Receives one `.twm-plot-config` child.\n * @param {{ layout: string, subplots: Object[] }} config - Already migrated (migrateData).\n * @param {Object} [options]\n * @param {Function} [options.onChange] - `(config)` after every edit.\n * @param {Function} [options.seriesProvider] - `({ value, role, subplot }) => items |\n * Promise<items>`: the pickers' suggestions (AutocompleteField items).\n * @param {Function} [options.overlaySources] - `() => options | Promise<options>`: choice\n * options (`{ value, label }`, or `{ group, options }`) for a series' overlay\n * source, written to `series.overlay.source`. Absent: no overlay controls.\n * @param {Object} [options.seriesTransforms] - `{ [id]: transform }` (series_transforms.js);\n * their toggles are drawn per subplot.\n * @param {Function} [options.extraSeriesFields] - `(el, series, { subplot, axis, onChange })\n * => { dispose? } | void`: fields of the embedder's own in each series row.\n * @param {Object} [options.logger] - Given to every AutocompleteField (provider errors);\n * its `warn` also hears a part (an `extraSeriesFields` handle, say) that throws on dispose.\n * @returns {{ dispose: Function, refresh: Function, selectSubplot: Function,\n * readonly activeSubplot: number }}\n */\nfunction renderPlotConfigEditor(container, config, options = {}) {\n const opts = {\n onChange: null,\n seriesProvider: null,\n overlaySources: null,\n seriesTransforms: null,\n extraSeriesFields: null,\n logger: null,\n ...options,\n };\n const editorId = `twm-plot-config-${++editorCount}`;\n let fieldCount = 0;\n let active = 0;\n let disposed = false;\n /** Teardown for everything the subplot body created; run before each redraw. */\n let bodyDisposers = [];\n /** Bumped on each body redraw, so an overlay-source answer for an old body is dropped. */\n let generation = 0;\n\n const notify = () => { if (!disposed) opts.onChange?.(config); };\n const track = (fn) => { bodyDisposers.push(fn); };\n const template = () => PLOT_LAYOUTS[config.layout] || PLOT_LAYOUTS['1x1'];\n const slots = () => template().slots;\n\n function ensureSubplots() {\n if (!Array.isArray(config.subplots)) config.subplots = [];\n while (config.subplots.length < slots()) {\n config.subplots.push(makeDefaultSubplot(config.subplots.length));\n }\n }\n\n const root = el('div', 'twm-plot-config');\n\n // \u2500\u2500 layout picker \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const layoutButtons = new Map();\n const picker = el('div', 'twm-plot-config__layouts');\n picker.setAttribute('role', 'group');\n picker.setAttribute('aria-label', 'Layout');\n for (const [key, tmpl] of Object.entries(PLOT_LAYOUTS)) {\n const b = button(tmpl.label, () => setLayout(key), { className: 'twm-btn twm-plot-config__layout' });\n layoutButtons.set(key, b);\n picker.appendChild(b);\n }\n const syncLayoutButtons = () => {\n for (const [key, b] of layoutButtons) {\n const on = key === config.layout;\n b.setAttribute('aria-pressed', on ? 'true' : 'false');\n b.classList.toggle('twm-plot-config__layout--on', on);\n }\n };\n root.appendChild(section('Layout', picker));\n\n // \u2500\u2500 subplot tabs and the body \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const tabsHost = el('div', 'twm-plot-config__tabs');\n const body = el('div', 'twm-plot-config__body');\n root.append(tabsHost, body);\n container.appendChild(root);\n\n ensureSubplots();\n const tabItems = () => Array.from({ length: slots() }, (_, i) => ({ id: i, label: `Subplot ${i + 1}` }));\n const tabs = createTabs(tabsHost, {\n items: tabItems(),\n active: 0,\n compact: true,\n label: 'Subplots',\n onSelect: (id) => {\n if (id == null || id === active) return;\n active = id;\n renderBody();\n },\n });\n const syncChrome = () => {\n syncLayoutButtons();\n tabs.update(tabItems(), active);\n tabsHost.hidden = slots() < 2;\n };\n\n function setLayout(key) {\n if (disposed || key === config.layout) return;\n config.layout = key;\n ensureSubplots();\n active = Math.min(active, slots() - 1);\n syncChrome();\n renderBody();\n notify();\n }\n\n function section(title, ...children) {\n const s = el('section', 'twm-plot-config__section');\n s.appendChild(el('h4', 'twm-plot-config__heading', title));\n for (const child of children) if (child) s.appendChild(child);\n return s;\n }\n\n function disposeBody() {\n generation += 1;\n const disposers = bodyDisposers;\n bodyDisposers = [];\n for (const fn of disposers) {\n try { fn(); } catch (error) {\n opts.logger?.warn?.('[plot config editor] a field failed to dispose', error);\n }\n }\n }\n\n // \u2500\u2500 shared controls \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /** A series-name picker writing `target[key]`. */\n function seriesPicker(target, key, role, sp, placeholder) {\n let alive = true;\n const ac = new AutocompleteField({\n fieldId: `${editorId}-field-${++fieldCount}`,\n field: { placeholder, value: target[key] ?? '' },\n skipNamespacePrefix: true,\n logger: opts.logger,\n provider: ({ value }) => (opts.seriesProvider\n ? opts.seriesProvider({ value, role, subplot: sp })\n : []),\n onChange: (value) => {\n // The field reports its value again on blur, after a redraw\n // may have disposed it: a disposed field writes nothing.\n if (!alive || (target[key] ?? '') === value) return;\n target[key] = value;\n notify();\n },\n });\n track(() => { alive = false; ac.dispose(); });\n const node = ac.render();\n node.classList.add('twm-plot-config__picker');\n return node;\n }\n\n function colorField(value, onSet, label) {\n const f = new ColorField({\n value: value ?? '',\n label,\n onChange: (v) => { if (v !== null) { onSet(v || null); notify(); } },\n });\n track(() => f.dispose());\n return f.render();\n }\n\n function toggle(label, checked, onSet) {\n const t = new ToggleField({ label, checked, compact: true, onChange: (on) => { onSet(on); notify(); } });\n track(() => t.dispose());\n return t.render();\n }\n\n /** Rows of objects under `sp[key]`, each with a remove button, and an add button. */\n function listEditor(sp, key, { addLabel, makeItem, fields }) {\n if (!Array.isArray(sp[key])) sp[key] = [];\n const items = sp[key];\n const wrap = el('div', 'twm-plot-config__list');\n items.forEach((item, i) => {\n const row = el('div', 'twm-plot-config__row');\n row.append(...fields(item), removeButton('Remove', () => {\n items.splice(i, 1);\n renderBody();\n notify();\n }));\n wrap.appendChild(row);\n });\n wrap.appendChild(button(addLabel, () => {\n items.push(makeItem());\n renderBody();\n notify();\n }));\n return wrap;\n }\n\n // \u2500\u2500 the subplot in front \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n function normalise(sp) {\n if (!sp.xAxis) sp.xAxis = { useTime: true, variable: '' };\n if (!Array.isArray(sp.yAxes) || !sp.yAxes.length) sp.yAxes = [makeDefaultYAxis(0)];\n for (const axis of sp.yAxes) if (!Array.isArray(axis.series)) axis.series = [];\n if (is3DChart(sp.chartType) && !sp.zAxis) sp.zAxis = makeZAxis();\n }\n\n function renderBody() {\n if (disposed) return;\n disposeBody();\n body.replaceChildren();\n const sp = config.subplots[active];\n if (!sp) return;\n normalise(sp);\n const is3D = is3DChart(sp.chartType);\n let sources = null;\n const overlaySources = () => (sources ??= Promise.resolve().then(() => opts.overlaySources()));\n\n body.append(\n section('Subplot', field('Title', textInput(sp.displayName, (v) => { sp.displayName = v; notify(); },\n { placeholder: 'Untitled' }))),\n section('Display', ...displayFields(sp)),\n section('X axis', ...xAxisFields(sp)),\n section('Y axes', yAxesEditor(sp, is3D, overlaySources)),\n is3D ? section('Z axis', ...zAxisFields(sp)) : null,\n section('Reference lines', referenceLinesEditor(sp)),\n section('Shaded bands', shadedBandsEditor(sp)),\n transformsSection(sp),\n );\n }\n\n function displayFields(sp) {\n return [\n field('Chart type', select(CHART_TYPE_OPTIONS, sp.chartType ?? 'line', (v) => {\n const was3D = is3DChart(sp.chartType);\n sp.chartType = v;\n const now3D = is3DChart(v);\n if (now3D) sp.zAxis ??= makeZAxis();\n else sp.zAxis = null;\n if (was3D !== now3D) renderBody();\n notify();\n })),\n field('Legend', select(LEGEND_POSITIONS, sp.legendPosition ?? 'hidden',\n (v) => { sp.legendPosition = v; notify(); })),\n field('Interpolation', select(INTERPOLATIONS, sp.interpolation ?? 'linear',\n (v) => { sp.interpolation = v; notify(); })),\n field('Missing values', select(NAN_STRATEGIES, sp.nanHandling ?? 'gap',\n (v) => { sp.nanHandling = v; notify(); })),\n toggle('Data points', sp.showDataPoints === true, (on) => { sp.showDataPoints = on; }),\n ];\n }\n\n function xAxisFields(sp) {\n const useTime = sp.xAxis.useTime !== false;\n const out = [field('Against', select(X_SOURCES, useTime ? 'time' : 'series', (v) => {\n sp.xAxis.useTime = v === 'time';\n renderBody();\n notify();\n }))];\n if (!useTime) {\n out.push(\n field('Series', seriesPicker(sp.xAxis, 'variable', 'x', sp, 'X series')),\n field('Label', textInput(sp.xAxis.label, (v) => { sp.xAxis.label = v; notify(); },\n { placeholder: sp.xAxis.variable || 'Axis title' })),\n );\n }\n return out;\n }\n\n function zAxisFields(sp) {\n const z = sp.zAxis;\n return [\n field('Series', seriesPicker(z, 'variable', 'z', sp, 'Z series')),\n field('Label', textInput(z.label, (v) => { z.label = v; notify(); }, { placeholder: 'Axis title' })),\n field('Scale', select(SCALES, z.scale ?? 'linear', (v) => { z.scale = v; notify(); })),\n field('Min', numberInput(z.min, (v) => { z.min = v; notify(); })),\n field('Max', numberInput(z.max, (v) => { z.max = v; notify(); })),\n field('Step', numberInput(z.step, (v) => { z.step = v; notify(); })),\n ];\n }\n\n function yAxesEditor(sp, is3D, overlaySources) {\n const wrap = el('div', 'twm-plot-config__axes');\n sp.yAxes.forEach((axis, i) => wrap.appendChild(yAxisEditor(sp, axis, i, is3D, overlaySources)));\n const add = button('Add Y axis', () => {\n sp.yAxes.push(makeDefaultYAxis(sp.yAxes.length));\n renderBody();\n notify();\n }, { title: is3D ? 'A 3D chart has one Y axis' : null });\n add.disabled = is3D;\n wrap.appendChild(add);\n return wrap;\n }\n\n function yAxisEditor(sp, axis, index, is3D, overlaySources) {\n const group = el('fieldset', 'twm-plot-config__axis');\n const legend = el('legend', 'twm-plot-config__axis-title', `Y axis ${index + 1}`);\n group.appendChild(legend);\n if (sp.yAxes.length > 1) {\n // Inside the legend, so it stays usable while the axis is disabled.\n legend.appendChild(removeButton('Remove Y axis', () => {\n sp.yAxes.splice(index, 1);\n renderBody();\n notify();\n }));\n }\n if (is3D && index > 0) {\n group.disabled = true;\n group.classList.add('twm-plot-config__axis--disabled');\n group.title = 'A 3D chart uses the first Y axis only';\n }\n\n const fields = el('div', 'twm-plot-config__axis-fields');\n fields.append(\n field('Label', textInput(axis.label, (v) => { axis.label = v; notify(); }, { placeholder: 'Axis title' })),\n field('Scale', select(SCALES, axis.scale ?? 'linear', (v) => { axis.scale = v; notify(); })),\n field('Position', select(POSITIONS, axis.position ?? 'left', (v) => { axis.position = v; notify(); })),\n field('Min', numberInput(axis.min, (v) => { axis.min = v; notify(); })),\n field('Max', numberInput(axis.max, (v) => { axis.max = v; notify(); })),\n field('Step', numberInput(axis.step, (v) => { axis.step = v; notify(); })),\n );\n group.appendChild(fields);\n\n const list = el('div', 'twm-plot-config__series-list');\n if (!axis.series.length) list.appendChild(el('div', 'twm-plot-config__empty', 'No series.'));\n for (const s of axis.series) list.appendChild(seriesRow(sp, axis, s, overlaySources));\n group.appendChild(list);\n\n group.appendChild(button('Add series', () => {\n const count = sp.yAxes.reduce((n, a) => n + (a.series?.length ?? 0), 0);\n axis.series.push(makeDefaultSeries(count));\n renderBody();\n notify();\n }));\n return group;\n }\n\n function seriesRow(sp, axis, s, overlaySources) {\n const row = el('div', 'twm-plot-config__series');\n const main = el('div', 'twm-plot-config__series-main');\n main.append(\n seriesPicker(s, 'variable', 'series', sp, 'Series'),\n textInput(s.label, (v) => { s.label = v; notify(); }, { placeholder: 'Legend label', label: 'Legend label' }),\n colorField(s.color, (v) => { if (v) s.color = v; else delete s.color; }, 'Colour'),\n numberInput(s.lineWidth ?? 2, (v) => { s.lineWidth = v ?? 2; notify(); },\n { placeholder: '2', label: 'Line width', min: 1, max: 10, step: 1 }),\n select(DASHES, s.lineStyle ?? 'solid', (v) => { s.lineStyle = v; notify(); }, { label: 'Dash' }),\n textInput(s.stackGroup, (v) => { s.stackGroup = v || null; notify(); },\n { placeholder: 'Stack group', label: 'Stack group' }),\n removeButton('Remove series', () => {\n const i = axis.series.indexOf(s);\n if (i >= 0) axis.series.splice(i, 1);\n renderBody();\n notify();\n }),\n );\n row.appendChild(main);\n\n if (opts.extraSeriesFields) {\n const extra = el('div', 'twm-plot-config__series-extra');\n row.appendChild(extra);\n const handle = opts.extraSeriesFields(extra, s, { subplot: sp, axis, onChange: notify });\n if (typeof handle?.dispose === 'function') track(() => handle.dispose());\n }\n if (opts.overlaySources) row.appendChild(overlayEditor(s, overlaySources));\n return row;\n }\n\n function overlayEditor(s, overlaySources) {\n const wrap = el('div', 'twm-plot-config__overlay');\n const head = el('div', 'twm-plot-config__overlay-source', 'Loading overlay sources\u2026');\n const details = el('div', 'twm-plot-config__overlay-fields');\n wrap.append(head, details);\n\n const drawDetails = () => {\n details.replaceChildren();\n const ov = s.overlay;\n if (!ov) return;\n details.append(\n field('Label', textInput(ov.label, (v) => { ov.label = v; notify(); },\n { placeholder: `${s.label || s.variable || 'Series'} (actual)` })),\n field('Colour', colorField(ov.color, (v) => { if (v) ov.color = v; else delete ov.color; }, 'Overlay colour')),\n field('Dash', select(DASHES, ov.lineStyle ?? 'dashed', (v) => { ov.lineStyle = v; notify(); })),\n field('Width', numberInput(ov.lineWidth ?? 2, (v) => { ov.lineWidth = v ?? 2; notify(); },\n { placeholder: '2', min: 1, max: 10, step: 1 })),\n field('Mode', select(OVERLAY_MODES, ov.mode ?? 'markers+lines', (v) => { ov.mode = v; notify(); })),\n );\n };\n\n const gen = generation;\n overlaySources().then((list) => {\n if (disposed || gen !== generation) return;\n head.replaceChildren(field('Overlay', select(Array.isArray(list) ? list : [], s.overlay?.source, (v) => {\n if (v === undefined) delete s.overlay;\n else s.overlay = { ...(s.overlay ?? {}), source: v };\n drawDetails();\n notify();\n }, { empty: 'None' })));\n drawDetails();\n }, () => {\n if (disposed || gen !== generation) return;\n head.textContent = 'Could not load overlay sources.';\n head.classList.add('twm-plot-config__overlay-source--error');\n });\n return wrap;\n }\n\n function referenceLinesEditor(sp) {\n const axisOptions = sp.yAxes.map((a, i) => ({ value: a.id, label: a.label || `Y axis ${i + 1}` }));\n return listEditor(sp, 'referenceLines', {\n addLabel: 'Add reference line',\n makeItem: () => ({ yAxisId: sp.yAxes[0].id, value: 0, label: '', lineStyle: 'dashed' }),\n fields: (line) => [\n select(axisOptions, line.yAxisId ?? sp.yAxes[0].id, (v) => { line.yAxisId = v; notify(); },\n { label: 'Axis' }),\n numberInput(line.value, (v) => { line.value = v; notify(); }, { placeholder: 'Value', label: 'Value' }),\n textInput(line.label, (v) => { line.label = v; notify(); }, { placeholder: 'Label', label: 'Label' }),\n colorField(line.color, (v) => { if (v) line.color = v; else delete line.color; }, 'Colour'),\n select(DASHES, line.lineStyle ?? 'dashed', (v) => { line.lineStyle = v; notify(); }, { label: 'Dash' }),\n ],\n });\n }\n\n function shadedBandsEditor(sp) {\n return listEditor(sp, 'shadedBands', {\n addLabel: 'Add shaded band',\n makeItem: () => ({ x0: null, x1: null, label: '' }),\n fields: (band) => [\n numberInput(band.x0, (v) => { band.x0 = v; notify(); }, { placeholder: 'From', label: 'From' }),\n numberInput(band.x1, (v) => { band.x1 = v; notify(); }, { placeholder: 'To', label: 'To' }),\n textInput(band.label, (v) => { band.label = v; notify(); }, { placeholder: 'Label', label: 'Label' }),\n colorField(band.color, (v) => { if (v) band.color = v; else delete band.color; }, 'Colour'),\n numberInput(band.opacity, (v) => {\n if (v == null) delete band.opacity; else band.opacity = v;\n notify();\n }, { placeholder: 'Opacity', label: 'Opacity', min: 0, max: 1, step: 0.05 }),\n ],\n });\n }\n\n function transformsSection(sp) {\n if (!Object.keys(opts.seriesTransforms ?? {}).length) return null;\n const s = section('Derived series');\n const controls = renderSeriesTransformControls(s, sp, opts.seriesTransforms, { onChange: notify });\n track(() => controls.dispose());\n return s;\n }\n\n syncChrome();\n renderBody();\n\n return {\n /** Dispose every field it created and remove the editor. Later calls do nothing. */\n dispose() {\n if (disposed) return;\n disposed = true;\n disposeBody();\n tabs.destroy();\n root.remove();\n },\n /** Redraw from the config, after it was changed from outside. */\n refresh() {\n if (disposed) return;\n ensureSubplots();\n active = Math.min(active, slots() - 1);\n syncChrome();\n renderBody();\n },\n /** Bring subplot `index` to the front. */\n selectSubplot(index) {\n if (disposed || !Number.isInteger(index) || index < 0 || index >= slots()) return;\n tabs.select(index);\n },\n /** The index of the subplot in front. */\n get activeSubplot() { return active; },\n };\n}\n\nexport { renderPlotConfigEditor };\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["select", "el", "LEGEND_POSITIONS"]
|
|
7
7
|
}
|
package/dist/chunk-3PHCPZHT.js
CHANGED
|
File without changes
|
|
File without changes
|