@cdc/chart 4.24.5 → 4.24.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/dist/cdcchart.js +44197 -38258
  2. package/examples/cases-year.json +13379 -0
  3. package/examples/feature/annotations/index.json +542 -0
  4. package/examples/gallery/bar-chart-vertical/combo-line-chart.json +76 -15
  5. package/examples/gallery/bar-chart-vertical/vertical-bar-chart-stacked.json +5 -5
  6. package/examples/xaxis.json +493 -0
  7. package/index.html +20 -10
  8. package/package.json +5 -4
  9. package/src/CdcChart.tsx +462 -172
  10. package/src/_stories/Chart.Legend.Gradient.tsx +19 -0
  11. package/src/_stories/Chart.stories.tsx +18 -171
  12. package/src/_stories/ChartAnnotation.stories.tsx +32 -0
  13. package/src/_stories/_mock/annotation_category_mock.json +473 -0
  14. package/src/_stories/_mock/annotation_date-linear_mock.json +530 -0
  15. package/{examples/feature/line/line-chart.json → src/_stories/_mock/annotation_date-time_mock.json} +150 -69
  16. package/src/_stories/_mock/legend.gradient_mock.json +236 -0
  17. package/src/_stories/_mock/line_chart_two_points_new_chart.json +128 -0
  18. package/src/_stories/_mock/line_chart_two_points_regression_test.json +127 -0
  19. package/src/_stories/_mock/lollipop.json +171 -0
  20. package/src/components/Annotations/components/AnnotationDraggable.styles.css +31 -0
  21. package/src/components/Annotations/components/AnnotationDraggable.tsx +207 -0
  22. package/src/components/Annotations/components/AnnotationDropdown.styles.css +14 -0
  23. package/src/components/Annotations/components/AnnotationDropdown.tsx +72 -0
  24. package/src/components/Annotations/components/AnnotationList.styles.css +45 -0
  25. package/src/components/Annotations/components/AnnotationList.tsx +42 -0
  26. package/src/components/Annotations/components/findNearestDatum.ts +138 -0
  27. package/src/components/Annotations/components/helpers/index.tsx +46 -0
  28. package/src/components/Annotations/index.tsx +13 -0
  29. package/src/components/AreaChart/components/AreaChart.Stacked.jsx +1 -1
  30. package/src/components/AreaChart/components/AreaChart.jsx +1 -1
  31. package/src/components/Axis/Categorical.Axis.tsx +145 -0
  32. package/src/components/BarChart/components/BarChart.Horizontal.tsx +47 -44
  33. package/src/components/BarChart/components/BarChart.StackedHorizontal.tsx +0 -1
  34. package/src/components/BarChart/components/BarChart.StackedVertical.tsx +11 -14
  35. package/src/components/BarChart/components/BarChart.Vertical.tsx +67 -30
  36. package/src/components/BarChart/helpers/index.ts +91 -0
  37. package/src/components/BrushChart.tsx +205 -0
  38. package/src/components/EditorPanel/EditorPanel.tsx +1794 -403
  39. package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +320 -0
  40. package/src/components/EditorPanel/components/Panels/Panel.General.tsx +282 -18
  41. package/src/components/EditorPanel/components/Panels/Panel.Sankey.tsx +43 -8
  42. package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +4 -4
  43. package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +4 -13
  44. package/src/components/EditorPanel/components/Panels/index.tsx +3 -1
  45. package/src/components/EditorPanel/components/panels.scss +4 -0
  46. package/src/components/EditorPanel/editor-panel.scss +35 -3
  47. package/src/components/EditorPanel/{useEditorPermissions.js → useEditorPermissions.ts} +105 -17
  48. package/src/components/Legend/Legend.Component.tsx +185 -194
  49. package/src/components/Legend/Legend.Suppression.tsx +146 -0
  50. package/src/components/Legend/Legend.tsx +21 -5
  51. package/src/components/Legend/helpers/createFormatLabels.tsx +1 -1
  52. package/src/components/Legend/helpers/index.ts +35 -0
  53. package/src/components/LegendWrapper.tsx +26 -0
  54. package/src/components/LineChart/LineChartProps.ts +1 -15
  55. package/src/components/LineChart/components/LineChart.BumpCircle.tsx +103 -0
  56. package/src/components/LineChart/components/LineChart.Circle.tsx +47 -8
  57. package/src/components/LineChart/helpers.ts +72 -14
  58. package/src/components/LineChart/index.tsx +117 -42
  59. package/src/components/LinearChart.jsx +179 -136
  60. package/src/components/LinearChart.tsx +1366 -0
  61. package/src/components/PairedBarChart.jsx +9 -9
  62. package/src/components/PieChart/PieChart.tsx +75 -18
  63. package/src/components/Sankey/index.tsx +89 -30
  64. package/src/components/ScatterPlot/ScatterPlot.jsx +22 -8
  65. package/src/components/Sparkline/components/SparkLine.tsx +2 -2
  66. package/src/components/ZoomBrush.tsx +90 -44
  67. package/src/data/initial-state.js +25 -7
  68. package/src/helpers/handleChartTabbing.ts +8 -0
  69. package/src/helpers/isConvertLineToBarGraph.ts +4 -0
  70. package/src/hooks/{useBarChart.js → useBarChart.ts} +2 -40
  71. package/src/hooks/useColorScale.ts +1 -1
  72. package/src/hooks/useLegendClasses.ts +68 -0
  73. package/src/hooks/useMinMax.ts +12 -7
  74. package/src/hooks/useScales.ts +58 -26
  75. package/src/hooks/useTooltip.tsx +135 -25
  76. package/src/scss/DataTable.scss +2 -1
  77. package/src/scss/main.scss +128 -28
  78. package/src/types/ChartConfig.ts +83 -10
  79. package/src/types/ChartContext.ts +14 -4
  80. package/tests-examples/helpers/testZeroValue.test.ts +30 -0
  81. package/LICENSE +0 -201
  82. package/src/components/BrushHandle.jsx +0 -17
  83. package/src/components/LineChart/index.scss +0 -1
  84. package/src/helpers/filterData.ts +0 -18
  85. package/src/helpers/tests/computeMarginBottom.test.ts +0 -21
  86. package/src/hooks/useLegendClasses.js +0 -31
  87. /package/src/hooks/{useReduceData.js → useReduceData.ts} +0 -0
@@ -1,7 +1,14 @@
1
1
  import { useState, useEffect, useCallback, memo, useContext } from 'react'
2
2
  import { DragDropContext, Droppable } from '@hello-pangea/dnd'
3
+ import chroma from 'chroma-js'
3
4
  import { isDateScale } from '@cdc/core/helpers/cove/date'
4
- import { Accordion, AccordionItem, AccordionItemHeading, AccordionItemPanel, AccordionItemButton } from 'react-accessible-accordion'
5
+ import {
6
+ Accordion,
7
+ AccordionItem,
8
+ AccordionItemHeading,
9
+ AccordionItemPanel,
10
+ AccordionItemButton
11
+ } from 'react-accessible-accordion'
5
12
  import Layout from '@cdc/core/components/Layout'
6
13
 
7
14
  // @cdc/core
@@ -13,6 +20,8 @@ import DataTableEditor from '@cdc/core/components/EditorPanel/DataTableEditor'
13
20
  import VizFilterEditor from '@cdc/core/components/EditorPanel/VizFilterEditor'
14
21
  import Tooltip from '@cdc/core/components/ui/Tooltip'
15
22
  import { Select, TextField, CheckBox } from '@cdc/core/components/EditorPanel/Inputs'
23
+ import { viewports } from '@cdc/core/helpers/getViewport'
24
+ import { approvedCurveTypes } from '@cdc/core/helpers/lineChartHelpers'
16
25
 
17
26
  // chart components
18
27
  import Panels from './components/Panels'
@@ -60,17 +69,16 @@ const PreliminaryData: React.FC<PreliminaryProps> = ({ config, updateConfig, dat
60
69
  'Dashed Small': '\u002D \u002D \u002D',
61
70
  'Dashed Medium': '\u2013 \u2013',
62
71
  'Dashed Large': '\u2014 \u2013',
63
- 'Open Circles': '\u25EF'
72
+ 'Open Circles': '\u25EF',
73
+ 'Filled Circles': ''
64
74
  }
65
75
 
66
76
  const getStyleOptions = type => {
67
- if (config.visualizationType === 'Line' || isCombo) {
68
- const options = Object.keys(lineCodes)
69
- if (type === 'suppression') {
70
- return options.slice(0, -1)
71
- } else {
72
- return options
73
- }
77
+ const options = Object.keys(lineCodes)
78
+ if (type === 'suppression') {
79
+ return options.slice(0, -1)
80
+ } else {
81
+ return options
74
82
  }
75
83
  }
76
84
 
@@ -107,7 +115,11 @@ const PreliminaryData: React.FC<PreliminaryProps> = ({ config, updateConfig, dat
107
115
  displayTable: true,
108
116
  symbol: '',
109
117
  iconCode: '',
110
- lineCode: ''
118
+ lineCode: '',
119
+ hideBarSymbol: false,
120
+ hideLineStyle: false,
121
+ circleSize: 6,
122
+ displayGray: true
111
123
  }
112
124
  preliminaryData.push(defaultValues)
113
125
  updateConfig({ ...config, preliminaryData })
@@ -133,44 +145,50 @@ const PreliminaryData: React.FC<PreliminaryProps> = ({ config, updateConfig, dat
133
145
  return (
134
146
  <>
135
147
  {config.preliminaryData &&
136
- config.preliminaryData?.map(({ column, displayLegend, displayTable, displayTooltip, label, seriesKey, style, symbol, type, value }, i) => {
137
- return (
138
- <div key={`preliminaryData-${i}`} className='edit-block'>
139
- <p> {type === 'suppression' ? 'Suppressed' : 'Effect'} Data</p>
140
- <button
141
- type='button'
142
- className='remove-column'
143
- onClick={event => {
144
- event.preventDefault()
145
- removeColumn(i)
146
- }}
147
- >
148
- Remove
149
- </button>
150
-
151
- <Select value={type} initial={config.visualizationType == 'Bar' ? '' : 'Select'} fieldName='type' label='Type' updateField={(_, __, fieldName, value) => update(fieldName, value, i)} options={getTypeOptions()} />
152
- {type === 'suppression' ? (
153
- <>
154
- <Select
155
- tooltip={
156
- <Tooltip style={{ textTransform: 'none' }}>
157
- <Tooltip.Target>
158
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
159
- </Tooltip.Target>
160
- <Tooltip.Content>
161
- <p>If no “Data Series" is selected, the symbol will be applied to "all" suppressed values indicated in the dataset.</p>
162
- </Tooltip.Content>
163
- </Tooltip>
164
- }
165
- value={column}
166
- initial='Select'
167
- fieldName='column'
168
- label='Add Data Series'
169
- updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
170
- options={config.runtime?.seriesKeys}
171
- />
172
- <TextField value={value} fieldName='value' label='Suppressed Data Value' updateField={(_, __, fieldName, value) => update(fieldName, value, i)} />
173
- {(hasComboLineSeries || config.visualizationType === 'Line') && (
148
+ config.preliminaryData?.map(
149
+ (
150
+ {
151
+ displayGray,
152
+ circleSize,
153
+ column,
154
+ displayLegend,
155
+ displayTable,
156
+ displayTooltip,
157
+ label,
158
+ seriesKey,
159
+ style,
160
+ symbol,
161
+ type,
162
+ value,
163
+ hideBarSymbol,
164
+ hideLineStyle
165
+ },
166
+ i
167
+ ) => {
168
+ return (
169
+ <div key={`preliminaryData-${i}`} className='edit-block'>
170
+ <p> {type === 'suppression' ? 'Suppressed' : 'Effect'} Data</p>
171
+ <button
172
+ type='button'
173
+ className='remove-column'
174
+ onClick={event => {
175
+ event.preventDefault()
176
+ removeColumn(i)
177
+ }}
178
+ >
179
+ Remove
180
+ </button>
181
+
182
+ <Select
183
+ value={type}
184
+ initial={config.visualizationType == 'Bar' ? '' : 'Select'}
185
+ fieldName='type'
186
+ label='Type'
187
+ updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
188
+ options={getTypeOptions()}
189
+ />
190
+ {type === 'suppression' ? (
191
+ <>
174
192
  <Select
175
193
  tooltip={
176
194
  <Tooltip style={{ textTransform: 'none' }}>
@@ -178,121 +196,394 @@ const PreliminaryData: React.FC<PreliminaryProps> = ({ config, updateConfig, dat
178
196
  <Icon display='question' style={{ marginLeft: '0.5rem' }} />
179
197
  </Tooltip.Target>
180
198
  <Tooltip.Content>
181
- <p>The recommended approach for presenting data is to include a footnote indicating any data suppression.</p>
199
+ <p>
200
+ {' '}
201
+ Without a selected "Data Series", the suppression symbol will be applied for all series in
202
+ the current dataset visualization. However, choosing a specific "data series" will isolate
203
+ the suppression to that series.
204
+ </p>
182
205
  </Tooltip.Content>
183
206
  </Tooltip>
184
207
  }
185
- value={style}
208
+ value={column}
186
209
  initial='Select'
187
- fieldName='style'
188
- label={'suppression line style'}
210
+ fieldName='column'
211
+ label='Add Data Series'
189
212
  updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
190
- options={getStyleOptions(type)}
213
+ options={config.runtime?.seriesKeys}
191
214
  />
192
- )}
215
+ <TextField
216
+ value={value}
217
+ fieldName='value'
218
+ label='Suppressed Data Value'
219
+ updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
220
+ />
221
+ {(hasComboLineSeries || config.visualizationType === 'Line') && (
222
+ <>
223
+ <Select
224
+ tooltip={
225
+ <Tooltip style={{ textTransform: 'none' }}>
226
+ <Tooltip.Target>
227
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
228
+ </Tooltip.Target>
229
+ <Tooltip.Content>
230
+ <p>
231
+ The recommended approach for presenting data is to include a footnote indicating any
232
+ data suppression.
233
+ </p>
234
+ </Tooltip.Content>
235
+ </Tooltip>
236
+ }
237
+ value={style}
238
+ initial='Select'
239
+ fieldName='style'
240
+ label={'suppression line style'}
241
+ updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
242
+ options={getStyleOptions(type)}
243
+ />
244
+ <CheckBox
245
+ value={hideLineStyle}
246
+ fieldName='hideLineStyle'
247
+ label='Hide Suppressed line Style'
248
+ updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
249
+ />
250
+ </>
251
+ )}
193
252
 
194
- {(hasComboBarSeries || config.visualizationType === 'Bar') && (
253
+ {(hasComboBarSeries || config.visualizationType === 'Bar') && (
254
+ <>
255
+ <Select
256
+ tooltip={
257
+ <Tooltip style={{ textTransform: 'none' }}>
258
+ <Tooltip.Target>
259
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
260
+ </Tooltip.Target>
261
+ <Tooltip.Content>
262
+ <p>
263
+ A symbol is <i>required</i> to indicate suppressed data. We suggest "double
264
+ asterisks." If "double asterisks" are already used elsewhere (e.g., footnotes), please
265
+ select an alternative symbol from the menu to denote data suppression.
266
+ </p>
267
+ </Tooltip.Content>
268
+ </Tooltip>
269
+ }
270
+ value={symbol}
271
+ initial='Select'
272
+ fieldName='symbol'
273
+ label={config.visualizationType === 'Combo' ? 'suppression bar symbol' : 'suppression symbol'}
274
+ updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
275
+ options={getSymbolOptions()}
276
+ />
277
+ <CheckBox
278
+ value={hideBarSymbol}
279
+ fieldName='hideBarSymbol'
280
+ label='Hide Suppressed Bar Symbol '
281
+ updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
282
+ />
283
+ </>
284
+ )}
285
+
286
+ <TextField
287
+ tooltip={
288
+ <Tooltip style={{ textTransform: 'none' }}>
289
+ <Tooltip.Target>
290
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
291
+ </Tooltip.Target>
292
+ <Tooltip.Content>
293
+ <p>This label will display in the tooltip and legend.</p>
294
+ </Tooltip.Content>
295
+ </Tooltip>
296
+ }
297
+ value={label ? label : 'Suppressed'}
298
+ fieldName='label'
299
+ label='Suppressed Data Label'
300
+ placeholder=''
301
+ updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
302
+ />
303
+ <CheckBox
304
+ display={config.visualizationSubType === 'regular'}
305
+ tooltip={
306
+ <Tooltip style={{ textTransform: 'none' }}>
307
+ <Tooltip.Target>
308
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
309
+ </Tooltip.Target>
310
+ <Tooltip.Content>
311
+ <p>
312
+ Deselecting the "Display In Tooltips" option prevents suppressed values from appearing in
313
+ tooltips.
314
+ </p>
315
+ </Tooltip.Content>
316
+ </Tooltip>
317
+ }
318
+ value={displayTooltip}
319
+ fieldName='displayTooltip'
320
+ label='Display in tooltips'
321
+ updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
322
+ />
323
+ <CheckBox
324
+ display={config.visualizationSubType === 'regular'}
325
+ tooltip={
326
+ <Tooltip style={{ textTransform: 'none' }}>
327
+ <Tooltip.Target>
328
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
329
+ </Tooltip.Target>
330
+ <Tooltip.Content>
331
+ <p>
332
+ Deselecting "Display in Legend" indicates that you do not want to display suppressed data
333
+ in the legend.
334
+ </p>
335
+ </Tooltip.Content>
336
+ </Tooltip>
337
+ }
338
+ value={displayLegend}
339
+ fieldName='displayLegend'
340
+ label='Display in legend'
341
+ updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
342
+ />
343
+ <CheckBox
344
+ display={config.visualizationSubType === 'regular'}
345
+ tooltip={
346
+ <Tooltip style={{ textTransform: 'none' }}>
347
+ <Tooltip.Target>
348
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
349
+ </Tooltip.Target>
350
+ <Tooltip.Content>
351
+ <p>
352
+ Deselecting "Display In Data Table" indicates that you do not want to display suppressed
353
+ data in the data table.
354
+ </p>
355
+ </Tooltip.Content>
356
+ </Tooltip>
357
+ }
358
+ value={displayTable}
359
+ fieldName='displayTable'
360
+ label='Display in table'
361
+ updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
362
+ />
363
+ <CheckBox
364
+ display={config.visualizationSubType === 'regular'}
365
+ tooltip={
366
+ <Tooltip style={{ textTransform: 'none' }}>
367
+ <Tooltip.Target>
368
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
369
+ </Tooltip.Target>
370
+ <Tooltip.Content>
371
+ <p>Selecting this option will apply to chart, tooltip hover, legend, and data table.</p>
372
+ </Tooltip.Content>
373
+ </Tooltip>
374
+ }
375
+ value={displayGray}
376
+ fieldName='displayGray'
377
+ label='Highlight Suppressed Data In Gray'
378
+ updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
379
+ />
380
+ </>
381
+ ) : (
382
+ <>
195
383
  <Select
384
+ value={seriesKey}
385
+ initial='Select'
386
+ fieldName='seriesKey'
387
+ label='ASSOCIATE TO SERIES'
388
+ updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
389
+ options={config.runtime.lineSeriesKeys ?? config.runtime?.seriesKeys}
390
+ />
391
+ <Select
392
+ value={column}
393
+ initial='Select'
394
+ fieldName='column'
395
+ label='COLUMN WITH CONFIGURATION VALUE'
396
+ updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
397
+ options={getColumnOptions()}
398
+ />
399
+ <TextField
196
400
  tooltip={
197
401
  <Tooltip style={{ textTransform: 'none' }}>
198
402
  <Tooltip.Target>
199
403
  <Icon display='question' style={{ marginLeft: '0.5rem' }} />
200
404
  </Tooltip.Target>
201
405
  <Tooltip.Content>
202
- <p>The suggested method for presenting suppressed data is to use "double asterisks". If "double asterisks" are already used elsewhere (e.g., footnotes), please select an alternative symbol from the menu to denote data suppression.</p>
406
+ <p>
407
+ If 'Filled Circles' is selected as the style, this field is optional, and the style
408
+ 'Filled Circles' will apply to all points within the associated series data.
409
+ </p>
203
410
  </Tooltip.Content>
204
411
  </Tooltip>
205
412
  }
206
- value={symbol}
413
+ value={value}
414
+ fieldName='value'
415
+ label='VALUE TO TRIGGER'
416
+ updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
417
+ />
418
+ <Select
419
+ value={style}
207
420
  initial='Select'
208
- fieldName='symbol'
209
- label={config.visualizationType === 'Combo' ? 'suppression bar symbol' : 'suppression symbol'}
421
+ fieldName='style'
422
+ label='Style'
210
423
  updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
211
- options={getSymbolOptions()}
424
+ options={getStyleOptions(type)}
212
425
  />
213
- )}
426
+ {style.includes('Circles') && (
427
+ <TextField
428
+ className='number-narrow'
429
+ type='number'
430
+ value={circleSize}
431
+ fieldName='circleSize'
432
+ label='circle size'
433
+ updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
434
+ />
435
+ )}
436
+ {style !== 'Filled Circles' && (
437
+ <TextField
438
+ value={label}
439
+ fieldName='label'
440
+ label='Label'
441
+ placeholder=''
442
+ updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
443
+ />
444
+ )}
445
+ </>
446
+ )}
447
+ </div>
448
+ )
449
+ }
450
+ )}
214
451
 
215
- <TextField
216
- tooltip={
217
- <Tooltip style={{ textTransform: 'none' }}>
218
- <Tooltip.Target>
219
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
220
- </Tooltip.Target>
221
- <Tooltip.Content>
222
- <p>This label will display in the tooltip and legend.</p>
223
- </Tooltip.Content>
224
- </Tooltip>
225
- }
226
- value={label ? label : 'Suppressed'}
227
- fieldName='label'
228
- label='Suppressed Data Label'
229
- placeholder=''
230
- updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
231
- />
232
- <CheckBox
233
- tooltip={
234
- <Tooltip style={{ textTransform: 'none' }}>
235
- <Tooltip.Target>
236
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
237
- </Tooltip.Target>
238
- <Tooltip.Content>
239
- <p>Enabling this tooltip will provide a clearer indication of 'suppressed' or 'zero data' values, whichever is applicable. Deselecting 'Display In Tooltip' indicates that you do not want to display 'suppressed' or 'zero data' values in tooltips when hovering over them.</p>
240
- </Tooltip.Content>
241
- </Tooltip>
242
- }
243
- value={displayTooltip}
244
- fieldName='displayTooltip'
245
- label='Display in tooltips'
246
- updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
247
- />
248
- <CheckBox
249
- tooltip={
250
- <Tooltip style={{ textTransform: 'none' }}>
251
- <Tooltip.Target>
252
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
253
- </Tooltip.Target>
254
- <Tooltip.Content>
255
- <p>Deselecting "Display in Legend" indicates that you do not want to display suppressed data in the legend.</p>
256
- </Tooltip.Content>
257
- </Tooltip>
258
- }
259
- value={displayLegend}
260
- fieldName='displayLegend'
261
- label='Display in legend'
262
- updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
263
- />
264
- <CheckBox
265
- tooltip={
266
- <Tooltip style={{ textTransform: 'none' }}>
267
- <Tooltip.Target>
268
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
269
- </Tooltip.Target>
270
- <Tooltip.Content>
271
- <p>Deselecting "Display In Data Table" indicates that you do not want to display suppressed data in the data table.</p>
272
- </Tooltip.Content>
273
- </Tooltip>
274
- }
275
- value={displayTable}
276
- fieldName='displayTable'
277
- label='Display in table'
278
- updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
279
- />
280
- </>
281
- ) : (
282
- <>
283
- <Select value={seriesKey} initial='Select' fieldName='seriesKey' label='ASSOCIATE TO SERIES' updateField={(_, __, fieldName, value) => update(fieldName, value, i)} options={config.runtime.lineSeriesKeys ?? config.runtime?.seriesKeys} />
284
- <Select value={column} initial='Select' fieldName='column' label='COLUMN WITH CONFIGURATION VALUE' updateField={(_, __, fieldName, value) => update(fieldName, value, i)} options={getColumnOptions()} />
285
- <TextField value={value} fieldName='value' label='VALUE TO TRIGGER' updateField={(_, __, fieldName, value) => update(fieldName, value, i)} />
286
- <Select value={style} initial='Select' fieldName='style' label='Style' updateField={(_, __, fieldName, value) => update(fieldName, value, i)} options={getStyleOptions(type)} />
287
- <TextField value={label} fieldName='label' label='Label' placeholder='' updateField={(_, __, fieldName, value) => update(fieldName, value, i)} />
288
- </>
452
+ <button type='button' onClick={addColumn} className='btn full-width'>
453
+ {config.visualizationType === 'Line'
454
+ ? 'Add Special Line'
455
+ : config.visualizationType === 'Bar'
456
+ ? ' Add Special Bar'
457
+ : 'Add Special Bar/Line'}
458
+ </button>
459
+ </>
460
+ )
461
+ }
462
+
463
+ interface CategoricalAxisProps {
464
+ config: ChartConfig
465
+ updateConfig: Function
466
+ display: boolean
467
+ }
468
+
469
+ const CategoricalAxis: React.FC<CategoricalAxisProps> = ({ config, updateConfig, display }) => {
470
+ const maxHeight = config?.yAxis?.maxValue
471
+
472
+ const totalEnteredHeight =
473
+ config?.yAxis?.categories?.reduce((sum, obj) => sum + (parseFloat(obj.height) || 0), 0) || 0
474
+
475
+ const removeColumn = i => {
476
+ let categories = []
477
+
478
+ if (config.yAxis.categories) {
479
+ categories = [...config.yAxis.categories]
480
+ }
481
+
482
+ categories.splice(i, 1)
483
+
484
+ updateConfig({ ...config, yAxis: { ...config.yAxis, categories } })
485
+ }
486
+
487
+ const getDarkerColor = () => {
488
+ const timesDarkened = config.yAxis?.categories?.length
489
+ const darkeningFactor = 0.4
490
+ const baseColor = '#ddd'
491
+ return chroma(baseColor)
492
+ .darken(darkeningFactor * timesDarkened)
493
+ .hex()
494
+ }
495
+
496
+ const addColumn = () => {
497
+ const categories = config.yAxis.categories ? [...config.yAxis.categories] : []
498
+ const defaultValues = {
499
+ label: 'Label ' + Number(categories.length + 1),
500
+ height: '',
501
+ color: getDarkerColor()
502
+ }
503
+ categories.push(defaultValues)
504
+ updateConfig({ ...config, yAxis: { ...config.yAxis, categories: categories } })
505
+ }
506
+
507
+ const update = (fieldName, value, i) => {
508
+ let categories = []
509
+
510
+ if (config.yAxis.categories) {
511
+ categories = [...config.yAxis.categories]
512
+ }
513
+
514
+ categories[i][fieldName] = value
515
+
516
+ updateConfig({ ...config, yAxis: { ...config.yAxis, categories } })
517
+ }
518
+
519
+ if (!display) {
520
+ return <></>
521
+ }
522
+
523
+ return (
524
+ <>
525
+ {config.yAxis.type === 'categorical' &&
526
+ config.yAxis.categories?.map(({ label, color, height }, i) => {
527
+ return (
528
+ <div key={`preliminaryData-${i}`} className='edit-block'>
529
+ <p>Axis Category {i + 1}</p>
530
+ <button
531
+ type='button'
532
+ className='remove-column'
533
+ onClick={event => {
534
+ event.preventDefault()
535
+ removeColumn(i)
536
+ }}
537
+ >
538
+ Remove
539
+ </button>
540
+ <TextField
541
+ tooltip={
542
+ <Tooltip style={{ textTransform: 'none' }}>
543
+ <Tooltip.Target>
544
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
545
+ </Tooltip.Target>
546
+ <Tooltip.Content>
547
+ <p>
548
+ {' '}
549
+ Category Height will be ignored for the last category. The last category will fill the rest of
550
+ the axis height.
551
+ </p>
552
+ </Tooltip.Content>
553
+ </Tooltip>
554
+ }
555
+ type='number'
556
+ value={height}
557
+ fieldName='height'
558
+ label='Category Height'
559
+ updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
560
+ />
561
+ {Number(totalEnteredHeight) > Number(maxHeight) && config.yAxis.categories.length - 1 === i && (
562
+ <span style={{ color: 'red', display: 'block', fontSize: '15px' }}>
563
+ Update Max value to show all categories
564
+ </span>
289
565
  )}
566
+
567
+ <div className='two-col-inputs'>
568
+ <TextField
569
+ value={color}
570
+ fieldName='color'
571
+ label='Color'
572
+ updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
573
+ />
574
+ <TextField
575
+ value={label}
576
+ fieldName='label'
577
+ label='Label'
578
+ updateField={(_, __, fieldName, value) => update(fieldName, value, i)}
579
+ />
580
+ </div>
290
581
  </div>
291
582
  )
292
583
  })}
293
584
 
294
585
  <button type='button' onClick={addColumn} className='btn full-width'>
295
- {config.visualizationType === 'Line' ? 'Add Special Line' : config.visualizationType === 'Bar' ? ' Add Special Bar' : 'Add Special Bar/Line'}
586
+ Add Axis Category
296
587
  </button>
297
588
  </>
298
589
  )
@@ -318,7 +609,8 @@ const EditorPanel = () => {
318
609
  lineOptions,
319
610
  rawData,
320
611
  highlight,
321
- highlightReset
612
+ highlightReset,
613
+ dimensions
322
614
  } = useContext<ChartContext>(ConfigContext)
323
615
 
324
616
  const { minValue, maxValue, existPositiveValue, isAllLine } = useReduceData(config, unfilteredData)
@@ -340,6 +632,7 @@ const EditorPanel = () => {
340
632
  visCanAnimate,
341
633
  visHasLegend,
342
634
  visHasLegendAxisAlign,
635
+ visHasLegendColorCategory,
343
636
  visHasBrushChart,
344
637
  visSupportsDateCategoryAxis,
345
638
  visSupportsValueAxisMin,
@@ -368,7 +661,9 @@ const EditorPanel = () => {
368
661
  visSupportsRankByValue,
369
662
  visSupportsResponsiveTicks,
370
663
  visSupportsDateCategoryHeight,
371
- visHasDataSuppression
664
+ visHasDataSuppression,
665
+ visHasCategoricalAxis,
666
+ visSupportsDynamicSeries
372
667
  } = useEditorPermissions()
373
668
 
374
669
  // when the visualization type changes we
@@ -381,7 +676,8 @@ const EditorPanel = () => {
381
676
  newSeries = config.series.map(series => {
382
677
  return {
383
678
  ...series,
384
- type: config.visualizationType === 'Combo' ? 'Bar' : config.visualizationType ? config.visualizationType : 'Bar',
679
+ type:
680
+ config.visualizationType === 'Combo' ? 'Bar' : config.visualizationType ? config.visualizationType : 'Bar',
385
681
  axis: 'Left'
386
682
  }
387
683
  })
@@ -448,10 +744,23 @@ const EditorPanel = () => {
448
744
  if (isDateScale(updatedConfig.xAxis) && !updatedConfig.xAxis.padding) {
449
745
  updatedConfig.xAxis.padding = 6
450
746
  }
747
+ // DEV-8008 - Remove Bar styling when Line is converted to Bar
748
+ if (updatedConfig.visualizationType === 'Line') {
749
+ updatedConfig.visualizationSubType = 'regular'
750
+ updatedConfig.barStyle = 'flat'
751
+ updatedConfig.isLollipopChart = false
752
+ }
451
753
  }
452
754
 
453
755
  const updateField = (section, subsection, fieldName, newValue) => {
454
- if (isDebug) console.log('#COVE: CHART: EditorPanel: section, subsection, fieldName, newValue', section, subsection, fieldName, newValue) // eslint-disable-line
756
+ if (isDebug)
757
+ console.log(
758
+ '#COVE: CHART: EditorPanel: section, subsection, fieldName, newValue',
759
+ section,
760
+ subsection,
761
+ fieldName,
762
+ newValue
763
+ ) // eslint-disable-line
455
764
 
456
765
  if (section === 'boxplot' && subsection === 'legend') {
457
766
  updateConfig({
@@ -531,6 +840,7 @@ const EditorPanel = () => {
531
840
  }
532
841
 
533
842
  const [displayPanel, setDisplayPanel] = useState(true)
843
+ const [displayViewportOverrides, setDisplayViewportOverrides] = useState(false)
534
844
 
535
845
  if (loading) {
536
846
  return null
@@ -566,7 +876,14 @@ const EditorPanel = () => {
566
876
  })
567
877
 
568
878
  if (config.visualizationType === 'Forecasting') {
569
- newSeries.push({ dataKey: seriesKey, type: config.visualizationType, stages: forecastingStageArr, stageColumn: seriesKey, axis: 'Left', tooltip: true })
879
+ newSeries.push({
880
+ dataKey: seriesKey,
881
+ type: config.visualizationType,
882
+ stages: forecastingStageArr,
883
+ stageColumn: seriesKey,
884
+ axis: 'Left',
885
+ tooltip: true
886
+ })
570
887
  } else {
571
888
  newSeries.push({ dataKey: seriesKey, type: config.visualizationType, axis: 'Left', tooltip: true })
572
889
  }
@@ -622,7 +939,14 @@ const EditorPanel = () => {
622
939
  if (filter) {
623
940
  const { lower, upper } = config.confidenceKeys || {}
624
941
  Object.keys(columns).forEach(key => {
625
- if ((config.series && config.series.filter(series => series.dataKey === key).length > 0) || (config.confidenceKeys && Object.keys(config.confidenceKeys).includes(key) && ((lower && upper) || lower || upper) && key !== lower && key !== upper)) {
942
+ if (
943
+ (config.series && config.series.filter(series => series.dataKey === key).length > 0) ||
944
+ (config.confidenceKeys &&
945
+ Object.keys(config.confidenceKeys).includes(key) &&
946
+ ((lower && upper) || lower || upper) &&
947
+ key !== lower &&
948
+ key !== upper)
949
+ ) {
626
950
  delete columns[key]
627
951
  }
628
952
  })
@@ -631,9 +955,37 @@ const EditorPanel = () => {
631
955
  return Object.keys(columns)
632
956
  }
633
957
 
634
- const getDataValueOptions = data => {
958
+ const getLegendStyleOptions = (option: 'style' | 'subStyle'): string[] => {
959
+ const options: string[] = []
960
+
961
+ switch (option) {
962
+ case 'style':
963
+ options.push('circles', 'boxes')
964
+ if (
965
+ config.visualizationType === 'Bar' &&
966
+ (!['right', 'left'].includes(config.legend.position) || !config.legend.position)
967
+ ) {
968
+ options.push('gradient')
969
+ }
970
+ if (config.visualizationType === 'Line') {
971
+ options.push('lines')
972
+ }
973
+ break
974
+ case 'subStyle':
975
+ if (config.visualizationType === 'Bar') {
976
+ options.push('linear blocks')
977
+ } else {
978
+ options.push('linear blocks', 'smooth')
979
+ }
980
+
981
+ break
982
+ }
983
+ return options
984
+ }
985
+
986
+ const getDataValueOptions = (data: Record<string, any>[]): string[] => {
635
987
  if (!data) return []
636
- const set = new Set()
988
+ const set = new Set<string>()
637
989
  for (let i = 0; i < data.length; i++) {
638
990
  for (const [key] of Object.entries(data[i])) {
639
991
  set.add(key)
@@ -820,7 +1172,9 @@ const EditorPanel = () => {
820
1172
  case config.visualizationType === 'Combo' && isAllLine && enteredValue > minVal:
821
1173
  message = 'Value should not exceed ' + minValue
822
1174
  break
823
- case (config.visualizationType === 'Bar' || (config.visualizationType === 'Combo' && !isAllLine)) && minVal > 0 && enteredValue > 0:
1175
+ case (config.visualizationType === 'Bar' || (config.visualizationType === 'Combo' && !isAllLine)) &&
1176
+ minVal > 0 &&
1177
+ enteredValue > 0:
824
1178
  message = config.useLogScale ? 'Value must be equal to 0' : 'Value must be less than or equal to 0'
825
1179
  break
826
1180
  case config.visualizationType === 'Deviation Bar' && enteredValue >= Math.min(minVal, config.xAxis.target):
@@ -872,7 +1226,17 @@ const EditorPanel = () => {
872
1226
  if (isDebug) console.log('### COVE DEBUG: Chart: Setting default datacol=', setdatacol) // eslint-disable-line
873
1227
  }
874
1228
 
875
- const chartsWithOptions = ['Area Chart', 'Combo', 'Line', 'Bar', 'Forecasting', 'Scatter Plot', 'Paired Bar', 'Deviation Bar']
1229
+ const chartsWithOptions = [
1230
+ 'Bump Chart',
1231
+ 'Area Chart',
1232
+ 'Combo',
1233
+ 'Line',
1234
+ 'Bar',
1235
+ 'Forecasting',
1236
+ 'Scatter Plot',
1237
+ 'Paired Bar',
1238
+ 'Deviation Bar'
1239
+ ]
876
1240
 
877
1241
  const columnsOptions = [
878
1242
  <option value='' key={'Select Option'}>
@@ -1000,7 +1364,10 @@ const EditorPanel = () => {
1000
1364
  })
1001
1365
  }
1002
1366
 
1003
- const colorCodeByCategory = config.visualizationType === 'Bar' && config.visualizationSubType === 'regular' && config.runtime.seriesKeys.length === 1
1367
+ const colorCodeByCategory =
1368
+ config.visualizationType === 'Bar' &&
1369
+ config.visualizationSubType === 'regular' &&
1370
+ config.runtime.seriesKeys.length === 1
1004
1371
  const getLegendColumns = () => {
1005
1372
  const colorCodeData = data.map(d => d[config.legend.colorCode])
1006
1373
  return colorCodeByCategory ? colorCodeData : getColumns(false).filter(d => d !== config.xAxis.dataKey)
@@ -1021,6 +1388,14 @@ const EditorPanel = () => {
1021
1388
  updateConfig(updatedConfig)
1022
1389
  }
1023
1390
 
1391
+ const updateViewportOverrides = (property, viewport, numTicks) => {
1392
+ const propertyObject = { ...config.xAxis[property] }
1393
+ propertyObject[viewport] = numTicks
1394
+ const updatedConfig = { ...config, xAxis: { ...config.xAxis, [property]: propertyObject } }
1395
+
1396
+ updateConfig(updatedConfig)
1397
+ }
1398
+
1024
1399
  const editorContextValues = {
1025
1400
  addNewExclusion,
1026
1401
  data,
@@ -1049,83 +1424,183 @@ const EditorPanel = () => {
1049
1424
  return (
1050
1425
  <EditorPanelContext.Provider value={editorContextValues}>
1051
1426
  <ErrorBoundary component='EditorPanel'>
1052
- <Layout.Sidebar displayPanel={displayPanel} isDashboard={isDashboard} title={'Configure Chart'} onBackClick={onBackClick}>
1427
+ <Layout.Sidebar
1428
+ displayPanel={displayPanel}
1429
+ isDashboard={isDashboard}
1430
+ title={'Configure Chart'}
1431
+ onBackClick={onBackClick}
1432
+ >
1053
1433
  <Accordion allowZeroExpanded={true}>
1054
1434
  <Panels.General name='General' />
1055
1435
  <Panels.ForestPlot name='Forest Plot Settings' />
1056
1436
  <Panels.Sankey name='Sankey' />
1057
- {config.visualizationType !== 'Pie' && config.visualizationType !== 'Forest Plot' && config.visualizationType !== 'Sankey' && (
1058
- <AccordionItem>
1059
- <AccordionItemHeading>
1060
- <AccordionItemButton>Data Series {(!config.series || config.series.length === 0 || (config.visualizationType === 'Paired Bar' && config.series.length < 2)) && <WarningImage width='25' className='warning-icon' />}</AccordionItemButton>
1061
- </AccordionItemHeading>
1062
- <AccordionItemPanel>
1063
- {(!config.series || config.series.length === 0) && config.visualizationType !== 'Paired Bar' && <p className='warning'>At least one series is required</p>}
1064
- {(!config.series || config.series.length === 0 || config.series.length < 2) && config.visualizationType === 'Paired Bar' && <p className='warning'>Select two data series for paired bar chart (e.g., Male and Female).</p>}
1065
- <>
1066
- <Select
1067
- fieldName='visualizationType'
1068
- label='Add Data Series'
1069
- initial='Select'
1070
- onChange={e => {
1071
- if (e.target.value !== '' && e.target.value !== 'Select') {
1072
- addNewSeries(e.target.value)
1073
- }
1074
- e.target.value = ''
1075
- }}
1076
- options={getColumns()}
1077
- />
1078
- {config.series && config.series.length !== 0 && (
1079
- <Panels.Series.Wrapper getColumns={getColumns}>
1080
- <fieldset>
1081
- <legend className='edit-label float-left'>Displaying</legend>
1082
- <Tooltip style={{ textTransform: 'none' }}>
1083
- <Tooltip.Target>
1084
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1085
- </Tooltip.Target>
1086
- <Tooltip.Content>
1087
- <p>A data series is a set of related data points plotted in a chart and typically represented in the chart legend.</p>
1088
- </Tooltip.Content>
1089
- </Tooltip>
1090
- </fieldset>
1091
-
1092
- <DragDropContext onDragEnd={({ source, destination }) => handleSeriesChange(source.index, destination.index)}>
1093
- <Droppable droppableId='filter_order'>
1094
- {/* prettier-ignore */}
1095
- {provided => {
1096
- return (
1097
- <ul {...provided.droppableProps} className='series-list' ref={provided.innerRef}>
1098
- <Panels.Series.List series={config.series} getItemStyle={getItemStyle} sortableItemStyles={sortableItemStyles} chartsWithOptions={chartsWithOptions} />
1099
- {provided.placeholder}
1100
- </ul>
1101
- )
1437
+ {config.visualizationType !== 'Pie' &&
1438
+ config.visualizationType !== 'Forest Plot' &&
1439
+ config.visualizationType !== 'Sankey' && (
1440
+ <AccordionItem>
1441
+ <AccordionItemHeading>
1442
+ <AccordionItemButton>
1443
+ Data Series{' '}
1444
+ {(!config.series ||
1445
+ config.series.length === 0 ||
1446
+ (config.visualizationType === 'Paired Bar' && config.series.length < 2)) &&
1447
+ !config.dynamicSeries && <WarningImage width='25' className='warning-icon' />}
1448
+ </AccordionItemButton>
1449
+ </AccordionItemHeading>
1450
+ <AccordionItemPanel>
1451
+ {visSupportsDynamicSeries() && (
1452
+ <CheckBox
1453
+ value={config.dynamicSeries}
1454
+ fieldName='dynamicSeries'
1455
+ label='Dynamically generate series'
1456
+ updateField={updateField}
1457
+ />
1458
+ )}
1459
+ {config.dynamicSeries && config.visualizationType === 'Line' && (
1460
+ <Select
1461
+ fieldName='dynamicSeriesType'
1462
+ value={config.dynamicSeriesType}
1463
+ label='Series Type'
1464
+ initial='Select'
1465
+ updateField={updateField}
1466
+ options={['Line', 'dashed-sm', 'dashed-md', 'dashed-lg']}
1467
+ />
1468
+ )}
1469
+ {config.dynamicSeries &&
1470
+ config.visualizationType === 'Line' &&
1471
+ config.dynamicSeriesType === 'Line' && (
1472
+ <Select
1473
+ fieldName='dynamicSeriesLineType'
1474
+ value={config.dynamicSeriesLineType ? config.dynamicSeriesLineType : 'curveLinear'}
1475
+ label='Line Type'
1476
+ initial='Select'
1477
+ updateField={updateField}
1478
+ options={Object.keys(approvedCurveTypes).map(curveName => approvedCurveTypes[curveName])}
1479
+ />
1480
+ )}
1481
+ {(!visSupportsDynamicSeries() || !config.dynamicSeries) && (
1482
+ <>
1483
+ {(!config.series || config.series.length === 0) &&
1484
+ !config.dynamicSeries &&
1485
+ config.visualizationType !== 'Paired Bar' && (
1486
+ <p className='warning'>At least one series is required</p>
1487
+ )}
1488
+ {(!config.series || config.series.length === 0 || config.series.length < 2) &&
1489
+ config.visualizationType === 'Paired Bar' && (
1490
+ <p className='warning'>
1491
+ Select two data series for paired bar chart (e.g., Male and Female).
1492
+ </p>
1493
+ )}
1494
+ <>
1495
+ <Select
1496
+ fieldName='visualizationType'
1497
+ label='Add Data Series'
1498
+ initial='Select'
1499
+ onChange={e => {
1500
+ if (e.target.value !== '' && e.target.value !== 'Select') {
1501
+ addNewSeries(e.target.value)
1502
+ }
1503
+ e.target.value = ''
1102
1504
  }}
1103
- </Droppable>
1104
- </DragDropContext>
1105
- </Panels.Series.Wrapper>
1505
+ options={getColumns()}
1506
+ />
1507
+ {config.series && config.series.length !== 0 && (
1508
+ <Panels.Series.Wrapper getColumns={getColumns}>
1509
+ <fieldset>
1510
+ <legend className='edit-label float-left'>Displaying</legend>
1511
+ <Tooltip style={{ textTransform: 'none' }}>
1512
+ <Tooltip.Target>
1513
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1514
+ </Tooltip.Target>
1515
+ <Tooltip.Content>
1516
+ <p>
1517
+ A data series is a set of related data points plotted in a chart and typically
1518
+ represented in the chart legend.
1519
+ </p>
1520
+ </Tooltip.Content>
1521
+ </Tooltip>
1522
+ </fieldset>
1523
+
1524
+ <DragDropContext
1525
+ onDragEnd={({ source, destination }) =>
1526
+ handleSeriesChange(source.index, destination.index)
1527
+ }
1528
+ >
1529
+ <Droppable droppableId='filter_order'>
1530
+ {/* prettier-ignore */}
1531
+ {provided => {
1532
+ return (
1533
+ <ul {...provided.droppableProps} className='series-list' ref={provided.innerRef}>
1534
+ <Panels.Series.List
1535
+ series={config.series}
1536
+ getItemStyle={getItemStyle}
1537
+ sortableItemStyles={sortableItemStyles}
1538
+ chartsWithOptions={chartsWithOptions}
1539
+ />
1540
+ {provided.placeholder}
1541
+ </ul>
1542
+ )
1543
+ }}
1544
+ </Droppable>
1545
+ </DragDropContext>
1546
+ </Panels.Series.Wrapper>
1547
+ )}
1548
+ </>
1549
+ {config.series && config.series.length <= 1 && config.visualizationType === 'Bar' && (
1550
+ <>
1551
+ <span className='divider-heading'>Confidence Keys</span>
1552
+ <Select
1553
+ value={config.confidenceKeys.upper || ''}
1554
+ section='confidenceKeys'
1555
+ fieldName='upper'
1556
+ label='Upper'
1557
+ updateField={updateField}
1558
+ initial='Select'
1559
+ options={getColumns()}
1560
+ />
1561
+ <Select
1562
+ value={config.confidenceKeys.lower || ''}
1563
+ section='confidenceKeys'
1564
+ fieldName='lower'
1565
+ label='Lower'
1566
+ updateField={updateField}
1567
+ initial='Select'
1568
+ options={getColumns()}
1569
+ />
1570
+ </>
1571
+ )}
1572
+ {visSupportsRankByValue() && config.series && config.series.length === 1 && (
1573
+ <Select
1574
+ fieldName='visualizationType'
1575
+ label='Rank by Value'
1576
+ initial='Select'
1577
+ onChange={e => sortSeries(e.target.value)}
1578
+ options={['asc', 'desc']}
1579
+ />
1580
+ )}
1581
+ {/* {visHasDataSuppression() && <DataSuppression config={config} updateConfig={updateConfig} data={data} />} */}
1582
+ {visSupportsPreliminaryData() && (
1583
+ <PreliminaryData config={config} updateConfig={updateConfig} data={data} />
1584
+ )}
1585
+ </>
1106
1586
  )}
1107
- </>
1108
- {config.series && config.series.length <= 1 && config.visualizationType === 'Bar' && (
1109
- <>
1110
- <span className='divider-heading'>Confidence Keys</span>
1111
- <Select value={config.confidenceKeys.upper || ''} section='confidenceKeys' fieldName='upper' label='Upper' updateField={updateField} initial='Select' options={getColumns()} />
1112
- <Select value={config.confidenceKeys.lower || ''} section='confidenceKeys' fieldName='lower' label='Lower' updateField={updateField} initial='Select' options={getColumns()} />
1113
- </>
1114
- )}
1115
- {visSupportsRankByValue() && config.series && config.series.length === 1 && <Select fieldName='visualizationType' label='Rank by Value' initial='Select' onChange={e => sortSeries(e.target.value)} options={['asc', 'desc']} />}
1116
- {/* {visHasDataSuppression() && <DataSuppression config={config} updateConfig={updateConfig} data={data} />} */}
1117
- {visSupportsPreliminaryData() && <PreliminaryData config={config} updateConfig={updateConfig} data={data} />}
1118
- </AccordionItemPanel>
1119
- </AccordionItem>
1120
- )}
1587
+ </AccordionItemPanel>
1588
+ </AccordionItem>
1589
+ )}
1121
1590
  <Panels.BoxPlot name='Measures' />
1122
1591
  {/* Left Value Axis */}
1123
1592
  {visSupportsLeftValueAxis() && (
1124
1593
  <AccordionItem>
1125
1594
  <AccordionItemHeading>
1126
1595
  <AccordionItemButton>
1127
- {config.visualizationType === 'Pie' ? 'Data Format' : config.orientation === 'vertical' ? 'Left Value Axis' : 'Value Axis'}
1128
- {config.visualizationType === 'Pie' && !config.yAxis.dataKey && <WarningImage width='25' className='warning-icon' />}
1596
+ {config.visualizationType === 'Pie'
1597
+ ? 'Data Format'
1598
+ : config.orientation === 'vertical'
1599
+ ? 'Left Value Axis'
1600
+ : 'Value Axis'}
1601
+ {config.visualizationType === 'Pie' && !config.yAxis.dataKey && (
1602
+ <WarningImage width='25' className='warning-icon' />
1603
+ )}
1129
1604
  </AccordionItemButton>
1130
1605
  </AccordionItemHeading>
1131
1606
  <AccordionItemPanel>
@@ -1153,11 +1628,91 @@ const EditorPanel = () => {
1153
1628
  )}
1154
1629
  {config.visualizationType !== 'Pie' && (
1155
1630
  <>
1156
- <TextField value={config.yAxis.label} section='yAxis' fieldName='label' label='Label ' updateField={updateField} />
1157
- {config.runtime.seriesKeys && config.runtime.seriesKeys.length === 1 && !['Box Plot', 'Deviation Bar', 'Forest Plot'].includes(config.visualizationType) && (
1158
- <CheckBox value={config.isLegendValue} fieldName='isLegendValue' label='Use Legend Value in Hover' updateField={updateField} />
1159
- )}
1160
- <TextField value={config.yAxis.numTicks} placeholder='Auto' type='number' section='yAxis' fieldName='numTicks' label='Number of ticks' className='number-narrow' updateField={updateField} />
1631
+ <label>
1632
+ <span className='edit-label'>
1633
+ Axis Type
1634
+ <Tooltip style={{ textTransform: 'none', display: 'inline-block' }}>
1635
+ <Tooltip.Target>
1636
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1637
+ </Tooltip.Target>
1638
+ <Tooltip.Content>
1639
+ Select 'Numeric (Linear Scale)' for uniform scaling, 'Numeric (Logarithmic Scale)' for
1640
+ exponential data, or 'Categorical' for discrete categories.
1641
+ </Tooltip.Content>
1642
+ </Tooltip>
1643
+ </span>
1644
+ <select
1645
+ value={config.yAxis.type}
1646
+ onChange={e =>
1647
+ updateConfig({
1648
+ ...config,
1649
+ yAxis: {
1650
+ ...config.yAxis,
1651
+ type: e.target.value
1652
+ }
1653
+ })
1654
+ }
1655
+ >
1656
+ <option value='linear'>Numeric (Linear Scale)</option>
1657
+ {config.visualizationSubType !== 'stacked' && (
1658
+ <option value='logarithmic'>Numeric (Logarithmic Scale)</option>
1659
+ )}
1660
+ {config.orientation !== 'horizontal' && <option value='categorical'>Categorical</option>}
1661
+ </select>
1662
+ </label>
1663
+ <CategoricalAxis
1664
+ config={config}
1665
+ updateConfig={updateConfig}
1666
+ data={data}
1667
+ display={visHasCategoricalAxis()}
1668
+ />
1669
+
1670
+ <TextField
1671
+ display={!visHasCategoricalAxis()}
1672
+ value={config.yAxis.label}
1673
+ section='yAxis'
1674
+ fieldName='label'
1675
+ label='Label '
1676
+ updateField={updateField}
1677
+ />
1678
+ {config.runtime.seriesKeys &&
1679
+ config.runtime.seriesKeys.length === 1 &&
1680
+ !['Box Plot', 'Deviation Bar', 'Forest Plot'].includes(config.visualizationType) && (
1681
+ <CheckBox
1682
+ value={config.isLegendValue}
1683
+ fieldName='isLegendValue'
1684
+ label='Use Legend Value in Hover'
1685
+ updateField={updateField}
1686
+ />
1687
+ )}
1688
+
1689
+ <TextField
1690
+ display={!visHasCategoricalAxis()}
1691
+ value={config.yAxis.numTicks}
1692
+ placeholder='Auto'
1693
+ type='number'
1694
+ section='yAxis'
1695
+ fieldName='numTicks'
1696
+ label='Number of ticks'
1697
+ className='number-narrow'
1698
+ tooltip={
1699
+ <Tooltip style={{ textTransform: 'none' }}>
1700
+ <Tooltip.Target>
1701
+ <Icon
1702
+ display='question'
1703
+ style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }}
1704
+ />
1705
+ </Tooltip.Target>
1706
+ <Tooltip.Content>
1707
+ <p>
1708
+ Apporoximate number of ticks. Other factors such as space available and data may change
1709
+ the exact number of ticks used.
1710
+ </p>
1711
+ </Tooltip.Content>
1712
+ </Tooltip>
1713
+ }
1714
+ updateField={updateField}
1715
+ />
1161
1716
  <TextField
1162
1717
  value={config.yAxis.size}
1163
1718
  type='number'
@@ -1169,7 +1724,10 @@ const EditorPanel = () => {
1169
1724
  tooltip={
1170
1725
  <Tooltip style={{ textTransform: 'none' }}>
1171
1726
  <Tooltip.Target>
1172
- <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
1727
+ <Icon
1728
+ display='question'
1729
+ style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }}
1730
+ />
1173
1731
  </Tooltip.Target>
1174
1732
  <Tooltip.Content>
1175
1733
  <p>{`Increase the size if elements in the ${config.orientation} axis are being crowded or hidden behind other elements. Decrease if less space is required for the value axis.`}</p>
@@ -1177,9 +1735,38 @@ const EditorPanel = () => {
1177
1735
  </Tooltip>
1178
1736
  }
1179
1737
  />
1180
- {config.orientation === 'horizontal' && config.visualizationType !== 'Paired Bar' && <CheckBox value={config.isResponsiveTicks} fieldName='isResponsiveTicks' label='Use Responsive Ticks' updateField={updateField} />}
1181
- {(config.orientation === 'vertical' || !config.isResponsiveTicks) && <TextField value={config.yAxis.tickRotation || 0} type='number' min={0} section='yAxis' fieldName='tickRotation' label='Tick rotation (Degrees)' className='number-narrow' updateField={updateField} />}
1182
- {config.isResponsiveTicks && config.orientation === 'horizontal' && config.visualizationType !== 'Paired Bar' && (
1738
+ <TextField
1739
+ display={!visHasCategoricalAxis()}
1740
+ value={config.yAxis.labelOffset}
1741
+ section='yAxis'
1742
+ fieldName='labelOffset'
1743
+ label='Label offset'
1744
+ type='number'
1745
+ className='number-narrow'
1746
+ updateField={updateField}
1747
+ />
1748
+ {config.orientation === 'horizontal' && (
1749
+ <CheckBox
1750
+ value={config.isResponsiveTicks}
1751
+ fieldName='isResponsiveTicks'
1752
+ label='Use Responsive Ticks'
1753
+ updateField={updateField}
1754
+ />
1755
+ )}
1756
+ {(config.orientation === 'vertical' || !config.isResponsiveTicks) && (
1757
+ <TextField
1758
+ display={!visHasCategoricalAxis()}
1759
+ value={config.yAxis.tickRotation || 0}
1760
+ type='number'
1761
+ min={0}
1762
+ section='yAxis'
1763
+ fieldName='tickRotation'
1764
+ label='Tick rotation (Degrees)'
1765
+ className='number-narrow'
1766
+ updateField={updateField}
1767
+ />
1768
+ )}
1769
+ {config.isResponsiveTicks && config.orientation === 'horizontal' && (
1183
1770
  <TextField
1184
1771
  value={config.xAxis.maxTickRotation}
1185
1772
  type='number'
@@ -1192,7 +1779,10 @@ const EditorPanel = () => {
1192
1779
  tooltip={
1193
1780
  <Tooltip style={{ textTransform: 'none' }}>
1194
1781
  <Tooltip.Target>
1195
- <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
1782
+ <Icon
1783
+ display='question'
1784
+ style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }}
1785
+ />
1196
1786
  </Tooltip.Target>
1197
1787
  <Tooltip.Content>
1198
1788
  <p>Degrees ticks will be rotated if values overlap, especially in smaller viewports.</p>
@@ -1204,11 +1794,33 @@ const EditorPanel = () => {
1204
1794
 
1205
1795
  {/* Hiding this for now, not interested in moving the axis lines away from chart comp. right now. */}
1206
1796
  {/* <TextField value={config.yAxis.axisPadding} type='number' max={10} min={0} section='yAxis' fieldName='axisPadding' label={'Axis Padding'} className='number-narrow' updateField={updateField} /> */}
1207
- {config.orientation === 'horizontal' && <TextField value={config.xAxis.labelOffset} section='xAxis' fieldName='labelOffset' label='Label offset' type='number' className='number-narrow' updateField={updateField} />}
1208
- {visSupportsValueAxisGridLines() && <CheckBox value={config.yAxis.gridLines} section='yAxis' fieldName='gridLines' label='Show Gridlines' updateField={updateField} />}
1209
- <CheckBox value={config.yAxis.enablePadding} section='yAxis' fieldName='enablePadding' label='Add Padding to Value Axis Scale' updateField={updateField} />
1210
- {config.yAxis.enablePadding && <TextField type='number' section='yAxis' fieldName='scalePadding' label='Padding Percentage' className='number-narrow' updateField={updateField} value={config.yAxis.scalePadding} />}
1211
- {config.visualizationSubType === 'regular' && config.visualizationType !== 'Forest Plot' && <CheckBox value={config.useLogScale} fieldName='useLogScale' label='use logarithmic scale' updateField={updateField} />}
1797
+ {visSupportsValueAxisGridLines() && (
1798
+ <CheckBox
1799
+ value={config.yAxis.gridLines}
1800
+ section='yAxis'
1801
+ fieldName='gridLines'
1802
+ label='Show Gridlines'
1803
+ updateField={updateField}
1804
+ />
1805
+ )}
1806
+ <CheckBox
1807
+ value={config.yAxis.enablePadding}
1808
+ section='yAxis'
1809
+ fieldName='enablePadding'
1810
+ label='Add Padding to Value Axis Scale'
1811
+ updateField={updateField}
1812
+ />
1813
+ {config.yAxis.enablePadding && (
1814
+ <TextField
1815
+ type='number'
1816
+ section='yAxis'
1817
+ fieldName='scalePadding'
1818
+ label='Padding Percentage'
1819
+ className='number-narrow'
1820
+ updateField={updateField}
1821
+ value={config.yAxis.scalePadding}
1822
+ />
1823
+ )}
1212
1824
  </>
1213
1825
  )}
1214
1826
  <span className='divider-heading'>Number Formatting</span>
@@ -1221,7 +1833,10 @@ const EditorPanel = () => {
1221
1833
  tooltip={
1222
1834
  <Tooltip style={{ textTransform: 'none' }}>
1223
1835
  <Tooltip.Target>
1224
- <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
1836
+ <Icon
1837
+ display='question'
1838
+ style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }}
1839
+ />
1225
1840
  </Tooltip.Target>
1226
1841
  <Tooltip.Content>
1227
1842
  <p>{`Selecting this option will add commas to the left value axis, tooltip hover, and data table.`}</p>
@@ -1230,6 +1845,7 @@ const EditorPanel = () => {
1230
1845
  }
1231
1846
  />
1232
1847
  <CheckBox
1848
+ display={!visHasCategoricalAxis()}
1233
1849
  value={config.dataFormat.abbreviated}
1234
1850
  section='dataFormat'
1235
1851
  fieldName='abbreviated'
@@ -1238,7 +1854,10 @@ const EditorPanel = () => {
1238
1854
  tooltip={
1239
1855
  <Tooltip style={{ textTransform: 'none' }}>
1240
1856
  <Tooltip.Target>
1241
- <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
1857
+ <Icon
1858
+ display='question'
1859
+ style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }}
1860
+ />
1242
1861
  </Tooltip.Target>
1243
1862
  <Tooltip.Content>
1244
1863
  <p>{`This option abbreviates very large or very small numbers on the value axis`}</p>
@@ -1246,7 +1865,16 @@ const EditorPanel = () => {
1246
1865
  </Tooltip>
1247
1866
  }
1248
1867
  />
1249
- <TextField value={config.dataFormat.roundTo ? config.dataFormat.roundTo : 0} type='number' section='dataFormat' fieldName='roundTo' label='Round to decimal point' className='number-narrow' updateField={updateField} min={0} />
1868
+ <TextField
1869
+ value={config.dataFormat.roundTo ? config.dataFormat.roundTo : 0}
1870
+ type='number'
1871
+ section='dataFormat'
1872
+ fieldName='roundTo'
1873
+ label='Round to decimal point'
1874
+ className='number-narrow'
1875
+ updateField={updateField}
1876
+ min={0}
1877
+ />
1250
1878
  <div className='two-col-inputs'>
1251
1879
  <TextField
1252
1880
  value={config.dataFormat.prefix}
@@ -1260,8 +1888,12 @@ const EditorPanel = () => {
1260
1888
  <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1261
1889
  </Tooltip.Target>
1262
1890
  <Tooltip.Content>
1263
- {config.visualizationType === 'Pie' && <p>Enter a data prefix to display in the data table and chart tooltips, if applicable.</p>}
1264
- {config.visualizationType !== 'Pie' && <p>Enter a data prefix (such as "$"), if applicable.</p>}
1891
+ {config.visualizationType === 'Pie' && (
1892
+ <p>Enter a data prefix to display in the data table and chart tooltips, if applicable.</p>
1893
+ )}
1894
+ {config.visualizationType !== 'Pie' && (
1895
+ <p>Enter a data prefix (such as "$"), if applicable.</p>
1896
+ )}
1265
1897
  </Tooltip.Content>
1266
1898
  </Tooltip>
1267
1899
  }
@@ -1278,8 +1910,12 @@ const EditorPanel = () => {
1278
1910
  <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1279
1911
  </Tooltip.Target>
1280
1912
  <Tooltip.Content>
1281
- {config.visualizationType === 'Pie' && <p>Enter a data suffix to display in the data table and tooltips, if applicable.</p>}
1282
- {config.visualizationType !== 'Pie' && <p>Enter a data suffix (such as "%"), if applicable.</p>}
1913
+ {config.visualizationType === 'Pie' && (
1914
+ <p>Enter a data suffix to display in the data table and tooltips, if applicable.</p>
1915
+ )}
1916
+ {config.visualizationType !== 'Pie' && (
1917
+ <p>Enter a data suffix (such as "%"), if applicable.</p>
1918
+ )}
1283
1919
  </Tooltip.Content>
1284
1920
  </Tooltip>
1285
1921
  }
@@ -1288,31 +1924,133 @@ const EditorPanel = () => {
1288
1924
 
1289
1925
  {config.orientation === 'horizontal' ? ( // horizontal - x is vertical y is horizontal
1290
1926
  <>
1291
- {visSupportsValueAxisLine() && <CheckBox value={config.xAxis.hideAxis} section='xAxis' fieldName='hideAxis' label='Hide Axis' updateField={updateField} />}
1292
- {visSupportsValueAxisLabels() && <CheckBox value={config.xAxis.hideLabel} section='xAxis' fieldName='hideLabel' label='Hide Label' updateField={updateField} />}
1293
- {visSupportsValueAxisTicks() && <CheckBox value={config.xAxis.hideTicks} section='xAxis' fieldName='hideTicks' label='Hide Ticks' updateField={updateField} />}
1294
- {visSupportsValueAxisMax() && <TextField value={config.xAxis.max} section='xAxis' fieldName='max' label='max value' type='number' placeholder='Auto' updateField={updateField} />}
1927
+ {visSupportsValueAxisLine() && (
1928
+ <CheckBox
1929
+ value={config.xAxis.hideAxis}
1930
+ section='xAxis'
1931
+ fieldName='hideAxis'
1932
+ label='Hide Axis'
1933
+ updateField={updateField}
1934
+ />
1935
+ )}
1936
+ {visSupportsValueAxisLabels() && (
1937
+ <CheckBox
1938
+ value={config.xAxis.hideLabel}
1939
+ section='xAxis'
1940
+ fieldName='hideLabel'
1941
+ label='Hide Tick Labels'
1942
+ updateField={updateField}
1943
+ />
1944
+ )}
1945
+ {visSupportsValueAxisTicks() && (
1946
+ <CheckBox
1947
+ value={config.xAxis.hideTicks}
1948
+ section='xAxis'
1949
+ fieldName='hideTicks'
1950
+ label='Hide Ticks'
1951
+ updateField={updateField}
1952
+ />
1953
+ )}
1954
+ {visSupportsValueAxisMax() && (
1955
+ <TextField
1956
+ value={config.xAxis.max}
1957
+ section='xAxis'
1958
+ fieldName='max'
1959
+ label='max value'
1960
+ type='number'
1961
+ placeholder='Auto'
1962
+ updateField={updateField}
1963
+ />
1964
+ )}
1295
1965
  <span style={{ color: 'red', display: 'block' }}>{warningMsg.maxMsg}</span>
1296
- {visSupportsValueAxisMin() && <TextField value={config.xAxis.min} section='xAxis' fieldName='min' type='number' label='min value' placeholder='Auto' updateField={updateField} />}
1966
+ {visSupportsValueAxisMin() && (
1967
+ <TextField
1968
+ value={config.xAxis.min}
1969
+ section='xAxis'
1970
+ fieldName='min'
1971
+ type='number'
1972
+ label='min value'
1973
+ placeholder='Auto'
1974
+ updateField={updateField}
1975
+ />
1976
+ )}
1297
1977
  <span style={{ color: 'red', display: 'block' }}>{warningMsg.minMsg}</span>
1298
1978
  {config.visualizationType === 'Deviation Bar' && (
1299
1979
  <>
1300
- <TextField value={config.xAxis.target} section='xAxis' fieldName='target' type='number' label='Deviation point' placeholder='Auto' updateField={updateField} />
1301
- <TextField value={config.xAxis.targetLabel || 'Target'} section='xAxis' fieldName='targetLabel' type='text' label='Deviation point Label' updateField={updateField} />
1302
- <CheckBox value={config.xAxis.showTargetLabel} section='xAxis' fieldName='showTargetLabel' label='Show Deviation point label' updateField={updateField} />
1980
+ <TextField
1981
+ value={config.xAxis.target}
1982
+ section='xAxis'
1983
+ fieldName='target'
1984
+ type='number'
1985
+ label='Deviation point'
1986
+ placeholder='Auto'
1987
+ updateField={updateField}
1988
+ />
1989
+ <TextField
1990
+ value={config.xAxis.targetLabel || 'Target'}
1991
+ section='xAxis'
1992
+ fieldName='targetLabel'
1993
+ type='text'
1994
+ label='Deviation point Label'
1995
+ updateField={updateField}
1996
+ />
1997
+ <CheckBox
1998
+ value={config.xAxis.showTargetLabel}
1999
+ section='xAxis'
2000
+ fieldName='showTargetLabel'
2001
+ label='Show Deviation point label'
2002
+ updateField={updateField}
2003
+ />
1303
2004
  </>
1304
2005
  )}
1305
2006
  </>
1306
2007
  ) : (
1307
2008
  config.visualizationType !== 'Pie' && (
1308
2009
  <>
1309
- <CheckBox value={config.yAxis.hideAxis} section='yAxis' fieldName='hideAxis' label='Hide Axis' updateField={updateField} />
1310
- <CheckBox value={config.yAxis.hideLabel} section='yAxis' fieldName='hideLabel' label='Hide Label' updateField={updateField} />
1311
- <CheckBox value={config.yAxis.hideTicks} section='yAxis' fieldName='hideTicks' label='Hide Ticks' updateField={updateField} />
2010
+ <CheckBox
2011
+ display={!visHasCategoricalAxis()}
2012
+ value={config.yAxis.hideAxis}
2013
+ section='yAxis'
2014
+ fieldName='hideAxis'
2015
+ label='Hide Axis'
2016
+ updateField={updateField}
2017
+ />
2018
+ <CheckBox
2019
+ display={!visHasCategoricalAxis()}
2020
+ value={config.yAxis.hideLabel}
2021
+ section='yAxis'
2022
+ fieldName='hideLabel'
2023
+ label='Hide Tick Labels'
2024
+ updateField={updateField}
2025
+ />
2026
+ <CheckBox
2027
+ display={!visHasCategoricalAxis()}
2028
+ value={config.yAxis.hideTicks}
2029
+ section='yAxis'
2030
+ fieldName='hideTicks'
2031
+ label='Hide Ticks'
2032
+ updateField={updateField}
2033
+ />
1312
2034
 
1313
- <TextField value={config.yAxis.max} section='yAxis' fieldName='max' type='number' label='left axis max value' placeholder='Auto' updateField={updateField} />
2035
+ <TextField
2036
+ value={config.yAxis.max}
2037
+ section='yAxis'
2038
+ fieldName='max'
2039
+ type='number'
2040
+ label='left axis max value'
2041
+ placeholder='Auto'
2042
+ updateField={updateField}
2043
+ />
1314
2044
  <span style={{ color: 'red', display: 'block' }}>{warningMsg.maxMsg}</span>
1315
- <TextField value={config.yAxis.min} section='yAxis' fieldName='min' type='number' label='left axis min value' placeholder='Auto' updateField={updateField} />
2045
+ <TextField
2046
+ value={config.yAxis.min}
2047
+ section='yAxis'
2048
+ fieldName='min'
2049
+ type='number'
2050
+ label='left axis min value'
2051
+ placeholder='Auto'
2052
+ updateField={updateField}
2053
+ />
1316
2054
  <span style={{ color: 'red', display: 'block' }}>{warningMsg.minMsg}</span>
1317
2055
  </>
1318
2056
  )
@@ -1581,14 +2319,60 @@ const EditorPanel = () => {
1581
2319
  <AccordionItemButton>Right Value Axis</AccordionItemButton>
1582
2320
  </AccordionItemHeading>
1583
2321
  <AccordionItemPanel>
1584
- <TextField value={config.yAxis.rightLabel} section='yAxis' fieldName='rightLabel' label='Label' updateField={updateField} />
1585
- <TextField value={config.yAxis.rightNumTicks} placeholder='Auto' type='number' section='yAxis' fieldName='rightNumTicks' label='Number of ticks' className='number-narrow' updateField={updateField} />
1586
- <TextField value={config.yAxis.rightAxisSize} type='number' section='yAxis' fieldName='rightAxisSize' label='Size (Width)' className='number-narrow' updateField={updateField} />
1587
- <TextField value={config.yAxis.rightLabelOffsetSize} type='number' section='yAxis' fieldName='rightLabelOffsetSize' label='Label Offset' className='number-narrow' updateField={updateField} />
2322
+ <TextField
2323
+ value={config.yAxis.rightLabel}
2324
+ section='yAxis'
2325
+ fieldName='rightLabel'
2326
+ label='Label'
2327
+ updateField={updateField}
2328
+ />
2329
+ <TextField
2330
+ value={config.yAxis.rightNumTicks}
2331
+ placeholder='Auto'
2332
+ type='number'
2333
+ section='yAxis'
2334
+ fieldName='rightNumTicks'
2335
+ label='Number of ticks'
2336
+ className='number-narrow'
2337
+ updateField={updateField}
2338
+ />
2339
+ <TextField
2340
+ value={config.yAxis.rightAxisSize}
2341
+ type='number'
2342
+ section='yAxis'
2343
+ fieldName='rightAxisSize'
2344
+ label='Size (Width)'
2345
+ className='number-narrow'
2346
+ updateField={updateField}
2347
+ />
2348
+ <TextField
2349
+ value={config.yAxis.rightLabelOffsetSize}
2350
+ type='number'
2351
+ section='yAxis'
2352
+ fieldName='rightLabelOffsetSize'
2353
+ label='Label Offset'
2354
+ className='number-narrow'
2355
+ updateField={updateField}
2356
+ />
1588
2357
 
1589
2358
  <span className='divider-heading'>Number Formatting</span>
1590
- <CheckBox value={config.dataFormat.rightCommas} section='dataFormat' fieldName='rightCommas' label='Add commas' updateField={updateField} />
1591
- <TextField value={config.dataFormat.rightRoundTo} type='number' section='dataFormat' fieldName='rightRoundTo' label='Round to decimal point' className='number-narrow' updateField={updateField} min={0} />
2359
+ <CheckBox
2360
+ value={config.dataFormat.rightCommas}
2361
+ section='dataFormat'
2362
+ fieldName='rightCommas'
2363
+ label='Add commas'
2364
+ updateField={updateField}
2365
+ />
2366
+ <TextField
2367
+ value={config.dataFormat.rightRoundTo}
2368
+ type='number'
2369
+ section='dataFormat'
2370
+ fieldName='rightRoundTo'
2371
+ label='Round to decimal point'
2372
+ className='number-narrow'
2373
+ updateField={updateField}
2374
+ min={0}
2375
+ />
1592
2376
  <div className='two-col-inputs'>
1593
2377
  <TextField
1594
2378
  value={config.dataFormat.rightPrefix}
@@ -1602,8 +2386,12 @@ const EditorPanel = () => {
1602
2386
  <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1603
2387
  </Tooltip.Target>
1604
2388
  <Tooltip.Content>
1605
- {config.visualizationType === 'Pie' && <p>Enter a data prefix to display in the data table and chart tooltips, if applicable.</p>}
1606
- {config.visualizationType !== 'Pie' && <p>Enter a data prefix (such as "$"), if applicable.</p>}
2389
+ {config.visualizationType === 'Pie' && (
2390
+ <p>Enter a data prefix to display in the data table and chart tooltips, if applicable.</p>
2391
+ )}
2392
+ {config.visualizationType !== 'Pie' && (
2393
+ <p>Enter a data prefix (such as "$"), if applicable.</p>
2394
+ )}
1607
2395
  </Tooltip.Content>
1608
2396
  </Tooltip>
1609
2397
  }
@@ -1620,21 +2408,59 @@ const EditorPanel = () => {
1620
2408
  <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1621
2409
  </Tooltip.Target>
1622
2410
  <Tooltip.Content>
1623
- {config.visualizationType === 'Pie' && <p>Enter a data suffix to display in the data table and tooltips, if applicable.</p>}
1624
- {config.visualizationType !== 'Pie' && <p>Enter a data suffix (such as "%"), if applicable.</p>}
2411
+ {config.visualizationType === 'Pie' && (
2412
+ <p>Enter a data suffix to display in the data table and tooltips, if applicable.</p>
2413
+ )}
2414
+ {config.visualizationType !== 'Pie' && (
2415
+ <p>Enter a data suffix (such as "%"), if applicable.</p>
2416
+ )}
1625
2417
  </Tooltip.Content>
1626
2418
  </Tooltip>
1627
2419
  }
1628
2420
  />
1629
2421
  </div>
1630
2422
 
1631
- <CheckBox value={config.yAxis.rightHideAxis} section='yAxis' fieldName='rightHideAxis' label='Hide Axis' updateField={updateField} />
1632
- <CheckBox value={config.yAxis.rightHideLabel} section='yAxis' fieldName='rightHideLabel' label='Hide Label' updateField={updateField} />
1633
- <CheckBox value={config.yAxis.rightHideTicks} section='yAxis' fieldName='rightHideTicks' label='Hide Ticks' updateField={updateField} />
2423
+ <CheckBox
2424
+ value={config.yAxis.rightHideAxis}
2425
+ section='yAxis'
2426
+ fieldName='rightHideAxis'
2427
+ label='Hide Axis'
2428
+ updateField={updateField}
2429
+ />
2430
+ <CheckBox
2431
+ value={config.yAxis.rightHideLabel}
2432
+ section='yAxis'
2433
+ fieldName='rightHideLabel'
2434
+ label='Hide Tick Labels'
2435
+ updateField={updateField}
2436
+ />
2437
+ <CheckBox
2438
+ value={config.yAxis.rightHideTicks}
2439
+ section='yAxis'
2440
+ fieldName='rightHideTicks'
2441
+ label='Hide Ticks'
2442
+ updateField={updateField}
2443
+ />
1634
2444
 
1635
- <TextField value={config.yAxis.max} section='yAxis' fieldName='rightMax' type='number' label='right axis max value' placeholder='Auto' updateField={updateField} />
2445
+ <TextField
2446
+ value={config.yAxis.max}
2447
+ section='yAxis'
2448
+ fieldName='rightMax'
2449
+ type='number'
2450
+ label='right axis max value'
2451
+ placeholder='Auto'
2452
+ updateField={updateField}
2453
+ />
1636
2454
  <span style={{ color: 'red', display: 'block' }}>{warningMsg.rightMaxMessage}</span>
1637
- <TextField value={config.yAxis.min} section='yAxis' fieldName='rightMin' type='number' label='right axis min value' placeholder='Auto' updateField={updateField} />
2455
+ <TextField
2456
+ value={config.yAxis.min}
2457
+ section='yAxis'
2458
+ fieldName='rightMin'
2459
+ type='number'
2460
+ label='right axis min value'
2461
+ placeholder='Auto'
2462
+ updateField={updateField}
2463
+ />
1638
2464
  <span style={{ color: 'red', display: 'block' }}>{warningMsg.minMsg}</span>
1639
2465
  </AccordionItemPanel>
1640
2466
  </AccordionItem>
@@ -1659,7 +2485,10 @@ const EditorPanel = () => {
1659
2485
  <Tooltip.Target>
1660
2486
  <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1661
2487
  </Tooltip.Target>
1662
- <Tooltip.Content>Linear scales are employed for quantitative data, while time scales are used for time-series data.</Tooltip.Content>
2488
+ <Tooltip.Content>
2489
+ Linear scales are employed for quantitative data, while time scales are used for
2490
+ time-series data.
2491
+ </Tooltip.Content>
1663
2492
  </Tooltip>
1664
2493
  </span>
1665
2494
  <select
@@ -1674,14 +2503,26 @@ const EditorPanel = () => {
1674
2503
  })
1675
2504
  }
1676
2505
  >
1677
- <option value='categorical'>Categorical (Linear Scale)</option>
1678
- <option value='date'>Date (Linear Scale)</option>
2506
+ {config.visualizationType !== 'Bump Chart' && (
2507
+ <option value='categorical'>Categorical (Linear Scale)</option>
2508
+ )}
2509
+ {config.visualizationType !== 'Bump Chart' && (
2510
+ <option value='date'>Date (Linear Scale)</option>
2511
+ )}
1679
2512
  <option value='date-time'>Date (Date Time Scale)</option>
1680
- {config.visualizationType === 'Scatter Plot' && <option value={'continuous'}>Continuous</option>}
2513
+ {config.visualizationType === 'Scatter Plot' && (
2514
+ <option value={'continuous'}>Continuous</option>
2515
+ )}
1681
2516
  </select>
1682
2517
  </label>
1683
2518
 
1684
- <CheckBox value={config.xAxis.manual} section='xAxis' fieldName='manual' label='Manual Ticks' updateField={updateField} />
2519
+ <CheckBox
2520
+ value={config.xAxis.manual}
2521
+ section='xAxis'
2522
+ fieldName='manual'
2523
+ label='Manual Ticks'
2524
+ updateField={updateField}
2525
+ />
1685
2526
 
1686
2527
  {visSupportsDateCategoryAxisPadding() && (
1687
2528
  <TextField
@@ -1699,7 +2540,10 @@ const EditorPanel = () => {
1699
2540
  <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1700
2541
  </Tooltip.Target>
1701
2542
  <Tooltip.Content>
1702
- <p>For use with date scale. Extends the earliest and latest dates represented on the scale by the percentage specified.</p>
2543
+ <p>
2544
+ For use with date scale. Extends the earliest and latest dates represented on the
2545
+ scale by the percentage specified.
2546
+ </p>
1703
2547
  </Tooltip.Content>
1704
2548
  </Tooltip>
1705
2549
  }
@@ -1746,7 +2590,10 @@ const EditorPanel = () => {
1746
2590
  <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1747
2591
  </Tooltip.Target>
1748
2592
  <Tooltip.Content>
1749
- <p>Select the source row or column that contains the segment labels. Depending on the data structure, it may be listed as "Key."</p>
2593
+ <p>
2594
+ Select the source row or column that contains the segment labels. Depending on the data
2595
+ structure, it may be listed as "Key."
2596
+ </p>
1750
2597
  </Tooltip.Content>
1751
2598
  </Tooltip>
1752
2599
  }
@@ -1755,7 +2602,13 @@ const EditorPanel = () => {
1755
2602
 
1756
2603
  {config.visualizationType !== 'Pie' && (
1757
2604
  <>
1758
- <TextField value={config.xAxis.label} section='xAxis' fieldName='label' label='Label' updateField={updateField} />
2605
+ <TextField
2606
+ value={config.xAxis.label}
2607
+ section='xAxis'
2608
+ fieldName='label'
2609
+ label='Label'
2610
+ updateField={updateField}
2611
+ />
1759
2612
 
1760
2613
  {config.xAxis.type === 'continuous' && (
1761
2614
  <>
@@ -1768,7 +2621,10 @@ const EditorPanel = () => {
1768
2621
  tooltip={
1769
2622
  <Tooltip style={{ textTransform: 'none' }}>
1770
2623
  <Tooltip.Target>
1771
- <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
2624
+ <Icon
2625
+ display='question'
2626
+ style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }}
2627
+ />
1772
2628
  </Tooltip.Target>
1773
2629
  <Tooltip.Content>
1774
2630
  <p>Enter a data prefix (such as "$"), if applicable.</p>
@@ -1786,7 +2642,10 @@ const EditorPanel = () => {
1786
2642
  tooltip={
1787
2643
  <Tooltip style={{ textTransform: 'none' }}>
1788
2644
  <Tooltip.Target>
1789
- <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
2645
+ <Icon
2646
+ display='question'
2647
+ style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }}
2648
+ />
1790
2649
  </Tooltip.Target>
1791
2650
  <Tooltip.Content>
1792
2651
  <p>Enter a data suffix (such as "%"), if applicable.</p>
@@ -1804,7 +2663,10 @@ const EditorPanel = () => {
1804
2663
  tooltip={
1805
2664
  <Tooltip style={{ textTransform: 'none' }}>
1806
2665
  <Tooltip.Target>
1807
- <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
2666
+ <Icon
2667
+ display='question'
2668
+ style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }}
2669
+ />
1808
2670
  </Tooltip.Target>
1809
2671
  <Tooltip.Content>
1810
2672
  <p>{`This option abbreviates very large or very small numbers on the value axis`}</p>
@@ -1819,7 +2681,11 @@ const EditorPanel = () => {
1819
2681
  <>
1820
2682
  <p style={{ padding: '1.5em 0 0.5em', fontSize: '.9rem', lineHeight: '1rem' }}>
1821
2683
  Format how charts should parse and display your dates using{' '}
1822
- <a href='https://github.com/d3/d3-time-format#locale_format' target='_blank' rel='noreferrer'>
2684
+ <a
2685
+ href='https://github.com/d3/d3-time-format#locale_format'
2686
+ target='_blank'
2687
+ rel='noreferrer'
2688
+ >
1823
2689
  these guidelines
1824
2690
  </a>
1825
2691
  .
@@ -1828,10 +2694,16 @@ const EditorPanel = () => {
1828
2694
  tooltip={
1829
2695
  <Tooltip style={{ textTransform: 'none' }}>
1830
2696
  <Tooltip.Target>
1831
- <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
2697
+ <Icon
2698
+ display='question'
2699
+ style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }}
2700
+ />
1832
2701
  </Tooltip.Target>
1833
2702
  <Tooltip.Content>
1834
- <p>This field specifies the pattern used to read and interpret dates in your dataset, ensuring the dates are correctly understood and processed. </p>
2703
+ <p>
2704
+ This field specifies the pattern used to read and interpret dates in your dataset,
2705
+ ensuring the dates are correctly understood and processed.{' '}
2706
+ </p>
1835
2707
  </Tooltip.Content>
1836
2708
  </Tooltip>
1837
2709
  }
@@ -1846,10 +2718,16 @@ const EditorPanel = () => {
1846
2718
  tooltip={
1847
2719
  <Tooltip style={{ textTransform: 'none' }}>
1848
2720
  <Tooltip.Target>
1849
- <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
2721
+ <Icon
2722
+ display='question'
2723
+ style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }}
2724
+ />
1850
2725
  </Tooltip.Target>
1851
2726
  <Tooltip.Content>
1852
- <p> Adjusts the date display format on the axis for clear, visual date representation.</p>
2727
+ <p>
2728
+ {' '}
2729
+ Adjusts the date display format on the axis for clear, visual date representation.
2730
+ </p>
1853
2731
  </Tooltip.Content>
1854
2732
  </Tooltip>
1855
2733
  }
@@ -1864,10 +2742,16 @@ const EditorPanel = () => {
1864
2742
  tooltip={
1865
2743
  <Tooltip style={{ textTransform: 'none' }}>
1866
2744
  <Tooltip.Target>
1867
- <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
2745
+ <Icon
2746
+ display='question'
2747
+ style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }}
2748
+ />
1868
2749
  </Tooltip.Target>
1869
2750
  <Tooltip.Content>
1870
- <p>Specify a custom format for displaying dates in data table. If left empty, dates will adopt the Axis Date Display format. </p>
2751
+ <p>
2752
+ Specify a custom format for displaying dates in data table. If left empty, dates
2753
+ will adopt the Axis Date Display format.{' '}
2754
+ </p>
1871
2755
  </Tooltip.Content>
1872
2756
  </Tooltip>
1873
2757
  }
@@ -1882,10 +2766,16 @@ const EditorPanel = () => {
1882
2766
  tooltip={
1883
2767
  <Tooltip style={{ textTransform: 'none' }}>
1884
2768
  <Tooltip.Target>
1885
- <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
2769
+ <Icon
2770
+ display='question'
2771
+ style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }}
2772
+ />
1886
2773
  </Tooltip.Target>
1887
2774
  <Tooltip.Content>
1888
- <p>Specify a custom format for displaying dates on hovers. If left empty, dates will adopt the Axis Date Display format. </p>
2775
+ <p>
2776
+ Specify a custom format for displaying dates on hovers. If left empty, dates will
2777
+ adopt the Axis Date Display format.{' '}
2778
+ </p>
1889
2779
  </Tooltip.Content>
1890
2780
  </Tooltip>
1891
2781
  }
@@ -1903,28 +2793,62 @@ const EditorPanel = () => {
1903
2793
  value={config.exclusions.active}
1904
2794
  section='exclusions'
1905
2795
  fieldName='active'
1906
- label={config.xAxis.type === 'date' ? 'Limit by start and/or end dates' : 'Exclude one or more values'}
2796
+ label={
2797
+ config.xAxis.type === 'date'
2798
+ ? 'Limit by start and/or end dates'
2799
+ : 'Exclude one or more values'
2800
+ }
1907
2801
  tooltip={
1908
2802
  <Tooltip style={{ textTransform: 'none' }}>
1909
2803
  <Tooltip.Target>
1910
- <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
2804
+ <Icon
2805
+ display='question'
2806
+ style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }}
2807
+ />
1911
2808
  </Tooltip.Target>
1912
2809
  <Tooltip.Content>
1913
- <p>When this option is checked, you can select source-file values for exclusion from the date/category axis. </p>
2810
+ <p>
2811
+ When this option is checked, you can select source-file values for exclusion from the
2812
+ date/category axis.{' '}
2813
+ </p>
1914
2814
  </Tooltip.Content>
1915
2815
  </Tooltip>
1916
2816
  }
1917
2817
  updateField={updateField}
1918
2818
  />
1919
- {/* {visHasBrushChart && <CheckBox value={config.brush.active} section='brush' fieldName='active' label='Brush Slider ' updateField={updateField} />} */}
1920
-
1921
- {config.exclusions.active && (
1922
- <>
1923
- {config.xAxis.type === 'categorical' && (
1924
- <>
1925
- {config.exclusions.keys.length > 0 && (
1926
- <>
1927
- <fieldset>
2819
+ {visHasBrushChart() && (
2820
+ <CheckBox
2821
+ value={config.brush?.active}
2822
+ section='brush'
2823
+ fieldName='active'
2824
+ label='Brush Slider '
2825
+ updateField={updateField}
2826
+ tooltip={
2827
+ <Tooltip style={{ textTransform: 'none' }}>
2828
+ <Tooltip.Target>
2829
+ <Icon
2830
+ display='question'
2831
+ style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }}
2832
+ />
2833
+ </Tooltip.Target>
2834
+ <Tooltip.Content>
2835
+ <p>
2836
+ Use the brush slider to narrow down your data view to specific values along the axis.
2837
+ This tool is useful for examining detailed data segments within the larger dataset.{' '}
2838
+ </p>
2839
+ </Tooltip.Content>
2840
+ </Tooltip>
2841
+ }
2842
+ />
2843
+ )}
2844
+
2845
+ {config.exclusions.active && (
2846
+ <>
2847
+ {config.xAxis.type === 'categorical' && (
2848
+ <>
2849
+ {config.exclusions.keys.length > 0 && (
2850
+ <>
2851
+ <fieldset>
1928
2852
  <legend className='edit-label'>Excluded Keys</legend>
1929
2853
  </fieldset>
1930
2854
  <ExclusionsList />
@@ -1948,102 +2872,312 @@ const EditorPanel = () => {
1948
2872
 
1949
2873
  {config.xAxis.type === 'date' && (
1950
2874
  <>
1951
- <TextField type='date' section='exclusions' fieldName='dateStart' label='Start Date' updateField={updateField} value={config.exclusions.dateStart || ''} />
1952
- <TextField type='date' section='exclusions' fieldName='dateEnd' label='End Date' updateField={updateField} value={config.exclusions.dateEnd || ''} />
2875
+ <TextField
2876
+ type='date'
2877
+ section='exclusions'
2878
+ fieldName='dateStart'
2879
+ label='Start Date'
2880
+ updateField={updateField}
2881
+ value={config.exclusions.dateStart || ''}
2882
+ />
2883
+ <TextField
2884
+ type='date'
2885
+ section='exclusions'
2886
+ fieldName='dateEnd'
2887
+ label='End Date'
2888
+ updateField={updateField}
2889
+ value={config.exclusions.dateEnd || ''}
2890
+ />
1953
2891
  </>
1954
2892
  )}
1955
2893
  </>
1956
2894
  )}
1957
2895
 
1958
- {visSupportsDateCategoryNumTicks() && config.xAxis.type !== 'date-time' && config.xAxis.manual && (
1959
- <TextField value={config.xAxis.manualStep} placeholder='Auto' type='number' min={1} section='xAxis' fieldName='manualStep' label='Step count' className='number-narrow' updateField={updateField} />
1960
- )}
1961
- {visSupportsDateCategoryNumTicks() && (config.xAxis.type === 'date-time' || !config.xAxis.manual) && (
1962
- <TextField value={config.xAxis.numTicks} placeholder='Auto' type='number' min={1} section='xAxis' fieldName='numTicks' label='Number of ticks' className='number-narrow' updateField={updateField} />
1963
- )}
1964
- {visSupportsDateCategoryHeight() && <TextField value={config.xAxis.padding} type='number' min={0} section='xAxis' fieldName='padding' label={config.orientation === 'horizontal' ? 'Size (Width)' : 'Size (Height)'} className='number-narrow' updateField={updateField} />}
1965
-
1966
- {/* Hiding this for now, not interested in moving the axis lines away from chart comp. right now. */}
1967
- {/* <TextField value={config.xAxis.axisPadding} type='number' max={10} min={0} section='xAxis' fieldName='axisPadding' label={'Axis Padding'} className='number-narrow' updateField={updateField} /> */}
1968
- {(config.xAxis.type === 'continuous' || config.forestPlot.type === 'Logarithmic') && (
1969
- <>
1970
- <CheckBox value={config.dataFormat.bottomCommas} section='dataFormat' fieldName='bottomCommas' label='Add commas' updateField={updateField} />
1971
- <TextField value={config.dataFormat.bottomRoundTo} type='number' section='dataFormat' fieldName='bottomRoundTo' label='Round to decimal point' className='number-narrow' updateField={updateField} min={0} />
1972
- </>
1973
- )}
1974
- {visSupportsResponsiveTicks() && config.orientation === 'vertical' && config.visualizationType !== 'Paired Bar' && <CheckBox value={config.isResponsiveTicks} fieldName='isResponsiveTicks' label='Use Responsive Ticks' updateField={updateField} />}
1975
- {(config.orientation === 'horizontal' || !config.isResponsiveTicks) && visSupportsDateCategoryTickRotation() && (
1976
- <TextField value={config.xAxis.tickRotation} type='number' min={0} section='xAxis' fieldName='tickRotation' label='Tick rotation (Degrees)' className='number-narrow' updateField={updateField} />
1977
- )}
1978
- {config.orientation === 'vertical' && config.isResponsiveTicks && config.visualizationType !== 'Paired Bar' && (
2896
+ {visSupportsDateCategoryNumTicks() &&
2897
+ config.xAxis.type !== 'date-time' &&
2898
+ config.xAxis.manual && (
2899
+ <>
2900
+ <TextField
2901
+ value={config.xAxis.manualStep}
2902
+ placeholder='Auto'
2903
+ type='number'
2904
+ min={1}
2905
+ section='xAxis'
2906
+ fieldName='manualStep'
2907
+ label='Step count'
2908
+ className='number-narrow'
2909
+ updateField={updateField}
2910
+ tooltip={
2911
+ <Tooltip style={{ textTransform: 'none' }}>
2912
+ <Tooltip.Target>
2913
+ <Icon
2914
+ display='question'
2915
+ style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }}
2916
+ />
2917
+ </Tooltip.Target>
2918
+ <Tooltip.Content>
2919
+ <p>
2920
+ Number of data points which are assigned a tick, starting from the right most data
2921
+ point. Value of 1 will show a tick at every data point, value of 2 will show a
2922
+ tick for every other, etc.
2923
+ </p>
2924
+ </Tooltip.Content>
2925
+ </Tooltip>
2926
+ }
2927
+ />
2928
+ <div className='viewport-overrides'>
2929
+ <label>
2930
+ <button
2931
+ onClick={() => setDisplayViewportOverrides(!displayViewportOverrides)}
2932
+ className='edit-label'
2933
+ >
2934
+ Step Count: viewport overrides{' '}
2935
+ <span style={{ transform: `rotate(${displayViewportOverrides ? '90deg' : '0deg'})` }}>
2936
+ &gt;
2937
+ </span>
2938
+ </button>
2939
+ </label>
2940
+ {displayViewportOverrides && (
2941
+ <div className='edit-block'>
2942
+ {Object.keys(viewports).map(viewport => (
2943
+ <TextField
2944
+ key={`viewport-step-count-input-${viewport}`}
2945
+ value={
2946
+ config.xAxis.viewportStepCount
2947
+ ? config.xAxis.viewportStepCount[viewport]
2948
+ : undefined
2949
+ }
2950
+ placeholder='Auto'
2951
+ type='number'
2952
+ label={viewport}
2953
+ className='number-narrow'
2954
+ updateField={(section, fieldName, label, val) =>
2955
+ updateViewportOverrides('viewportStepCount', viewport, val)
2956
+ }
2957
+ />
2958
+ ))}
2959
+ </div>
2960
+ )}
2961
+ </div>
2962
+ </>
2963
+ )}
2964
+ {visSupportsDateCategoryNumTicks() &&
2965
+ (config.xAxis.type === 'date-time' || !config.xAxis.manual) && (
2966
+ <>
2967
+ <TextField
2968
+ value={config.xAxis.numTicks}
2969
+ placeholder='Auto'
2970
+ type='number'
2971
+ min={1}
2972
+ section='xAxis'
2973
+ fieldName='numTicks'
2974
+ label='Number of ticks'
2975
+ className='number-narrow'
2976
+ updateField={updateField}
2977
+ tooltip={
2978
+ <Tooltip style={{ textTransform: 'none' }}>
2979
+ <Tooltip.Target>
2980
+ <Icon
2981
+ display='question'
2982
+ style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }}
2983
+ />
2984
+ </Tooltip.Target>
2985
+ <Tooltip.Content>
2986
+ <p>
2987
+ Apporoximate number of ticks. Other factors such as space available and data may
2988
+ change the exact number of ticks used. To enforce an exact number of ticks, check
2989
+ "Manual Ticks" above.
2990
+ </p>
2991
+ </Tooltip.Content>
2992
+ </Tooltip>
2993
+ }
2994
+ />
2995
+ <div className='viewport-overrides'>
2996
+ <label>
2997
+ <button
2998
+ onClick={() => setDisplayViewportOverrides(!displayViewportOverrides)}
2999
+ className='edit-label'
3000
+ >
3001
+ Number of ticks: viewport overrides{' '}
3002
+ <span style={{ transform: `rotate(${displayViewportOverrides ? '90deg' : '0deg'})` }}>
3003
+ &gt;
3004
+ </span>
3005
+ </button>
3006
+ </label>
3007
+ {displayViewportOverrides && (
3008
+ <div className='edit-block'>
3009
+ {Object.keys(viewports).map(viewport => (
3010
+ <TextField
3011
+ key={`viewport-num-ticks-input-${viewport}`}
3012
+ value={
3013
+ config.xAxis.viewportNumTicks
3014
+ ? config.xAxis.viewportNumTicks[viewport]
3015
+ : undefined
3016
+ }
3017
+ placeholder='Auto'
3018
+ type='number'
3019
+ label={viewport}
3020
+ className='number-narrow'
3021
+ updateField={(section, fieldName, label, val) =>
3022
+ updateViewportOverrides('viewportNumTicks', viewport, val)
3023
+ }
3024
+ />
3025
+ ))}
3026
+ </div>
3027
+ )}
3028
+ </div>
3029
+ </>
3030
+ )}
3031
+ {visSupportsDateCategoryHeight() && (
1979
3032
  <TextField
1980
- value={config.xAxis.maxTickRotation}
3033
+ value={config.xAxis.size}
1981
3034
  type='number'
1982
3035
  min={0}
1983
3036
  section='xAxis'
1984
- fieldName='maxTickRotation'
1985
- label='Max Tick Rotation'
3037
+ fieldName='size'
3038
+ label={config.orientation === 'horizontal' ? 'Size (Width)' : 'Size (Height)'}
1986
3039
  className='number-narrow'
1987
3040
  updateField={updateField}
1988
- tooltip={
1989
- <Tooltip style={{ textTransform: 'none' }}>
1990
- <Tooltip.Target>
1991
- <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
1992
- </Tooltip.Target>
1993
- <Tooltip.Content>
1994
- <p>Degrees ticks will be rotated if values overlap, especially in smaller viewports.</p>
1995
- </Tooltip.Content>
1996
- </Tooltip>
1997
- }
1998
3041
  />
1999
3042
  )}
3043
+ <TextField
3044
+ value={config.xAxis.labelOffset}
3045
+ section='xAxis'
3046
+ fieldName='labelOffset'
3047
+ label='Label offset'
3048
+ type='number'
3049
+ className='number-narrow'
3050
+ updateField={updateField}
3051
+ />
3052
+
3053
+ {/* Hiding this for now, not interested in moving the axis lines away from chart comp. right now. */}
3054
+ {/* <TextField value={config.xAxis.axisPadding} type='number' max={10} min={0} section='xAxis' fieldName='axisPadding' label={'Axis Padding'} className='number-narrow' updateField={updateField} /> */}
3055
+ {(config.xAxis.type === 'continuous' || config.forestPlot.type === 'Logarithmic') && (
3056
+ <>
3057
+ <CheckBox
3058
+ value={config.dataFormat.bottomCommas}
3059
+ section='dataFormat'
3060
+ fieldName='bottomCommas'
3061
+ label='Add commas'
3062
+ updateField={updateField}
3063
+ />
3064
+ <TextField
3065
+ value={config.dataFormat.bottomRoundTo}
3066
+ type='number'
3067
+ section='dataFormat'
3068
+ fieldName='bottomRoundTo'
3069
+ label='Round to decimal point'
3070
+ className='number-narrow'
3071
+ updateField={updateField}
3072
+ min={0}
3073
+ />
3074
+ </>
3075
+ )}
3076
+ {visSupportsResponsiveTicks() &&
3077
+ config.orientation === 'vertical' &&
3078
+ config.visualizationType !== 'Paired Bar' && (
3079
+ <CheckBox
3080
+ value={config.isResponsiveTicks}
3081
+ fieldName='isResponsiveTicks'
3082
+ label='Use Responsive Ticks'
3083
+ updateField={updateField}
3084
+ />
3085
+ )}
3086
+ {(config.orientation === 'horizontal' || !config.isResponsiveTicks) &&
3087
+ visSupportsDateCategoryTickRotation() && (
3088
+ <TextField
3089
+ value={config.xAxis.tickRotation}
3090
+ type='number'
3091
+ min={0}
3092
+ section='xAxis'
3093
+ fieldName='tickRotation'
3094
+ label='Tick rotation (Degrees)'
3095
+ className='number-narrow'
3096
+ updateField={updateField}
3097
+ />
3098
+ )}
3099
+ {config.orientation === 'vertical' &&
3100
+ config.isResponsiveTicks &&
3101
+ config.visualizationType !== 'Paired Bar' && (
3102
+ <TextField
3103
+ value={config.xAxis.maxTickRotation}
3104
+ type='number'
3105
+ min={0}
3106
+ section='xAxis'
3107
+ fieldName='maxTickRotation'
3108
+ label='Max Tick Rotation'
3109
+ className='number-narrow'
3110
+ updateField={updateField}
3111
+ tooltip={
3112
+ <Tooltip style={{ textTransform: 'none' }}>
3113
+ <Tooltip.Target>
3114
+ <Icon
3115
+ display='question'
3116
+ style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }}
3117
+ />
3118
+ </Tooltip.Target>
3119
+ <Tooltip.Content>
3120
+ <p>
3121
+ Degrees ticks will be rotated if values overlap, especially in smaller viewports.
3122
+ </p>
3123
+ </Tooltip.Content>
3124
+ </Tooltip>
3125
+ }
3126
+ />
3127
+ )}
2000
3128
 
2001
3129
  {config.orientation === 'horizontal' ? (
2002
3130
  <>
2003
- {visSupportsDateCategoryAxisLine() && <CheckBox value={config.yAxis.hideAxis} section='yAxis' fieldName='hideAxis' label='Hide Axis' updateField={updateField} />}
2004
- {visSupportsDateCategoryAxisLabel() && <CheckBox value={config.yAxis.hideLabel} section='yAxis' fieldName='hideLabel' label='Hide Label' updateField={updateField} />}
3131
+ {visSupportsDateCategoryAxisLine() && (
3132
+ <CheckBox
3133
+ value={config.yAxis.hideAxis}
3134
+ section='yAxis'
3135
+ fieldName='hideAxis'
3136
+ label='Hide Axis'
3137
+ updateField={updateField}
3138
+ />
3139
+ )}
3140
+ {visSupportsDateCategoryAxisLabel() && (
3141
+ <CheckBox
3142
+ value={config.yAxis.hideLabel}
3143
+ section='yAxis'
3144
+ fieldName='hideLabel'
3145
+ label='Hide Tick Labels'
3146
+ updateField={updateField}
3147
+ />
3148
+ )}
2005
3149
  </>
2006
3150
  ) : (
2007
3151
  <>
2008
- {visSupportsDateCategoryAxisLine() && <CheckBox value={config.xAxis.hideAxis} section='xAxis' fieldName='hideAxis' label='Hide Axis' updateField={updateField} />}
2009
- {visSupportsDateCategoryAxisLabel() && <CheckBox value={config.xAxis.hideLabel} section='xAxis' fieldName='hideLabel' label='Hide Label' updateField={updateField} />}
2010
- {visSupportsDateCategoryAxisTicks() && <CheckBox value={config.xAxis.hideTicks} section='xAxis' fieldName='hideTicks' label='Hide Ticks' updateField={updateField} />}
3152
+ {visSupportsDateCategoryAxisLine() && (
3153
+ <CheckBox
3154
+ value={config.xAxis.hideAxis}
3155
+ section='xAxis'
3156
+ fieldName='hideAxis'
3157
+ label='Hide Axis'
3158
+ updateField={updateField}
3159
+ />
3160
+ )}
3161
+ {visSupportsDateCategoryAxisLabel() && (
3162
+ <CheckBox
3163
+ value={config.xAxis.hideLabel}
3164
+ section='xAxis'
3165
+ fieldName='hideLabel'
3166
+ label='Hide Tick Labels'
3167
+ updateField={updateField}
3168
+ />
3169
+ )}
3170
+ {visSupportsDateCategoryAxisTicks() && (
3171
+ <CheckBox
3172
+ value={config.xAxis.hideTicks}
3173
+ section='xAxis'
3174
+ fieldName='hideTicks'
3175
+ label='Hide Ticks'
3176
+ updateField={updateField}
3177
+ />
3178
+ )}
2011
3179
  </>
2012
3180
  )}
2013
- <CheckBox
2014
- tooltip={
2015
- <Tooltip style={{ textTransform: 'none' }}>
2016
- <Tooltip.Target>
2017
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
2018
- </Tooltip.Target>
2019
- <Tooltip.Content>
2020
- <p>Selecting this option will display a "thin line" slightly above the Date/Category Axis to indicate "suppressed data" where "suppressed data" values are indicated in the Data Series.</p>
2021
- </Tooltip.Content>
2022
- </Tooltip>
2023
- }
2024
- value={config.xAxis.showSuppressedLine}
2025
- section='xAxis'
2026
- fieldName='showSuppressedLine'
2027
- label='Display suppressed data line'
2028
- updateField={updateField}
2029
- />
2030
- <CheckBox
2031
- tooltip={
2032
- <Tooltip style={{ textTransform: 'none' }}>
2033
- <Tooltip.Target>
2034
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
2035
- </Tooltip.Target>
2036
- <Tooltip.Content>
2037
- <p>Selecting this option will display "suppressed data symbol" on the Date/Category Axis where suppressed data values are indicated in the Data Series, unless a different symbol was chosen from the data series (e.g., suppression symbol) menu.</p>
2038
- </Tooltip.Content>
2039
- </Tooltip>
2040
- }
2041
- value={config.xAxis.showSuppressedSymbol}
2042
- section='xAxis'
2043
- fieldName='showSuppressedSymbol'
2044
- label='Display suppressed data symbol'
2045
- updateField={updateField}
2046
- />
2047
3181
 
2048
3182
  {config.series?.length === 1 && config.visualizationType === 'Bar' && (
2049
3183
  <>
@@ -2059,22 +3193,54 @@ const EditorPanel = () => {
2059
3193
  <p>Highlighted Bar {i + 1}</p>
2060
3194
  <label>
2061
3195
  <span className='edit-label column-heading'>Value</span>
2062
- <select value={config.highlightedBarValues[i].value} onChange={e => handleUpdateHighlightedBar(e, i)}>
3196
+ <select
3197
+ value={config.highlightedBarValues[i].value}
3198
+ onChange={e => handleUpdateHighlightedBar(e, i)}
3199
+ >
2063
3200
  <option value=''>- Select Value -</option>
2064
- {highlightedSeriesValues && [...new Set(highlightedSeriesValues)].sort().map(option => <option key={`special-class-value-option-${i}-${option}`}>{option}</option>)}
3201
+ {highlightedSeriesValues &&
3202
+ [...new Set(highlightedSeriesValues)]
3203
+ .sort()
3204
+ .map(option => (
3205
+ <option key={`special-class-value-option-${i}-${option}`}>{option}</option>
3206
+ ))}
2065
3207
  </select>
2066
3208
  </label>
2067
3209
  <label>
2068
3210
  <span className='edit-label column-heading'>Color</span>
2069
- <input type='text' value={config.highlightedBarValues[i].color ? config.highlightedBarValues[i].color : ''} onChange={e => handleUpdateHighlightedBarColor(e, i)} />
3211
+ <input
3212
+ type='text'
3213
+ value={
3214
+ config.highlightedBarValues[i].color ? config.highlightedBarValues[i].color : ''
3215
+ }
3216
+ onChange={e => handleUpdateHighlightedBarColor(e, i)}
3217
+ />
2070
3218
  </label>
2071
3219
  <label>
2072
3220
  <span className='edit-label column-heading'>Border Width</span>
2073
- <input max='5' min='0' type='number' value={config.highlightedBarValues[i].borderWidth ? config.highlightedBarValues[i].borderWidth : ''} onChange={e => handleUpdateHighlightedBorderWidth(e, i)} />
3221
+ <input
3222
+ max='5'
3223
+ min='0'
3224
+ type='number'
3225
+ value={
3226
+ config.highlightedBarValues[i].borderWidth
3227
+ ? config.highlightedBarValues[i].borderWidth
3228
+ : ''
3229
+ }
3230
+ onChange={e => handleUpdateHighlightedBorderWidth(e, i)}
3231
+ />
2074
3232
  </label>
2075
3233
  <label>
2076
3234
  <span className='edit-label column-heading'>Legend Label</span>
2077
- <input type='text' value={config.highlightedBarValues[i].legendLabel ? config.highlightedBarValues[i].legendLabel : ''} onChange={e => handleHighlightedBarLegendLabel(e, i)} />
3235
+ <input
3236
+ type='text'
3237
+ value={
3238
+ config.highlightedBarValues[i].legendLabel
3239
+ ? config.highlightedBarValues[i].legendLabel
3240
+ : ''
3241
+ }
3242
+ onChange={e => handleHighlightedBarLegendLabel(e, i)}
3243
+ />
2078
3244
  </label>
2079
3245
  </div>
2080
3246
  </fieldset>
@@ -2098,10 +3264,15 @@ const EditorPanel = () => {
2098
3264
  tooltip={
2099
3265
  <Tooltip style={{ textTransform: 'none' }}>
2100
3266
  <Tooltip.Target>
2101
- <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
3267
+ <Icon
3268
+ display='question'
3269
+ style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }}
3270
+ />
2102
3271
  </Tooltip.Target>
2103
3272
  <Tooltip.Content>
2104
- <p>When this option is checked, you can select values for exclusion from the pie segments.</p>
3273
+ <p>
3274
+ When this option is checked, you can select values for exclusion from the pie segments.
3275
+ </p>
2105
3276
  </Tooltip.Content>
2106
3277
  </Tooltip>
2107
3278
  }
@@ -2266,7 +3437,10 @@ const EditorPanel = () => {
2266
3437
  <span className='edit-label column-heading'>Anchors</span>
2267
3438
  <Accordion allowZeroExpanded>
2268
3439
  {config.yAxis?.anchors?.map((anchor, index) => (
2269
- <AccordionItem className='series-item series-item--chart' key={`accordion-yaxis-anchors-${index}`}>
3440
+ <AccordionItem
3441
+ className='series-item series-item--chart'
3442
+ key={`accordion-yaxis-anchors-${index}`}
3443
+ >
2270
3444
  <AccordionItemHeading className='series-item__title'>
2271
3445
  <>
2272
3446
  <AccordionItemButton className={'accordion__button accordion__button'}>
@@ -2392,7 +3566,7 @@ const EditorPanel = () => {
2392
3566
  <Panels.Regions name='Regions' />
2393
3567
 
2394
3568
  {/* Columns */}
2395
- {config.visualizationType !== 'Box Plot' && (
3569
+ {config.visualizationType !== 'Box Plot' && config.visualizationType !== 'Sankey' && (
2396
3570
  <AccordionItem>
2397
3571
  <AccordionItemHeading>
2398
3572
  <AccordionItemButton>Columns</AccordionItemButton>
@@ -2409,7 +3583,69 @@ const EditorPanel = () => {
2409
3583
  <AccordionItemButton>Legend</AccordionItemButton>
2410
3584
  </AccordionItemHeading>
2411
3585
  <AccordionItemPanel>
2412
- <CheckBox value={config.legend.reverseLabelOrder} section='legend' fieldName='reverseLabelOrder' label='Reverse Labels' updateField={updateField} />
3586
+ <Select
3587
+ value={config.legend?.position}
3588
+ section='legend'
3589
+ fieldName='position'
3590
+ label='Position'
3591
+ updateField={updateField}
3592
+ options={['right', 'left', 'bottom', 'top']}
3593
+ />
3594
+ {(config.legend.position === 'left' ||
3595
+ config.legend.position === 'right' ||
3596
+ !config.legend.position) &&
3597
+ config.legend.style === 'gradient' && (
3598
+ <span style={{ color: 'red', fontSize: '14px' }}>
3599
+ Position must be set to top or bottom to use gradient style.
3600
+ </span>
3601
+ )}
3602
+
3603
+ <Select
3604
+ tooltip={
3605
+ <Tooltip style={{ textTransform: 'none' }}>
3606
+ <Tooltip.Target>
3607
+ <Icon
3608
+ display='question'
3609
+ style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }}
3610
+ />
3611
+ </Tooltip.Target>
3612
+ <Tooltip.Content>
3613
+ <p>
3614
+ If using gradient style, limit the legend to five items for better mobile visibility, and
3615
+ position the legend at the top or bottom.
3616
+ </p>
3617
+ </Tooltip.Content>
3618
+ </Tooltip>
3619
+ }
3620
+ display={!config.legend.hide}
3621
+ value={config.legend.style}
3622
+ section='legend'
3623
+ fieldName='style'
3624
+ label='Legend Style'
3625
+ updateField={updateField}
3626
+ options={getLegendStyleOptions('style')}
3627
+ />
3628
+
3629
+ <Select
3630
+ display={!config.legend.hide && config.legend.style === 'gradient'}
3631
+ value={config.legend.subStyle}
3632
+ section='legend'
3633
+ fieldName='subStyle'
3634
+ label='Gradient Style'
3635
+ updateField={updateField}
3636
+ options={getLegendStyleOptions('subStyle')}
3637
+ />
3638
+ <TextField
3639
+ display={config.legend.style === 'gradient' && !config.legend.hide}
3640
+ className='number-narrow'
3641
+ type='number'
3642
+ value={config.legend.tickRotation}
3643
+ section='legend'
3644
+ fieldName='tickRotation'
3645
+ label='Tick Rotation (Degrees)'
3646
+ updateField={updateField}
3647
+ />
3648
+
2413
3649
  {/* <fieldset className="checkbox-group">
2414
3650
  <CheckBox value={config.legend.dynamicLegend} section="legend" fieldName="dynamicLegend" label="Dynamic Legend" updateField={updateField}/>
2415
3651
  {config.legend.dynamicLegend && (
@@ -2421,6 +3657,7 @@ const EditorPanel = () => {
2421
3657
  </>
2422
3658
  )}
2423
3659
  </fieldset> */}
3660
+
2424
3661
  <CheckBox
2425
3662
  value={config.legend.hide ? true : false}
2426
3663
  section='legend'
@@ -2430,7 +3667,10 @@ const EditorPanel = () => {
2430
3667
  tooltip={
2431
3668
  <Tooltip style={{ textTransform: 'none' }}>
2432
3669
  <Tooltip.Target>
2433
- <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
3670
+ <Icon
3671
+ display='question'
3672
+ style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }}
3673
+ />
2434
3674
  </Tooltip.Target>
2435
3675
  <Tooltip.Content>
2436
3676
  <p>With a single-series chart, consider hiding the legend to reduce visual clutter.</p>
@@ -2439,6 +3679,7 @@ const EditorPanel = () => {
2439
3679
  }
2440
3680
  />
2441
3681
  <CheckBox
3682
+ display={config.preliminaryData?.some(pd => pd.label && pd.type === 'suppression' && pd.value)}
2442
3683
  value={config.legend.hideSuppressedLabels}
2443
3684
  section='legend'
2444
3685
  fieldName='hideSuppressedLabels'
@@ -2447,10 +3688,37 @@ const EditorPanel = () => {
2447
3688
  tooltip={
2448
3689
  <Tooltip style={{ textTransform: 'none' }}>
2449
3690
  <Tooltip.Target>
2450
- <Icon display='question' style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }} />
3691
+ <Icon
3692
+ display='question'
3693
+ style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }}
3694
+ />
3695
+ </Tooltip.Target>
3696
+ <Tooltip.Content>
3697
+ <p>
3698
+ Hiding suppressed labels will not override the 'Special Class' assigned to line chart
3699
+ indicating "suppressed" data in the Data Series Panel.
3700
+ </p>
3701
+ </Tooltip.Content>
3702
+ </Tooltip>
3703
+ }
3704
+ />
3705
+ <CheckBox
3706
+ display={config.preliminaryData?.some(pd => pd.label && pd.type === 'suppression' && pd.value)}
3707
+ value={config.legend.hideSuppressionLink}
3708
+ section='legend'
3709
+ fieldName='hideSuppressionLink'
3710
+ label='Hide Suppression Definition Link'
3711
+ updateField={updateField}
3712
+ tooltip={
3713
+ <Tooltip style={{ textTransform: 'none' }}>
3714
+ <Tooltip.Target>
3715
+ <Icon
3716
+ display='question'
3717
+ style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }}
3718
+ />
2451
3719
  </Tooltip.Target>
2452
3720
  <Tooltip.Content>
2453
- <p>Hiding suppressed labels will not override the 'Special Class' assigned to line chart indicating "suppressed" data in the Data Series Panel.</p>
3721
+ <p>Selecting this option will hide the suppression definition link from display.</p>
2454
3722
  </Tooltip.Content>
2455
3723
  </Tooltip>
2456
3724
  }
@@ -2461,15 +3729,43 @@ const EditorPanel = () => {
2461
3729
  <TextField type='textarea' value={config.boxplot.legend.howToReadText} updateField={updateField} fieldName='howToReadText' section='boxplot' subsection='legend' label='How to read text' />
2462
3730
  </>
2463
3731
  } */}
2464
- {config.visualizationType === 'Line' && <CheckBox value={config.legend.lineMode} section='legend' fieldName='lineMode' label='Show Lined Style Legend' updateField={updateField} />}
2465
- {config.visualizationType === 'Bar' && config.visualizationSubType === 'regular' && config.runtime.seriesKeys.length === 1 && (
2466
- <Select value={config.legend.colorCode} section='legend' fieldName='colorCode' label='Color code by category' initial='Select' updateField={updateField} options={getDataValueOptions(data)} />
3732
+ <Select
3733
+ display={config.series?.length > 1}
3734
+ value={config.legend.behavior}
3735
+ section='legend'
3736
+ fieldName='behavior'
3737
+ label='Legend Behavior (When clicked)'
3738
+ updateField={(...[section, , fieldName, value]) => updateBehavior(section, fieldName, value)}
3739
+ options={['highlight', 'isolate']}
3740
+ />
3741
+ <Select
3742
+ display={visHasLegendColorCategory()}
3743
+ value={config.legend.colorCode}
3744
+ section='legend'
3745
+ fieldName='colorCode'
3746
+ label='Color code by category'
3747
+ initial='Select'
3748
+ updateField={updateField}
3749
+ options={getDataValueOptions(data)}
3750
+ />
3751
+ {visHasLegendAxisAlign() && (
3752
+ <CheckBox
3753
+ value={config.legend.axisAlign}
3754
+ fieldName='axisAlign'
3755
+ section='legend'
3756
+ label='Align to Axis on Isolate'
3757
+ updateField={updateField}
3758
+ />
3759
+ )}
3760
+ {config.legend.behavior === 'highlight' && config.tooltips.singleSeries && (
3761
+ <CheckBox
3762
+ value={config.legend.highlightOnHover}
3763
+ section='legend'
3764
+ fieldName='highlightOnHover'
3765
+ label='HIGHLIGHT DATA SERIES ON HOVER'
3766
+ updateField={updateField}
3767
+ />
2467
3768
  )}
2468
- <Select value={config.legend.behavior} section='legend' fieldName='behavior' label='Legend Behavior (When clicked)' updateField={(...[section, , fieldName, value]) => updateBehavior(section, fieldName, value)} options={['highlight', 'isolate']} />
2469
- {visHasLegendAxisAlign() && <CheckBox value={config.legend.axisAlign} fieldName='axisAlign' section='legend' label='Align to Axis on Isolate' updateField={updateField} />}
2470
-
2471
- {config.legend.behavior === 'highlight' && config.tooltips.singleSeries && <CheckBox value={config.legend.highlightOnHover} section='legend' fieldName='highlightOnHover' label='HIGHLIGHT DATA SERIES ON HOVER' updateField={updateField} />}
2472
-
2473
3769
  {/* start: isolated values */}
2474
3770
  {visHasSelectableLegendValues && config.legend.behavior === 'isolate' && !colorCodeByCategory && (
2475
3771
  <fieldset className='primary-fieldset edit-block' key={'additional-highlight-values'}>
@@ -2481,7 +3777,10 @@ const EditorPanel = () => {
2481
3777
  <Icon display='question' style={{ marginLeft: '0.5rem' }} />
2482
3778
  </Tooltip.Target>
2483
3779
  <Tooltip.Content>
2484
- <p>You can choose data series that are shown on load. Others will be added when the user clicks on them in the legend.</p>
3780
+ <p>
3781
+ You can choose data series that are shown on load. Others will be added when the user
3782
+ clicks on them in the legend.
3783
+ </p>
2485
3784
  </Tooltip.Content>
2486
3785
  </Tooltip>
2487
3786
  </span>
@@ -2537,16 +3836,99 @@ const EditorPanel = () => {
2537
3836
  </fieldset>
2538
3837
  )}
2539
3838
  {/* end: isolated values */}
2540
-
2541
- <TextField value={config.legend.label} section='legend' fieldName='label' label='Title' updateField={updateField} />
2542
- <Select value={config.legend.position} section='legend' fieldName='position' label='Position' updateField={updateField} options={['right', 'left', 'bottom']} />
2543
- {config.legend.position === 'bottom' && (
2544
- <>
2545
- <CheckBox value={config.legend.singleRow} section='legend' fieldName='singleRow' label='Single Row Legend' updateField={updateField} />
2546
- <CheckBox value={config.legend.verticalSorted} section='legend' fieldName='verticalSorted' label='Vertical sorted Legend' updateField={updateField} />
2547
- </>
2548
- )}
2549
- <TextField type='textarea' value={config.legend.description} updateField={updateField} section='legend' fieldName='description' label='Legend Description' />
3839
+ <CheckBox
3840
+ display={!config.legend.hide && config.legend.style !== 'gradient'}
3841
+ value={config.legend.reverseLabelOrder}
3842
+ section='legend'
3843
+ fieldName='reverseLabelOrder'
3844
+ label='Reverse Labels'
3845
+ updateField={updateField}
3846
+ />
3847
+ <CheckBox
3848
+ display={!config.legend.hide}
3849
+ value={
3850
+ ['left', 'right'].includes(config.legend.position)
3851
+ ? config.legend.hideBorder.side
3852
+ : config.legend.hideBorder.topBottom
3853
+ }
3854
+ section='legend'
3855
+ subsection='hideBorder'
3856
+ fieldName={['left', 'right'].includes(config.legend.position) ? 'side' : 'topBottom'}
3857
+ label='Hide Legend Box'
3858
+ updateField={updateField}
3859
+ tooltip={
3860
+ <Tooltip style={{ textTransform: 'none' }}>
3861
+ <Tooltip.Target>
3862
+ <Icon
3863
+ display='question'
3864
+ style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }}
3865
+ />
3866
+ </Tooltip.Target>
3867
+ <Tooltip.Content>
3868
+ <p>Default option for top and bottom legends is ‘No Box.’.</p>
3869
+ </Tooltip.Content>
3870
+ </Tooltip>
3871
+ }
3872
+ />
3873
+ <CheckBox
3874
+ display={
3875
+ !config.legend.hide &&
3876
+ !['left', 'right'].includes(config.legend.position) &&
3877
+ config.legend.style !== 'gradient'
3878
+ }
3879
+ value={config.legend.singleRow}
3880
+ section='legend'
3881
+ fieldName='singleRow'
3882
+ label='Single Row Legend'
3883
+ updateField={updateField}
3884
+ />
3885
+ <CheckBox
3886
+ display={
3887
+ ['bottom', 'top'].includes(config.legend.position) &&
3888
+ !config.legend.hide &&
3889
+ config.legend.style !== 'gradient'
3890
+ }
3891
+ value={config.legend.verticalSorted}
3892
+ section='legend'
3893
+ fieldName='verticalSorted'
3894
+ label='Vertical sorted Legend'
3895
+ updateField={updateField}
3896
+ />
3897
+ <CheckBox
3898
+ value={config.legend.hide ? true : false}
3899
+ section='legend'
3900
+ fieldName='hide'
3901
+ label='Hide Legend'
3902
+ updateField={updateField}
3903
+ tooltip={
3904
+ <Tooltip style={{ textTransform: 'none' }}>
3905
+ <Tooltip.Target>
3906
+ <Icon
3907
+ display='question'
3908
+ style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }}
3909
+ />
3910
+ </Tooltip.Target>
3911
+ <Tooltip.Content>
3912
+ <p>With a single-series chart, consider hiding the legend to reduce visual clutter.</p>
3913
+ </Tooltip.Content>
3914
+ </Tooltip>
3915
+ }
3916
+ />
3917
+ <TextField
3918
+ value={config.legend.label}
3919
+ section='legend'
3920
+ fieldName='label'
3921
+ label='Title'
3922
+ updateField={updateField}
3923
+ />
3924
+ <TextField
3925
+ type='textarea'
3926
+ value={config.legend.description}
3927
+ updateField={updateField}
3928
+ section='legend'
3929
+ fieldName='description'
3930
+ label='Legend Description'
3931
+ />
2550
3932
  </AccordionItemPanel>
2551
3933
  </AccordionItem>
2552
3934
  )}
@@ -2568,13 +3950,22 @@ const EditorPanel = () => {
2568
3950
  <AccordionItemButton>Data Table</AccordionItemButton>
2569
3951
  </AccordionItemHeading>
2570
3952
  <AccordionItemPanel>
2571
- <DataTableEditor config={config} columns={Object.keys(data[0] || {})} updateField={updateField} isDashboard={isDashboard} isLoadedFromUrl={isLoadedFromUrl} />{' '}
3953
+ <DataTableEditor
3954
+ config={config}
3955
+ columns={Object.keys(data[0] || {})}
3956
+ updateField={updateField}
3957
+ isDashboard={isDashboard}
3958
+ isLoadedFromUrl={isLoadedFromUrl}
3959
+ />{' '}
2572
3960
  </AccordionItemPanel>
2573
3961
  </AccordionItem>
2574
3962
  )}
3963
+ <Panels.Annotate name='Text Annotations' />
2575
3964
  {/* {(config.visualizationType === 'Bar' || config.visualizationType === 'Line') && <Panels.DateHighlighting name='Date Highlighting' />} */}
2576
3965
  </Accordion>
2577
- {config.type !== 'Spark Line' && <AdvancedEditor loadConfig={updateConfig} state={config} convertStateToConfig={convertStateToConfig} />}
3966
+ {config.type !== 'Spark Line' && (
3967
+ <AdvancedEditor loadConfig={updateConfig} config={config} convertStateToConfig={convertStateToConfig} />
3968
+ )}
2578
3969
  </Layout.Sidebar>
2579
3970
  </ErrorBoundary>
2580
3971
  </EditorPanelContext.Provider>