@cdc/chart 4.25.11 → 4.26.2
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/CLAUDE.local.md +79 -0
- package/dist/{cdcchart-dgT_1dIT.es.js → cdcchart-DQ00cQCm.es.js} +1 -20
- package/dist/cdcchart.js +51401 -50814
- package/examples/default.json +378 -0
- package/examples/feature/__data__/horizon-chart-data.json +373 -0
- package/examples/feature/annotations/index.json +3 -6
- package/examples/feature/horizon/horizon-chart.json +395 -0
- package/examples/feature/pie/planet-pie-example-config.json +48 -2
- package/examples/line-chart-states.json +1085 -0
- package/examples/private/123.json +694 -0
- package/examples/private/DEV-12100.json +1303 -0
- package/examples/private/anchor-issue.json +4094 -0
- package/examples/private/backwards-slider.json +10430 -0
- package/examples/private/cat-y.json +1235 -0
- package/examples/private/data-points.json +228 -0
- package/examples/private/georgia.csv +160 -0
- package/examples/private/height.json +3915 -0
- package/examples/private/links.json +569 -0
- package/examples/private/quadrant.txt +30 -0
- package/examples/private/test-forecast.json +5510 -0
- package/examples/private/timeline-data.json +1 -0
- package/examples/private/timeline.json +389 -0
- package/examples/private/warming-stripe-test.json +2578 -0
- package/examples/private/warming-stripes.json +4763 -0
- package/examples/radar-chart-simple.json +133 -0
- package/examples/radar-chart.json +148 -0
- package/examples/tech-adoption-with-links.json +560 -0
- package/index.html +1 -36
- package/package.json +59 -60
- package/src/CdcChartComponent.tsx +206 -89
- package/src/_stories/Chart.Anchors.stories.tsx +10 -0
- package/src/_stories/Chart.BoxPlot.stories.tsx +7 -0
- package/src/_stories/Chart.CI.stories.tsx +13 -0
- package/src/_stories/Chart.Combo.stories.tsx +17 -0
- package/src/_stories/Chart.CustomColors.stories.tsx +4 -0
- package/src/_stories/Chart.DynamicSeries.stories.tsx +19 -0
- package/src/_stories/Chart.Filters.stories.tsx +4 -0
- package/src/_stories/Chart.Forecast.stories.tsx +4 -0
- package/src/_stories/Chart.HTMLInDataTable.stories.tsx +22 -0
- package/src/_stories/Chart.Legend.Gradient.stories.tsx +28 -0
- package/src/_stories/Chart.Patterns.stories.tsx +4 -0
- package/src/_stories/Chart.PreserveDecimals.stories.tsx +25 -0
- package/src/_stories/Chart.Regions.Categorical.stories.tsx +161 -0
- package/src/_stories/Chart.Regions.DateScale.stories.tsx +216 -0
- package/src/_stories/Chart.Regions.DateTimeScale.stories.tsx +312 -0
- package/src/_stories/Chart.ScatterPlot.stories.tsx +4 -0
- package/src/_stories/Chart.SmallMultiples.stories.tsx +16 -0
- package/src/_stories/Chart.stories.tsx +45 -0
- package/src/_stories/Chart.tooltip.stories.tsx +7 -0
- package/src/_stories/ChartAnnotation.stories.tsx +10 -0
- package/src/_stories/ChartAxisLabels.stories.tsx +4 -0
- package/src/_stories/ChartAxisTitles.stories.tsx +10 -0
- package/src/_stories/ChartBar.Editor.stories.tsx +11 -6
- package/src/_stories/ChartBrush.Editor.stories.tsx +295 -0
- package/src/_stories/ChartBrush.Matrix.Continuous.stories.tsx +41 -0
- package/src/_stories/ChartBrush.Matrix.Date.stories.tsx +114 -0
- package/src/_stories/ChartBrush.Matrix.DateTime.stories.tsx +78 -0
- package/src/_stories/ChartBrush.stories.tsx +57 -0
- package/src/_stories/ChartEditor.Editor.stories.tsx +3 -5
- package/src/_stories/ChartEditor.stories.tsx +7 -0
- package/src/_stories/ChartLine.QuadrantAngles.stories.tsx +89 -0
- package/src/_stories/ChartLine.Suppression.stories.tsx +7 -0
- package/src/_stories/ChartLine.Symbols.stories.tsx +4 -0
- package/src/_stories/ChartPrefixSuffix.stories.tsx +46 -1
- package/src/_stories/TechAdoptionWithLinks.stories.tsx +34 -0
- package/src/_stories/_mock/brush_continuous.json +86 -0
- package/src/_stories/_mock/brush_date_large.json +176 -0
- package/src/_stories/_mock/brush_enabled.json +326 -0
- package/src/_stories/_mock/brush_mock.json +2 -69
- package/src/_stories/_mock/horizontal-bars-dynamic-y-axis.json +413 -0
- package/src/_stories/_mock/line_chart_angle_near_zero_fall.json +195 -0
- package/src/_stories/_mock/line_chart_angle_near_zero_rise.json +195 -0
- package/src/_stories/_mock/line_chart_angle_q1_steep_upward.json +195 -0
- package/src/_stories/_mock/line_chart_angle_q2_gentle_downward.json +195 -0
- package/src/_stories/_mock/line_chart_angle_q3_steep_downward.json +195 -0
- package/src/_stories/_mock/line_chart_angle_q4_gentle_upward.json +195 -0
- package/src/_stories/_mock/line_chart_quadrant_angles.json +264 -0
- package/src/components/Annotations/components/AnnotationDraggable.styles.css +11 -17
- package/src/components/Annotations/components/AnnotationDraggable.tsx +240 -116
- package/src/components/Annotations/components/AnnotationDropdown.styles.css +1 -2
- package/src/components/Annotations/components/AnnotationDropdown.tsx +8 -12
- package/src/components/Annotations/components/AnnotationList.styles.css +4 -10
- package/src/components/Annotations/components/AnnotationList.tsx +5 -4
- package/src/components/Annotations/components/findNearestDatum.ts +75 -85
- package/src/components/Annotations/helpers/getVisibleAnnotations.ts +38 -0
- package/src/components/AreaChart/components/AreaChart.Stacked.jsx +1 -2
- package/src/components/Axis/BottomAxis.tsx +270 -0
- package/src/components/Axis/Categorical.Axis.tsx +6 -7
- package/src/components/Axis/LeftAxis.tsx +404 -0
- package/src/components/Axis/LeftAxisGridlines.tsx +77 -0
- package/src/components/Axis/PairedBarAxis.tsx +186 -0
- package/src/components/Axis/README.md +94 -0
- package/src/components/Axis/RightAxis.tsx +108 -0
- package/src/components/Axis/axis.constants.ts +21 -0
- package/src/components/Axis/index.ts +7 -0
- package/src/components/BarChart/components/BarChart.Horizontal.tsx +178 -24
- package/src/components/BarChart/components/BarChart.StackedHorizontal.tsx +3 -1
- package/src/components/BarChart/components/BarChart.StackedVertical.tsx +1 -0
- package/src/components/BarChart/components/BarChart.Vertical.tsx +6 -8
- package/src/components/BarChart/components/BarChart.tsx +7 -1
- package/src/components/BarChart/components/context.tsx +1 -0
- package/src/components/BarChart/helpers/useBarChart.ts +14 -2
- package/src/components/Brush/BrushSelector.tsx +1390 -0
- package/src/components/Brush/MiniChartPreview.tsx +400 -0
- package/src/components/DeviationBar.jsx +9 -7
- package/src/components/EditorPanel/EditorPanel.tsx +2734 -2595
- package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +60 -22
- package/src/components/EditorPanel/components/Panels/Panel.ForestPlotSettings.tsx +56 -34
- package/src/components/EditorPanel/components/Panels/Panel.General.tsx +137 -30
- package/src/components/EditorPanel/components/Panels/Panel.PatternSettings.tsx +2 -0
- package/src/components/EditorPanel/components/Panels/Panel.Radar.tsx +353 -0
- package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +0 -1
- package/src/components/EditorPanel/components/Panels/Panel.SmallMultiples.tsx +30 -25
- package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +42 -28
- package/src/components/EditorPanel/components/Panels/index.tsx +2 -0
- package/src/components/EditorPanel/useEditorPermissions.ts +81 -39
- package/src/components/HorizonChart/HorizonChart.tsx +131 -0
- package/src/components/HorizonChart/components/HorizonBand.tsx +160 -0
- package/src/components/HorizonChart/helpers/calculateHorizonBands.ts +27 -0
- package/src/components/HorizonChart/helpers/getHorizonLayerColors.ts +40 -0
- package/src/components/HorizonChart/index.tsx +3 -0
- package/src/components/Legend/Legend.Component.tsx +52 -4
- package/src/components/Legend/Legend.tsx +4 -3
- package/src/components/Legend/LegendValueRange.tsx +77 -0
- package/src/components/Legend/helpers/createFormatLabels.tsx +164 -2
- package/src/components/Legend/helpers/generateValueRanges.ts +92 -0
- package/src/components/Legend/helpers/index.ts +10 -6
- package/src/components/LineChart/helpers/README.md +292 -0
- package/src/components/LineChart/helpers/labelPositioning.test.ts +245 -0
- package/src/components/LineChart/helpers/labelPositioning.ts +304 -0
- package/src/components/LineChart/index.tsx +44 -8
- package/src/components/LinearChart/README.md +109 -0
- package/src/components/LinearChart/VisualizationRenderer.tsx +267 -0
- package/src/components/LinearChart/linearChart.constants.ts +84 -0
- package/src/components/LinearChart/tests/LinearChart.test.tsx +201 -0
- package/src/components/LinearChart/tests/mockConfigContext.ts +129 -0
- package/src/components/LinearChart/utils/tickFormatting.ts +146 -0
- package/src/components/LinearChart.tsx +338 -1082
- package/src/components/PairedBarChart.jsx +20 -3
- package/src/components/PieChart/PieChart.tsx +1 -1
- package/src/components/RadarChart/RadarAxis.tsx +78 -0
- package/src/components/RadarChart/RadarChart.tsx +298 -0
- package/src/components/RadarChart/RadarGrid.tsx +64 -0
- package/src/components/RadarChart/RadarPolygon.tsx +91 -0
- package/src/components/RadarChart/helpers.ts +83 -0
- package/src/components/RadarChart/index.tsx +3 -0
- package/src/components/Regions/components/Regions.tsx +365 -122
- package/src/components/ScatterPlot/ScatterPlot.jsx +2 -2
- package/src/components/SmallMultiples/SmallMultipleTile.tsx +5 -1
- package/src/components/WarmingStripes/WarmingStripes.tsx +230 -0
- package/src/components/WarmingStripes/WarmingStripesGradientLegend.css +35 -0
- package/src/components/WarmingStripes/WarmingStripesGradientLegend.tsx +104 -0
- package/src/components/WarmingStripes/index.tsx +3 -0
- package/src/data/initial-state.js +17 -2
- package/src/helpers/calculateHorizontalBarCategoryLabelWidth.ts +57 -0
- package/src/helpers/getExcludedData.ts +4 -0
- package/src/helpers/getMinMax.ts +12 -7
- package/src/helpers/handleChartAriaLabels.ts +19 -19
- package/src/helpers/handleLineType.ts +22 -18
- package/src/helpers/sizeHelpers.ts +0 -20
- package/src/helpers/smallMultiplesHelpers.ts +1 -1
- package/src/hooks/useChartHoverAnalytics.tsx +10 -9
- package/src/hooks/useProgrammaticTooltip.ts +23 -2
- package/src/hooks/useScales.ts +18 -1
- package/src/hooks/useTooltip.tsx +34 -10
- package/src/scss/DataTable.scss +0 -4
- package/src/scss/main.scss +22 -3
- package/src/selectors/README.md +68 -0
- package/src/store/chart.reducer.ts +2 -0
- package/src/test/CdcChart.test.jsx +1 -1
- package/src/types/ChartConfig.ts +21 -0
- package/src/types/ChartContext.ts +1 -0
- package/src/types/Horizon.ts +64 -0
- package/src/types/Label.ts +1 -0
- package/src/utils/analyticsTracking.ts +19 -0
- package/LICENSE +0 -201
- package/src/components/Annotations/components/helpers/index.tsx +0 -46
- package/src/components/Brush/BrushChart.tsx +0 -128
- package/src/components/Brush/BrushController.tsx +0 -71
- package/src/components/Brush/types.tsx +0 -8
- package/src/components/BrushChart.tsx +0 -223
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React, { useContext } from 'react'
|
|
2
2
|
import ConfigContext from '../../../../ConfigContext.js'
|
|
3
|
+
import { useEditorPermissions } from '../../useEditorPermissions'
|
|
3
4
|
|
|
4
5
|
// CDC Core
|
|
5
6
|
import Accordion from '@cdc/core/components/ui/Accordion'
|
|
@@ -13,7 +14,8 @@ import { type PanelProps } from './../PanelProps'
|
|
|
13
14
|
import './../panels.scss'
|
|
14
15
|
|
|
15
16
|
const PanelAnnotate: React.FC<PanelProps> = props => {
|
|
16
|
-
const { updateConfig, config,
|
|
17
|
+
const { updateConfig, config, transformedData } = useContext(ConfigContext)
|
|
18
|
+
const { visSupportsDataAnnotations } = useEditorPermissions()
|
|
17
19
|
|
|
18
20
|
const updateField = (section, subsection, fieldName, value) => {
|
|
19
21
|
if (subsection) {
|
|
@@ -39,11 +41,8 @@ const PanelAnnotate: React.FC<PanelProps> = props => {
|
|
|
39
41
|
}
|
|
40
42
|
|
|
41
43
|
const handleAnnotationUpdate = (value, property, index) => {
|
|
42
|
-
const svgContainer = document.querySelector('.chart-container > svg')?.getBoundingClientRect()
|
|
43
|
-
const newSvgDims = [svgContainer?.width, svgContainer?.height]
|
|
44
44
|
const annotations = [...config?.annotations]
|
|
45
45
|
annotations[index][property] = value
|
|
46
|
-
annotations[index].savedDimensions = newSvgDims
|
|
47
46
|
|
|
48
47
|
updateConfig({
|
|
49
48
|
...config,
|
|
@@ -52,15 +51,9 @@ const PanelAnnotate: React.FC<PanelProps> = props => {
|
|
|
52
51
|
}
|
|
53
52
|
|
|
54
53
|
const handleAddAnnotation = () => {
|
|
55
|
-
// check if svg is animated svg or standard svg
|
|
56
|
-
const newSvgDims = [
|
|
57
|
-
svgRef?.current?.width?.baseVal?.value || svgRef?.current?.width,
|
|
58
|
-
svgRef?.current?.height?.baseVal?.value || svgRef?.current?.height
|
|
59
|
-
]
|
|
60
|
-
|
|
61
54
|
const newAnnotation = {
|
|
62
|
-
text: 'New
|
|
63
|
-
|
|
55
|
+
text: 'New annotation',
|
|
56
|
+
anchorMode: 'fixed',
|
|
64
57
|
fontSize: 16,
|
|
65
58
|
bezier: 10,
|
|
66
59
|
show: {
|
|
@@ -84,20 +77,12 @@ const PanelAnnotate: React.FC<PanelProps> = props => {
|
|
|
84
77
|
subject: true,
|
|
85
78
|
label: true
|
|
86
79
|
},
|
|
87
|
-
seriesKey
|
|
80
|
+
// seriesKey and dataX are only set when switching to data mode
|
|
88
81
|
x: 50,
|
|
89
|
-
y:
|
|
90
|
-
xKey:
|
|
91
|
-
config.xAxis.type === 'date'
|
|
92
|
-
? new Date(config?.data?.[0]?.[config.xAxis.dataKey]).getTime()
|
|
93
|
-
: config.xAxis.type === 'categorical'
|
|
94
|
-
? '1/15/2016'
|
|
95
|
-
: '',
|
|
96
|
-
yKey: '',
|
|
82
|
+
y: 50,
|
|
97
83
|
dx: 20,
|
|
98
84
|
dy: -20,
|
|
99
85
|
opacity: '100',
|
|
100
|
-
savedDimensions: newSvgDims,
|
|
101
86
|
connectionType: 'line'
|
|
102
87
|
}
|
|
103
88
|
|
|
@@ -163,6 +148,59 @@ const PanelAnnotate: React.FC<PanelProps> = props => {
|
|
|
163
148
|
onChange={e => handleAnnotationUpdate(e.target.value, 'text', index)}
|
|
164
149
|
/>
|
|
165
150
|
</label>
|
|
151
|
+
|
|
152
|
+
{visSupportsDataAnnotations() && (
|
|
153
|
+
<Select
|
|
154
|
+
label='Position Mode:'
|
|
155
|
+
value={annotation.anchorMode || 'fixed'}
|
|
156
|
+
options={[
|
|
157
|
+
{ value: 'fixed', label: 'Fixed position' },
|
|
158
|
+
{ value: 'data', label: 'Snap to data' }
|
|
159
|
+
]}
|
|
160
|
+
section='annotations'
|
|
161
|
+
subsection={null}
|
|
162
|
+
fieldName='anchorMode'
|
|
163
|
+
updateField={(section, subsection, fieldName, value) => {
|
|
164
|
+
const updatedAnnotations = _.cloneDeep(config?.annotations)
|
|
165
|
+
updatedAnnotations[index].anchorMode = value
|
|
166
|
+
|
|
167
|
+
// When switching to data mode, ensure seriesKey and dataX are initialized
|
|
168
|
+
if (value === 'data') {
|
|
169
|
+
if (!updatedAnnotations[index].seriesKey) {
|
|
170
|
+
updatedAnnotations[index].seriesKey = config.series?.[0]?.dataKey || ''
|
|
171
|
+
}
|
|
172
|
+
if (!updatedAnnotations[index].dataX) {
|
|
173
|
+
updatedAnnotations[index].dataX = transformedData?.[0]?.[config.xAxis.dataKey] || ''
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
updateConfig({
|
|
178
|
+
...config,
|
|
179
|
+
annotations: updatedAnnotations
|
|
180
|
+
})
|
|
181
|
+
}}
|
|
182
|
+
/>
|
|
183
|
+
)}
|
|
184
|
+
|
|
185
|
+
{visSupportsDataAnnotations() && annotation.anchorMode === 'data' && (
|
|
186
|
+
<Select
|
|
187
|
+
label='Series:'
|
|
188
|
+
value={annotation.seriesKey || config.series?.[0]?.dataKey || ''}
|
|
189
|
+
options={config.series.map(s => s.dataKey)}
|
|
190
|
+
section='annotations'
|
|
191
|
+
subsection={null}
|
|
192
|
+
fieldName='seriesKey'
|
|
193
|
+
updateField={(section, subsection, fieldName, value) => {
|
|
194
|
+
const updatedAnnotations = _.cloneDeep(config?.annotations)
|
|
195
|
+
updatedAnnotations[index].seriesKey = value || config.series?.[0]?.dataKey
|
|
196
|
+
updateConfig({
|
|
197
|
+
...config,
|
|
198
|
+
annotations: updatedAnnotations
|
|
199
|
+
})
|
|
200
|
+
}}
|
|
201
|
+
/>
|
|
202
|
+
)}
|
|
203
|
+
|
|
166
204
|
<label>
|
|
167
205
|
Opacity
|
|
168
206
|
<br />
|
|
@@ -8,18 +8,24 @@ import WarningImage from '../../../../images/warning.svg'
|
|
|
8
8
|
|
|
9
9
|
// contexts
|
|
10
10
|
import ConfigContext from '../../../../ConfigContext'
|
|
11
|
+
import { useEditorPanelContext } from '../../EditorPanelContext'
|
|
11
12
|
|
|
12
13
|
// types
|
|
13
14
|
import { type ChartContext } from '../../../../types/ChartContext'
|
|
14
15
|
import { type PanelProps } from '../PanelProps'
|
|
15
16
|
|
|
16
|
-
import {
|
|
17
|
+
import {
|
|
18
|
+
AccordionItem,
|
|
19
|
+
AccordionItemHeading,
|
|
20
|
+
AccordionItemPanel,
|
|
21
|
+
AccordionItemButton
|
|
22
|
+
} from 'react-accessible-accordion'
|
|
17
23
|
|
|
18
24
|
const ForestPlotSettings: FC<PanelProps> = ({ name }) => {
|
|
19
25
|
const { config, rawData: unfilteredData, updateConfig } = useContext<ChartContext>(ConfigContext)
|
|
26
|
+
const { getColumns } = useEditorPanelContext()
|
|
20
27
|
if (config.visualizationType !== 'Forest Plot') return
|
|
21
28
|
|
|
22
|
-
// todo: get from editor context?
|
|
23
29
|
const enforceRestrictions = updatedConfig => {
|
|
24
30
|
if (updatedConfig.orientation === 'horizontal') {
|
|
25
31
|
updatedConfig.labels = false
|
|
@@ -33,31 +39,6 @@ const ForestPlotSettings: FC<PanelProps> = ({ name }) => {
|
|
|
33
39
|
}
|
|
34
40
|
}
|
|
35
41
|
|
|
36
|
-
// todo: get from editor context?
|
|
37
|
-
const getColumns = (filter = true) => {
|
|
38
|
-
let columns = {}
|
|
39
|
-
unfilteredData.forEach(row => {
|
|
40
|
-
Object.keys(row).forEach(columnName => (columns[columnName] = true))
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
if (filter) {
|
|
44
|
-
Object.keys(columns).forEach(key => {
|
|
45
|
-
if (
|
|
46
|
-
(config.series && config.series.filter(series => series.dataKey === key).length > 0) ||
|
|
47
|
-
(config.confidenceKeys && Object.keys(config.confidenceKeys).includes(key))
|
|
48
|
-
/*
|
|
49
|
-
TODO: Resolve errors when config keys exist, but have no value
|
|
50
|
-
Proposal: (((confidenceUpper && confidenceLower) || confidenceUpper || confidenceLower) && Object.keys(config.confidenceKeys).includes(key))
|
|
51
|
-
*/
|
|
52
|
-
) {
|
|
53
|
-
delete columns[key]
|
|
54
|
-
}
|
|
55
|
-
})
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
return Object.keys(columns)
|
|
59
|
-
}
|
|
60
|
-
|
|
61
42
|
// todo: editor context?
|
|
62
43
|
const updateField = (section, subsection, fieldName, newValue) => {
|
|
63
44
|
if (section === 'boxplot' && subsection === 'legend') {
|
|
@@ -151,7 +132,9 @@ const ForestPlotSettings: FC<PanelProps> = ({ name }) => {
|
|
|
151
132
|
<AccordionItemHeading>
|
|
152
133
|
<AccordionItemButton>
|
|
153
134
|
{name}
|
|
154
|
-
{(!config.forestPlot.estimateField || !config.forestPlot.upper || !config.forestPlot.lower) &&
|
|
135
|
+
{(!config.forestPlot.estimateField || !config.forestPlot.upper || !config.forestPlot.lower) && (
|
|
136
|
+
<WarningImage width='25' className='warning-icon' />
|
|
137
|
+
)}
|
|
155
138
|
</AccordionItemButton>
|
|
156
139
|
</AccordionItemHeading>
|
|
157
140
|
<AccordionItemPanel>
|
|
@@ -201,14 +184,22 @@ const ForestPlotSettings: FC<PanelProps> = ({ name }) => {
|
|
|
201
184
|
<Tooltip.Content>
|
|
202
185
|
<p>
|
|
203
186
|
Linear - Typically used for continuous outcomes. Line of no effect is positioned on 0 (zero) <br />
|
|
204
|
-
<br /> Logarithmic - Typically used for binary outcomes such as risk ratios and odds ratios. Line of
|
|
187
|
+
<br /> Logarithmic - Typically used for binary outcomes such as risk ratios and odds ratios. Line of
|
|
188
|
+
no effect is positioned on 1.
|
|
205
189
|
</p>
|
|
206
190
|
</Tooltip.Content>
|
|
207
191
|
</Tooltip>
|
|
208
192
|
}
|
|
209
193
|
/>
|
|
210
194
|
|
|
211
|
-
<TextField
|
|
195
|
+
<TextField
|
|
196
|
+
type='text'
|
|
197
|
+
value={config.forestPlot?.title || ''}
|
|
198
|
+
updateField={updateField}
|
|
199
|
+
section='forestPlot'
|
|
200
|
+
fieldName='title'
|
|
201
|
+
label='Plot Title'
|
|
202
|
+
/>
|
|
212
203
|
|
|
213
204
|
<br />
|
|
214
205
|
<hr />
|
|
@@ -317,7 +308,14 @@ const ForestPlotSettings: FC<PanelProps> = ({ name }) => {
|
|
|
317
308
|
</span>
|
|
318
309
|
</label>
|
|
319
310
|
|
|
320
|
-
<CheckBox
|
|
311
|
+
<CheckBox
|
|
312
|
+
value={config.forestPlot?.lineOfNoEffect?.show || false}
|
|
313
|
+
section='forestPlot'
|
|
314
|
+
subsection='lineOfNoEffect'
|
|
315
|
+
fieldName='show'
|
|
316
|
+
label='Show Line of No Effect'
|
|
317
|
+
updateField={updateField}
|
|
318
|
+
/>
|
|
321
319
|
|
|
322
320
|
<br />
|
|
323
321
|
<hr />
|
|
@@ -400,13 +398,37 @@ const ForestPlotSettings: FC<PanelProps> = ({ name }) => {
|
|
|
400
398
|
/>
|
|
401
399
|
</label>
|
|
402
400
|
|
|
403
|
-
<TextField
|
|
401
|
+
<TextField
|
|
402
|
+
type='number'
|
|
403
|
+
min={20}
|
|
404
|
+
max={45}
|
|
405
|
+
value={config.forestPlot.rowHeight ? config.forestPlot.rowHeight : 10}
|
|
406
|
+
updateField={updateField}
|
|
407
|
+
section='forestPlot'
|
|
408
|
+
fieldName='rowHeight'
|
|
409
|
+
label='Row Height'
|
|
410
|
+
placeholder='10'
|
|
411
|
+
/>
|
|
404
412
|
<br />
|
|
405
413
|
<hr />
|
|
406
414
|
<br />
|
|
407
415
|
<h4>Labels Settings</h4>
|
|
408
|
-
<TextField
|
|
409
|
-
|
|
416
|
+
<TextField
|
|
417
|
+
type='text'
|
|
418
|
+
value={config.forestPlot?.leftLabel || ''}
|
|
419
|
+
updateField={updateField}
|
|
420
|
+
section='forestPlot'
|
|
421
|
+
fieldName='leftLabel'
|
|
422
|
+
label='Left Label'
|
|
423
|
+
/>
|
|
424
|
+
<TextField
|
|
425
|
+
type='text'
|
|
426
|
+
value={config.forestPlot?.rightLabel || ''}
|
|
427
|
+
updateField={updateField}
|
|
428
|
+
section='forestPlot'
|
|
429
|
+
fieldName='rightLabel'
|
|
430
|
+
label='Right Label'
|
|
431
|
+
/>
|
|
410
432
|
|
|
411
433
|
<br />
|
|
412
434
|
<hr />
|
|
@@ -206,6 +206,86 @@ const PanelGeneral: FC<PanelProps> = props => {
|
|
|
206
206
|
options={['Below Bar', 'On Date/Category Axis']}
|
|
207
207
|
/>
|
|
208
208
|
)}
|
|
209
|
+
{visualizationType === 'Horizon Chart' && (
|
|
210
|
+
<>
|
|
211
|
+
<TextField
|
|
212
|
+
type='number'
|
|
213
|
+
value={config.horizon?.numLayers || 4}
|
|
214
|
+
section='horizon'
|
|
215
|
+
fieldName='numLayers'
|
|
216
|
+
label='Number of Layers'
|
|
217
|
+
updateField={updateField}
|
|
218
|
+
min={1}
|
|
219
|
+
max={9}
|
|
220
|
+
onBlur={e => {
|
|
221
|
+
const parsed = Number(e.target.value)
|
|
222
|
+
if (!isNaN(parsed)) {
|
|
223
|
+
const value = Math.round(parsed)
|
|
224
|
+
const clamped = Math.min(9, Math.max(1, value))
|
|
225
|
+
if (clamped !== parsed) {
|
|
226
|
+
updateField('horizon', null, 'numLayers', clamped)
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}}
|
|
230
|
+
tooltip={
|
|
231
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
232
|
+
<Tooltip.Target>
|
|
233
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
234
|
+
</Tooltip.Target>
|
|
235
|
+
<Tooltip.Content>
|
|
236
|
+
<p>
|
|
237
|
+
The number of layers determines how many "bands" the horizon chart is divided into. The optimal
|
|
238
|
+
number of layers may depend on the data range and the desired level of detail.
|
|
239
|
+
</p>
|
|
240
|
+
<hr />
|
|
241
|
+
<p>Valid range: 1-9. Defaults to 4 layers.</p>
|
|
242
|
+
</Tooltip.Content>
|
|
243
|
+
</Tooltip>
|
|
244
|
+
}
|
|
245
|
+
/>
|
|
246
|
+
<TextField
|
|
247
|
+
type='number'
|
|
248
|
+
value={config.horizon?.bandGap ?? 15}
|
|
249
|
+
section='horizon'
|
|
250
|
+
fieldName='bandGap'
|
|
251
|
+
label='Band Gap'
|
|
252
|
+
updateField={updateField}
|
|
253
|
+
tooltip={
|
|
254
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
255
|
+
<Tooltip.Target>
|
|
256
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
257
|
+
</Tooltip.Target>
|
|
258
|
+
<Tooltip.Content>
|
|
259
|
+
<p>The vertical spacing (in pixels) between each series row in the horizon chart.</p>
|
|
260
|
+
<hr />
|
|
261
|
+
<p>Defaults to 15 pixels.</p>
|
|
262
|
+
</Tooltip.Content>
|
|
263
|
+
</Tooltip>
|
|
264
|
+
}
|
|
265
|
+
/>
|
|
266
|
+
<TextField
|
|
267
|
+
type='number'
|
|
268
|
+
value={config.horizon?.bottomPadding ?? 15}
|
|
269
|
+
section='horizon'
|
|
270
|
+
fieldName='bottomPadding'
|
|
271
|
+
label='Bottom Padding'
|
|
272
|
+
updateField={updateField}
|
|
273
|
+
tooltip={
|
|
274
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
275
|
+
<Tooltip.Target>
|
|
276
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
277
|
+
</Tooltip.Target>
|
|
278
|
+
<Tooltip.Content>
|
|
279
|
+
<p>The padding (in pixels) below the last series row in the horizon chart.</p>
|
|
280
|
+
<hr />
|
|
281
|
+
<p>Defaults to 15 pixels.</p>
|
|
282
|
+
</Tooltip.Content>
|
|
283
|
+
</Tooltip>
|
|
284
|
+
}
|
|
285
|
+
/>
|
|
286
|
+
</>
|
|
287
|
+
)}
|
|
288
|
+
|
|
209
289
|
{visHasNumbersOnBars() ? (
|
|
210
290
|
<CheckBox
|
|
211
291
|
value={config.yAxis.displayNumbersOnBar}
|
|
@@ -316,36 +396,37 @@ const PanelGeneral: FC<PanelProps> = props => {
|
|
|
316
396
|
/>
|
|
317
397
|
</>
|
|
318
398
|
)}
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
399
|
+
{config.visualizationType !== 'Warming Stripes' && config.visualizationType !== 'Radar' && (
|
|
400
|
+
<CheckBox
|
|
401
|
+
tooltip={
|
|
402
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
403
|
+
<Tooltip.Target>
|
|
404
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
405
|
+
</Tooltip.Target>
|
|
406
|
+
<Tooltip.Content>
|
|
407
|
+
{config.visualizationSubType === 'stacked' && (
|
|
408
|
+
<p>
|
|
409
|
+
We do not recommend using stacked vertical/horizontal bar charts for missing data. If you choose
|
|
410
|
+
to proceed, selecting this option will display 'N/A' in the tooltip hover and data table (e.g.
|
|
411
|
+
nothing will display in chart).
|
|
412
|
+
</p>
|
|
413
|
+
)}
|
|
414
|
+
{config.visualizationSubType !== 'stacked' && (
|
|
415
|
+
<p>
|
|
416
|
+
Selecting this option will display 'N/A' on the Date/Category Axis, in the tooltip hover, and in
|
|
417
|
+
the data table to indicate missing or undefined data values.
|
|
418
|
+
</p>
|
|
419
|
+
)}
|
|
420
|
+
</Tooltip.Content>
|
|
421
|
+
</Tooltip>
|
|
422
|
+
}
|
|
423
|
+
value={config.general.showMissingDataLabel}
|
|
424
|
+
section='general'
|
|
425
|
+
fieldName='showMissingDataLabel'
|
|
426
|
+
label='Display "Missing Data" Label'
|
|
427
|
+
updateField={updateField}
|
|
428
|
+
/>
|
|
429
|
+
)}
|
|
349
430
|
|
|
350
431
|
{visualizationType === 'Pie' && (
|
|
351
432
|
<Select fieldName='pieType' label='Pie Chart Type' updateField={updateField} options={['Regular', 'Donut']} />
|
|
@@ -389,6 +470,32 @@ const PanelGeneral: FC<PanelProps> = props => {
|
|
|
389
470
|
</Tooltip>
|
|
390
471
|
}
|
|
391
472
|
/>
|
|
473
|
+
|
|
474
|
+
<Select
|
|
475
|
+
value={config.titleStyle}
|
|
476
|
+
fieldName='titleStyle'
|
|
477
|
+
label='Title Style'
|
|
478
|
+
updateField={updateField}
|
|
479
|
+
options={[
|
|
480
|
+
{ value: 'small', label: 'Small (h3)' },
|
|
481
|
+
{ value: 'large', label: 'Large (h2)' },
|
|
482
|
+
{ value: 'legacy', label: 'Legacy' }
|
|
483
|
+
]}
|
|
484
|
+
tooltip={
|
|
485
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
486
|
+
<Tooltip.Target>
|
|
487
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
488
|
+
</Tooltip.Target>
|
|
489
|
+
<Tooltip.Content>
|
|
490
|
+
<p>
|
|
491
|
+
Choose the visual style for the title. Consider heading order on your page when selecting the title
|
|
492
|
+
style. For 508 reasons, ensure your page follows a proper heading order.
|
|
493
|
+
</p>
|
|
494
|
+
</Tooltip.Content>
|
|
495
|
+
</Tooltip>
|
|
496
|
+
}
|
|
497
|
+
/>
|
|
498
|
+
|
|
392
499
|
<CheckBox value={config.showTitle} fieldName='showTitle' label='Show Title' updateField={updateField} />
|
|
393
500
|
|
|
394
501
|
{visSupportsSuperTitle() && (
|
|
@@ -311,6 +311,8 @@ const PanelPatternSettings: FC<PanelProps> = props => {
|
|
|
311
311
|
updateConfig(updatedConfig)
|
|
312
312
|
}
|
|
313
313
|
|
|
314
|
+
if (config.visualizationType === 'Warming Stripes' || config.visualizationType === 'Radar') return
|
|
315
|
+
|
|
314
316
|
return (
|
|
315
317
|
<AccordionItem>
|
|
316
318
|
<AccordionItemHeading>
|