@cdc/chart 4.24.9 → 4.24.11
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 +45911 -41739
- package/examples/feature/boxplot/boxplot-data.json +88 -22
- package/examples/feature/boxplot/boxplot.json +540 -16
- package/examples/feature/boxplot/testing.csv +7 -7
- package/examples/feature/sankey/sankey-example-data.json +0 -1
- package/examples/private/test.json +20092 -0
- package/index.html +4 -4
- package/package.json +2 -2
- package/src/CdcChart.tsx +209 -188
- package/src/_stories/Chart.CustomColors.stories.tsx +19 -0
- package/src/_stories/Chart.DynamicSeries.stories.tsx +27 -0
- package/src/_stories/Chart.Legend.Gradient.stories.tsx +74 -0
- package/src/_stories/Chart.stories.tsx +30 -3
- package/src/_stories/ChartAxisLabels.stories.tsx +20 -0
- package/src/_stories/ChartAxisTitles.stories.tsx +53 -0
- package/src/_stories/ChartEditor.stories.tsx +27 -0
- package/src/_stories/ChartLine.Suppression.stories.tsx +25 -0
- package/src/_stories/ChartPrefixSuffix.stories.tsx +159 -0
- package/src/_stories/_mock/boxplot_multiseries.json +647 -0
- package/src/_stories/_mock/dynamic_series_bar_config.json +723 -0
- package/src/_stories/_mock/dynamic_series_config.json +979 -0
- package/src/_stories/_mock/horizontal_bar.json +257 -0
- package/src/_stories/_mock/large_x_axis_labels.json +261 -0
- package/src/_stories/_mock/paired-bar.json +262 -0
- package/src/_stories/_mock/pie_with_data.json +255 -0
- package/{examples/feature/scatterplot/scatterplot.json → src/_stories/_mock/scatterplot_mock.json} +62 -92
- package/src/_stories/_mock/simplified_line.json +1510 -0
- package/src/_stories/_mock/suppression_mock.json +1549 -0
- package/src/components/Annotations/components/AnnotationDraggable.tsx +0 -3
- package/src/components/Annotations/components/AnnotationDropdown.tsx +1 -1
- package/src/components/Axis/Categorical.Axis.tsx +22 -4
- package/src/components/BarChart/components/BarChart.Horizontal.tsx +95 -16
- package/src/components/BarChart/components/BarChart.StackedHorizontal.tsx +41 -17
- package/src/components/BarChart/components/BarChart.StackedVertical.tsx +43 -9
- package/src/components/BarChart/components/BarChart.Vertical.tsx +123 -47
- package/src/components/BarChart/helpers/index.ts +23 -5
- package/src/components/BoxPlot/BoxPlot.tsx +189 -0
- package/src/components/BrushChart.tsx +3 -2
- package/src/components/DeviationBar.jsx +58 -8
- package/src/components/EditorPanel/EditorPanel.tsx +127 -102
- package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +11 -28
- package/src/components/EditorPanel/components/Panels/Panel.BoxPlot.tsx +51 -6
- package/src/components/EditorPanel/components/Panels/Panel.General.tsx +21 -4
- package/src/components/EditorPanel/components/Panels/Panel.Regions.tsx +40 -9
- package/src/components/EditorPanel/components/Panels/Panel.Sankey.tsx +3 -3
- package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +121 -56
- package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +296 -35
- package/src/components/EditorPanel/components/panels.scss +4 -6
- package/src/components/EditorPanel/editor-panel.scss +0 -8
- package/src/components/EditorPanel/helpers/tests/updateFieldRankByValue.test.ts +38 -0
- package/src/components/EditorPanel/helpers/updateFieldRankByValue.ts +42 -0
- package/src/components/EditorPanel/useEditorPermissions.ts +16 -1
- package/src/components/ForestPlot/ForestPlot.tsx +2 -3
- package/src/components/ForestPlot/ForestPlotProps.ts +2 -0
- package/src/components/Legend/Legend.Component.tsx +23 -24
- package/src/components/Legend/Legend.Suppression.tsx +25 -20
- package/src/components/Legend/Legend.tsx +16 -18
- package/src/components/Legend/helpers/index.ts +16 -19
- package/src/components/LegendWrapper.tsx +3 -1
- package/src/components/LineChart/components/LineChart.Circle.tsx +10 -0
- package/src/components/LineChart/helpers.ts +48 -43
- package/src/components/LineChart/index.tsx +88 -82
- package/src/components/LinearChart.tsx +747 -562
- package/src/components/PairedBarChart.jsx +50 -10
- package/src/components/PieChart/PieChart.tsx +1 -6
- package/src/components/Regions/components/Regions.tsx +33 -19
- package/src/components/Sankey/index.tsx +50 -32
- package/src/components/Sankey/sankey.scss +6 -5
- package/src/components/Sankey/useSankeyAlert.tsx +60 -0
- package/src/components/ScatterPlot/ScatterPlot.jsx +20 -4
- package/src/components/ZoomBrush.tsx +25 -6
- package/src/coreStyles_chart.scss +3 -0
- package/src/data/initial-state.js +8 -10
- package/src/helpers/configHelpers.ts +28 -0
- package/src/helpers/handleRankByValue.ts +15 -0
- package/src/helpers/sizeHelpers.ts +25 -0
- package/src/helpers/tests/handleRankByValue.test.ts +37 -0
- package/src/helpers/tests/sizeHelpers.test.ts +80 -0
- package/src/hooks/useColorPalette.js +10 -2
- package/src/hooks/useLegendClasses.ts +13 -22
- package/src/hooks/useMinMax.ts +27 -13
- package/src/hooks/useReduceData.ts +43 -10
- package/src/hooks/useScales.ts +87 -38
- package/src/hooks/useTooltip.tsx +62 -53
- package/src/index.jsx +1 -0
- package/src/scss/DataTable.scss +5 -4
- package/src/scss/main.scss +57 -70
- package/src/types/ChartConfig.ts +43 -34
- package/src/types/ChartContext.ts +22 -15
- package/src/types/ForestPlot.ts +8 -0
- package/src/_stories/Chart.Legend.Gradient.tsx +0 -19
- package/src/_stories/ChartBrush.stories.tsx +0 -19
- package/src/components/BoxPlot/BoxPlot.jsx +0 -111
- package/src/components/LinearChart.jsx +0 -817
|
@@ -6,13 +6,30 @@ import { Text } from '@visx/text'
|
|
|
6
6
|
import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
|
|
7
7
|
import useIntersectionObserver from '../hooks/useIntersectionObserver'
|
|
8
8
|
import { getContrastColor } from '@cdc/core/helpers/cove/accessibility'
|
|
9
|
+
import { getTextWidth } from '@cdc/core/helpers/getTextWidth'
|
|
9
10
|
|
|
10
11
|
export default function DeviationBar({ height, xScale }) {
|
|
11
|
-
const {
|
|
12
|
+
const {
|
|
13
|
+
transformedData: data,
|
|
14
|
+
config,
|
|
15
|
+
formatNumber,
|
|
16
|
+
twoColorPalette,
|
|
17
|
+
updateConfig,
|
|
18
|
+
parseDate,
|
|
19
|
+
formatDate,
|
|
20
|
+
currentViewport
|
|
21
|
+
} = useContext(ConfigContext)
|
|
12
22
|
const { barStyle, tipRounding, roundingStyle, twoColor } = config
|
|
13
23
|
const barRefs = useRef([])
|
|
14
24
|
const [windowWidth, setWindowWidth] = useState(window.innerWidth)
|
|
15
|
-
const radius =
|
|
25
|
+
const radius =
|
|
26
|
+
roundingStyle === 'standard'
|
|
27
|
+
? '8px'
|
|
28
|
+
: roundingStyle === 'shallow'
|
|
29
|
+
? '5px'
|
|
30
|
+
: roundingStyle === 'finger'
|
|
31
|
+
? '15px'
|
|
32
|
+
: '0px'
|
|
16
33
|
const fontSize = { small: 16, medium: 18, large: 20 }
|
|
17
34
|
const isRounded = config.barStyle === 'rounded'
|
|
18
35
|
const target = Number(config.xAxis.target)
|
|
@@ -148,7 +165,10 @@ export default function DeviationBar({ height, xScale }) {
|
|
|
148
165
|
config.heights.horizontal = totalheight
|
|
149
166
|
|
|
150
167
|
// text,labels postiions
|
|
151
|
-
const textWidth = getTextWidth(
|
|
168
|
+
const textWidth = getTextWidth(
|
|
169
|
+
formatNumber(barValue, 'left'),
|
|
170
|
+
`normal ${fontSize[config.fontSize]}px sans-serif`
|
|
171
|
+
)
|
|
152
172
|
const textFits = textWidth < barWidth - 6
|
|
153
173
|
const textX = barBaseX
|
|
154
174
|
const textY = barY + barHeight / 2
|
|
@@ -167,7 +187,10 @@ export default function DeviationBar({ height, xScale }) {
|
|
|
167
187
|
let textProps = getTextProps(config.isLollipopChart, textFits, lollipopShapeSize, fill)
|
|
168
188
|
// tooltips
|
|
169
189
|
const xAxisValue = formatNumber(barValue, 'left')
|
|
170
|
-
const yAxisValue =
|
|
190
|
+
const yAxisValue =
|
|
191
|
+
config.runtime.yAxis.type === 'date'
|
|
192
|
+
? formatDate(parseDate(data[index][config.runtime.originalXAxis.dataKey]))
|
|
193
|
+
: data[index][config.runtime.originalXAxis.dataKey]
|
|
171
194
|
let yAxisTooltip = config.runtime.yAxis.label ? `${config.runtime.yAxis.label}: ${yAxisValue}` : yAxisValue
|
|
172
195
|
let xAxisTooltip = config.runtime.xAxis.label ? `${config.runtime.xAxis.label}: ${xAxisValue}` : xAxisValue
|
|
173
196
|
const tooltip = `<div>
|
|
@@ -190,7 +213,15 @@ export default function DeviationBar({ height, xScale }) {
|
|
|
190
213
|
data-tooltip-id={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`}
|
|
191
214
|
tabIndex={-1}
|
|
192
215
|
>
|
|
193
|
-
<div
|
|
216
|
+
<div
|
|
217
|
+
style={{
|
|
218
|
+
width: barWidth,
|
|
219
|
+
height: barHeight,
|
|
220
|
+
border: `${borderWidth}px solid #333`,
|
|
221
|
+
backgroundColor: barColor[barPosition],
|
|
222
|
+
...borderRadius
|
|
223
|
+
}}
|
|
224
|
+
></div>
|
|
194
225
|
</foreignObject>
|
|
195
226
|
{config.yAxis.displayNumbersOnBar && (
|
|
196
227
|
<Text verticalAnchor='middle' x={textX} y={textY} {...textProps[barPosition]}>
|
|
@@ -198,8 +229,25 @@ export default function DeviationBar({ height, xScale }) {
|
|
|
198
229
|
</Text>
|
|
199
230
|
)}
|
|
200
231
|
|
|
201
|
-
{config.isLollipopChart && config.lollipopShape === 'circle' &&
|
|
202
|
-
|
|
232
|
+
{config.isLollipopChart && config.lollipopShape === 'circle' && (
|
|
233
|
+
<circle
|
|
234
|
+
cx={circleX}
|
|
235
|
+
cy={circleY}
|
|
236
|
+
r={lollipopShapeSize / 2}
|
|
237
|
+
fill={barColor[barPosition]}
|
|
238
|
+
style={{ filter: 'unset', opacity: 1 }}
|
|
239
|
+
/>
|
|
240
|
+
)}
|
|
241
|
+
{config.isLollipopChart && config.lollipopShape === 'square' && (
|
|
242
|
+
<rect
|
|
243
|
+
x={squareX}
|
|
244
|
+
y={squareY}
|
|
245
|
+
width={lollipopShapeSize}
|
|
246
|
+
height={lollipopShapeSize}
|
|
247
|
+
fill={barColor[barPosition]}
|
|
248
|
+
style={{ opacity: 1, filter: 'unset' }}
|
|
249
|
+
></rect>
|
|
250
|
+
)}
|
|
203
251
|
</Group>
|
|
204
252
|
)
|
|
205
253
|
})}
|
|
@@ -209,7 +257,9 @@ export default function DeviationBar({ height, xScale }) {
|
|
|
209
257
|
</Text>
|
|
210
258
|
)}
|
|
211
259
|
|
|
212
|
-
{shouldShowTargetLine &&
|
|
260
|
+
{shouldShowTargetLine && (
|
|
261
|
+
<Line from={{ x: targetX, y: 0 }} to={{ x: targetX, y: height }} stroke='#333' strokeWidth={2} />
|
|
262
|
+
)}
|
|
213
263
|
</Group>
|
|
214
264
|
<foreignObject y={height / 2} ref={targetRef}></foreignObject>
|
|
215
265
|
</ErrorBoundary>
|
|
@@ -43,6 +43,7 @@ import { Anchor } from '@cdc/core/types/Axis'
|
|
|
43
43
|
import EditorPanelContext from './EditorPanelContext'
|
|
44
44
|
import _ from 'lodash'
|
|
45
45
|
import { adjustedSymbols as symbolCodes } from '@cdc/core/helpers/footnoteSymbols'
|
|
46
|
+
import { updateFieldRankByValue } from './helpers/updateFieldRankByValue'
|
|
46
47
|
|
|
47
48
|
interface PreliminaryProps {
|
|
48
49
|
config: ChartConfig
|
|
@@ -76,7 +77,7 @@ const PreliminaryData: React.FC<PreliminaryProps> = ({ config, updateConfig, dat
|
|
|
76
77
|
const getStyleOptions = type => {
|
|
77
78
|
const options = Object.keys(lineCodes)
|
|
78
79
|
if (type === 'suppression') {
|
|
79
|
-
return options.slice(0, -
|
|
80
|
+
return options.slice(0, -2)
|
|
80
81
|
} else {
|
|
81
82
|
return options
|
|
82
83
|
}
|
|
@@ -170,7 +171,7 @@ const PreliminaryData: React.FC<PreliminaryProps> = ({ config, updateConfig, dat
|
|
|
170
171
|
<p> {type === 'suppression' ? 'Suppressed' : 'Effect'} Data</p>
|
|
171
172
|
<button
|
|
172
173
|
type='button'
|
|
173
|
-
className='
|
|
174
|
+
className='btn btn-danger'
|
|
174
175
|
onClick={event => {
|
|
175
176
|
event.preventDefault()
|
|
176
177
|
removeColumn(i)
|
|
@@ -449,7 +450,7 @@ const PreliminaryData: React.FC<PreliminaryProps> = ({ config, updateConfig, dat
|
|
|
449
450
|
}
|
|
450
451
|
)}
|
|
451
452
|
|
|
452
|
-
<button type='button' onClick={addColumn} className='btn full-width'>
|
|
453
|
+
<button type='button' onClick={addColumn} className='btn btn-primary full-width'>
|
|
453
454
|
{config.visualizationType === 'Line'
|
|
454
455
|
? 'Add Special Line'
|
|
455
456
|
: config.visualizationType === 'Bar'
|
|
@@ -529,7 +530,7 @@ const CategoricalAxis: React.FC<CategoricalAxisProps> = ({ config, updateConfig,
|
|
|
529
530
|
<p>Axis Category {i + 1}</p>
|
|
530
531
|
<button
|
|
531
532
|
type='button'
|
|
532
|
-
className='
|
|
533
|
+
className='btn btn-danger'
|
|
533
534
|
onClick={event => {
|
|
534
535
|
event.preventDefault()
|
|
535
536
|
removeColumn(i)
|
|
@@ -582,7 +583,7 @@ const CategoricalAxis: React.FC<CategoricalAxisProps> = ({ config, updateConfig,
|
|
|
582
583
|
)
|
|
583
584
|
})}
|
|
584
585
|
|
|
585
|
-
<button type='button' onClick={addColumn} className='btn full-width'>
|
|
586
|
+
<button type='button' onClick={addColumn} className='btn btn-primary full-width'>
|
|
586
587
|
Add Axis Category
|
|
587
588
|
</button>
|
|
588
589
|
</>
|
|
@@ -618,52 +619,35 @@ const EditorPanel = () => {
|
|
|
618
619
|
const { leftMax, rightMax } = useMinMax(properties)
|
|
619
620
|
|
|
620
621
|
const {
|
|
621
|
-
headerColors,
|
|
622
|
-
visSupportsTooltipLines,
|
|
623
|
-
visSupportsNonSequentialPallete,
|
|
624
|
-
visSupportsSequentialPallete,
|
|
625
|
-
visSupportsReverseColorPalette,
|
|
626
|
-
visHasLabelOnData,
|
|
627
|
-
visHasNumbersOnBars,
|
|
628
622
|
visHasAnchors,
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
visHasSelectableLegendValues,
|
|
632
|
-
visCanAnimate,
|
|
623
|
+
visHasBrushChart,
|
|
624
|
+
visHasCategoricalAxis,
|
|
633
625
|
visHasLegend,
|
|
634
626
|
visHasLegendAxisAlign,
|
|
635
627
|
visHasLegendColorCategory,
|
|
636
|
-
|
|
628
|
+
visHasSelectableLegendValues,
|
|
637
629
|
visSupportsDateCategoryAxis,
|
|
638
|
-
visSupportsValueAxisMin,
|
|
639
|
-
visSupportsValueAxisMax,
|
|
640
630
|
visSupportsDateCategoryAxisLabel,
|
|
641
631
|
visSupportsDateCategoryAxisLine,
|
|
632
|
+
visSupportsDateCategoryAxisMax,
|
|
633
|
+
visSupportsDateCategoryAxisMin,
|
|
634
|
+
visSupportsDateCategoryAxisPadding,
|
|
642
635
|
visSupportsDateCategoryAxisTicks,
|
|
643
|
-
|
|
636
|
+
visSupportsDateCategoryHeight,
|
|
644
637
|
visSupportsDateCategoryNumTicks,
|
|
645
|
-
|
|
646
|
-
|
|
638
|
+
visSupportsDateCategoryTickRotation,
|
|
639
|
+
visSupportsDynamicSeries,
|
|
647
640
|
visSupportsFilters,
|
|
648
|
-
visSupportsPreliminaryData,
|
|
649
|
-
visSupportsValueAxisGridLines,
|
|
650
|
-
visSupportsValueAxisLine,
|
|
651
|
-
visSupportsValueAxisTicks,
|
|
652
|
-
visSupportsValueAxisLabels,
|
|
653
|
-
visSupportsBarSpace,
|
|
654
|
-
visSupportsBarThickness,
|
|
655
|
-
visSupportsFootnotes,
|
|
656
|
-
visSupportsSuperTitle,
|
|
657
|
-
visSupportsDataCutoff,
|
|
658
|
-
visSupportsChartHeight,
|
|
659
641
|
visSupportsLeftValueAxis,
|
|
660
|
-
|
|
642
|
+
visSupportsPreliminaryData,
|
|
661
643
|
visSupportsRankByValue,
|
|
662
644
|
visSupportsResponsiveTicks,
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
645
|
+
visSupportsValueAxisGridLines,
|
|
646
|
+
visSupportsValueAxisLabels,
|
|
647
|
+
visSupportsValueAxisLine,
|
|
648
|
+
visSupportsValueAxisMax,
|
|
649
|
+
visSupportsValueAxisMin,
|
|
650
|
+
visSupportsValueAxisTicks
|
|
667
651
|
} = useEditorPermissions()
|
|
668
652
|
|
|
669
653
|
// when the visualization type changes we
|
|
@@ -742,7 +726,7 @@ const EditorPanel = () => {
|
|
|
742
726
|
updatedConfig.orientation = 'vertical'
|
|
743
727
|
}
|
|
744
728
|
if (isDateScale(updatedConfig.xAxis) && !updatedConfig.xAxis.padding) {
|
|
745
|
-
updatedConfig.xAxis.padding =
|
|
729
|
+
updatedConfig.xAxis.padding = 0
|
|
746
730
|
}
|
|
747
731
|
// DEV-8008 - Remove Bar styling when Line is converted to Bar
|
|
748
732
|
if (updatedConfig.visualizationType === 'Line') {
|
|
@@ -762,21 +746,7 @@ const EditorPanel = () => {
|
|
|
762
746
|
newValue
|
|
763
747
|
) // eslint-disable-line
|
|
764
748
|
|
|
765
|
-
if (section === 'boxplot' && subsection === 'legend') {
|
|
766
|
-
updateConfig({
|
|
767
|
-
...config,
|
|
768
|
-
[section]: {
|
|
769
|
-
...config[section],
|
|
770
|
-
[subsection]: {
|
|
771
|
-
...config.boxplot[subsection],
|
|
772
|
-
[fieldName]: newValue
|
|
773
|
-
}
|
|
774
|
-
}
|
|
775
|
-
})
|
|
776
|
-
return
|
|
777
|
-
}
|
|
778
|
-
|
|
779
|
-
if (section === 'boxplot' && subsection === 'labels') {
|
|
749
|
+
if (section === 'boxplot' && (subsection === 'legend' || subsection === 'labels')) {
|
|
780
750
|
updateConfig({
|
|
781
751
|
...config,
|
|
782
752
|
[section]: {
|
|
@@ -846,19 +816,6 @@ const EditorPanel = () => {
|
|
|
846
816
|
return null
|
|
847
817
|
}
|
|
848
818
|
|
|
849
|
-
useEffect(() => {
|
|
850
|
-
if (!config.general?.boxplot) return
|
|
851
|
-
if (!config.general.boxplot.firstQuartilePercentage) {
|
|
852
|
-
updateConfig({
|
|
853
|
-
...config,
|
|
854
|
-
boxplot: {
|
|
855
|
-
...config.boxplot,
|
|
856
|
-
firstQuartilePercentage: 25
|
|
857
|
-
}
|
|
858
|
-
})
|
|
859
|
-
}
|
|
860
|
-
}, [config])
|
|
861
|
-
|
|
862
819
|
const setLollipopShape = shape => {
|
|
863
820
|
updateConfig({
|
|
864
821
|
...config,
|
|
@@ -890,13 +847,6 @@ const EditorPanel = () => {
|
|
|
890
847
|
updateConfig({ ...config, series: newSeries }) // left axis series keys
|
|
891
848
|
}
|
|
892
849
|
|
|
893
|
-
const sortSeries = e => {
|
|
894
|
-
const series = config.series[0].dataKey
|
|
895
|
-
const sorted = data.sort((a, b) => a[series] - b[series])
|
|
896
|
-
const newData = e === 'asc' ? sorted : sorted.reverse()
|
|
897
|
-
updateConfig({ ...config }, newData)
|
|
898
|
-
}
|
|
899
|
-
|
|
900
850
|
const addNewExclusion = exclusionKey => {
|
|
901
851
|
let newExclusion = [...config.exclusions.keys]
|
|
902
852
|
newExclusion.push(exclusionKey)
|
|
@@ -1407,7 +1357,6 @@ const EditorPanel = () => {
|
|
|
1407
1357
|
handleSeriesChange,
|
|
1408
1358
|
handleAddNewHighlightedBar,
|
|
1409
1359
|
setCategoryAxis,
|
|
1410
|
-
sortSeries,
|
|
1411
1360
|
updateField,
|
|
1412
1361
|
warningMsg,
|
|
1413
1362
|
highlightedBarValues,
|
|
@@ -1448,14 +1397,15 @@ const EditorPanel = () => {
|
|
|
1448
1397
|
</AccordionItemButton>
|
|
1449
1398
|
</AccordionItemHeading>
|
|
1450
1399
|
<AccordionItemPanel>
|
|
1451
|
-
{
|
|
1400
|
+
{/* FEATURE to be reintroduced by DEV-9747 */}
|
|
1401
|
+
{/* {visSupportsDynamicSeries() && (
|
|
1452
1402
|
<CheckBox
|
|
1453
1403
|
value={config.dynamicSeries}
|
|
1454
1404
|
fieldName='dynamicSeries'
|
|
1455
1405
|
label='Dynamically generate series'
|
|
1456
1406
|
updateField={updateField}
|
|
1457
1407
|
/>
|
|
1458
|
-
)}
|
|
1408
|
+
)} */}
|
|
1459
1409
|
{config.dynamicSeries && config.visualizationType === 'Line' && (
|
|
1460
1410
|
<Select
|
|
1461
1411
|
fieldName='dynamicSeriesType'
|
|
@@ -1571,10 +1521,14 @@ const EditorPanel = () => {
|
|
|
1571
1521
|
)}
|
|
1572
1522
|
{visSupportsRankByValue() && config.series && config.series.length === 1 && (
|
|
1573
1523
|
<Select
|
|
1574
|
-
|
|
1524
|
+
value={config.rankByValue}
|
|
1525
|
+
fieldName='rankByValue'
|
|
1575
1526
|
label='Rank by Value'
|
|
1576
1527
|
initial='Select'
|
|
1577
|
-
|
|
1528
|
+
updateField={(_section, _subsection, _fieldName, value) => {
|
|
1529
|
+
const [newConfig, newData] = updateFieldRankByValue(config, value, data)
|
|
1530
|
+
updateConfig(newConfig, newData)
|
|
1531
|
+
}}
|
|
1578
1532
|
options={['asc', 'desc']}
|
|
1579
1533
|
/>
|
|
1580
1534
|
)}
|
|
@@ -1803,6 +1757,17 @@ const EditorPanel = () => {
|
|
|
1803
1757
|
updateField={updateField}
|
|
1804
1758
|
/>
|
|
1805
1759
|
)}
|
|
1760
|
+
{visSupportsValueAxisGridLines() && (
|
|
1761
|
+
<CheckBox
|
|
1762
|
+
value={config.yAxis.labelsAboveGridlines}
|
|
1763
|
+
section='yAxis'
|
|
1764
|
+
fieldName='labelsAboveGridlines'
|
|
1765
|
+
label='Tick labels above gridlines'
|
|
1766
|
+
updateField={updateField}
|
|
1767
|
+
disabled={!config.yAxis.gridLines}
|
|
1768
|
+
title={!config.yAxis.gridLines ? 'Show gridlines to enable' : ''}
|
|
1769
|
+
/>
|
|
1770
|
+
)}
|
|
1806
1771
|
<CheckBox
|
|
1807
1772
|
value={config.yAxis.enablePadding}
|
|
1808
1773
|
section='yAxis'
|
|
@@ -2007,6 +1972,14 @@ const EditorPanel = () => {
|
|
|
2007
1972
|
) : (
|
|
2008
1973
|
config.visualizationType !== 'Pie' && (
|
|
2009
1974
|
<>
|
|
1975
|
+
<CheckBox
|
|
1976
|
+
display={!visHasCategoricalAxis()}
|
|
1977
|
+
value={config.dataFormat.onlyShowTopPrefixSuffix}
|
|
1978
|
+
section='dataFormat'
|
|
1979
|
+
fieldName='onlyShowTopPrefixSuffix'
|
|
1980
|
+
label='Only Show Top Prefix/Suffix'
|
|
1981
|
+
updateField={updateField}
|
|
1982
|
+
/>
|
|
2010
1983
|
<CheckBox
|
|
2011
1984
|
display={!visHasCategoricalAxis()}
|
|
2012
1985
|
value={config.yAxis.hideAxis}
|
|
@@ -2164,7 +2137,7 @@ const EditorPanel = () => {
|
|
|
2164
2137
|
</Accordion>
|
|
2165
2138
|
|
|
2166
2139
|
<button
|
|
2167
|
-
className='btn full-width'
|
|
2140
|
+
className='btn btn-primary full-width'
|
|
2168
2141
|
onClick={e => {
|
|
2169
2142
|
e.preventDefault()
|
|
2170
2143
|
const anchors = [...config.yAxis.anchors]
|
|
@@ -2290,7 +2263,7 @@ const EditorPanel = () => {
|
|
|
2290
2263
|
</Accordion>
|
|
2291
2264
|
|
|
2292
2265
|
<button
|
|
2293
|
-
className='btn full-width'
|
|
2266
|
+
className='btn btn-primary full-width'
|
|
2294
2267
|
onClick={e => {
|
|
2295
2268
|
e.preventDefault()
|
|
2296
2269
|
const anchors = [...config.xAxis.anchors]
|
|
@@ -2515,7 +2488,6 @@ const EditorPanel = () => {
|
|
|
2515
2488
|
)}
|
|
2516
2489
|
</select>
|
|
2517
2490
|
</label>
|
|
2518
|
-
|
|
2519
2491
|
<CheckBox
|
|
2520
2492
|
value={config.xAxis.manual}
|
|
2521
2493
|
section='xAxis'
|
|
@@ -2523,6 +2495,14 @@ const EditorPanel = () => {
|
|
|
2523
2495
|
label='Manual Ticks'
|
|
2524
2496
|
updateField={updateField}
|
|
2525
2497
|
/>
|
|
2498
|
+
<CheckBox
|
|
2499
|
+
display={config.xAxis.type !== 'categorical'}
|
|
2500
|
+
value={config.xAxis.sortByRecentDate}
|
|
2501
|
+
section='xAxis'
|
|
2502
|
+
fieldName='sortByRecentDate'
|
|
2503
|
+
label='Show dates newest to oldest'
|
|
2504
|
+
updateField={updateField}
|
|
2505
|
+
/>
|
|
2526
2506
|
|
|
2527
2507
|
{visSupportsDateCategoryAxisPadding() && (
|
|
2528
2508
|
<TextField
|
|
@@ -2681,11 +2661,7 @@ const EditorPanel = () => {
|
|
|
2681
2661
|
<>
|
|
2682
2662
|
<p style={{ padding: '1.5em 0 0.5em', fontSize: '.9rem', lineHeight: '1rem' }}>
|
|
2683
2663
|
Format how charts should parse and display your dates using{' '}
|
|
2684
|
-
<a
|
|
2685
|
-
href='https://github.com/d3/d3-time-format#locale_format'
|
|
2686
|
-
target='_blank'
|
|
2687
|
-
rel='noreferrer'
|
|
2688
|
-
>
|
|
2664
|
+
<a href='https://d3js.org/d3-time-format#locale_format' target='_blank' rel='noreferrer'>
|
|
2689
2665
|
these guidelines
|
|
2690
2666
|
</a>
|
|
2691
2667
|
.
|
|
@@ -2816,6 +2792,29 @@ const EditorPanel = () => {
|
|
|
2816
2792
|
}
|
|
2817
2793
|
updateField={updateField}
|
|
2818
2794
|
/>
|
|
2795
|
+
<CheckBox
|
|
2796
|
+
value={config.xAxis.showYearsOnce}
|
|
2797
|
+
section='xAxis'
|
|
2798
|
+
fieldName='showYearsOnce'
|
|
2799
|
+
label='Show years once'
|
|
2800
|
+
tooltip={
|
|
2801
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
2802
|
+
<Tooltip.Target>
|
|
2803
|
+
<Icon
|
|
2804
|
+
display='question'
|
|
2805
|
+
style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }}
|
|
2806
|
+
/>
|
|
2807
|
+
</Tooltip.Target>
|
|
2808
|
+
<Tooltip.Content>
|
|
2809
|
+
<p>
|
|
2810
|
+
When this option is checked and the date format for the axis includes years, each year
|
|
2811
|
+
will only be shown once in the axis.
|
|
2812
|
+
</p>
|
|
2813
|
+
</Tooltip.Content>
|
|
2814
|
+
</Tooltip>
|
|
2815
|
+
}
|
|
2816
|
+
updateField={updateField}
|
|
2817
|
+
/>
|
|
2819
2818
|
{visHasBrushChart() && (
|
|
2820
2819
|
<CheckBox
|
|
2821
2820
|
value={config.brush?.active}
|
|
@@ -3040,15 +3039,17 @@ const EditorPanel = () => {
|
|
|
3040
3039
|
updateField={updateField}
|
|
3041
3040
|
/>
|
|
3042
3041
|
)}
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3042
|
+
{config.orientation === 'horizontal' && (
|
|
3043
|
+
<TextField
|
|
3044
|
+
value={config.xAxis.labelOffset}
|
|
3045
|
+
section='xAxis'
|
|
3046
|
+
fieldName='labelOffset'
|
|
3047
|
+
label='Label offset'
|
|
3048
|
+
type='number'
|
|
3049
|
+
className='number-narrow'
|
|
3050
|
+
updateField={updateField}
|
|
3051
|
+
/>
|
|
3052
|
+
)}
|
|
3052
3053
|
|
|
3053
3054
|
{/* Hiding this for now, not interested in moving the axis lines away from chart comp. right now. */}
|
|
3054
3055
|
{/* <TextField value={config.xAxis.axisPadding} type='number' max={10} min={0} section='xAxis' fieldName='axisPadding' label={'Axis Padding'} className='number-narrow' updateField={updateField} /> */}
|
|
@@ -3187,7 +3188,7 @@ const EditorPanel = () => {
|
|
|
3187
3188
|
highlightedBarValues.map((highlightedBarValue, i) => (
|
|
3188
3189
|
<fieldset>
|
|
3189
3190
|
<div className='edit-block' key={`highlighted-bar-${i}`}>
|
|
3190
|
-
<button className='
|
|
3191
|
+
<button className='btn btn-danger' onClick={e => handleRemoveHighlightedBar(e, i)}>
|
|
3191
3192
|
Remove
|
|
3192
3193
|
</button>
|
|
3193
3194
|
<p>Highlighted Bar {i + 1}</p>
|
|
@@ -3245,7 +3246,7 @@ const EditorPanel = () => {
|
|
|
3245
3246
|
</div>
|
|
3246
3247
|
</fieldset>
|
|
3247
3248
|
))}
|
|
3248
|
-
<button className='btn full-width' onClick={e => handleAddNewHighlightedBar(e)}>
|
|
3249
|
+
<button className='btn btn-primary full-width' onClick={e => handleAddNewHighlightedBar(e)}>
|
|
3249
3250
|
Add Highlighted Bar
|
|
3250
3251
|
</button>
|
|
3251
3252
|
</>
|
|
@@ -3305,6 +3306,30 @@ const EditorPanel = () => {
|
|
|
3305
3306
|
</>
|
|
3306
3307
|
)}
|
|
3307
3308
|
|
|
3309
|
+
{visSupportsDateCategoryAxisMin() && (
|
|
3310
|
+
<TextField
|
|
3311
|
+
value={config.xAxis.min}
|
|
3312
|
+
section='xAxis'
|
|
3313
|
+
fieldName='min'
|
|
3314
|
+
type='number'
|
|
3315
|
+
label='min value'
|
|
3316
|
+
placeholder='Auto'
|
|
3317
|
+
updateField={updateField}
|
|
3318
|
+
/>
|
|
3319
|
+
)}
|
|
3320
|
+
|
|
3321
|
+
{visSupportsDateCategoryAxisMax() && (
|
|
3322
|
+
<TextField
|
|
3323
|
+
value={config.xAxis.max}
|
|
3324
|
+
section='xAxis'
|
|
3325
|
+
fieldName='max'
|
|
3326
|
+
type='number'
|
|
3327
|
+
label='max value'
|
|
3328
|
+
placeholder='Auto'
|
|
3329
|
+
updateField={updateField}
|
|
3330
|
+
/>
|
|
3331
|
+
)}
|
|
3332
|
+
|
|
3308
3333
|
{/* anchors */}
|
|
3309
3334
|
{visHasAnchors() && config.orientation !== 'horizontal' && (
|
|
3310
3335
|
<div className='edit-block'>
|
|
@@ -3413,7 +3438,7 @@ const EditorPanel = () => {
|
|
|
3413
3438
|
</Accordion>
|
|
3414
3439
|
|
|
3415
3440
|
<button
|
|
3416
|
-
className='btn full-width'
|
|
3441
|
+
className='btn btn-primary full-width'
|
|
3417
3442
|
onClick={e => {
|
|
3418
3443
|
e.preventDefault()
|
|
3419
3444
|
const anchors = [...config.xAxis.anchors]
|
|
@@ -3542,7 +3567,7 @@ const EditorPanel = () => {
|
|
|
3542
3567
|
</Accordion>
|
|
3543
3568
|
|
|
3544
3569
|
<button
|
|
3545
|
-
className='btn full-width'
|
|
3570
|
+
className='btn btn-primary full-width'
|
|
3546
3571
|
onClick={e => {
|
|
3547
3572
|
e.preventDefault()
|
|
3548
3573
|
const anchors = [...config.yAxis.anchors]
|
|
@@ -3789,7 +3814,7 @@ const EditorPanel = () => {
|
|
|
3789
3814
|
config.legend.seriesHighlight.map((val, i) => (
|
|
3790
3815
|
<fieldset className='edit-block' key={`${val}-${i}`}>
|
|
3791
3816
|
<button
|
|
3792
|
-
className='
|
|
3817
|
+
className='btn btn-danger'
|
|
3793
3818
|
onClick={event => {
|
|
3794
3819
|
event.preventDefault()
|
|
3795
3820
|
const updatedSeriesHighlight = [...config.legend.seriesHighlight]
|
|
@@ -3818,7 +3843,7 @@ const EditorPanel = () => {
|
|
|
3818
3843
|
</fieldset>
|
|
3819
3844
|
))}
|
|
3820
3845
|
<button
|
|
3821
|
-
className={'btn full-width'}
|
|
3846
|
+
className={'btn btn-primary full-width'}
|
|
3822
3847
|
onClick={event => {
|
|
3823
3848
|
event.preventDefault()
|
|
3824
3849
|
const legendColumns = getLegendColumns()
|
|
@@ -12,31 +12,11 @@ import { type PanelProps } from './../PanelProps'
|
|
|
12
12
|
import './../panels.scss'
|
|
13
13
|
|
|
14
14
|
const PanelAnnotate: React.FC<PanelProps> = props => {
|
|
15
|
-
const { updateConfig, config,
|
|
16
|
-
|
|
17
|
-
const getColumns = (filter = true) => {
|
|
18
|
-
const columns = {}
|
|
19
|
-
unfilteredData.forEach(row => {
|
|
20
|
-
Object.keys(row).forEach(columnName => (columns[columnName] = true))
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
if (filter) {
|
|
24
|
-
Object.keys(columns).forEach(key => {
|
|
25
|
-
if (
|
|
26
|
-
(config.series && config.series.filter(series => series.dataKey === key).length > 0) ||
|
|
27
|
-
(config.confidenceKeys && Object.keys(config.confidenceKeys).includes(key))
|
|
28
|
-
) {
|
|
29
|
-
delete columns[key]
|
|
30
|
-
}
|
|
31
|
-
})
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
return Object.keys(columns)
|
|
35
|
-
}
|
|
15
|
+
const { updateConfig, config, svgRef } = useContext(ConfigContext)
|
|
36
16
|
|
|
37
17
|
const handleAnnotationUpdate = (value, property, index) => {
|
|
38
|
-
const svgContainer = document.querySelector('.chart-container
|
|
39
|
-
const newSvgDims = [svgContainer
|
|
18
|
+
const svgContainer = document.querySelector('.chart-container > svg')?.getBoundingClientRect()
|
|
19
|
+
const newSvgDims = [svgContainer?.width, svgContainer?.height]
|
|
40
20
|
const annotations = [...config?.annotations]
|
|
41
21
|
annotations[index][property] = value
|
|
42
22
|
annotations[index].savedDimensions = newSvgDims
|
|
@@ -48,8 +28,11 @@ const PanelAnnotate: React.FC<PanelProps> = props => {
|
|
|
48
28
|
}
|
|
49
29
|
|
|
50
30
|
const handleAddAnnotation = () => {
|
|
51
|
-
|
|
52
|
-
const newSvgDims = [
|
|
31
|
+
// check if svg is animated svg or standard svg
|
|
32
|
+
const newSvgDims = [
|
|
33
|
+
svgRef?.current?.width?.baseVal?.value || svgRef?.current?.width,
|
|
34
|
+
svgRef?.current?.height?.baseVal?.value || svgRef?.current?.height
|
|
35
|
+
]
|
|
53
36
|
|
|
54
37
|
const newAnnotation = {
|
|
55
38
|
text: 'New Annotation',
|
|
@@ -300,7 +283,7 @@ const PanelAnnotate: React.FC<PanelProps> = props => {
|
|
|
300
283
|
</select>
|
|
301
284
|
</label>
|
|
302
285
|
|
|
303
|
-
<Button className='
|
|
286
|
+
<Button className='btn btn-danger full-width' onClick={() => handleRemoveAnnotation(index)}>
|
|
304
287
|
Delete Annotation
|
|
305
288
|
</Button>
|
|
306
289
|
</div>
|
|
@@ -308,9 +291,9 @@ const PanelAnnotate: React.FC<PanelProps> = props => {
|
|
|
308
291
|
</Accordion>
|
|
309
292
|
))}
|
|
310
293
|
{config?.annotations?.length < 3 && (
|
|
311
|
-
<
|
|
294
|
+
<button onClick={handleAddAnnotation} className='btn btn-primary mt-2 full-width'>
|
|
312
295
|
Add Annotation
|
|
313
|
-
</
|
|
296
|
+
</button>
|
|
314
297
|
)}
|
|
315
298
|
</Accordion.Section>
|
|
316
299
|
</Accordion>
|