From 71e93e521b9c59b656a81e676852cadb3a672aae Mon Sep 17 00:00:00 2001 From: Ryan McKinley Date: Thu, 7 Jan 2021 09:59:21 -0800 Subject: [PATCH] GraphNG: support dashes (#30070) --- .../dev-dashboards/panel-graph/graph-ng.json | 1038 +++++++++++------ .../src/components/GraphNG/GraphNG.tsx | 1 + .../grafana-ui/src/components/uPlot/config.ts | 10 +- .../uPlot/config/UPlotSeriesBuilder.ts | 7 + .../plugins/panel/graph3/LineStyleEditor.tsx | 123 ++ .../__snapshots__/migrations.test.ts.snap | 17 + .../plugins/panel/graph3/migrations.test.ts | 5 +- public/app/plugins/panel/graph3/migrations.ts | 39 + public/app/plugins/panel/graph3/module.tsx | 12 + 9 files changed, 884 insertions(+), 368 deletions(-) create mode 100644 public/app/plugins/panel/graph3/LineStyleEditor.tsx diff --git a/devenv/dev-dashboards/panel-graph/graph-ng.json b/devenv/dev-dashboards/panel-graph/graph-ng.json index 3f60a4b9f76..902cd7fc262 100644 --- a/devenv/dev-dashboards/panel-graph/graph-ng.json +++ b/devenv/dev-dashboards/panel-graph/graph-ng.json @@ -2093,351 +2093,495 @@ "y": 34 }, "id": 11, - "panels": [], + "panels": [ + { + "datasource": "gdev-testdata", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axis": { + "grid": true, + "label": "Temperature", + "side": 3, + "width": 60 + }, + "axisLabel": "", + "axisPlacement": "auto", + "bars": { + "show": false + }, + "drawStyle": "line", + "fill": { + "alpha": 0 + }, + "fillGradient": { + "label": "None" + }, + "fillOpacity": 10, + "hideFrom": { + "graph": false, + "legend": false, + "tooltip": false + }, + "line": { + "color": { + "mode": "palette-classic" + }, + "show": true, + "width": 1 + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "nullValues": "null", + "pointSize": 5, + "points": { + "radius": 8, + "show": true + }, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "celsius" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 6, + "x": 0, + "y": 35 + }, + "id": 43, + "options": { + "graph": { + "realTimeUpdates": false + }, + "legend": { + "asTable": false, + "displayMode": "hidden", + "isVisible": true, + "placement": "bottom" + }, + "tooltipOptions": { + "mode": "single" + } + }, + "pluginVersion": "7.2.0-pre", + "targets": [ + { + "refId": "C", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,0" + }, + { + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "10,25,40" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Diff num datapoints & show gaps", + "transformations": [], + "type": "graph3" + }, + { + "datasource": "gdev-testdata", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axis": { + "grid": true, + "label": "Temperature", + "side": 3, + "width": 60 + }, + "axisLabel": "", + "axisPlacement": "auto", + "bars": { + "show": false + }, + "drawStyle": "line", + "fill": { + "alpha": 0 + }, + "fillGradient": { + "label": "None" + }, + "fillOpacity": 10, + "hideFrom": { + "graph": false, + "legend": false, + "tooltip": false + }, + "line": { + "color": { + "mode": "palette-classic" + }, + "show": true, + "width": 1 + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "nullValues": "null", + "pointSize": 5, + "points": { + "radius": 8, + "show": true + }, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "celsius" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 6, + "x": 6, + "y": 35 + }, + "id": 8, + "options": { + "graph": { + "realTimeUpdates": false + }, + "legend": { + "asTable": false, + "displayMode": "hidden", + "isVisible": true, + "placement": "bottom" + }, + "tooltipOptions": { + "mode": "single" + } + }, + "pluginVersion": "7.2.0-pre", + "targets": [ + { + "refId": "C", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,0" + }, + { + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "10,25,null,null,50,10" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Null values & show gaps", + "transformations": [], + "type": "graph3" + }, + { + "datasource": "gdev-testdata", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axis": { + "grid": true, + "label": "Temperature", + "side": 3, + "width": 60 + }, + "axisLabel": "", + "axisPlacement": "auto", + "bars": { + "show": false + }, + "drawStyle": "line", + "fill": { + "alpha": 0 + }, + "fillGradient": { + "label": "None" + }, + "fillOpacity": 10, + "hideFrom": { + "graph": false, + "legend": false, + "tooltip": false + }, + "line": { + "color": { + "mode": "palette-classic" + }, + "show": true, + "width": 1 + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "nullValues": "null", + "pointSize": 5, + "points": { + "radius": 8, + "show": true + }, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "celsius" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 6, + "x": 12, + "y": 35 + }, + "id": 58, + "options": { + "graph": { + "realTimeUpdates": false + }, + "legend": { + "asTable": false, + "displayMode": "hidden", + "isVisible": true, + "placement": "bottom" + }, + "tooltipOptions": { + "mode": "single" + } + }, + "pluginVersion": "7.2.0-pre", + "targets": [ + { + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "10,25,null,null,50,10" + }, + { + "refId": "C", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,0" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Null values & show gaps 2", + "transformations": [], + "type": "graph3" + }, + { + "datasource": "gdev-testdata", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axis": { + "grid": true, + "label": "", + "side": 3, + "width": 60 + }, + "axisLabel": "", + "axisPlacement": "auto", + "bars": { + "show": false + }, + "custom": { + "axis": { + "grid": true, + "label": "Temperature", + "side": 3 + }, + "bars": { + "show": false + }, + "line": { + "show": true + }, + "points": { + "radius": 8, + "show": true + } + }, + "drawStyle": "line", + "fill": { + "alpha": 0 + }, + "fillGradient": { + "label": "None" + }, + "fillOpacity": 10, + "hideFrom": { + "graph": false, + "legend": false, + "tooltip": false + }, + "line": { + "color": { + "mode": "palette-classic" + }, + "show": true, + "width": 1 + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "nullValues": "asZero", + "pointSize": 5, + "points": { + "radius": 5, + "show": false + }, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": true + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "celsius" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 6, + "x": 18, + "y": 35 + }, + "id": 13, + "options": { + "graph": { + "realTimeUpdates": false + }, + "legend": { + "asTable": false, + "displayMode": "hidden", + "isVisible": true, + "placement": "bottom" + }, + "tooltipOptions": { + "mode": "single" + } + }, + "pluginVersion": "7.2.0-pre", + "targets": [ + { + "refId": "C", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90,30,5,0" + }, + { + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "10,25,null,null,50,10" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Null values & show connected", + "transformations": [], + "type": "graph3" + } + ], "title": "Show gaps & Connected", "type": "row" }, { - "datasource": "gdev-testdata", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axis": { - "grid": true, - "label": "Temperature", - "side": 3, - "width": 60 - }, - "axisLabel": "", - "axisPlacement": "auto", - "bars": { - "show": false - }, - "drawStyle": "line", - "fill": { - "alpha": 0 - }, - "fillGradient": { - "label": "None" - }, - "fillOpacity": 10, - "hideFrom": { - "graph": false, - "legend": false, - "tooltip": false - }, - "line": { - "color": { - "mode": "palette-classic" - }, - "show": true, - "width": 1 - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "nullValues": "null", - "pointSize": 5, - "points": { - "radius": 8, - "show": true - }, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "celsius" - }, - "overrides": [] - }, + "collapsed": false, + "datasource": null, "gridPos": { - "h": 8, - "w": 6, + "h": 1, + "w": 24, "x": 0, "y": 35 }, - "id": 43, - "options": { - "graph": { - "realTimeUpdates": false - }, - "legend": { - "asTable": false, - "displayMode": "hidden", - "isVisible": true, - "placement": "bottom" - }, - "tooltipOptions": { - "mode": "single" - } - }, - "pluginVersion": "7.2.0-pre", - "targets": [ - { - "refId": "C", - "scenarioId": "csv_metric_values", - "stringInput": "1,20,90,30,5,0" - }, - { - "refId": "A", - "scenarioId": "csv_metric_values", - "stringInput": "10,25,40" - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Diff num datapoints & show gaps", - "transformations": [], - "type": "graph3" + "id": 62, + "panels": [], + "title": "Line Styles", + "type": "row" }, { - "datasource": "gdev-testdata", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axis": { - "grid": true, - "label": "Temperature", - "side": 3, - "width": 60 - }, - "axisLabel": "", - "axisPlacement": "auto", - "bars": { - "show": false - }, - "drawStyle": "line", - "fill": { - "alpha": 0 - }, - "fillGradient": { - "label": "None" - }, - "fillOpacity": 10, - "hideFrom": { - "graph": false, - "legend": false, - "tooltip": false - }, - "line": { - "color": { - "mode": "palette-classic" - }, - "show": true, - "width": 1 - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "nullValues": "null", - "pointSize": 5, - "points": { - "radius": 8, - "show": true - }, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "celsius" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 6, - "x": 6, - "y": 35 - }, - "id": 8, - "options": { - "graph": { - "realTimeUpdates": false - }, - "legend": { - "asTable": false, - "displayMode": "hidden", - "isVisible": true, - "placement": "bottom" - }, - "tooltipOptions": { - "mode": "single" - } - }, - "pluginVersion": "7.2.0-pre", - "targets": [ - { - "refId": "C", - "scenarioId": "csv_metric_values", - "stringInput": "1,20,90,30,5,0" - }, - { - "refId": "A", - "scenarioId": "csv_metric_values", - "stringInput": "10,25,null,null,50,10" - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Null values & show gaps", - "transformations": [], - "type": "graph3" - }, - { - "datasource": "gdev-testdata", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axis": { - "grid": true, - "label": "Temperature", - "side": 3, - "width": 60 - }, - "axisLabel": "", - "axisPlacement": "auto", - "bars": { - "show": false - }, - "drawStyle": "line", - "fill": { - "alpha": 0 - }, - "fillGradient": { - "label": "None" - }, - "fillOpacity": 10, - "hideFrom": { - "graph": false, - "legend": false, - "tooltip": false - }, - "line": { - "color": { - "mode": "palette-classic" - }, - "show": true, - "width": 1 - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "nullValues": "null", - "pointSize": 5, - "points": { - "radius": 8, - "show": true - }, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "celsius" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 6, - "x": 12, - "y": 35 - }, - "id": 58, - "options": { - "graph": { - "realTimeUpdates": false - }, - "legend": { - "asTable": false, - "displayMode": "hidden", - "isVisible": true, - "placement": "bottom" - }, - "tooltipOptions": { - "mode": "single" - } - }, - "pluginVersion": "7.2.0-pre", - "targets": [ - { - "refId": "A", - "scenarioId": "csv_metric_values", - "stringInput": "10,25,null,null,50,10" - }, - { - "refId": "C", - "scenarioId": "csv_metric_values", - "stringInput": "1,20,90,30,5,0" - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Null values & show gaps 2", - "transformations": [], - "type": "graph3" - }, - { - "datasource": "gdev-testdata", + "datasource": null, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { + "align": null, "axis": { "grid": true, "label": "", @@ -2449,23 +2593,6 @@ "bars": { "show": false }, - "custom": { - "axis": { - "grid": true, - "label": "Temperature", - "side": 3 - }, - "bars": { - "show": false - }, - "line": { - "show": true - }, - "points": { - "radius": 8, - "show": true - } - }, "drawStyle": "line", "fill": { "alpha": 0 @@ -2473,7 +2600,7 @@ "fillGradient": { "label": "None" }, - "fillOpacity": 10, + "fillOpacity": 0, "hideFrom": { "graph": false, "legend": false, @@ -2487,8 +2614,12 @@ "width": 1 }, "lineInterpolation": "linear", - "lineWidth": 1, - "nullValues": "asZero", + "lineStyle": { + "dash": [10, 10], + "fill": "dash" + }, + "lineWidth": 2, + "nullValues": "null", "pointSize": 5, "points": { "radius": 5, @@ -2498,7 +2629,7 @@ "type": "linear" }, "showPoints": "auto", - "spanNulls": true + "spanNulls": false }, "mappings": [], "thresholds": { @@ -2513,18 +2644,74 @@ "value": 80 } ] - }, - "unit": "celsius" + } }, - "overrides": [] + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "B-series" + }, + "properties": [ + { + "id": "custom.lineStyle", + "value": { + "dash": [10, 20], + "fill": "dash" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "C-series" + }, + "properties": [ + { + "id": "custom.lineStyle", + "value": { + "dash": [10, 30], + "fill": "dash" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "D-series" + }, + "properties": [ + { + "id": "custom.lineStyle", + "value": { + "dash": [30, 3, 3], + "fill": "dash" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "E-series" + }, + "properties": [ + { + "id": "custom.lineStyle" + } + ] + } + ] }, "gridPos": { - "h": 8, + "h": 7, "w": 6, - "x": 18, - "y": 35 + "x": 0, + "y": 36 }, - "id": 13, + "id": 60, "options": { "graph": { "realTimeUpdates": false @@ -2542,20 +2729,139 @@ "pluginVersion": "7.2.0-pre", "targets": [ { - "refId": "C", - "scenarioId": "csv_metric_values", - "stringInput": "1,20,90,30,5,0" - }, - { + "alias": "", + "csvWave": { + "timeStep": 60, + "valuesCSV": "0,0,2,2,1,1" + }, + "lines": 10, + "points": [], + "pulseWave": { + "offCount": 3, + "offValue": 1, + "onCount": 3, + "onValue": 2, + "timeStep": 60 + }, "refId": "A", "scenarioId": "csv_metric_values", - "stringInput": "10,25,null,null,50,10" + "stream": { + "bands": 1, + "noise": 2.2, + "speed": 250, + "spread": 3.5, + "type": "signal" + }, + "stringInput": "10,10" + }, + { + "alias": "", + "csvWave": { + "timeStep": 60, + "valuesCSV": "0,0,2,2,1,1" + }, + "lines": 10, + "points": [], + "pulseWave": { + "offCount": 3, + "offValue": 1, + "onCount": 3, + "onValue": 2, + "timeStep": 60 + }, + "refId": "B", + "scenarioId": "csv_metric_values", + "stream": { + "bands": 1, + "noise": 2.2, + "speed": 250, + "spread": 3.5, + "type": "signal" + }, + "stringInput": "9,9" + }, + { + "alias": "", + "csvWave": { + "timeStep": 60, + "valuesCSV": "0,0,2,2,1,1" + }, + "lines": 10, + "points": [], + "pulseWave": { + "offCount": 3, + "offValue": 1, + "onCount": 3, + "onValue": 2, + "timeStep": 60 + }, + "refId": "C", + "scenarioId": "csv_metric_values", + "stream": { + "bands": 1, + "noise": 2.2, + "speed": 250, + "spread": 3.5, + "type": "signal" + }, + "stringInput": "8,8" + }, + { + "alias": "", + "csvWave": { + "timeStep": 60, + "valuesCSV": "0,0,2,2,1,1" + }, + "lines": 10, + "points": [], + "pulseWave": { + "offCount": 3, + "offValue": 1, + "onCount": 3, + "onValue": 2, + "timeStep": 60 + }, + "refId": "D", + "scenarioId": "csv_metric_values", + "stream": { + "bands": 1, + "noise": 2.2, + "speed": 250, + "spread": 3.5, + "type": "signal" + }, + "stringInput": "7,7" + }, + { + "alias": "", + "csvWave": { + "timeStep": 60, + "valuesCSV": "0,0,2,2,1,1" + }, + "lines": 10, + "points": [], + "pulseWave": { + "offCount": 3, + "offValue": 1, + "onCount": 3, + "onValue": 2, + "timeStep": 60 + }, + "refId": "E", + "scenarioId": "csv_metric_values", + "stream": { + "bands": 1, + "noise": 2.2, + "speed": 250, + "spread": 3.5, + "type": "signal" + }, + "stringInput": "6,6" } ], "timeFrom": null, "timeShift": null, - "title": "Null values & show connected", - "transformations": [], + "title": "Dashed lines", "type": "graph3" }, { @@ -2714,5 +3020,5 @@ "timezone": "", "title": "Panel Tests - Graph NG", "uid": "TkZXxlNG3", - "version": 2 + "version": 1 } diff --git a/packages/grafana-ui/src/components/GraphNG/GraphNG.tsx b/packages/grafana-ui/src/components/GraphNG/GraphNG.tsx index ce9fa5b80f6..64a84201c50 100755 --- a/packages/grafana-ui/src/components/GraphNG/GraphNG.tsx +++ b/packages/grafana-ui/src/components/GraphNG/GraphNG.tsx @@ -175,6 +175,7 @@ export const GraphNG: React.FC = ({ lineColor: customConfig.lineColor ?? seriesColor, lineWidth: customConfig.lineWidth, lineInterpolation: customConfig.lineInterpolation, + lineStyle: customConfig.lineStyle, showPoints, pointSize: customConfig.pointSize, pointColor: customConfig.pointColor ?? seriesColor, diff --git a/packages/grafana-ui/src/components/uPlot/config.ts b/packages/grafana-ui/src/components/uPlot/config.ts index 23019000cdb..87362e6a481 100644 --- a/packages/grafana-ui/src/components/uPlot/config.ts +++ b/packages/grafana-ui/src/components/uPlot/config.ts @@ -48,6 +48,14 @@ export enum ScaleDistribution { Logarithmic = 'log', } +/** + * @alpha + */ +export interface LineStyle { + fill?: 'solid' | 'dash' | 'dot' | 'square'; // cap = 'butt' | 'round' | 'square' + dash?: number[]; +} + /** * @alpha */ @@ -55,7 +63,7 @@ export interface LineConfig { lineColor?: string; lineWidth?: number; lineInterpolation?: LineInterpolation; - lineDash?: number[]; + lineStyle?: LineStyle; spanNulls?: boolean; } diff --git a/packages/grafana-ui/src/components/uPlot/config/UPlotSeriesBuilder.ts b/packages/grafana-ui/src/components/uPlot/config/UPlotSeriesBuilder.ts index 14ba5996a9e..56a126fab25 100755 --- a/packages/grafana-ui/src/components/uPlot/config/UPlotSeriesBuilder.ts +++ b/packages/grafana-ui/src/components/uPlot/config/UPlotSeriesBuilder.ts @@ -25,6 +25,7 @@ export class UPlotSeriesBuilder extends PlotConfigBuilder { lineInterpolation, lineColor, lineWidth, + lineStyle, showPoints, pointColor, pointSize, @@ -40,6 +41,12 @@ export class UPlotSeriesBuilder extends PlotConfigBuilder { } else { lineConfig.stroke = lineColor; lineConfig.width = lineWidth; + if (lineStyle && lineStyle.fill !== 'solid') { + if (lineStyle.fill === 'dot') { + // lineConfig.dashCap = 'round'; // square or butt + } + lineConfig.dash = lineStyle.dash ?? [10, 10]; + } lineConfig.paths = (self: uPlot, seriesIdx: number, idx0: number, idx1: number) => { let pathsBuilder = mapDrawStyleToPathBuilder(drawStyle, lineInterpolation); return pathsBuilder(self, seriesIdx, idx0, idx1); diff --git a/public/app/plugins/panel/graph3/LineStyleEditor.tsx b/public/app/plugins/panel/graph3/LineStyleEditor.tsx new file mode 100644 index 00000000000..f73ab3b8a7d --- /dev/null +++ b/public/app/plugins/panel/graph3/LineStyleEditor.tsx @@ -0,0 +1,123 @@ +import React, { useMemo } from 'react'; +import { FieldOverrideEditorProps, SelectableValue } from '@grafana/data'; +import { HorizontalGroup, IconButton, LineStyle, RadioButtonGroup, Select } from '@grafana/ui'; + +type LineFill = 'solid' | 'dash' | 'dot'; + +const lineFillOptions: Array> = [ + { + label: 'Solid', + value: 'solid', + }, + { + label: 'Dash', + value: 'dash', + }, + // { + // label: 'Dots', + // value: 'dot', + // }, +]; + +const dashOptions: Array> = [ + '10, 10', // default + '10, 15', + '10, 20', + '10, 25', + '10, 30', + '10, 40', + '15, 10', + '20, 10', + '25, 10', + '30, 10', + '40, 10', + '50, 10', + '5, 10', + '30, 3, 3', +].map(txt => ({ + label: txt, + value: txt, +})); + +const dotOptions: Array> = [ + '0, 10', // default + '0, 20', + '0, 30', + '0, 40', + '0, 3, 3', +].map(txt => ({ + label: txt, + value: txt, +})); + +export const LineStyleEditor: React.FC> = ({ value, onChange }) => { + const options = useMemo(() => (value?.fill === 'dash' ? dashOptions : dotOptions), [value]); + const current = useMemo(() => { + if (!value?.dash?.length) { + return options[0]; + } + const str = value.dash?.join(', '); + const val = options.find(o => o.value === str); + if (!val) { + return { + label: str, + value: str, + }; + } + return val; + }, [value, options]); + + return ( + + { + onChange({ + ...value, + fill: v!, + }); + }} + /> + {value?.fill && value?.fill !== 'solid' && ( + <> +