@cdc/chart 4.23.1 → 4.23.3

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 (74) hide show
  1. package/dist/cdcchart.js +56289 -702
  2. package/examples/Barchart_with_negative.json +34 -0
  3. package/examples/area-chart.json +187 -0
  4. package/examples/big-small-test-bar.json +328 -0
  5. package/examples/big-small-test-line.json +328 -0
  6. package/examples/big-small-test-negative.json +328 -0
  7. package/examples/box-plot.json +1 -2
  8. package/examples/dynamic-legends.json +1 -1
  9. package/examples/example-bar-chart-nonnumeric.json +36 -0
  10. package/examples/example-bar-chart.json +36 -0
  11. package/examples/example-combo-bar-nonnumeric.json +105 -0
  12. package/examples/example-sparkline.json +76 -0
  13. package/examples/gallery/bar-chart-horizontal/horizontal-bar-chart.json +31 -172
  14. package/examples/gallery/bar-chart-vertical/vertical-bar-chart-categorical.json +1 -1
  15. package/examples/gallery/bar-chart-vertical/vertical-bar-chart-confidence.json +1 -0
  16. package/examples/gallery/bar-chart-vertical/vertical-bar-chart-with-confidence.json +96 -14
  17. package/examples/gallery/bar-chart-vertical/vertical-bar-chart.json +2 -2
  18. package/examples/gallery/line/line.json +1 -0
  19. package/examples/gallery/paired-bar/paired-bar-chart.json +65 -13
  20. package/examples/horizontal-chart-max-increase.json +38 -0
  21. package/examples/line-chart-max-increase.json +32 -0
  22. package/examples/line-chart-nonnumeric.json +32 -0
  23. package/examples/line-chart.json +21 -63
  24. package/examples/newdata.json +1 -1
  25. package/examples/planet-combo-example-config.json +143 -20
  26. package/examples/planet-deviation-config.json +168 -0
  27. package/examples/planet-deviation-data.json +38 -0
  28. package/examples/planet-example-config.json +139 -20
  29. package/examples/planet-example-data-max-increase.json +56 -0
  30. package/examples/planet-example-data-nonnumeric.json +56 -0
  31. package/examples/planet-example-data.json +9 -9
  32. package/examples/planet-pie-example-config-nonnumeric.json +30 -0
  33. package/examples/scatterplot-continuous.csv +17 -0
  34. package/examples/scatterplot.json +136 -0
  35. package/examples/sparkline-chart-nonnumeric.json +76 -0
  36. package/examples/stacked-vertical-bar-example-negative.json +154 -0
  37. package/examples/stacked-vertical-bar-example-nonnumerics.json +154 -0
  38. package/index.html +91 -0
  39. package/package.json +33 -24
  40. package/src/{CdcChart.tsx → CdcChart.jsx} +196 -124
  41. package/src/components/AreaChart.jsx +198 -0
  42. package/src/components/{BarChart.tsx → BarChart.jsx} +154 -122
  43. package/src/components/BoxPlot.jsx +101 -0
  44. package/src/components/{DataTable.tsx → DataTable.jsx} +109 -28
  45. package/src/components/DeviationBar.jsx +191 -0
  46. package/src/components/{EditorPanel.js → EditorPanel.jsx} +676 -157
  47. package/src/components/{Filters.js → Filters.jsx} +6 -11
  48. package/src/components/Legend.jsx +316 -0
  49. package/src/components/{LineChart.tsx → LineChart.jsx} +22 -26
  50. package/src/components/{LinearChart.tsx → LinearChart.jsx} +214 -91
  51. package/src/components/{PairedBarChart.tsx → PairedBarChart.jsx} +44 -78
  52. package/src/components/{PieChart.tsx → PieChart.jsx} +26 -44
  53. package/src/components/ScatterPlot.jsx +51 -0
  54. package/src/components/SparkLine.jsx +218 -0
  55. package/src/components/{useIntersectionObserver.tsx → useIntersectionObserver.jsx} +2 -2
  56. package/src/data/initial-state.js +51 -5
  57. package/src/hooks/useColorPalette.js +68 -0
  58. package/src/hooks/{useReduceData.ts → useReduceData.js} +26 -16
  59. package/src/hooks/useRightAxis.js +3 -1
  60. package/src/index.jsx +16 -0
  61. package/src/scss/DataTable.scss +22 -0
  62. package/src/scss/editor-panel.scss +5 -0
  63. package/src/scss/main.scss +30 -10
  64. package/src/test/CdcChart.test.jsx +6 -0
  65. package/vite.config.js +4 -0
  66. package/dist/495.js +0 -3
  67. package/dist/703.js +0 -1
  68. package/src/components/BoxPlot.js +0 -92
  69. package/src/components/Legend.js +0 -291
  70. package/src/components/SparkLine.js +0 -185
  71. package/src/hooks/useColorPalette.ts +0 -76
  72. package/src/index.html +0 -67
  73. package/src/index.tsx +0 -18
  74. /package/src/{context.tsx → ConfigContext.jsx} +0 -0
@@ -1,11 +1,11 @@
1
1
  import React, { useState, useEffect, useCallback, memo, useContext } from 'react'
2
- import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd'
2
+ import { DragDropContext, Droppable, Draggable } from '@hello-pangea/dnd'
3
3
 
4
4
  import { Accordion, AccordionItem, AccordionItemHeading, AccordionItemPanel, AccordionItemButton } from 'react-accessible-accordion'
5
5
 
6
6
  import { useDebounce } from 'use-debounce'
7
7
 
8
- import Context from '../context'
8
+ import ConfigContext from '../ConfigContext'
9
9
  import WarningImage from '../images/warning.svg'
10
10
  import AdvancedEditor from '@cdc/core/components/AdvancedEditor'
11
11
 
@@ -17,12 +17,9 @@ import Tooltip from '@cdc/core/components/ui/Tooltip'
17
17
  import Icon from '@cdc/core/components/ui/Icon'
18
18
  import useReduceData from '../hooks/useReduceData'
19
19
  import useRightAxis from '../hooks/useRightAxis'
20
-
21
- // TODO: Remove unused imports
22
- // TDOO: Move inline styles to a scss file
20
+ import * as allCurves from '@visx/curve'
23
21
 
24
22
  /* eslint-disable react-hooks/rules-of-hooks */
25
-
26
23
  const TextField = memo(({ label, tooltip, section = null, subsection = null, fieldName, updateField, value: stateValue, type = 'input', i = null, min = null, ...attributes }) => {
27
24
  const [value, setValue] = useState(stateValue)
28
25
 
@@ -79,7 +76,7 @@ const CheckBox = memo(({ label, value, fieldName, section = null, subsection = n
79
76
  type='checkbox'
80
77
  name={fieldName}
81
78
  checked={value}
82
- onChange={() => {
79
+ onChange={e => {
83
80
  updateField(section, subsection, fieldName, !value)
84
81
  }}
85
82
  {...attributes}
@@ -209,17 +206,11 @@ const Regions = memo(({ config, updateConfig }) => {
209
206
  const headerColors = ['theme-blue', 'theme-purple', 'theme-brown', 'theme-teal', 'theme-pink', 'theme-orange', 'theme-slate', 'theme-indigo', 'theme-cyan', 'theme-green', 'theme-amber']
210
207
 
211
208
  const EditorPanel = () => {
212
- const { config, updateConfig, transformedData: data, loading, colorPalettes, unfilteredData, excludedData, isDashboard, setParentConfig, missingRequiredSections } = useContext(Context)
209
+ const { config, updateConfig, transformedData: data, loading, colorPalettes, twoColorPalette, unfilteredData, excludedData, isDashboard, setParentConfig, missingRequiredSections } = useContext(ConfigContext)
213
210
 
214
211
  const { minValue, maxValue, existPositiveValue, isAllLine } = useReduceData(config, unfilteredData)
215
- const { paletteName, isPaletteReversed, filteredPallets, filteredQualitative, dispatch } = useColorPalette(colorPalettes, config)
216
- useEffect(() => {
217
- if (paletteName) updateConfig({ ...config, palette: paletteName })
218
- }, [paletteName]) // eslint-disable-line
219
212
 
220
- useEffect(() => {
221
- dispatch({ type: 'GET_PALETTE', payload: colorPalettes, paletteName: config.palette })
222
- }, [dispatch, config.palette]) // eslint-disable-line
213
+ const { twoColorPalettes, sequential, nonSequential } = useColorPalette(config, updateConfig)
223
214
 
224
215
  // when the visualization type changes we
225
216
  // have to update the individual series type & axis details
@@ -243,6 +234,19 @@ const EditorPanel = () => {
243
234
  })
244
235
  }, [config.visualizationType]) // eslint-disable-line
245
236
 
237
+ // Scatter Plots default date/category axis is 'continuous'
238
+ useEffect(() => {
239
+ if (config.visualizationType === 'Scatter Plot') {
240
+ updateConfig({
241
+ ...config,
242
+ xAxis: {
243
+ ...config.xAxis,
244
+ type: 'continuous'
245
+ }
246
+ })
247
+ }
248
+ }, [])
249
+
246
250
  const { hasRightAxis } = useRightAxis({ config: config, yMax: config.yAxis.size, data: config.data, updateConfig })
247
251
 
248
252
  const filterOptions = [
@@ -287,15 +291,43 @@ const EditorPanel = () => {
287
291
  if (updatedConfig.table.show === undefined) {
288
292
  updatedConfig.table.show = !isDashboard
289
293
  }
294
+ // DEV-3293 - Force combo to always be vertical
295
+ if (updatedConfig.visualizationType === 'Combo') {
296
+ updatedConfig.orientation = 'vertical'
297
+ }
290
298
  }
291
299
 
292
300
  const updateField = (section, subsection, fieldName, newValue) => {
293
- // Top level
301
+ if (section === 'boxplot' && subsection === 'legend') {
302
+ updateConfig({
303
+ ...config,
304
+ [section]: {
305
+ ...config[section],
306
+ [subsection]: {
307
+ ...config.boxplot[subsection],
308
+ [fieldName]: newValue
309
+ }
310
+ }
311
+ })
312
+ return
313
+ }
314
+
315
+ if (section === 'boxplot' && subsection === 'labels') {
316
+ updateConfig({
317
+ ...config,
318
+ [section]: {
319
+ ...config[section],
320
+ [subsection]: {
321
+ ...config.boxplot[subsection],
322
+ [fieldName]: newValue
323
+ }
324
+ }
325
+ })
326
+ return
327
+ }
294
328
  if (null === section && null === subsection) {
295
329
  let updatedConfig = { ...config, [fieldName]: newValue }
296
-
297
330
  enforceRestrictions(updatedConfig)
298
-
299
331
  updateConfig(updatedConfig)
300
332
  return
301
333
  }
@@ -328,6 +360,19 @@ const EditorPanel = () => {
328
360
  return null
329
361
  }
330
362
 
363
+ useEffect(() => {
364
+ if (!config.general?.boxplot) return
365
+ if (!config.general.boxplot.firstQuartilePercentage) {
366
+ updateConfig({
367
+ ...config,
368
+ boxplot: {
369
+ ...config.boxplot,
370
+ firstQuartilePercentage: 25
371
+ }
372
+ })
373
+ }
374
+ }, [config])
375
+
331
376
  const setLollipopShape = shape => {
332
377
  updateConfig({
333
378
  ...config,
@@ -361,7 +406,7 @@ const EditorPanel = () => {
361
406
 
362
407
  const addNewSeries = seriesKey => {
363
408
  let newSeries = config.series ? [...config.series] : []
364
- newSeries.push({ dataKey: seriesKey, type: 'Bar' })
409
+ newSeries.push({ dataKey: seriesKey, type: config.visualizationType })
365
410
  updateConfig({ ...config, series: newSeries }) // left axis series keys
366
411
  }
367
412
 
@@ -481,7 +526,7 @@ const EditorPanel = () => {
481
526
  }
482
527
 
483
528
  const showBarStyleOptions = () => {
484
- if (config.visualizationType === 'Bar' && config.visualizationSubType !== 'stacked' && (config.orientation === 'horizontal' || config.orientation === 'vertical')) {
529
+ if ((config.visualizationType === 'Bar' || config.visualizationType === 'Deviation Bar') && config.visualizationSubType !== 'stacked' && (config.orientation === 'horizontal' || config.orientation === 'vertical')) {
485
530
  return ['flat', 'rounded', 'lollipop']
486
531
  } else {
487
532
  return ['flat', 'rounded']
@@ -565,6 +610,13 @@ const EditorPanel = () => {
565
610
  }
566
611
  }, [config.isLollipopChart, config.lollipopShape]) // eslint-disable-line
567
612
 
613
+ /// temporary force orientation untill we support Vartical deviaton bar
614
+ useEffect(() => {
615
+ if (config.visualizationType === 'Deviation Bar') {
616
+ updateConfig({ ...config, orientation: 'horizontal' })
617
+ }
618
+ }, [config.visualizationType])
619
+
568
620
  const ExclusionsList = useCallback(() => {
569
621
  const exclusions = [...config.exclusions.keys]
570
622
  return (
@@ -602,6 +654,63 @@ const EditorPanel = () => {
602
654
  updateConfig({ ...config, filters })
603
655
  }
604
656
 
657
+ const visHasLegend = () => {
658
+ const { visualizationType } = config
659
+
660
+ switch (visualizationType) {
661
+ case 'Box Plot':
662
+ return false
663
+ default:
664
+ return true
665
+ }
666
+ }
667
+
668
+ const visCanAnimate = () => {
669
+ const { visualizationType } = config
670
+ switch (visualizationType) {
671
+ case 'Scatter Plot':
672
+ return false
673
+ case 'Box Plot':
674
+ return false
675
+ default:
676
+ return true
677
+ }
678
+ }
679
+
680
+ const visHasDataCutoff = () => {
681
+ const { visualizationType } = config
682
+ switch (visualizationType) {
683
+ case 'Box Plot':
684
+ return false
685
+ case 'Pie':
686
+ return false
687
+ default:
688
+ return true
689
+ }
690
+ }
691
+
692
+ const visHasLabelOnData = () => {
693
+ const { visualizationType } = config
694
+ switch (visualizationType) {
695
+ case 'Box Plot':
696
+ return false
697
+ case 'Pie':
698
+ return false
699
+ case 'Scatter Plot':
700
+ return false
701
+ default:
702
+ return true
703
+ }
704
+ }
705
+
706
+ const visHasBarBorders = () => {
707
+ const { series, visualizationType } = config
708
+ if (visualizationType === 'Box Plot') return false
709
+ if (visualizationType === 'Scatter Plot') return false
710
+ if (visualizationType === 'Pie') return false
711
+ return series?.some(series => series.type === 'Bar' || series.type === 'Paired Bar' || series.type === 'Deviation Bar')
712
+ }
713
+
605
714
  const handleSeriesChange = (idx1, idx2) => {
606
715
  let seriesOrder = config.series
607
716
  let [movedItem] = seriesOrder.splice(idx1, 1)
@@ -651,7 +760,7 @@ const EditorPanel = () => {
651
760
  case config.visualizationType === 'Combo' && isAllLine && enteredValue && parseFloat(enteredValue) > minVal:
652
761
  message = 'Value must be less than ' + minValue
653
762
  break
654
- case (config.visualizationType === 'Bar' || (config.visualizationType === 'Combo' && !isAllLine)) && enteredValue && minVal > 0 && parseFloat(enteredValue) > 0:
763
+ case (config.visualizationType === 'Bar' || config.visualizationType === 'Deviation Bar' || (config.visualizationType === 'Combo' && !isAllLine)) && enteredValue && minVal > 0 && parseFloat(enteredValue) > 0:
655
764
  message = 'Value must be less than or equal to 0'
656
765
  break
657
766
  case enteredValue && minVal < 0 && parseFloat(enteredValue) > minVal:
@@ -669,6 +778,19 @@ const EditorPanel = () => {
669
778
  validateMaxValue()
670
779
  }, [minValue, maxValue, config]) // eslint-disable-line
671
780
 
781
+ const enabledChartTypes = [
782
+ 'Pie',
783
+ 'Line',
784
+ 'Bar',
785
+ 'Combo',
786
+ 'Paired Bar',
787
+ 'Spark Line',
788
+ // 'Area Chart',
789
+ 'Scatter Plot',
790
+ 'Box Plot',
791
+ 'Deviation Bar'
792
+ ]
793
+
672
794
  return (
673
795
  <ErrorBoundary component='EditorPanel'>
674
796
  {config.newViz && <Confirm />}
@@ -688,21 +810,44 @@ const EditorPanel = () => {
688
810
  <AccordionItemButton>General</AccordionItemButton>
689
811
  </AccordionItemHeading>
690
812
  <AccordionItemPanel>
691
- <Select value={config.visualizationType} fieldName='visualizationType' label='Chart Type' updateField={updateField} options={['Pie', 'Line', 'Bar', 'Combo', 'Paired Bar', 'Spark Line']} />
813
+ <Select value={config.visualizationType} fieldName='visualizationType' label='Chart Type' updateField={updateField} options={enabledChartTypes} />
692
814
  {(config.visualizationType === 'Bar' || config.visualizationType === 'Combo') && <Select value={config.visualizationSubType || 'Regular'} fieldName='visualizationSubType' label='Chart Subtype' updateField={updateField} options={['regular', 'stacked']} />}
693
815
  {config.visualizationType === 'Bar' && <Select value={config.orientation || 'vertical'} fieldName='orientation' label='Orientation' updateField={updateField} options={['vertical', 'horizontal']} />}
694
- {config.visualizationType === 'Bar' && <Select value={config.isLollipopChart ? 'lollipop' : config.barStyle || 'flat'} fieldName='barStyle' label='bar style' updateField={updateField} options={showBarStyleOptions()} />}
695
- {config.visualizationType === 'Bar' && config.barStyle === 'rounded' && <Select value={config.tipRounding || 'top'} fieldName='tipRounding' label='tip rounding' updateField={updateField} options={['top', 'full']} />}
696
- {config.visualizationType === 'Bar' && config.barStyle === 'rounded' && <Select value={config.roundingStyle || 'standard'} fieldName='roundingStyle' label='rounding style' updateField={updateField} options={['standard', 'shallow', 'finger']} />}
816
+ {config.visualizationType === 'Deviation Bar' && <Select label='Orientation' options={['horizontal']} />}
817
+ {(config.visualizationType === 'Bar' || config.visualizationType === 'Deviation Bar') && <Select value={config.isLollipopChart ? 'lollipop' : config.barStyle || 'flat'} fieldName='barStyle' label='bar style' updateField={updateField} options={showBarStyleOptions()} />}
818
+ {(config.visualizationType === 'Bar' || config.visualizationType === 'Deviation Bar') && config.barStyle === 'rounded' && <Select value={config.tipRounding || 'top'} fieldName='tipRounding' label='tip rounding' updateField={updateField} options={['top', 'full']} />}
819
+ {(config.visualizationType === 'Bar' || config.visualizationType === 'Deviation Bar') && config.barStyle === 'rounded' && (
820
+ <Select value={config.roundingStyle || 'standard'} fieldName='roundingStyle' label='rounding style' updateField={updateField} options={['standard', 'shallow', 'finger']} />
821
+ )}
697
822
  {config.visualizationType === 'Bar' && config.orientation === 'horizontal' && <Select value={config.yAxis.labelPlacement || 'Below Bar'} section='yAxis' fieldName='labelPlacement' label='Label Placement' updateField={updateField} options={['Below Bar', 'On Date/Category Axis']} />}
698
- {config.orientation === 'horizontal' && (config.yAxis.labelPlacement === 'Below Bar' || config.yAxis.labelPlacement === 'On Date/Category Axis' || config.visualizationType === 'Paired Bar') ? (
823
+ {config.orientation === 'horizontal' && (config.yAxis.labelPlacement === 'Below Bar' || config.yAxis.labelPlacement === 'On Date/Category Axis' || config.visualizationType === 'Paired Bar' || config.visualizationType === 'Deviation Bar') ? (
699
824
  <CheckBox value={config.yAxis.displayNumbersOnBar} section='yAxis' fieldName='displayNumbersOnBar' label={config.isLollipopChart ? 'Display Numbers after Bar' : 'Display Numbers on Bar'} updateField={updateField} />
700
825
  ) : (
701
- config.visualizationType !== 'Pie' && <CheckBox value={config.labels} fieldName='labels' label='Display label on data' updateField={updateField} />
826
+ visHasLabelOnData() && <CheckBox value={config.labels} fieldName='labels' label='Display label on data' updateField={updateField} />
702
827
  )}
703
828
  {config.visualizationType === 'Pie' && <Select fieldName='pieType' label='Pie Chart Type' updateField={updateField} options={['Regular', 'Donut']} />}
704
829
 
705
- <TextField value={config.title} fieldName='title' label='Title' updateField={updateField} />
830
+ <TextField
831
+ value={config.title || 'Chart Title'}
832
+ fieldName='title'
833
+ id='title'
834
+ label='Title'
835
+ placeholder='Chart Title'
836
+ //defaultValue='Chart Title'
837
+ updateField={updateField}
838
+ //onChange={handleTitleChange}
839
+ tooltip={
840
+ <Tooltip style={{ textTransform: 'none' }}>
841
+ <Tooltip.Target>
842
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
843
+ </Tooltip.Target>
844
+ <Tooltip.Content>
845
+ <p>Title is required to set the name of the download file but can be hidden using the option below.</p>
846
+ </Tooltip.Content>
847
+ </Tooltip>
848
+ }
849
+ />
850
+ <CheckBox value={config.showTitle} fieldName='showTitle' label='Show Title' updateField={updateField} />
706
851
  <TextField
707
852
  value={config.superTitle}
708
853
  updateField={updateField}
@@ -806,7 +951,7 @@ const EditorPanel = () => {
806
951
  {provided => (
807
952
  <ul {...provided.droppableProps} className='series-list' ref={provided.innerRef} style={{ marginTop: '1em' }}>
808
953
  {config.series.map((series, i) => {
809
- if (config.visualizationType === 'Combo') {
954
+ if (config.visualizationType === 'Combo' || 'Area Chart') {
810
955
  let changeType = (i, value) => {
811
956
  let series = [...config.series]
812
957
  series[i].type = value
@@ -816,6 +961,12 @@ const EditorPanel = () => {
816
961
  updateConfig({ ...config, series })
817
962
  }
818
963
 
964
+ let changeLineType = (i, value) => {
965
+ let series = [...config.series]
966
+ series[i].lineType = value
967
+ updateConfig({ ...config, series })
968
+ }
969
+
819
970
  let typeDropdown = (
820
971
  <select
821
972
  value={series.type}
@@ -823,33 +974,69 @@ const EditorPanel = () => {
823
974
  changeType(i, event.target.value)
824
975
  }}
825
976
  style={{ width: '100px', marginRight: '10px' }}
977
+ >
978
+ <option value='' default key='default'>
979
+ Select
980
+ </option>
981
+ {config.visualizationType === 'Combo' && <option value='Bar'>Bar</option>}
982
+ <option value='Line' key='Line'>
983
+ Solid Line
984
+ </option>
985
+ <option value='dashed-sm' key='dashed-sm'>
986
+ Small Dashed
987
+ </option>
988
+ <option value='dashed-md' key='dashed-md'>
989
+ Medium Dashed
990
+ </option>
991
+ <option value='dashed-lg' key='dashed-lg'>
992
+ Large Dashed
993
+ </option>
994
+ </select>
995
+ )
996
+
997
+ const lineType = (
998
+ <select
999
+ value={series.lineStyle}
1000
+ onChange={event => {
1001
+ changeLineType(i, event.target.value)
1002
+ }}
1003
+ style={{ width: '100px', marginRight: '10px' }}
1004
+ key='lineTypeSelection'
826
1005
  >
827
1006
  <option value='' default>
828
1007
  Select
829
1008
  </option>
830
- <option value='Bar'>Bar</option>
831
- <option value='Line'>Solid Line</option>
832
- <option value='dashed-sm'>Small Dashed</option>
833
- <option value='dashed-md'>Medium Dashed</option>
834
- <option value='dashed-lg'>Large Dashed</option>
1009
+
1010
+ {Object.keys(allCurves).map(curveName => (
1011
+ <option key={`curve-option-${curveName}`} value={curveName}>
1012
+ {curveName}
1013
+ </option>
1014
+ ))}
835
1015
  </select>
836
1016
  )
837
1017
 
838
1018
  return (
839
1019
  <Draggable key={series.dataKey} draggableId={`draggableFilter-${series.dataKey}`} index={i}>
840
1020
  {(provided, snapshot) => (
841
- <li>
1021
+ <li key={i}>
842
1022
  <div className={snapshot.isDragging ? 'currently-dragging' : ''} style={getItemStyle(snapshot.isDragging, provided.draggableProps.style, sortableItemStyles)} ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}>
843
1023
  <div className={`series-list__name${series.dataKey.length > 15 ? ' series-list__name--truncate' : ''}`} data-title={series.dataKey}>
844
1024
  <div className='series-list__name-text'>{series.dataKey}</div>
845
1025
  </div>
846
1026
  <span>
847
- <span className='series-list__dropdown'>{typeDropdown}</span>
848
- {config.series && config.series.length > 1 && (
849
- <button className='series-list__remove' onClick={() => removeSeries(series.dataKey)}>
850
- &#215;
851
- </button>
852
- )}
1027
+ <>
1028
+ {(config.visualizationType === 'Combo' || config.visualizationType === 'Area Chart') && (
1029
+ <>
1030
+ <span className='series-list__dropdown'>{typeDropdown}</span>
1031
+ {config.visualizationType === 'Area Chart' && <span className='series-list__dropdown series-list__dropdown--lineType'>{lineType}</span>}
1032
+ </>
1033
+ )}
1034
+ {config.series && config.series.length > 1 && (
1035
+ <button className='series-list__remove' onClick={() => removeSeries(series.dataKey)}>
1036
+ &#215;
1037
+ </button>
1038
+ )}
1039
+ </>
853
1040
  </span>
854
1041
  </div>
855
1042
  </li>
@@ -859,7 +1046,7 @@ const EditorPanel = () => {
859
1046
  }
860
1047
 
861
1048
  return (
862
- <Draggable key={series.dataKey} draggableId={`draggableFilter-${series.dataKey}`} index={i}>
1049
+ <Draggable key={`series.dataKey--${i}`} draggableId={`draggableFilter-${series.dataKey}`} index={i}>
863
1050
  {(provided, snapshot) => (
864
1051
  <li
865
1052
  key={series.dataKey}
@@ -904,6 +1091,7 @@ const EditorPanel = () => {
904
1091
  }}
905
1092
  options={getColumns()}
906
1093
  />
1094
+
907
1095
  {config.series && config.series.length <= 1 && config.visualizationType === 'Bar' && (
908
1096
  <>
909
1097
  <span className='divider-heading'>Confidence Keys</span>
@@ -917,6 +1105,183 @@ const EditorPanel = () => {
917
1105
  </AccordionItem>
918
1106
  )}
919
1107
 
1108
+ {config.visualizationType === 'Box Plot' && (
1109
+ <AccordionItem>
1110
+ <AccordionItemHeading>
1111
+ <AccordionItemButton>Measures</AccordionItemButton>
1112
+ </AccordionItemHeading>
1113
+ <AccordionItemPanel>
1114
+ <h4 style={{ fontSize: '18px' }}>Labels for 5-Number Summary</h4>
1115
+
1116
+ {/* prettier-ignore */}
1117
+ {/* max */}
1118
+ <TextField
1119
+ type='text'
1120
+ value={config.boxplot.labels.maximum}
1121
+ fieldName='maximum'
1122
+ section='boxplot'
1123
+ subsection='labels'
1124
+ label='Maximum'
1125
+ updateField={updateField}
1126
+ tooltip={
1127
+ <Tooltip style={{ textTransform: 'none' }}>
1128
+ <Tooltip.Target>
1129
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1130
+ </Tooltip.Target>
1131
+ <Tooltip.Content>
1132
+ <p>Highest value, excluding outliers</p>
1133
+ </Tooltip.Content>
1134
+ </Tooltip>
1135
+ }
1136
+ />
1137
+
1138
+ {/* prettier-ignore */}
1139
+ {/* Q3 */}
1140
+ <TextField
1141
+ type='text'
1142
+ value={config.boxplot.labels.q3}
1143
+ fieldName='q3'
1144
+ section='boxplot'
1145
+ subsection='labels'
1146
+ label='Upper Quartile'
1147
+ updateField={updateField}
1148
+ tooltip={
1149
+ <Tooltip style={{ textTransform: 'none' }}>
1150
+ <Tooltip.Target>
1151
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1152
+ </Tooltip.Target>
1153
+ <Tooltip.Content>
1154
+ <p>Represented by top line of box. 25% of data are higher.</p>
1155
+ </Tooltip.Content>
1156
+ </Tooltip>
1157
+ }
1158
+ />
1159
+
1160
+ {/* prettier-ignore */}
1161
+ {/* median */}
1162
+ <TextField
1163
+ type='text'
1164
+ value={config.boxplot.labels.median}
1165
+ fieldName='median'
1166
+ section='boxplot'
1167
+ subsection='labels'
1168
+ label='Median'
1169
+ updateField={updateField}
1170
+ tooltip={
1171
+ <Tooltip style={{ textTransform: 'none' }}>
1172
+ <Tooltip.Target>
1173
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1174
+ </Tooltip.Target>
1175
+ <Tooltip.Content>
1176
+ <p>Middle data point. Half of data are higher value.</p>
1177
+ </Tooltip.Content>
1178
+ </Tooltip>
1179
+ }
1180
+ />
1181
+
1182
+ {/* prettier-ignore */}
1183
+ {/* q1 */}
1184
+ <TextField
1185
+ type='text'
1186
+ value={config.boxplot.labels.q1}
1187
+ fieldName='q1'
1188
+ section='boxplot'
1189
+ subsection='labels'
1190
+ label='Lower Quartile'
1191
+ updateField={updateField}
1192
+ tooltip={
1193
+ <Tooltip style={{ textTransform: 'none' }}>
1194
+ <Tooltip.Target>
1195
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1196
+ </Tooltip.Target>
1197
+ <Tooltip.Content>
1198
+ <p>Represented by bottom line of box. 25% of data are lower.</p>
1199
+ </Tooltip.Content>
1200
+ </Tooltip>
1201
+ }
1202
+ />
1203
+
1204
+ {/* prettier-ignore */}
1205
+ {/* minimum */}
1206
+ <TextField
1207
+ type='text'
1208
+ value={config.boxplot.labels.minimum}
1209
+ fieldName='minimum'
1210
+ section='boxplot'
1211
+ subsection='labels'
1212
+ label='Minimum'
1213
+ updateField={updateField}
1214
+ tooltip={
1215
+ <Tooltip style={{ textTransform: 'none' }}>
1216
+ <Tooltip.Target>
1217
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1218
+ </Tooltip.Target>
1219
+ <Tooltip.Content>
1220
+ <p>Lowest value, excluding outliers</p>
1221
+ </Tooltip.Content>
1222
+ </Tooltip>
1223
+ }
1224
+ />
1225
+ <br />
1226
+ <h4 style={{ fontSize: '18px' }}>Labels for Additional Measures</h4>
1227
+
1228
+ {/* iqr */}
1229
+ <TextField type='text' value={config.boxplot.labels.iqr} fieldName='iqr' section='boxplot' subsection='labels' label='Interquartile Range' updateField={updateField} />
1230
+
1231
+ {/* count */}
1232
+ <TextField type='text' value={config.boxplot.labels.total} fieldName='total' section='boxplot' subsection='labels' label='Total' updateField={updateField} />
1233
+
1234
+ {/* mean */}
1235
+ <TextField type='text' value={config.boxplot.labels.mean} fieldName='mean' section='boxplot' subsection='labels' label='Mean' updateField={updateField} />
1236
+ {/* outliers */}
1237
+ <TextField type='text' value={config.boxplot.labels.outliers} fieldName='outliers' section='boxplot' subsection='labels' label='Outliers' updateField={updateField} />
1238
+ {/* values */}
1239
+ <TextField type='text' value={config.boxplot.labels.values} fieldName='values' section='boxplot' subsection='labels' label='Values' updateField={updateField} />
1240
+ <br />
1241
+ <h4 style={{ fontSize: '18px' }}>Percentages for Quartiles</h4>
1242
+ <TextField
1243
+ type='number'
1244
+ value={config.boxplot.firstQuartilePercentage ? config.boxplot.firstQuartilePercentage : 25}
1245
+ fieldName='firstQuartilePercentage'
1246
+ section='boxplot'
1247
+ label='Lower Quartile'
1248
+ max={100}
1249
+ updateField={updateField}
1250
+ tooltip={
1251
+ <Tooltip style={{ textTransform: 'none' }}>
1252
+ <Tooltip.Target>
1253
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1254
+ </Tooltip.Target>
1255
+ <Tooltip.Content>
1256
+ <p>Represented by bottom line of box. 25% of data are lower.</p>
1257
+ </Tooltip.Content>
1258
+ </Tooltip>
1259
+ }
1260
+ />
1261
+
1262
+ <TextField
1263
+ type='number'
1264
+ value={config.boxplot.thirdQuartilePercentage ? config.boxplot.thirdQuartilePercentage : 75}
1265
+ fieldName='thirdQuartilePercentage'
1266
+ label='Upper Quartile'
1267
+ section='boxplot'
1268
+ max={100}
1269
+ updateField={updateField}
1270
+ tooltip={
1271
+ <Tooltip style={{ textTransform: 'none' }}>
1272
+ <Tooltip.Target>
1273
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1274
+ </Tooltip.Target>
1275
+ <Tooltip.Content>
1276
+ <p>Represented by top line of box. 25% of data are higher.</p>
1277
+ </Tooltip.Content>
1278
+ </Tooltip>
1279
+ }
1280
+ />
1281
+ </AccordionItemPanel>
1282
+ </AccordionItem>
1283
+ )}
1284
+
920
1285
  {hasRightAxis && config.series && config.visualizationType === 'Combo' && (
921
1286
  <AccordionItem>
922
1287
  <AccordionItemHeading>
@@ -956,10 +1321,12 @@ const EditorPanel = () => {
956
1321
  }}
957
1322
  style={{ width: '100px', marginRight: '10px' }}
958
1323
  >
959
- <option value='Left' default>
1324
+ <option value='Left' default key='left'>
960
1325
  left
961
1326
  </option>
962
- <option value='Right'>right</option>
1327
+ <option value='Right' key='right'>
1328
+ right
1329
+ </option>
963
1330
  </select>
964
1331
  )
965
1332
 
@@ -1014,8 +1381,9 @@ const EditorPanel = () => {
1014
1381
  {config.visualizationType !== 'Pie' && (
1015
1382
  <>
1016
1383
  <TextField value={config.yAxis.label} section='yAxis' fieldName='label' label='Label' updateField={updateField} />
1017
- {config.runtime.seriesKeys && config.runtime.seriesKeys.length === 1 && <CheckBox value={config.isLegendValue} fieldName='isLegendValue' label='Use Legend Value in Hover' updateField={updateField} />}
1384
+ {config.runtime.seriesKeys && config.runtime.seriesKeys.length === 1 && config.visualizationType !== 'Box Plot' && <CheckBox value={config.isLegendValue} fieldName='isLegendValue' label='Use Legend Value in Hover' updateField={updateField} />}
1018
1385
  <TextField value={config.yAxis.numTicks} placeholder='Auto' type='number' section='yAxis' fieldName='numTicks' label='Number of ticks' className='number-narrow' updateField={updateField} />
1386
+ {config.visualizationType === 'Paired Bar' && <TextField value={config.yAxis.tickRotation || 0} type='number' min='0' section='yAxis' fieldName='tickRotation' label='Tick rotation (Degrees)' className='number-narrow' updateField={updateField} />}
1019
1387
  <TextField
1020
1388
  value={config.yAxis.size}
1021
1389
  type='number'
@@ -1035,8 +1403,11 @@ const EditorPanel = () => {
1035
1403
  </Tooltip>
1036
1404
  }
1037
1405
  />
1406
+ {/* Hiding this for now, not interested in moving the axis lines away from chart comp. right now. */}
1407
+ {/* <TextField value={config.yAxis.axisPadding} type='number' max={10} min={0} section='yAxis' fieldName='axisPadding' label={'Axis Padding'} className='number-narrow' updateField={updateField} /> */}
1038
1408
  {config.orientation === 'horizontal' && <TextField value={config.xAxis.labelOffset} section='xAxis' fieldName='labelOffset' label='Label offset' type='number' className='number-narrow' updateField={updateField} />}
1039
1409
  {config.orientation !== 'horizontal' && <CheckBox value={config.yAxis.gridLines} section='yAxis' fieldName='gridLines' label='Display Gridlines' updateField={updateField} />}
1410
+ <CheckBox value={config.yAxis.enablePadding} section='yAxis' fieldName='enablePadding' label='Add Padding to Value Axis Scale' updateField={updateField} />
1040
1411
  </>
1041
1412
  )}
1042
1413
  <span className='divider-heading'>Number Formatting</span>
@@ -1103,8 +1474,17 @@ const EditorPanel = () => {
1103
1474
  <CheckBox value={config.xAxis.hideAxis} section='xAxis' fieldName='hideAxis' label='Hide Axis' updateField={updateField} />
1104
1475
  <CheckBox value={config.xAxis.hideLabel} section='xAxis' fieldName='hideLabel' label='Hide Label' updateField={updateField} />
1105
1476
  <CheckBox value={config.xAxis.hideTicks} section='xAxis' fieldName='hideTicks' label='Hide Ticks' updateField={updateField} />
1106
- <TextField value={config.xAxis.max} section='xAxis' fieldName='max' label='update max value' type='number' placeholder='Auto' updateField={updateField} />
1477
+ <TextField value={config.xAxis.max} section='xAxis' fieldName='max' label='max value' type='number' placeholder='Auto' updateField={updateField} />
1107
1478
  <span style={{ color: 'red', display: 'block' }}>{warningMsg.maxMsg}</span>
1479
+ {config.visualizationType === 'Deviation Bar' && (
1480
+ <>
1481
+ <TextField value={config.xAxis.min} section='xAxis' fieldName='min' type='number' label='min value' placeholder='Auto' updateField={updateField} />
1482
+ <span style={{ color: 'red', display: 'block' }}>{warningMsg.minMsg}</span>
1483
+ <TextField value={config.xAxis.target} section='xAxis' fieldName='target' type='number' label='Deviation point' placeholder='Auto' updateField={updateField} />
1484
+ <TextField value={config.xAxis.targetLabel || 'Target'} section='xAxis' fieldName='targetLabel' type='text' label='Deviation point Label' updateField={updateField} />
1485
+ <CheckBox value={config.xAxis.showTargetLabel} section='xAxis' fieldName='showTargetLabel' label='Display Deviation point label' updateField={updateField} />
1486
+ </>
1487
+ )}
1108
1488
  </>
1109
1489
  ) : (
1110
1490
  config.visualizationType !== 'Pie' && (
@@ -1112,9 +1492,9 @@ const EditorPanel = () => {
1112
1492
  <CheckBox value={config.yAxis.hideAxis} section='yAxis' fieldName='hideAxis' label='Hide Axis' updateField={updateField} />
1113
1493
  <CheckBox value={config.yAxis.hideLabel} section='yAxis' fieldName='hideLabel' label='Hide Label' updateField={updateField} />
1114
1494
  <CheckBox value={config.yAxis.hideTicks} section='yAxis' fieldName='hideTicks' label='Hide Ticks' updateField={updateField} />
1115
- <TextField value={config.yAxis.max} section='yAxis' fieldName='max' type='number' label='update max value' placeholder='Auto' updateField={updateField} />
1495
+ <TextField value={config.yAxis.max} section='yAxis' fieldName='max' type='number' label='max value' placeholder='Auto' updateField={updateField} />
1116
1496
  <span style={{ color: 'red', display: 'block' }}>{warningMsg.maxMsg}</span>
1117
- <TextField value={config.yAxis.min} section='yAxis' fieldName='min' type='number' label='update min value' placeholder='Auto' updateField={updateField} />
1497
+ <TextField value={config.yAxis.min} section='yAxis' fieldName='min' type='number' label='min value' placeholder='Auto' updateField={updateField} />
1118
1498
  <span style={{ color: 'red', display: 'block' }}>{warningMsg.minMsg}</span>
1119
1499
  </>
1120
1500
  )
@@ -1193,7 +1573,7 @@ const EditorPanel = () => {
1193
1573
  <AccordionItemPanel>
1194
1574
  {config.visualizationType !== 'Pie' && (
1195
1575
  <>
1196
- <Select value={config.xAxis.type} section='xAxis' fieldName='type' label='Data Type' updateField={updateField} options={['categorical', 'date']} />
1576
+ <Select value={config.xAxis.type} section='xAxis' fieldName='type' label='Data Type' updateField={updateField} options={config.visualizationType !== 'Scatter Plot' ? ['categorical', 'date'] : ['categorical', 'continuous', 'date']} />
1197
1577
  <Select
1198
1578
  value={config.xAxis.dataKey || ''}
1199
1579
  section='xAxis'
@@ -1244,6 +1624,66 @@ const EditorPanel = () => {
1244
1624
  <>
1245
1625
  <TextField value={config.xAxis.label} section='xAxis' fieldName='label' label='Label' updateField={updateField} />
1246
1626
 
1627
+ {config.xAxis.type === 'continuous' && (
1628
+ <>
1629
+ <TextField
1630
+ value={config.dataFormat.bottomPrefix}
1631
+ section='dataFormat'
1632
+ fieldName='bottomPrefix'
1633
+ label='Prefix'
1634
+ updateField={updateField}
1635
+ tooltip={
1636
+ <Tooltip style={{ textTransform: 'none' }}>
1637
+ <Tooltip.Target>
1638
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1639
+ </Tooltip.Target>
1640
+ <Tooltip.Content>
1641
+ {config.visualizationType === 'Pie' && <p>Enter a data suffix to display in the data table and tooltips, if applicable.</p>}
1642
+ {config.visualizationType !== 'Pie' && <p>Enter a data suffix (such as "%"), if applicable.</p>}
1643
+ </Tooltip.Content>
1644
+ </Tooltip>
1645
+ }
1646
+ />
1647
+
1648
+ <TextField
1649
+ value={config.dataFormat.bottomSuffix}
1650
+ section='dataFormat'
1651
+ fieldName='bottomSuffix'
1652
+ label='Suffix'
1653
+ updateField={updateField}
1654
+ tooltip={
1655
+ <Tooltip style={{ textTransform: 'none' }}>
1656
+ <Tooltip.Target>
1657
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1658
+ </Tooltip.Target>
1659
+ <Tooltip.Content>
1660
+ {config.visualizationType === 'Pie' && <p>Enter a data suffix to display in the data table and tooltips, if applicable.</p>}
1661
+ {config.visualizationType !== 'Pie' && <p>Enter a data suffix (such as "%"), if applicable.</p>}
1662
+ </Tooltip.Content>
1663
+ </Tooltip>
1664
+ }
1665
+ />
1666
+
1667
+ <CheckBox
1668
+ value={config.dataFormat.bottomAbbreviated}
1669
+ section='dataFormat'
1670
+ fieldName='bottomAbbreviated'
1671
+ label='Abbreviate Axis Values'
1672
+ updateField={updateField}
1673
+ tooltip={
1674
+ <Tooltip style={{ textTransform: 'none' }}>
1675
+ <Tooltip.Target>
1676
+ <Icon display='question' />
1677
+ </Tooltip.Target>
1678
+ <Tooltip.Content>
1679
+ <p>{`This option abbreviates very large or very small numbers on the value axis`}</p>
1680
+ </Tooltip.Content>
1681
+ </Tooltip>
1682
+ }
1683
+ />
1684
+ </>
1685
+ )}
1686
+
1247
1687
  {config.xAxis.type === 'date' && (
1248
1688
  <>
1249
1689
  <p style={{ padding: '1.5em 0 0.5em', fontSize: '.9rem', lineHeight: '1rem' }}>
@@ -1316,6 +1756,16 @@ const EditorPanel = () => {
1316
1756
 
1317
1757
  <TextField value={config.xAxis.size} type='number' min='0' section='xAxis' fieldName='size' label={config.orientation === 'horizontal' ? 'Size (Width)' : 'Size (Height)'} className='number-narrow' updateField={updateField} />
1318
1758
 
1759
+ {/* Hiding this for now, not interested in moving the axis lines away from chart comp. right now. */}
1760
+ {/* <TextField value={config.xAxis.axisPadding} type='number' max={10} min={0} section='xAxis' fieldName='axisPadding' label={'Axis Padding'} className='number-narrow' updateField={updateField} /> */}
1761
+
1762
+ {config.xAxis.type === 'continuous' && (
1763
+ <>
1764
+ <CheckBox value={config.dataFormat.bottomCommas} section='dataFormat' fieldName='bottomCommas' label='Add commas' updateField={updateField} />
1765
+ <TextField value={config.dataFormat.bottomRoundTo} type='number' section='dataFormat' fieldName='bottomRoundTo' label='Round to decimal point' className='number-narrow' updateField={updateField} min={0} />
1766
+ </>
1767
+ )}
1768
+
1319
1769
  {config.yAxis.labelPlacement !== 'Below Bar' && <TextField value={config.xAxis.tickRotation} type='number' min='0' section='xAxis' fieldName='tickRotation' label='Tick rotation (Degrees)' className='number-narrow' updateField={updateField} />}
1320
1770
  {config.orientation === 'horizontal' ? (
1321
1771
  <>
@@ -1392,13 +1842,14 @@ const EditorPanel = () => {
1392
1842
  </AccordionItem>
1393
1843
  )}
1394
1844
 
1395
- <AccordionItem>
1396
- <AccordionItemHeading>
1397
- <AccordionItemButton>Legend</AccordionItemButton>
1398
- </AccordionItemHeading>
1399
- <AccordionItemPanel>
1400
- <CheckBox value={config.legend.reverseLabelOrder} section='legend' fieldName='reverseLabelOrder' label='Reverse Labels' updateField={updateField} />
1401
- {/* <fieldset className="checkbox-group">
1845
+ {visHasLegend() && (
1846
+ <AccordionItem>
1847
+ <AccordionItemHeading>
1848
+ <AccordionItemButton>Legend</AccordionItemButton>
1849
+ </AccordionItemHeading>
1850
+ <AccordionItemPanel>
1851
+ <CheckBox value={config.legend.reverseLabelOrder} section='legend' fieldName='reverseLabelOrder' label='Reverse Labels' updateField={updateField} />
1852
+ {/* <fieldset className="checkbox-group">
1402
1853
  <CheckBox value={config.legend.dynamicLegend} section="legend" fieldName="dynamicLegend" label="Dynamic Legend" updateField={updateField}/>
1403
1854
  {config.legend.dynamicLegend && (
1404
1855
  <>
@@ -1409,35 +1860,44 @@ const EditorPanel = () => {
1409
1860
  </>
1410
1861
  )}
1411
1862
  </fieldset> */}
1412
- <CheckBox
1413
- value={config.legend.hide}
1414
- section='legend'
1415
- fieldName='hide'
1416
- label='Hide Legend'
1417
- updateField={updateField}
1418
- tooltip={
1419
- <Tooltip style={{ textTransform: 'none' }}>
1420
- <Tooltip.Target>
1421
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1422
- </Tooltip.Target>
1423
- <Tooltip.Content>
1424
- <p>With a single-series chart, consider hiding the legend to reduce visual clutter.</p>
1425
- </Tooltip.Content>
1426
- </Tooltip>
1427
- }
1428
- />
1429
- <CheckBox value={config.legend.showLegendValuesTooltip} section='legend' fieldName='showLegendValuesTooltip' label='Show Legend Values in Tooltip' updateField={updateField} />
1863
+ <CheckBox
1864
+ value={config.legend.hide ? true : false}
1865
+ section='legend'
1866
+ fieldName='hide'
1867
+ label='Hide Legend'
1868
+ updateField={updateField}
1869
+ tooltip={
1870
+ <Tooltip style={{ textTransform: 'none' }}>
1871
+ <Tooltip.Target>
1872
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
1873
+ </Tooltip.Target>
1874
+ <Tooltip.Content>
1875
+ <p>With a single-series chart, consider hiding the legend to reduce visual clutter.</p>
1876
+ </Tooltip.Content>
1877
+ </Tooltip>
1878
+ }
1879
+ />
1430
1880
 
1431
- {config.visualizationType === 'Bar' && config.visualizationSubType === 'regular' && config.runtime.seriesKeys.length === 1 && (
1432
- <Select value={config.legend.colorCode} section='legend' fieldName='colorCode' label='Color code by category' initial='Select' updateField={updateField} options={getDataValueOptions(data)} />
1433
- )}
1434
- <Select value={config.legend.behavior} section='legend' fieldName='behavior' label='Legend Behavior (When clicked)' updateField={updateField} options={['highlight', 'isolate']} />
1435
- <TextField value={config.legend.label} section='legend' fieldName='label' label='Title' updateField={updateField} />
1436
- <Select value={config.legend.position} section='legend' fieldName='position' label='Position' updateField={updateField} options={['right', 'left', 'bottom']} />
1437
- {config.legend.position === 'bottom' && <CheckBox value={config.legend.singleRow} section='legend' fieldName='singleRow' label='Single Row Legend' updateField={updateField} />}
1438
- <TextField type='textarea' value={config.legend.description} updateField={updateField} section='legend' fieldName='description' label='Legend Description' />
1439
- </AccordionItemPanel>
1440
- </AccordionItem>
1881
+ {/* {config.visualizationType === 'Box Plot' &&
1882
+ <>
1883
+ <CheckBox value={config.boxplot.legend.displayHowToReadText} fieldName='displayHowToReadText' section='boxplot' subsection='legend' label='Display How To Read Text' updateField={updateField} />
1884
+ <TextField type='textarea' value={config.boxplot.legend.howToReadText} updateField={updateField} fieldName='howToReadText' section='boxplot' subsection='legend' label='How to read text' />
1885
+ </>
1886
+ } */}
1887
+
1888
+ {config.visualizationType !== 'Box Plot' && <CheckBox value={config.legend.showLegendValuesTooltip ? true : false} section='legend' fieldName='showLegendValuesTooltip' label='Show Legend Values in Tooltip' updateField={updateField} />}
1889
+
1890
+ {config.visualizationType === 'Bar' && config.visualizationSubType === 'regular' && config.runtime.seriesKeys.length === 1 && (
1891
+ <Select value={config.legend.colorCode} section='legend' fieldName='colorCode' label='Color code by category' initial='Select' updateField={updateField} options={getDataValueOptions(data)} />
1892
+ )}
1893
+ <Select value={config.legend.behavior} section='legend' fieldName='behavior' label='Legend Behavior (When clicked)' updateField={updateField} options={['highlight', 'isolate']} />
1894
+ <TextField value={config.legend.label} section='legend' fieldName='label' label='Title' updateField={updateField} />
1895
+ <Select value={config.legend.position} section='legend' fieldName='position' label='Position' updateField={updateField} options={['right', 'left', 'bottom']} />
1896
+ {config.legend.position === 'bottom' && <CheckBox value={config.legend.singleRow} section='legend' fieldName='singleRow' label='Single Row Legend' updateField={updateField} />}
1897
+ <TextField type='textarea' value={config.legend.description} updateField={updateField} section='legend' fieldName='description' label='Legend Description' />
1898
+ </AccordionItemPanel>
1899
+ </AccordionItem>
1900
+ )}
1441
1901
 
1442
1902
  <AccordionItem>
1443
1903
  <AccordionItemHeading>
@@ -1561,11 +2021,18 @@ const EditorPanel = () => {
1561
2021
  </>
1562
2022
  )}
1563
2023
 
1564
- <Select value={config.fontSize} fieldName='fontSize' label='Font Size' updateField={updateField} options={['small', 'medium', 'large']} />
1565
-
1566
- {config.series?.some(series => series.type === 'Bar' || series.type === 'Paired Bar') && <Select value={config.barHasBorder} fieldName='barHasBorder' label='Bar Borders' updateField={updateField} options={['true', 'false']} />}
2024
+ {config.visualizationType === 'Box Plot' && (
2025
+ <fieldset className='fieldset fieldset--boxplot'>
2026
+ <legend className=''>Box Plot Settings</legend>
2027
+ <Select value={config.boxplot.borders} fieldName='borders' section='boxplot' label='Box Plot Borders' updateField={updateField} options={['true', 'false']} />
2028
+ <CheckBox value={config.boxplot.plotOutlierValues} fieldName='plotOutlierValues' section='boxplot' label='Plot Outliers' updateField={updateField} />
2029
+ <CheckBox value={config.boxplot.plotNonOutlierValues} fieldName='plotNonOutlierValues' section='boxplot' label='Plot non-outlier values' updateField={updateField} />
2030
+ </fieldset>
2031
+ )}
1567
2032
 
1568
- <CheckBox value={config.animate} fieldName='animate' label='Animate Visualization' updateField={updateField} />
2033
+ <Select value={config.fontSize} fieldName='fontSize' label='Font Size' updateField={updateField} options={['small', 'medium', 'large']} />
2034
+ {visHasBarBorders() && <Select value={config.barHasBorder} fieldName='barHasBorder' label='Bar Borders' updateField={updateField} options={['true', 'false']} />}
2035
+ {visCanAnimate() && <CheckBox value={config.animate} fieldName='animate' label='Animate Visualization' updateField={updateField} />}
1569
2036
 
1570
2037
  {/*<CheckBox value={config.animateReplay} fieldName="animateReplay" label="Replay Animation When Filters Are Changed" updateField={updateField} />*/}
1571
2038
 
@@ -1594,74 +2061,108 @@ const EditorPanel = () => {
1594
2061
  <span className='edit-label'>Chart Color Palette</span>
1595
2062
  </label>
1596
2063
  {/* eslint-enable */}
1597
- {/* <InputCheckbox fieldName='isPaletteReversed' size='small' label='Use selected palette in reverse order' updateField={updateField} value={isPaletteReversed} /> */}
1598
- <InputToggle fieldName='isPaletteReversed' size='small' label='Use selected palette in reverse order' updateField={updateField} value={isPaletteReversed} />
1599
- <span>Sequential</span>
1600
- <ul className='color-palette'>
1601
- {filteredPallets.map(palette => {
1602
- const colorOne = {
1603
- backgroundColor: colorPalettes[palette][2]
1604
- }
1605
-
1606
- const colorTwo = {
1607
- backgroundColor: colorPalettes[palette][3]
1608
- }
1609
-
1610
- const colorThree = {
1611
- backgroundColor: colorPalettes[palette][5]
1612
- }
1613
-
1614
- return (
1615
- <button
1616
- title={palette}
1617
- key={palette}
1618
- onClick={e => {
1619
- e.preventDefault()
1620
- updateConfig({ ...config, palette })
1621
- }}
1622
- className={config.palette === palette ? 'selected' : ''}
1623
- >
1624
- <span style={colorOne}></span>
1625
- <span style={colorTwo}></span>
1626
- <span style={colorThree}></span>
1627
- </button>
1628
- )
1629
- })}
1630
- </ul>
1631
- <span>Non-Sequential</span>
1632
- <ul className='color-palette'>
1633
- {filteredQualitative.map(palette => {
1634
- const colorOne = {
1635
- backgroundColor: colorPalettes[palette][2]
1636
- }
1637
-
1638
- const colorTwo = {
1639
- backgroundColor: colorPalettes[palette][4]
1640
- }
1641
-
1642
- const colorThree = {
1643
- backgroundColor: colorPalettes[palette][6]
1644
- }
1645
-
1646
- return (
1647
- <button
1648
- title={palette}
1649
- key={palette}
1650
- onClick={e => {
1651
- e.preventDefault()
1652
- updateConfig({ ...config, palette })
1653
- }}
1654
- className={config.palette === palette ? 'selected' : ''}
1655
- >
1656
- <span style={colorOne}></span>
1657
- <span style={colorTwo}></span>
1658
- <span style={colorThree}></span>
1659
- </button>
1660
- )
1661
- })}
1662
- </ul>
2064
+ {config.visualizationType !== 'Paired Bar' && config.visualizationType !== 'Deviation Bar' && (
2065
+ <>
2066
+ <InputToggle fieldName='isPaletteReversed' size='small' label='Use selected palette in reverse order' updateField={updateField} value={config.isPaletteReversed} />
2067
+ <span>Sequential</span>
2068
+ <ul className='color-palette'>
2069
+ {sequential.map(palette => {
2070
+ const colorOne = {
2071
+ backgroundColor: colorPalettes[palette][2]
2072
+ }
2073
+
2074
+ const colorTwo = {
2075
+ backgroundColor: colorPalettes[palette][3]
2076
+ }
2077
+
2078
+ const colorThree = {
2079
+ backgroundColor: colorPalettes[palette][5]
2080
+ }
2081
+
2082
+ return (
2083
+ <button
2084
+ title={palette}
2085
+ key={palette}
2086
+ onClick={e => {
2087
+ e.preventDefault()
2088
+ updateConfig({ ...config, palette })
2089
+ }}
2090
+ className={config.palette === palette ? 'selected' : ''}
2091
+ >
2092
+ <span style={colorOne}></span>
2093
+ <span style={colorTwo}></span>
2094
+ <span style={colorThree}></span>
2095
+ </button>
2096
+ )
2097
+ })}
2098
+ </ul>
2099
+ <span>Non-Sequential</span>
2100
+ <ul className='color-palette'>
2101
+ {nonSequential.map(palette => {
2102
+ const colorOne = {
2103
+ backgroundColor: colorPalettes[palette][2]
2104
+ }
2105
+
2106
+ const colorTwo = {
2107
+ backgroundColor: colorPalettes[palette][4]
2108
+ }
2109
+
2110
+ const colorThree = {
2111
+ backgroundColor: colorPalettes[palette][6]
2112
+ }
2113
+
2114
+ return (
2115
+ <button
2116
+ title={palette}
2117
+ key={palette}
2118
+ onClick={e => {
2119
+ e.preventDefault()
2120
+ updateConfig({ ...config, palette })
2121
+ }}
2122
+ className={config.palette === palette ? 'selected' : ''}
2123
+ >
2124
+ <span style={colorOne}></span>
2125
+ <span style={colorTwo}></span>
2126
+ <span style={colorThree}></span>
2127
+ </button>
2128
+ )
2129
+ })}
2130
+ </ul>
2131
+ </>
2132
+ )}
2133
+ {(config.visualizationType === 'Paired Bar' || config.visualizationType === 'Deviation Bar') && (
2134
+ <>
2135
+ <InputToggle section='twoColor' fieldName='isPaletteReversed' size='small' label='Use selected palette in reverse order' updateField={updateField} value={config.twoColor.isPaletteReversed} />
2136
+ <ul className='color-palette'>
2137
+ {twoColorPalettes.map(palette => {
2138
+ const colorOne = {
2139
+ backgroundColor: twoColorPalette[palette][0]
2140
+ }
2141
+
2142
+ const colorTwo = {
2143
+ backgroundColor: twoColorPalette[palette][1]
2144
+ }
2145
+
2146
+ return (
2147
+ <button
2148
+ title={palette}
2149
+ key={palette}
2150
+ onClick={e => {
2151
+ e.preventDefault()
2152
+ updateConfig({ ...config, twoColor: { ...config.twoColor, palette } })
2153
+ }}
2154
+ className={config.twoColor.palette === palette ? 'selected' : ''}
2155
+ >
2156
+ <span className='two-color' style={colorOne}></span>
2157
+ <span className='two-color' style={colorTwo}></span>
2158
+ </button>
2159
+ )
2160
+ })}
2161
+ </ul>
2162
+ </>
2163
+ )}
1663
2164
 
1664
- {config.visualizationType !== 'Pie' && (
2165
+ {visHasDataCutoff() && (
1665
2166
  <>
1666
2167
  <TextField
1667
2168
  value={config.dataCutoff}
@@ -1685,7 +2186,7 @@ const EditorPanel = () => {
1685
2186
  )}
1686
2187
  {config.orientation === 'horizontal' && !config.isLollipopChart && config.yAxis.labelPlacement !== 'On Bar' && <TextField type='number' value={config.barHeight || '25'} fieldName='barHeight' label=' Bar Thickness' updateField={updateField} min='15' />}
1687
2188
  {((config.visualizationType === 'Bar' && config.orientation !== 'horizontal') || config.visualizationType === 'Combo') && <TextField value={config.barThickness} type='number' fieldName='barThickness' label='Bar Thickness' updateField={updateField} />}
1688
- {config.orientation === 'horizontal' && <TextField type='number' value={config.barSpace || '20'} fieldName='barSpace' label='Bar Space' updateField={updateField} min='0' />}
2189
+ {(config.orientation === 'horizontal' || config.visualizationType === 'Paired Bar') && <TextField type='number' value={config.barSpace || '15'} fieldName='barSpace' label='Bar Space' updateField={updateField} min='0' />}
1689
2190
  {(config.visualizationType === 'Bar' || config.visualizationType === 'Line' || config.visualizationType === 'Combo') && <CheckBox value={config.topAxis.hasLine} section='topAxis' fieldName='hasLine' label='Add Top Axis Line' updateField={updateField} />}
1690
2191
 
1691
2192
  {config.visualizationType === 'Spark Line' && (
@@ -1710,6 +2211,25 @@ const EditorPanel = () => {
1710
2211
  <AccordionItemButton>Data Table</AccordionItemButton>
1711
2212
  </AccordionItemHeading>
1712
2213
  <AccordionItemPanel>
2214
+ <TextField
2215
+ value={config.table.label}
2216
+ updateField={updateField}
2217
+ section='table'
2218
+ fieldName='label'
2219
+ id='tableLabel'
2220
+ label='Data Table Title'
2221
+ placeholder='Data Table'
2222
+ tooltip={
2223
+ <Tooltip style={{ textTransform: 'none' }}>
2224
+ <Tooltip.Target>
2225
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
2226
+ </Tooltip.Target>
2227
+ <Tooltip.Content>
2228
+ <p>Label is required for Data Table for 508 Compliance</p>
2229
+ </Tooltip.Content>
2230
+ </Tooltip>
2231
+ }
2232
+ />
1713
2233
  <CheckBox
1714
2234
  value={config.table.show}
1715
2235
  section='table'
@@ -1753,7 +2273,6 @@ const EditorPanel = () => {
1753
2273
  <CheckBox value={config.table.showDownloadUrl} section='table' fieldName='showDownloadUrl' label='Display Link to Dataset' updateField={updateField} />
1754
2274
  {/* <CheckBox value={config.table.showDownloadImgButton} section='table' fieldName='showDownloadImgButton' label='Display Image Button' updateField={updateField} /> */}
1755
2275
  {/* <CheckBox value={config.table.showDownloadPdfButton} section='table' fieldName='showDownloadPdfButton' label='Display PDF Button' updateField={updateField} /> */}
1756
- <TextField value={config.table.label} section='table' fieldName='label' label='Label' updateField={updateField} />
1757
2276
  {config.visualizationType !== 'Pie' && <TextField value={config.table.indexLabel} section='table' fieldName='indexLabel' label='Index Column Header' updateField={updateField} />}
1758
2277
  </AccordionItemPanel>
1759
2278
  </AccordionItem>