@cdc/chart 4.23.7 → 4.23.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/dist/cdcchart.js +27964 -26942
- package/examples/feature/__data__/area-chart-date-apple.json +5122 -0
- package/examples/feature/__data__/city-temperature.json +2198 -0
- package/examples/feature/area/area-chart-category.json +45 -45
- package/examples/feature/area/area-chart-date-apple.json +10376 -0
- package/examples/feature/area/area-chart-date-city-temperature.json +4528 -0
- package/examples/feature/area/area-chart-date.json +111 -3
- package/examples/feature/forest-plot/broken.json +700 -0
- package/examples/feature/forest-plot/data.csv +24 -0
- package/examples/feature/forest-plot/forest-plot.json +717 -0
- package/examples/feature/pie/planet-pie-example-config.json +1 -1
- package/examples/private/confidence_interval_test.json +248 -0
- package/examples/private/tooltip-issue.json +45275 -0
- package/index.html +13 -11
- package/package.json +4 -3
- package/src/CdcChart.jsx +24 -14
- package/src/components/AreaChart.jsx +84 -59
- package/src/components/BarChart.Horizontal.jsx +251 -0
- package/src/components/BarChart.StackedHorizontal.jsx +118 -0
- package/src/components/BarChart.StackedVertical.jsx +93 -0
- package/src/components/BarChart.Vertical.jsx +204 -0
- package/src/components/BarChart.jsx +14 -674
- package/src/components/BarChartType.jsx +15 -0
- package/src/components/BrushHandle.jsx +17 -0
- package/src/components/DataTable.jsx +63 -21
- package/src/components/EditorPanel.jsx +351 -303
- package/src/components/ForestPlot.jsx +191 -0
- package/src/components/ForestPlotSettings.jsx +508 -0
- package/src/components/LineChart.jsx +2 -2
- package/src/components/LinearChart.jsx +115 -310
- package/src/data/initial-state.js +43 -0
- package/src/hooks/useBarChart.js +186 -0
- package/src/hooks/useEditorPermissions.js +218 -0
- package/src/hooks/useMinMax.js +15 -3
- package/src/hooks/useScales.js +45 -2
- package/src/hooks/useTooltip.jsx +407 -0
- package/src/scss/main.scss +7 -0
|
@@ -21,6 +21,9 @@ import { useFilters } from '@cdc/core/components/Filters'
|
|
|
21
21
|
import Series from './Series'
|
|
22
22
|
import { useHighlightedBars } from '../hooks/useHighlightedBars'
|
|
23
23
|
|
|
24
|
+
import ForestPlotSettings from './ForestPlotSettings'
|
|
25
|
+
import { useEditorPermissions } from '../hooks/useEditorPermissions'
|
|
26
|
+
|
|
24
27
|
/* eslint-disable react-hooks/rules-of-hooks */
|
|
25
28
|
const TextField = memo(({ label, tooltip, section = null, subsection = null, fieldName, updateField, value: stateValue, type = 'input', i = null, min = null, ...attributes }) => {
|
|
26
29
|
const [value, setValue] = useState(stateValue)
|
|
@@ -138,6 +141,7 @@ const Regions = memo(({ config, updateConfig }) => {
|
|
|
138
141
|
updateConfig({ ...config, regions })
|
|
139
142
|
}
|
|
140
143
|
|
|
144
|
+
// only for Regions
|
|
141
145
|
let updateField = (section, subsection, fieldName, value, i) => regionUpdate(fieldName, value, i)
|
|
142
146
|
|
|
143
147
|
let removeColumn = i => {
|
|
@@ -214,6 +218,35 @@ const EditorPanel = () => {
|
|
|
214
218
|
|
|
215
219
|
const { twoColorPalettes, sequential, nonSequential } = useColorPalette(config, updateConfig)
|
|
216
220
|
|
|
221
|
+
const {
|
|
222
|
+
enabledChartTypes,
|
|
223
|
+
visSupportsTooltipLines,
|
|
224
|
+
visSupportsNonSequentialPallete,
|
|
225
|
+
visSupportsSequentialPallete,
|
|
226
|
+
visSupportsReverseColorPalette,
|
|
227
|
+
visHasLabelOnData,
|
|
228
|
+
visHasNumbersOnBars,
|
|
229
|
+
visHasAnchors,
|
|
230
|
+
visHasBarBorders,
|
|
231
|
+
visHasDataCutoff,
|
|
232
|
+
visCanAnimate,
|
|
233
|
+
visHasLegend,
|
|
234
|
+
visSupportsDateCategoryAxisLabel,
|
|
235
|
+
visSupportsDateCategoryAxisLine,
|
|
236
|
+
visSupportsDateCategoryAxisTicks,
|
|
237
|
+
visSupportsDateCategoryTickRotation,
|
|
238
|
+
visSupportsDateCategoryNumTicks,
|
|
239
|
+
visSupportsRegions,
|
|
240
|
+
visSupportsFilters,
|
|
241
|
+
visSupportsValueAxisGridLines,
|
|
242
|
+
visSupportsValueAxisLine,
|
|
243
|
+
visSupportsValueAxisTicks,
|
|
244
|
+
visSupportsValueAxisLabels,
|
|
245
|
+
visSupportsBarSpace,
|
|
246
|
+
visSupportsBarThickness,
|
|
247
|
+
visSupportsDataCutoff
|
|
248
|
+
} = useEditorPermissions()
|
|
249
|
+
|
|
217
250
|
// argument acts as props
|
|
218
251
|
const { handleFilterOrder, filterOrderOptions, filterStyleOptions } = useFilters({ config, setConfig: updateConfig, filteredData: data, setFilteredData })
|
|
219
252
|
|
|
@@ -237,6 +270,11 @@ const EditorPanel = () => {
|
|
|
237
270
|
...config,
|
|
238
271
|
series: newSeries
|
|
239
272
|
})
|
|
273
|
+
|
|
274
|
+
// disable brush if categorical - or - for now if not Area Chart
|
|
275
|
+
if (config.xAxis.type === 'categorical' || config.visualizationType !== 'Area Chart') {
|
|
276
|
+
config.showChartBrush = false
|
|
277
|
+
}
|
|
240
278
|
}, [config.visualizationType]) // eslint-disable-line
|
|
241
279
|
|
|
242
280
|
// Scatter Plots default date/category axis is 'continuous'
|
|
@@ -635,6 +673,16 @@ const EditorPanel = () => {
|
|
|
635
673
|
})
|
|
636
674
|
}, [config.orientation])
|
|
637
675
|
|
|
676
|
+
// Set paired bars to be horizontal, even though that option doesn't display
|
|
677
|
+
useEffect(() => {
|
|
678
|
+
if (config.visualizationType === 'Paired Bar') {
|
|
679
|
+
updateConfig({
|
|
680
|
+
...config,
|
|
681
|
+
orientation: 'horizontal'
|
|
682
|
+
})
|
|
683
|
+
}
|
|
684
|
+
}, []) // eslint-disable-line
|
|
685
|
+
|
|
638
686
|
useEffect(() => {
|
|
639
687
|
if (config.orientation === 'horizontal') {
|
|
640
688
|
updateConfig({
|
|
@@ -644,6 +692,13 @@ const EditorPanel = () => {
|
|
|
644
692
|
}
|
|
645
693
|
}, [config.isLollipopChart, config.lollipopShape]) // eslint-disable-line
|
|
646
694
|
|
|
695
|
+
/// temporary force orientation untill we support Vartical deviaton bar
|
|
696
|
+
useEffect(() => {
|
|
697
|
+
if (config.visualizationType === 'Deviation Bar') {
|
|
698
|
+
updateConfig({ ...config, orientation: 'horizontal' })
|
|
699
|
+
}
|
|
700
|
+
}, [config.visualizationType])
|
|
701
|
+
|
|
647
702
|
const ExclusionsList = useCallback(() => {
|
|
648
703
|
const exclusions = [...config.exclusions.keys]
|
|
649
704
|
return (
|
|
@@ -664,91 +719,6 @@ const EditorPanel = () => {
|
|
|
664
719
|
)
|
|
665
720
|
}, [config]) // eslint-disable-line
|
|
666
721
|
|
|
667
|
-
const visSupportsTooltipLines = () => {
|
|
668
|
-
const chartsWithTooltipGuides = ['Combo', 'Forecasting', 'Area Chart', 'Line', 'Bar']
|
|
669
|
-
if (chartsWithTooltipGuides.includes(config.visualizationType)) return true
|
|
670
|
-
return false
|
|
671
|
-
}
|
|
672
|
-
|
|
673
|
-
const visHasLegend = () => {
|
|
674
|
-
const { visualizationType } = config
|
|
675
|
-
|
|
676
|
-
switch (visualizationType) {
|
|
677
|
-
case 'Box Plot':
|
|
678
|
-
return false
|
|
679
|
-
default:
|
|
680
|
-
return true
|
|
681
|
-
}
|
|
682
|
-
}
|
|
683
|
-
|
|
684
|
-
const visCanAnimate = () => {
|
|
685
|
-
const { visualizationType } = config
|
|
686
|
-
switch (visualizationType) {
|
|
687
|
-
case 'Area Chart':
|
|
688
|
-
return false
|
|
689
|
-
case 'Scatter Plot':
|
|
690
|
-
return false
|
|
691
|
-
case 'Box Plot':
|
|
692
|
-
return false
|
|
693
|
-
default:
|
|
694
|
-
return true
|
|
695
|
-
}
|
|
696
|
-
}
|
|
697
|
-
|
|
698
|
-
const visHasDataCutoff = () => {
|
|
699
|
-
const { visualizationType } = config
|
|
700
|
-
switch (visualizationType) {
|
|
701
|
-
case 'Box Plot':
|
|
702
|
-
return false
|
|
703
|
-
case 'Pie':
|
|
704
|
-
return false
|
|
705
|
-
default:
|
|
706
|
-
return true
|
|
707
|
-
}
|
|
708
|
-
}
|
|
709
|
-
|
|
710
|
-
const visHasLabelOnData = () => {
|
|
711
|
-
const { visualizationType } = config
|
|
712
|
-
switch (visualizationType) {
|
|
713
|
-
case 'Area Chart':
|
|
714
|
-
return false
|
|
715
|
-
case 'Box Plot':
|
|
716
|
-
return false
|
|
717
|
-
case 'Pie':
|
|
718
|
-
return false
|
|
719
|
-
case 'Scatter Plot':
|
|
720
|
-
return false
|
|
721
|
-
default:
|
|
722
|
-
return true
|
|
723
|
-
}
|
|
724
|
-
}
|
|
725
|
-
|
|
726
|
-
const visHasAnchors = () => {
|
|
727
|
-
const { visualizationType } = config
|
|
728
|
-
switch (visualizationType) {
|
|
729
|
-
case 'Area Chart':
|
|
730
|
-
return true
|
|
731
|
-
case 'Combo':
|
|
732
|
-
return true
|
|
733
|
-
case 'Line':
|
|
734
|
-
return true
|
|
735
|
-
case 'Bar':
|
|
736
|
-
return true
|
|
737
|
-
case 'Scatter Plot':
|
|
738
|
-
return true
|
|
739
|
-
default:
|
|
740
|
-
return false
|
|
741
|
-
}
|
|
742
|
-
}
|
|
743
|
-
|
|
744
|
-
const visHasBarBorders = () => {
|
|
745
|
-
const { series, visualizationType } = config
|
|
746
|
-
if (visualizationType === 'Box Plot') return false
|
|
747
|
-
if (visualizationType === 'Scatter Plot') return false
|
|
748
|
-
if (visualizationType === 'Pie') return false
|
|
749
|
-
return series?.some(series => series.type === 'Bar' || series.type === 'Paired Bar' || series.type === 'Deviation Bar')
|
|
750
|
-
}
|
|
751
|
-
|
|
752
722
|
const handleSeriesChange = (idx1, idx2) => {
|
|
753
723
|
let seriesOrder = config.series
|
|
754
724
|
let [movedItem] = seriesOrder.splice(idx1, 1)
|
|
@@ -759,6 +729,9 @@ const EditorPanel = () => {
|
|
|
759
729
|
if (config.isLollipopChart && config?.series?.length > 1) {
|
|
760
730
|
config.runtime.editorErrorMessage = 'Lollipop charts must use only one data series'
|
|
761
731
|
}
|
|
732
|
+
if (config.visualizationType === 'Paired Bar' && config?.series?.length !== 2) {
|
|
733
|
+
config.runtime.editorErrorMessage = 'Paired Bar charts must use exactly two data series'
|
|
734
|
+
}
|
|
762
735
|
|
|
763
736
|
if (config.isLollipopChart && config?.series?.length === 0) {
|
|
764
737
|
config.runtime.editorErrorMessage = 'Add a data series'
|
|
@@ -818,21 +791,6 @@ const EditorPanel = () => {
|
|
|
818
791
|
validateMaxValue()
|
|
819
792
|
}, [minValue, maxValue, config]) // eslint-disable-line
|
|
820
793
|
|
|
821
|
-
// prettier-ignore
|
|
822
|
-
const enabledChartTypes = [
|
|
823
|
-
'Area Chart',
|
|
824
|
-
'Bar',
|
|
825
|
-
'Box Plot',
|
|
826
|
-
'Combo',
|
|
827
|
-
'Deviation Bar',
|
|
828
|
-
'Forecasting',
|
|
829
|
-
'Line',
|
|
830
|
-
'Paired Bar',
|
|
831
|
-
'Pie',
|
|
832
|
-
'Scatter Plot',
|
|
833
|
-
'Spark Line'
|
|
834
|
-
]
|
|
835
|
-
|
|
836
794
|
const isLoadedFromUrl = config?.dataKey?.includes('http://') || config?.dataKey?.includes('https://')
|
|
837
795
|
|
|
838
796
|
// if isDebug = true, then try to set the category and data col to reduce clicking
|
|
@@ -877,7 +835,7 @@ const EditorPanel = () => {
|
|
|
877
835
|
if (config.data && config.series) {
|
|
878
836
|
Object.keys(config.data[0]).map(colName => {
|
|
879
837
|
// OMIT ANY COLUMNS THAT ARE IN DATA SERIES!
|
|
880
|
-
const found = config?.series.some(
|
|
838
|
+
const found = config?.series.some(series => series.dataKey === colName)
|
|
881
839
|
if (colName !== config.xAxis.dataKey && !found) {
|
|
882
840
|
// if not the index then add it
|
|
883
841
|
return columnsOptions.push(
|
|
@@ -953,7 +911,10 @@ const EditorPanel = () => {
|
|
|
953
911
|
dataTable: false,
|
|
954
912
|
tooltips: false,
|
|
955
913
|
prefix: '',
|
|
956
|
-
suffix: ''
|
|
914
|
+
suffix: '',
|
|
915
|
+
forestPlot: false,
|
|
916
|
+
startingPoint: '0',
|
|
917
|
+
forestPlotAlignRight: false
|
|
957
918
|
}
|
|
958
919
|
}
|
|
959
920
|
})
|
|
@@ -1012,6 +973,21 @@ const EditorPanel = () => {
|
|
|
1012
973
|
handleUpdateHighlightedBorderWidth
|
|
1013
974
|
} = useHighlightedBars(config, updateConfig)
|
|
1014
975
|
|
|
976
|
+
const updateSeriesTooltip = (column, event) => {
|
|
977
|
+
console.log('tooltip value', event)
|
|
978
|
+
|
|
979
|
+
let updatedColumns = config.columns
|
|
980
|
+
|
|
981
|
+
updatedColumns[column].tooltips = event
|
|
982
|
+
|
|
983
|
+
console.log('updatedColumns', updatedColumns)
|
|
984
|
+
|
|
985
|
+
updateConfig({
|
|
986
|
+
...config,
|
|
987
|
+
columns: updatedColumns
|
|
988
|
+
})
|
|
989
|
+
}
|
|
990
|
+
|
|
1015
991
|
return (
|
|
1016
992
|
<ErrorBoundary component='EditorPanel'>
|
|
1017
993
|
{config.newViz && <Confirm />}
|
|
@@ -1040,7 +1016,7 @@ const EditorPanel = () => {
|
|
|
1040
1016
|
<Select value={config.roundingStyle || 'standard'} fieldName='roundingStyle' label='rounding style' updateField={updateField} options={['standard', 'shallow', 'finger']} />
|
|
1041
1017
|
)}
|
|
1042
1018
|
{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']} />}
|
|
1043
|
-
{
|
|
1019
|
+
{visHasNumbersOnBars() ? (
|
|
1044
1020
|
<CheckBox value={config.yAxis.displayNumbersOnBar} section='yAxis' fieldName='displayNumbersOnBar' label={config.isLollipopChart ? 'Display Numbers after Bar' : 'Display Numbers on Bar'} updateField={updateField} />
|
|
1045
1021
|
) : (
|
|
1046
1022
|
visHasLabelOnData() && <CheckBox value={config.labels} fieldName='labels' label='Display label on data' updateField={updateField} />
|
|
@@ -1143,7 +1119,8 @@ const EditorPanel = () => {
|
|
|
1143
1119
|
{config.orientation === 'vertical' && <TextField type='number' value={config.heights.vertical} section='heights' fieldName='vertical' label='Chart Height' updateField={updateField} />}
|
|
1144
1120
|
</AccordionItemPanel>
|
|
1145
1121
|
</AccordionItem>
|
|
1146
|
-
{config.visualizationType
|
|
1122
|
+
{config.visualizationType === 'Forest Plot' && <ForestPlotSettings />}
|
|
1123
|
+
{config.visualizationType !== 'Pie' && config.visualizationType !== 'Forest Plot' && (
|
|
1147
1124
|
<AccordionItem>
|
|
1148
1125
|
<AccordionItemHeading>
|
|
1149
1126
|
<AccordionItemButton>Data Series {(!config.series || config.series.length === 0 || (config.visualizationType === 'Paired Bar' && config.series.length < 2)) && <WarningImage width='25' className='warning-icon' />}</AccordionItemButton>
|
|
@@ -1345,7 +1322,7 @@ const EditorPanel = () => {
|
|
|
1345
1322
|
<AccordionItem>
|
|
1346
1323
|
<AccordionItemHeading>
|
|
1347
1324
|
<AccordionItemButton>
|
|
1348
|
-
{config.visualizationType
|
|
1325
|
+
{config.visualizationType === 'Pie' ? 'Data Format' : config.orientation === 'vertical' ? 'Left Value Axis' : 'Value Axis'}
|
|
1349
1326
|
{config.visualizationType === 'Pie' && !config.yAxis.dataKey && <WarningImage width='25' className='warning-icon' />}
|
|
1350
1327
|
</AccordionItemButton>
|
|
1351
1328
|
</AccordionItemHeading>
|
|
@@ -1425,7 +1402,7 @@ const EditorPanel = () => {
|
|
|
1425
1402
|
{/* Hiding this for now, not interested in moving the axis lines away from chart comp. right now. */}
|
|
1426
1403
|
{/* <TextField value={config.yAxis.axisPadding} type='number' max={10} min={0} section='yAxis' fieldName='axisPadding' label={'Axis Padding'} className='number-narrow' updateField={updateField} /> */}
|
|
1427
1404
|
{config.orientation === 'horizontal' && <TextField value={config.xAxis.labelOffset} section='xAxis' fieldName='labelOffset' label='Label offset' type='number' className='number-narrow' updateField={updateField} />}
|
|
1428
|
-
{
|
|
1405
|
+
{visSupportsValueAxisGridLines() && <CheckBox value={config.yAxis.gridLines} section='yAxis' fieldName='gridLines' label='Show Gridlines' updateField={updateField} />}
|
|
1429
1406
|
<CheckBox value={config.yAxis.enablePadding} section='yAxis' fieldName='enablePadding' label='Add Padding to Value Axis Scale' updateField={updateField} />
|
|
1430
1407
|
{config.visualizationSubType === 'regular' && <CheckBox value={config.useLogScale} fieldName='useLogScale' label='use logarithmic scale' updateField={updateField} />}
|
|
1431
1408
|
</>
|
|
@@ -1491,9 +1468,9 @@ const EditorPanel = () => {
|
|
|
1491
1468
|
|
|
1492
1469
|
{config.orientation === 'horizontal' ? ( // horizontal - x is vertical y is horizontal
|
|
1493
1470
|
<>
|
|
1494
|
-
<CheckBox value={config.xAxis.hideAxis} section='xAxis' fieldName='hideAxis' label='Hide Axis' updateField={updateField} />
|
|
1495
|
-
<CheckBox value={config.xAxis.hideLabel} section='xAxis' fieldName='hideLabel' label='Hide Label' updateField={updateField} />
|
|
1496
|
-
<CheckBox value={config.xAxis.hideTicks} section='xAxis' fieldName='hideTicks' label='Hide Ticks' updateField={updateField} />
|
|
1471
|
+
{visSupportsValueAxisLine() && <CheckBox value={config.xAxis.hideAxis} section='xAxis' fieldName='hideAxis' label='Hide Axis' updateField={updateField} />}
|
|
1472
|
+
{visSupportsValueAxisLabels() && <CheckBox value={config.xAxis.hideLabel} section='xAxis' fieldName='hideLabel' label='Hide Label' updateField={updateField} />}
|
|
1473
|
+
{visSupportsValueAxisTicks() && <CheckBox value={config.xAxis.hideTicks} section='xAxis' fieldName='hideTicks' label='Hide Ticks' updateField={updateField} />}
|
|
1497
1474
|
<TextField value={config.xAxis.max} section='xAxis' fieldName='max' label='max value' type='number' placeholder='Auto' updateField={updateField} />
|
|
1498
1475
|
<span style={{ color: 'red', display: 'block' }}>{warningMsg.maxMsg}</span>
|
|
1499
1476
|
<TextField value={config.xAxis.min} section='xAxis' fieldName='min' type='number' label='min value' placeholder='Auto' updateField={updateField} />
|
|
@@ -1839,14 +1816,16 @@ const EditorPanel = () => {
|
|
|
1839
1816
|
<AccordionItem>
|
|
1840
1817
|
<AccordionItemHeading>
|
|
1841
1818
|
<AccordionItemButton>
|
|
1842
|
-
{config.visualizationType
|
|
1819
|
+
{config.visualizationType === 'Pie' ? 'Segments' : 'Date/Category Axis'}
|
|
1843
1820
|
{!config.xAxis.dataKey && <WarningImage width='25' className='warning-icon' />}
|
|
1844
1821
|
</AccordionItemButton>
|
|
1845
1822
|
</AccordionItemHeading>
|
|
1846
1823
|
<AccordionItemPanel>
|
|
1847
1824
|
{config.visualizationType !== 'Pie' && (
|
|
1848
1825
|
<>
|
|
1849
|
-
|
|
1826
|
+
{config.visualizationType !== 'Forest Plot' && (
|
|
1827
|
+
<Select value={config.xAxis.type} section='xAxis' fieldName='type' label='Data Type' updateField={updateField} options={config.visualizationType !== 'Scatter Plot' ? ['categorical', 'date'] : ['categorical', 'continuous', 'date']} />
|
|
1828
|
+
)}
|
|
1850
1829
|
<Select
|
|
1851
1830
|
value={config.xAxis.dataKey || setCategoryAxis() || ''}
|
|
1852
1831
|
section='xAxis'
|
|
@@ -2025,7 +2004,8 @@ const EditorPanel = () => {
|
|
|
2025
2004
|
)}
|
|
2026
2005
|
</>
|
|
2027
2006
|
)}
|
|
2028
|
-
|
|
2007
|
+
|
|
2008
|
+
{visSupportsDateCategoryNumTicks() && <TextField value={config.xAxis.numTicks} placeholder='Auto' type='number' min='1' section='xAxis' fieldName='numTicks' label='Number of ticks' className='number-narrow' updateField={updateField} />}
|
|
2029
2009
|
|
|
2030
2010
|
<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} />
|
|
2031
2011
|
|
|
@@ -2039,7 +2019,9 @@ const EditorPanel = () => {
|
|
|
2039
2019
|
</>
|
|
2040
2020
|
)}
|
|
2041
2021
|
{config.orientation === 'vertical' && config.visualizationType !== 'Paired Bar' && <CheckBox value={config.isResponsiveTicks} fieldName='isResponsiveTicks' label='Use Responsive Ticks' updateField={updateField} />}
|
|
2042
|
-
{(config.orientation === 'horizontal' || !config.isResponsiveTicks) &&
|
|
2022
|
+
{(config.orientation === 'horizontal' || !config.isResponsiveTicks) && visSupportsDateCategoryTickRotation() && (
|
|
2023
|
+
<TextField value={config.xAxis.tickRotation} type='number' min='0' section='xAxis' fieldName='tickRotation' label='Tick rotation (Degrees)' className='number-narrow' updateField={updateField} />
|
|
2024
|
+
)}
|
|
2043
2025
|
{config.orientation === 'vertical' && config.isResponsiveTicks && config.visualizationType !== 'Paired Bar' && (
|
|
2044
2026
|
<TextField
|
|
2045
2027
|
value={config.xAxis.maxTickRotation}
|
|
@@ -2065,8 +2047,8 @@ const EditorPanel = () => {
|
|
|
2065
2047
|
|
|
2066
2048
|
{config.orientation === 'horizontal' ? (
|
|
2067
2049
|
<>
|
|
2068
|
-
<CheckBox value={config.yAxis.hideAxis} section='yAxis' fieldName='hideAxis' label='Hide Axis' updateField={updateField} />
|
|
2069
|
-
<CheckBox value={config.yAxis.hideLabel} section='yAxis' fieldName='hideLabel' label='Hide Label' updateField={updateField} />
|
|
2050
|
+
{visSupportsDateCategoryAxisLine() && <CheckBox value={config.yAxis.hideAxis} section='yAxis' fieldName='hideAxis' label='Hide Axis' updateField={updateField} />}
|
|
2051
|
+
{visSupportsDateCategoryAxisLabel() && <CheckBox value={config.yAxis.hideLabel} section='yAxis' fieldName='hideLabel' label='Hide Label' updateField={updateField} />}
|
|
2070
2052
|
</>
|
|
2071
2053
|
) : (
|
|
2072
2054
|
<>
|
|
@@ -2419,7 +2401,7 @@ const EditorPanel = () => {
|
|
|
2419
2401
|
)}
|
|
2420
2402
|
</AccordionItemPanel>
|
|
2421
2403
|
</AccordionItem>
|
|
2422
|
-
{
|
|
2404
|
+
{visSupportsRegions() && (
|
|
2423
2405
|
<AccordionItem>
|
|
2424
2406
|
<AccordionItemHeading>
|
|
2425
2407
|
<AccordionItemButton>Regions</AccordionItemButton>
|
|
@@ -2519,6 +2501,62 @@ const EditorPanel = () => {
|
|
|
2519
2501
|
</label>
|
|
2520
2502
|
</li>
|
|
2521
2503
|
*/}
|
|
2504
|
+
|
|
2505
|
+
{config.visualizationType === 'Forest Plot' && (
|
|
2506
|
+
<>
|
|
2507
|
+
<li>
|
|
2508
|
+
<label className='checkbox'>
|
|
2509
|
+
<input
|
|
2510
|
+
type='checkbox'
|
|
2511
|
+
checked={config.columns[val].forestPlot || false}
|
|
2512
|
+
onChange={event => {
|
|
2513
|
+
editColumn(val, 'forestPlot', event.target.checked)
|
|
2514
|
+
}}
|
|
2515
|
+
/>
|
|
2516
|
+
<span className='edit-label'>Show in Forest Plot</span>
|
|
2517
|
+
</label>
|
|
2518
|
+
</li>
|
|
2519
|
+
<li>
|
|
2520
|
+
<label className='checkbox'>
|
|
2521
|
+
<input
|
|
2522
|
+
type='checkbox'
|
|
2523
|
+
checked={config.columns[val].tooltips || false}
|
|
2524
|
+
onChange={event => {
|
|
2525
|
+
updateSeriesTooltip(val, event.target.checked)
|
|
2526
|
+
}}
|
|
2527
|
+
/>
|
|
2528
|
+
<span className='edit-label'>Show in tooltip</span>
|
|
2529
|
+
</label>
|
|
2530
|
+
</li>
|
|
2531
|
+
<li>
|
|
2532
|
+
<label className='checkbox'>
|
|
2533
|
+
<input
|
|
2534
|
+
type='checkbox'
|
|
2535
|
+
checked={config.columns[val].forestPlotAlignRight || false}
|
|
2536
|
+
onChange={event => {
|
|
2537
|
+
editColumn(val, 'forestPlotAlignRight', event.target.checked)
|
|
2538
|
+
}}
|
|
2539
|
+
/>
|
|
2540
|
+
<span className='edit-label'>Align Right</span>
|
|
2541
|
+
</label>
|
|
2542
|
+
</li>
|
|
2543
|
+
|
|
2544
|
+
{!config.columns[val].forestPlotAlignRight && (
|
|
2545
|
+
<li>
|
|
2546
|
+
<label className='text'>
|
|
2547
|
+
<span className='edit-label'>Forest Plot Starting Point</span>
|
|
2548
|
+
<input
|
|
2549
|
+
type='number'
|
|
2550
|
+
value={config.columns[val].forestPlotStartingPoint || 0}
|
|
2551
|
+
onChange={event => {
|
|
2552
|
+
editColumn(val, 'forestPlotStartingPoint', event.target.value)
|
|
2553
|
+
}}
|
|
2554
|
+
/>
|
|
2555
|
+
</label>
|
|
2556
|
+
</li>
|
|
2557
|
+
)}
|
|
2558
|
+
</>
|
|
2559
|
+
)}
|
|
2522
2560
|
</ul>
|
|
2523
2561
|
</fieldset>
|
|
2524
2562
|
))}
|
|
@@ -2651,15 +2689,16 @@ const EditorPanel = () => {
|
|
|
2651
2689
|
</AccordionItemPanel>
|
|
2652
2690
|
</AccordionItem>
|
|
2653
2691
|
)}
|
|
2654
|
-
|
|
2655
|
-
<
|
|
2656
|
-
<
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2692
|
+
{visSupportsFilters() && (
|
|
2693
|
+
<AccordionItem>
|
|
2694
|
+
<AccordionItemHeading>
|
|
2695
|
+
<AccordionItemButton>Filters</AccordionItemButton>
|
|
2696
|
+
</AccordionItemHeading>
|
|
2697
|
+
<AccordionItemPanel>
|
|
2698
|
+
{config.filters && (
|
|
2699
|
+
<>
|
|
2700
|
+
{/* prettier-ignore */}
|
|
2701
|
+
<Select
|
|
2663
2702
|
value={config.filterBehavior}
|
|
2664
2703
|
fieldName='filterBehavior'
|
|
2665
2704
|
label='Filter Behavior'
|
|
@@ -2676,128 +2715,129 @@ const EditorPanel = () => {
|
|
|
2676
2715
|
</Tooltip>
|
|
2677
2716
|
}
|
|
2678
2717
|
/>
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2718
|
+
<br />
|
|
2719
|
+
</>
|
|
2720
|
+
)}
|
|
2721
|
+
{config.filters && (
|
|
2722
|
+
<ul className='filters-list'>
|
|
2723
|
+
{/* Whether filters should apply onChange or Apply Button */}
|
|
2685
2724
|
|
|
2686
|
-
|
|
2687
|
-
|
|
2725
|
+
{config.filters.map((filter, index) => {
|
|
2726
|
+
if (filter.type === 'url') return <></>
|
|
2688
2727
|
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
}}
|
|
2697
|
-
>
|
|
2698
|
-
Remove
|
|
2699
|
-
</button>
|
|
2700
|
-
<label>
|
|
2701
|
-
<span className='edit-label column-heading'>Filter</span>
|
|
2702
|
-
<select
|
|
2703
|
-
value={filter.columnName}
|
|
2704
|
-
onChange={e => {
|
|
2705
|
-
updateFilterProp('columnName', index, e.target.value)
|
|
2728
|
+
return (
|
|
2729
|
+
<fieldset className='edit-block' key={index}>
|
|
2730
|
+
<button
|
|
2731
|
+
type='button'
|
|
2732
|
+
className='remove-column'
|
|
2733
|
+
onClick={() => {
|
|
2734
|
+
removeFilter(index)
|
|
2706
2735
|
}}
|
|
2707
2736
|
>
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2737
|
+
Remove
|
|
2738
|
+
</button>
|
|
2739
|
+
<label>
|
|
2740
|
+
<span className='edit-label column-heading'>Filter</span>
|
|
2741
|
+
<select
|
|
2742
|
+
value={filter.columnName}
|
|
2743
|
+
onChange={e => {
|
|
2744
|
+
updateFilterProp('columnName', index, e.target.value)
|
|
2745
|
+
}}
|
|
2746
|
+
>
|
|
2747
|
+
<option value=''>- Select Option -</option>
|
|
2748
|
+
{getFilters(true).map((dataKey, index) => (
|
|
2749
|
+
<option value={dataKey} key={index}>
|
|
2750
|
+
{dataKey}
|
|
2751
|
+
</option>
|
|
2752
|
+
))}
|
|
2753
|
+
</select>
|
|
2754
|
+
</label>
|
|
2716
2755
|
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2756
|
+
<label>
|
|
2757
|
+
<span className='edit-showDropdown column-heading'>Show Filter Input</span>
|
|
2758
|
+
<input
|
|
2759
|
+
type='checkbox'
|
|
2760
|
+
checked={filter.showDropdown === undefined ? true : filter.showDropdown}
|
|
2761
|
+
onChange={e => {
|
|
2762
|
+
updateFilterProp('showDropdown', index, e.target.checked)
|
|
2763
|
+
}}
|
|
2764
|
+
/>
|
|
2765
|
+
</label>
|
|
2727
2766
|
|
|
2728
|
-
|
|
2729
|
-
|
|
2767
|
+
<label>
|
|
2768
|
+
<span className='edit-label column-heading'>Filter Style</span>
|
|
2730
2769
|
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2770
|
+
<select
|
|
2771
|
+
value={filter.filterStyle}
|
|
2772
|
+
onChange={e => {
|
|
2773
|
+
updateFilterProp('filterStyle', index, e.target.value)
|
|
2774
|
+
}}
|
|
2775
|
+
>
|
|
2776
|
+
{filterStyleOptions.map(item => {
|
|
2777
|
+
return <option value={item}>{item}</option>
|
|
2778
|
+
})}
|
|
2779
|
+
</select>
|
|
2780
|
+
</label>
|
|
2781
|
+
<label>
|
|
2782
|
+
<span className='edit-label column-heading'>Label</span>
|
|
2783
|
+
<input
|
|
2784
|
+
type='text'
|
|
2785
|
+
value={filter.label}
|
|
2786
|
+
onChange={e => {
|
|
2787
|
+
updateFilterProp('label', index, e.target.value)
|
|
2788
|
+
}}
|
|
2789
|
+
/>
|
|
2790
|
+
</label>
|
|
2752
2791
|
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2792
|
+
<label>
|
|
2793
|
+
<span className='edit-filterOrder column-heading'>Filter Order</span>
|
|
2794
|
+
<select value={filter.order ? filter.order : 'asc'} onChange={e => updateFilterProp('order', index, e.target.value)}>
|
|
2795
|
+
{filterOrderOptions.map((option, index) => {
|
|
2796
|
+
return (
|
|
2797
|
+
<option value={option.value} key={`filter-${index}`}>
|
|
2798
|
+
{option.label}
|
|
2799
|
+
</option>
|
|
2800
|
+
)
|
|
2801
|
+
})}
|
|
2802
|
+
</select>
|
|
2764
2803
|
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2804
|
+
{filter.order === 'cust' && (
|
|
2805
|
+
<DragDropContext onDragEnd={({ source, destination }) => handleFilterOrder(source.index, destination.index, index, config.filters[index])}>
|
|
2806
|
+
<Droppable droppableId='filter_order'>
|
|
2807
|
+
{provided => (
|
|
2808
|
+
<ul {...provided.droppableProps} className='sort-list' ref={provided.innerRef} style={{ marginTop: '1em' }}>
|
|
2809
|
+
{config.filters[index]?.values.map((value, index) => {
|
|
2810
|
+
return (
|
|
2811
|
+
<Draggable key={value} draggableId={`draggableFilter-${value}`} index={index}>
|
|
2812
|
+
{(provided, snapshot) => (
|
|
2813
|
+
<li>
|
|
2814
|
+
<div className={snapshot.isDragging ? 'currently-dragging' : ''} style={getItemStyle(snapshot.isDragging, provided.draggableProps.style, sortableItemStyles)} ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}>
|
|
2815
|
+
{value}
|
|
2816
|
+
</div>
|
|
2817
|
+
</li>
|
|
2818
|
+
)}
|
|
2819
|
+
</Draggable>
|
|
2820
|
+
)
|
|
2821
|
+
})}
|
|
2822
|
+
{provided.placeholder}
|
|
2823
|
+
</ul>
|
|
2824
|
+
)}
|
|
2825
|
+
</Droppable>
|
|
2826
|
+
</DragDropContext>
|
|
2827
|
+
)}
|
|
2828
|
+
</label>
|
|
2829
|
+
</fieldset>
|
|
2830
|
+
)
|
|
2831
|
+
})}
|
|
2832
|
+
</ul>
|
|
2833
|
+
)}
|
|
2834
|
+
{!config.filters && <p style={{ textAlign: 'center' }}>There are currently no filters.</p>}
|
|
2835
|
+
<button type='button' onClick={addNewFilter} className='btn full-width'>
|
|
2836
|
+
Add Filter
|
|
2837
|
+
</button>
|
|
2838
|
+
</AccordionItemPanel>
|
|
2839
|
+
</AccordionItem>
|
|
2840
|
+
)}
|
|
2801
2841
|
<AccordionItem>
|
|
2802
2842
|
<AccordionItemHeading>
|
|
2803
2843
|
<AccordionItemButton>Visual</AccordionItemButton>
|
|
@@ -2863,77 +2903,85 @@ const EditorPanel = () => {
|
|
|
2863
2903
|
))}
|
|
2864
2904
|
</ul>
|
|
2865
2905
|
</label>
|
|
2866
|
-
<label>
|
|
2867
|
-
<span className='edit-label'>Chart Color Palette</span>
|
|
2868
|
-
</label>
|
|
2869
2906
|
{/* eslint-enable */}
|
|
2870
|
-
{
|
|
2907
|
+
{(visSupportsNonSequentialPallete() || visSupportsNonSequentialPallete()) && (
|
|
2871
2908
|
<>
|
|
2872
|
-
<
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2909
|
+
<label>
|
|
2910
|
+
<span className='edit-label'>Chart Color Palette</span>
|
|
2911
|
+
</label>
|
|
2912
|
+
{visSupportsReverseColorPalette() && <InputToggle fieldName='isPaletteReversed' size='small' label='Use selected palette in reverse order' updateField={updateField} value={config.isPaletteReversed} />}
|
|
2913
|
+
{visSupportsSequentialPallete() && (
|
|
2914
|
+
<>
|
|
2915
|
+
<span>Sequential</span>
|
|
2916
|
+
<ul className='color-palette'>
|
|
2917
|
+
{sequential.map(palette => {
|
|
2918
|
+
const colorOne = {
|
|
2919
|
+
backgroundColor: colorPalettes[palette][2]
|
|
2920
|
+
}
|
|
2879
2921
|
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2922
|
+
const colorTwo = {
|
|
2923
|
+
backgroundColor: colorPalettes[palette][3]
|
|
2924
|
+
}
|
|
2883
2925
|
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2926
|
+
const colorThree = {
|
|
2927
|
+
backgroundColor: colorPalettes[palette][5]
|
|
2928
|
+
}
|
|
2887
2929
|
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2930
|
+
return (
|
|
2931
|
+
<button
|
|
2932
|
+
title={palette}
|
|
2933
|
+
key={palette}
|
|
2934
|
+
onClick={e => {
|
|
2935
|
+
e.preventDefault()
|
|
2936
|
+
updateConfig({ ...config, palette })
|
|
2937
|
+
}}
|
|
2938
|
+
className={config.palette === palette ? 'selected' : ''}
|
|
2939
|
+
>
|
|
2940
|
+
<span style={colorOne}></span>
|
|
2941
|
+
<span style={colorTwo}></span>
|
|
2942
|
+
<span style={colorThree}></span>
|
|
2943
|
+
</button>
|
|
2944
|
+
)
|
|
2945
|
+
})}
|
|
2946
|
+
</ul>
|
|
2947
|
+
</>
|
|
2948
|
+
)}
|
|
2949
|
+
{visSupportsNonSequentialPallete() && (
|
|
2950
|
+
<>
|
|
2951
|
+
<span>Non-Sequential</span>
|
|
2952
|
+
<ul className='color-palette'>
|
|
2953
|
+
{nonSequential.map(palette => {
|
|
2954
|
+
const colorOne = {
|
|
2955
|
+
backgroundColor: colorPalettes[palette][2]
|
|
2956
|
+
}
|
|
2911
2957
|
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2958
|
+
const colorTwo = {
|
|
2959
|
+
backgroundColor: colorPalettes[palette][4]
|
|
2960
|
+
}
|
|
2915
2961
|
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2962
|
+
const colorThree = {
|
|
2963
|
+
backgroundColor: colorPalettes[palette][6]
|
|
2964
|
+
}
|
|
2919
2965
|
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2966
|
+
return (
|
|
2967
|
+
<button
|
|
2968
|
+
title={palette}
|
|
2969
|
+
key={palette}
|
|
2970
|
+
onClick={e => {
|
|
2971
|
+
e.preventDefault()
|
|
2972
|
+
updateConfig({ ...config, palette })
|
|
2973
|
+
}}
|
|
2974
|
+
className={config.palette === palette ? 'selected' : ''}
|
|
2975
|
+
>
|
|
2976
|
+
<span style={colorOne}></span>
|
|
2977
|
+
<span style={colorTwo}></span>
|
|
2978
|
+
<span style={colorThree}></span>
|
|
2979
|
+
</button>
|
|
2980
|
+
)
|
|
2981
|
+
})}
|
|
2982
|
+
</ul>
|
|
2983
|
+
</>
|
|
2984
|
+
)}
|
|
2937
2985
|
</>
|
|
2938
2986
|
)}
|
|
2939
2987
|
{(config.visualizationType === 'Paired Bar' || config.visualizationType === 'Deviation Bar') && (
|
|
@@ -2990,9 +3038,9 @@ const EditorPanel = () => {
|
|
|
2990
3038
|
/>
|
|
2991
3039
|
</>
|
|
2992
3040
|
)}
|
|
2993
|
-
{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' />}
|
|
3041
|
+
{visSupportsBarThickness() && 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' />}
|
|
2994
3042
|
{((config.visualizationType === 'Bar' && config.orientation !== 'horizontal') || config.visualizationType === 'Combo') && <TextField value={config.barThickness} type='number' fieldName='barThickness' label='Bar Thickness' updateField={updateField} />}
|
|
2995
|
-
{(
|
|
3043
|
+
{visSupportsBarSpace() && <TextField type='number' value={config.barSpace || '15'} fieldName='barSpace' label='Bar Space' updateField={updateField} min='0' />}
|
|
2996
3044
|
{(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} />}
|
|
2997
3045
|
|
|
2998
3046
|
{config.visualizationType === 'Spark Line' && (
|