@cdc/chart 4.24.5 → 4.24.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/dist/cdcchart.js +39128 -35959
  2. package/examples/feature/annotations/index.json +542 -0
  3. package/examples/xaxis.json +493 -0
  4. package/index.html +5 -4
  5. package/package.json +5 -4
  6. package/src/CdcChart.tsx +104 -64
  7. package/src/_stories/Chart.stories.tsx +18 -171
  8. package/src/_stories/ChartAnnotation.stories.tsx +32 -0
  9. package/src/_stories/_mock/annotation_category_mock.json +473 -0
  10. package/src/_stories/_mock/annotation_date-linear_mock.json +530 -0
  11. package/src/_stories/_mock/annotation_date-time_mock.json +530 -0
  12. package/src/_stories/_mock/line_chart_two_points_new_chart.json +128 -0
  13. package/src/_stories/_mock/line_chart_two_points_regression_test.json +127 -0
  14. package/src/_stories/_mock/lollipop.json +171 -0
  15. package/src/components/Annotations/components/AnnotationDraggable.styles.css +31 -0
  16. package/src/components/Annotations/components/AnnotationDraggable.tsx +154 -0
  17. package/src/components/Annotations/components/AnnotationDropdown.styles.css +14 -0
  18. package/src/components/Annotations/components/AnnotationDropdown.tsx +72 -0
  19. package/src/components/Annotations/components/AnnotationList.styles.css +45 -0
  20. package/src/components/Annotations/components/AnnotationList.tsx +42 -0
  21. package/src/components/Annotations/components/findNearestDatum.ts +138 -0
  22. package/src/components/Annotations/components/helpers/index.tsx +46 -0
  23. package/src/components/Annotations/index.tsx +13 -0
  24. package/src/components/AreaChart/components/AreaChart.Stacked.jsx +1 -1
  25. package/src/components/AreaChart/components/AreaChart.jsx +1 -1
  26. package/src/components/BarChart/components/BarChart.Horizontal.tsx +44 -42
  27. package/src/components/BarChart/components/BarChart.StackedHorizontal.tsx +1 -2
  28. package/src/components/BarChart/components/BarChart.StackedVertical.tsx +11 -11
  29. package/src/components/BarChart/components/BarChart.Vertical.tsx +50 -22
  30. package/src/components/BarChart/helpers/index.ts +102 -0
  31. package/src/components/EditorPanel/EditorPanel.tsx +232 -98
  32. package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +306 -0
  33. package/src/components/EditorPanel/components/Panels/Panel.General.tsx +117 -6
  34. package/src/components/EditorPanel/components/Panels/Panel.Sankey.tsx +2 -3
  35. package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +3 -2
  36. package/src/components/EditorPanel/components/Panels/index.tsx +3 -1
  37. package/src/components/EditorPanel/components/panels.scss +4 -0
  38. package/src/components/EditorPanel/editor-panel.scss +19 -0
  39. package/src/components/EditorPanel/useEditorPermissions.js +19 -2
  40. package/src/components/Legend/Legend.Component.tsx +7 -8
  41. package/src/components/Legend/helpers/createFormatLabels.tsx +1 -1
  42. package/src/components/Legend/helpers/index.ts +5 -0
  43. package/src/components/LineChart/LineChartProps.ts +3 -0
  44. package/src/components/LineChart/helpers.ts +21 -7
  45. package/src/components/LineChart/index.tsx +7 -7
  46. package/src/components/LinearChart.jsx +179 -136
  47. package/src/components/PairedBarChart.jsx +9 -9
  48. package/src/components/PieChart/PieChart.tsx +4 -4
  49. package/src/components/Sankey/index.tsx +73 -20
  50. package/src/components/ScatterPlot/ScatterPlot.jsx +22 -8
  51. package/src/components/ZoomBrush.tsx +90 -44
  52. package/src/data/initial-state.js +14 -6
  53. package/src/helpers/handleChartTabbing.ts +8 -0
  54. package/src/helpers/isConvertLineToBarGraph.ts +4 -0
  55. package/src/hooks/{useBarChart.js → useBarChart.ts} +2 -40
  56. package/src/hooks/useColorScale.ts +1 -1
  57. package/src/hooks/useMinMax.ts +8 -3
  58. package/src/hooks/useScales.ts +25 -3
  59. package/src/hooks/useTooltip.tsx +58 -11
  60. package/src/scss/main.scss +21 -14
  61. package/src/types/ChartConfig.ts +50 -3
  62. package/src/types/ChartContext.ts +9 -0
  63. package/tests-examples/helpers/testZeroValue.test.ts +30 -0
  64. package/LICENSE +0 -201
  65. package/src/helpers/filterData.ts +0 -18
  66. package/src/helpers/tests/computeMarginBottom.test.ts +0 -21
  67. /package/src/hooks/{useLegendClasses.js → useLegendClasses.ts} +0 -0
  68. /package/src/hooks/{useReduceData.js → useReduceData.ts} +0 -0
@@ -0,0 +1,306 @@
1
+ import React, { useContext } from 'react'
2
+ import ConfigContext from '../../../../ConfigContext.js'
3
+
4
+ // CDC Core
5
+ import Accordion from '@cdc/core/components/ui/Accordion'
6
+ import Button from '@cdc/core/components/elements/Button'
7
+ import _ from 'lodash'
8
+
9
+ // types
10
+ import { type PanelProps } from './../PanelProps'
11
+ // styles
12
+ import './../panels.scss'
13
+
14
+ const PanelAnnotate: React.FC<PanelProps> = props => {
15
+ const { updateConfig, config, unfilteredData, dimensions, isDraggingAnnotation } = useContext(ConfigContext)
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 ((config.series && config.series.filter(series => series.dataKey === key).length > 0) || (config.confidenceKeys && Object.keys(config.confidenceKeys).includes(key))) {
26
+ delete columns[key]
27
+ }
28
+ })
29
+ }
30
+
31
+ return Object.keys(columns)
32
+ }
33
+
34
+ const handleAnnotationUpdate = (value, property, index) => {
35
+ const svgContainer = document.querySelector('.chart-container > div > svg')?.getBoundingClientRect()
36
+ const newSvgDims = [svgContainer.width, svgContainer.height]
37
+ const annotations = [...config?.annotations]
38
+ annotations[index][property] = value
39
+ annotations[index].savedDimensions = newSvgDims
40
+
41
+ updateConfig({
42
+ ...config,
43
+ annotations
44
+ })
45
+ }
46
+
47
+ const handleAddAnnotation = () => {
48
+ const svgContainer = document.querySelector('.chart-container > div > svg')?.getBoundingClientRect()
49
+ const newSvgDims = [svgContainer.width, svgContainer.height]
50
+
51
+ const newAnnotation = {
52
+ text: 'New Annotation',
53
+ snapToNearestPoint: false,
54
+ fontSize: 16,
55
+ bezier: 10,
56
+ show: {
57
+ desktop: true,
58
+ tablet: true,
59
+ mobile: true
60
+ },
61
+ connectorType: 'line',
62
+ colors: {
63
+ label: 'black',
64
+ connector: 'black',
65
+ marker: 'black'
66
+ },
67
+ selected: true,
68
+ anchor: {
69
+ vertical: false,
70
+ horizontal: false
71
+ },
72
+ marker: 'arrow',
73
+ edit: {
74
+ subject: true,
75
+ label: true
76
+ },
77
+ seriesKey: '',
78
+ x: 50,
79
+ y: Number(newSvgDims?.[1] / 2),
80
+ xKey: config.xAxis.type === 'date' ? new Date(config?.data?.[0]?.[config.xAxis.dataKey]).getTime() : config.xAxis.type === 'categorical' ? '1/15/2016' : '',
81
+ yKey: '',
82
+ dx: 20,
83
+ dy: -20,
84
+ opacity: '100',
85
+ savedDimensions: newSvgDims,
86
+ connectionType: 'line'
87
+ }
88
+
89
+ const annotations = Array.isArray(config.annotations) ? config.annotations : []
90
+
91
+ updateConfig({
92
+ ...config,
93
+ annotations: [...annotations, newAnnotation]
94
+ })
95
+ }
96
+
97
+ const handleRemoveAnnotation = (annotationIndex: number) => {
98
+ const updated = config.annotations.filter((_, index) => index !== annotationIndex)
99
+ updateConfig({
100
+ ...config,
101
+ annotations: updated
102
+ })
103
+ }
104
+
105
+ return (
106
+ <Accordion key={props.name}>
107
+ <Accordion.Section title={props.name} key={props.name}>
108
+ <label key={`key-1`}>
109
+ Show Annotation Dropdown
110
+ <input
111
+ type='checkbox'
112
+ checked={config?.general?.showAnnotationDropdown || false}
113
+ onChange={e => {
114
+ updateConfig({
115
+ ...config,
116
+ general: {
117
+ ...config.general,
118
+ showAnnotationDropdown: e.target.checked
119
+ }
120
+ })
121
+ }}
122
+ />
123
+ </label>
124
+
125
+ {config.general.showAnnotationDropdown && (
126
+ <label key={`key-2`}>
127
+ Annotation Dropdown Title:
128
+ <input
129
+ type='text'
130
+ style={{ marginBottom: '10px' }}
131
+ value={config?.general?.annotationDropdownText}
132
+ onChange={e => {
133
+ updateConfig({
134
+ ...config,
135
+ general: {
136
+ ...config.general,
137
+ annotationDropdownText: e.target.value
138
+ }
139
+ })
140
+ }}
141
+ />
142
+ </label>
143
+ )}
144
+ {config?.annotations &&
145
+ config?.annotations.map((annotation, index) => (
146
+ <Accordion key={index}>
147
+ <Accordion.Section title={annotation.text ? annotation.text.substring(0, 15) + '...' : `Annotation ${index + 1}`}>
148
+ <div className='annotation-group'>
149
+ <label>
150
+ Annotation Text:
151
+ <textarea rows={5} value={annotation.text} onChange={e => handleAnnotationUpdate(e.target.value, 'text', index)} />
152
+ </label>
153
+ <label>
154
+ Opacity
155
+ <br />
156
+ <input
157
+ type='range'
158
+ onChange={e => {
159
+ const updatedAnnotations = _.cloneDeep(config?.annotations)
160
+ updatedAnnotations[index].opacity = e.target.value
161
+ updateConfig({
162
+ ...config,
163
+ annotations: updatedAnnotations
164
+ })
165
+ }}
166
+ value={config?.annotations?.[index]?.opacity || '100'}
167
+ />
168
+ </label>
169
+
170
+ <label>
171
+ Edit Subject
172
+ <input
173
+ type='checkbox'
174
+ checked={config?.annotations[index]?.edit?.subject || false}
175
+ onChange={e => {
176
+ const updatedAnnotations = _.cloneDeep(config?.annotations)
177
+ updatedAnnotations[index].edit.subject = e.target.checked
178
+ updateConfig({
179
+ ...config,
180
+ annotations: updatedAnnotations
181
+ })
182
+ }}
183
+ />
184
+ </label>
185
+ <label>
186
+ Edit Label
187
+ <input
188
+ type='checkbox'
189
+ checked={config?.annotations[index]?.edit?.label || false}
190
+ onChange={e => {
191
+ const updatedAnnotations = _.cloneDeep(config?.annotations)
192
+ updatedAnnotations[index].edit.label = e.target.checked
193
+ updateConfig({
194
+ ...config,
195
+ annotations: updatedAnnotations
196
+ })
197
+ }}
198
+ />
199
+ </label>
200
+
201
+ <label>
202
+ Connection Type:
203
+ <select
204
+ key='annotation-connection-type'
205
+ onChange={e => {
206
+ const updatedAnnotations = _.cloneDeep(config?.annotations)
207
+ updatedAnnotations[index].connectionType = e.target.value
208
+ updateConfig({
209
+ ...config,
210
+ annotations: updatedAnnotations
211
+ })
212
+ }}
213
+ value={config?.annotations[index]?.connectionType}
214
+ >
215
+ <option key='select' value='select'>
216
+ Select
217
+ </option>
218
+ {['curve', 'line', 'elbow', 'none'].map((side, index) => (
219
+ <option key={side} value={side}>
220
+ {side}
221
+ </option>
222
+ ))}
223
+ </select>
224
+ </label>
225
+
226
+ {annotation.connectionType === 'curve' && (
227
+ <>
228
+ <label>
229
+ Curve Control
230
+ {/* create a range input */}
231
+ <input
232
+ type='range'
233
+ min='-20'
234
+ max='20'
235
+ value={config?.annotations[index]?.bezier || 0}
236
+ onChange={e => {
237
+ const updatedAnnotations = _.cloneDeep(config?.annotations)
238
+ updatedAnnotations[index].bezier = e.target.value
239
+ updateConfig({
240
+ ...config,
241
+ annotations: updatedAnnotations
242
+ })
243
+ }}
244
+ />
245
+ </label>
246
+ </>
247
+ )}
248
+
249
+ {/* <label>
250
+ Connection Location:
251
+ <select
252
+ onChange={e => {
253
+ const updatedAnnotations = _.cloneDeep(config?.annotations)
254
+ updatedAnnotations[index].connectionLocation = e.target.value
255
+ updateConfig({
256
+ ...config,
257
+ annotations: updatedAnnotations
258
+ })
259
+ }}
260
+ >
261
+ {['auto', 'left', 'top', 'bottom', 'right'].map((side, index) => (
262
+ <option key={side} value={side}>
263
+ {side}
264
+ </option>
265
+ ))}
266
+ </select>
267
+ </label> */}
268
+
269
+ <label>
270
+ Marker
271
+ <select
272
+ key='annotation-marker'
273
+ value={annotation.marker}
274
+ onChange={e => {
275
+ const updatedAnnotations = _.cloneDeep(config?.annotations)
276
+ updatedAnnotations[index].marker = e.target.value
277
+ updateConfig({
278
+ ...config,
279
+ annotations: updatedAnnotations
280
+ })
281
+ }}
282
+ >
283
+ {['arrow', 'circle'].map((column, columnIndex) => {
284
+ return <option key={`col-${columnIndex}`}>{column}</option>
285
+ })}
286
+ </select>
287
+ </label>
288
+
289
+ <Button className='warn btn-warn btn btn-remove delete' onClick={() => handleRemoveAnnotation(index)}>
290
+ Delete Annotation
291
+ </Button>
292
+ </div>
293
+ </Accordion.Section>
294
+ </Accordion>
295
+ ))}
296
+ {config?.annotations?.length < 3 && (
297
+ <Button onClick={handleAddAnnotation} className='mt-2'>
298
+ Add Annotation
299
+ </Button>
300
+ )}
301
+ </Accordion.Section>
302
+ </Accordion>
303
+ )
304
+ }
305
+
306
+ export default PanelAnnotate
@@ -18,7 +18,7 @@ import { PanelProps } from '../PanelProps'
18
18
  const PanelGeneral: FC<PanelProps> = props => {
19
19
  const { config } = useContext(ConfigContext)
20
20
  const { updateField } = useEditorPanelContext()
21
- const { enabledChartTypes, visHasNumbersOnBars, visHasLabelOnData, visSupportsChartHeight, visSupportsSuperTitle, visSupportsFootnotes } = useEditorPermissions()
21
+ const { enabledChartTypes, visHasNumbersOnBars, visHasaAdditionalLabelsOnBars, visHasLabelOnData, visSupportsChartHeight, visSupportsSuperTitle, visSupportsFootnotes } = useEditorPermissions()
22
22
  const { visualizationType, visualizationSubType, barStyle } = config
23
23
 
24
24
  const showBarStyleOptions = () => {
@@ -37,12 +37,50 @@ const PanelGeneral: FC<PanelProps> = props => {
37
37
  <AccordionItemButton>General</AccordionItemButton>
38
38
  </AccordionItemHeading>
39
39
  <AccordionItemPanel>
40
- <Select value={visualizationType} fieldName='visualizationType' label='Chart Type' updateField={updateField} options={enabledChartTypes} />
40
+ {config?.visualizationType !== 'Sankey' && <Select value={visualizationType} fieldName='visualizationType' label='Chart Type' updateField={updateField} options={enabledChartTypes} />}
41
+ {visSupportsChartHeight() && config.orientation === 'vertical' && (
42
+ <TextField
43
+ type='number'
44
+ value={config.heights.vertical}
45
+ section='heights'
46
+ fieldName='vertical'
47
+ label='Chart Height'
48
+ updateField={updateField}
49
+ tooltip={
50
+ <Tooltip style={{ textTransform: 'none' }}>
51
+ <Tooltip.Target>
52
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
53
+ </Tooltip.Target>
54
+ <Tooltip.Content>
55
+ <p>For some visualization types, such as the sankey diagram, it may be necessary to adjust to chart height for optimal display.</p>
56
+ </Tooltip.Content>
57
+ </Tooltip>
58
+ }
59
+ />
60
+ )}
41
61
  {(visualizationType === 'Bar' || visualizationType === 'Combo' || visualizationType === 'Area Chart') && <Select value={visualizationSubType || 'Regular'} fieldName='visualizationSubType' label='Chart Subtype' updateField={updateField} options={['regular', 'stacked']} />}
42
62
  {visualizationType === 'Area Chart' && visualizationSubType === 'stacked' && <Select value={config.stackedAreaChartLineType || 'Linear'} fieldName='stackedAreaChartLineType' label='Stacked Area Chart Line Type' updateField={updateField} options={Object.keys(approvedCurveTypes)} />}
43
63
  {visualizationType === 'Bar' && <Select value={config.orientation || 'vertical'} fieldName='orientation' label='Orientation' updateField={updateField} options={['vertical', 'horizontal']} />}
44
64
  {visualizationType === 'Deviation Bar' && <Select label='Orientation' options={['horizontal']} />}
45
- {(visualizationType === 'Bar' || visualizationType === 'Deviation Bar') && <Select value={config.isLollipopChart ? 'lollipop' : barStyle || 'flat'} fieldName='barStyle' label='bar style' updateField={updateField} options={showBarStyleOptions()} />}
65
+ {(visualizationType === 'Bar' || visualizationType === 'Deviation Bar') && (
66
+ <Select
67
+ value={config.isLollipopChart ? 'lollipop' : barStyle || 'flat'}
68
+ fieldName='barStyle'
69
+ label='bar style'
70
+ updateField={updateField}
71
+ options={showBarStyleOptions()}
72
+ tooltip={
73
+ <Tooltip style={{ textTransform: 'none' }}>
74
+ <Tooltip.Target>
75
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
76
+ </Tooltip.Target>
77
+ <Tooltip.Content>
78
+ <p>Consider using the 'Flat' bar style when presenting data that includes '0' values.</p>
79
+ </Tooltip.Content>
80
+ </Tooltip>
81
+ }
82
+ />
83
+ )}
46
84
  {(visualizationType === 'Bar' || visualizationType === 'Deviation Bar') && barStyle === 'rounded' && <Select value={config.tipRounding || 'top'} fieldName='tipRounding' label='tip rounding' updateField={updateField} options={['top', 'full']} />}
47
85
  {(visualizationType === 'Bar' || visualizationType === 'Deviation Bar') && barStyle === 'rounded' && <Select value={config.roundingStyle || 'standard'} fieldName='roundingStyle' label='rounding style' updateField={updateField} options={['standard', 'shallow', 'finger']} />}
48
86
  {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']} />}
@@ -61,14 +99,89 @@ const PanelGeneral: FC<PanelProps> = props => {
61
99
  <Icon display='question' style={{ marginLeft: '0.5rem' }} />
62
100
  </Tooltip.Target>
63
101
  <Tooltip.Content>
64
- <p>Selecting this option will not hide the display of "zero value", "suppressed data", or "no data" indicators on the chart (if applicable).</p>
102
+ <p>Selecting this option will not hide the display of "zero value", "suppressed data", or "missing data" indicators on the chart (if applicable).</p>
65
103
  </Tooltip.Content>
66
104
  </Tooltip>
67
105
  }
68
106
  />
69
107
  )
70
108
  )}
109
+ {visHasaAdditionalLabelsOnBars() && (
110
+ <>
111
+ <CheckBox
112
+ tooltip={
113
+ <Tooltip style={{ textTransform: 'none' }}>
114
+ <Tooltip.Target>
115
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
116
+ </Tooltip.Target>
117
+ <Tooltip.Content>
118
+ <p>Selecting this option will display 'N/A' on the Date/Category Axis, in the tooltip hover, and in the data table to indicate missing or undefined data values.</p>
119
+ </Tooltip.Content>
120
+ </Tooltip>
121
+ }
122
+ value={config.general.showMissingDataLabel}
123
+ section='general'
124
+ fieldName='showMissingDataLabel'
125
+ label='Display "Missing Data" Label'
126
+ updateField={updateField}
127
+ />
128
+ <CheckBox
129
+ tooltip={
130
+ <Tooltip style={{ textTransform: 'none' }}>
131
+ <Tooltip.Target>
132
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
133
+ </Tooltip.Target>
134
+ <Tooltip.Content>
135
+ <p> Selecting this option will display a thin line slightly above the Date/Category Axis to indicate "zero value" where zero values are indicated in the Data Series.</p>
136
+ </Tooltip.Content>
137
+ </Tooltip>
138
+ }
139
+ value={config.general.showZeroValueDataLabel}
140
+ section='general'
141
+ fieldName='showZeroValueDataLabel'
142
+ label='Display "Zero Value Data" Label'
143
+ updateField={updateField}
144
+ />
145
+
146
+ <CheckBox
147
+ tooltip={
148
+ <Tooltip style={{ textTransform: 'none' }}>
149
+ <Tooltip.Target>
150
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
151
+ </Tooltip.Target>
152
+ <Tooltip.Content>
153
+ <p>Selecting this option will display the 'suppressed data symbol' on the Date/Category Axis, in the tooltip hover, and in the data table where suppressed data values are indicated in the Data Series</p>
154
+ </Tooltip.Content>
155
+ </Tooltip>
156
+ }
157
+ value={config.general.showSuppressedSymbol}
158
+ section='general'
159
+ fieldName='showSuppressedSymbol'
160
+ label='Display "suppressed data" label'
161
+ updateField={updateField}
162
+ />
163
+ </>
164
+ )}
165
+
71
166
  {visualizationType === 'Pie' && <Select fieldName='pieType' label='Pie Chart Type' updateField={updateField} options={['Regular', 'Donut']} />}
167
+ {visualizationType === 'Line' && (
168
+ <CheckBox
169
+ value={config.allowLineToBarGraph}
170
+ fieldName='allowLineToBarGraph'
171
+ label='Convert to Bar Graph'
172
+ updateField={updateField}
173
+ tooltip={
174
+ <Tooltip style={{ textTransform: 'none' }}>
175
+ <Tooltip.Target>
176
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
177
+ </Tooltip.Target>
178
+ <Tooltip.Content>
179
+ <p>Switch to bar graph when less than 3 data points available.</p>
180
+ </Tooltip.Content>
181
+ </Tooltip>
182
+ }
183
+ />
184
+ )}
72
185
 
73
186
  <TextField
74
187
  value={config.title || 'Chart Title'}
@@ -167,8 +280,6 @@ const PanelGeneral: FC<PanelProps> = props => {
167
280
  }
168
281
  />
169
282
  )}
170
-
171
- {visSupportsChartHeight() && config.orientation === 'vertical' && <TextField type='number' value={config.heights.vertical} section='heights' fieldName='vertical' label='Chart Height' updateField={updateField} />}
172
283
  </AccordionItemPanel>
173
284
  </AccordionItem>
174
285
  )
@@ -64,6 +64,7 @@ const SankeySettings = () => {
64
64
  <AccordionItemButton>Sankey Settings</AccordionItemButton>
65
65
  </AccordionItemHeading>
66
66
  <AccordionItemPanel>
67
+ <p>Node stories can provide additional details to support public health messaging. COVE can display a maximum of 3 node stories.</p>
67
68
  {data?.storyNodeText &&
68
69
  data?.storyNodeText.map(({ StoryNode, segmentTextBefore, segmentTextAfter }, i) => (
69
70
  <div key={i} style={{ border: '1px solid black', margin: '15px auto', padding: '15px', borderRadius: '10px' }}>
@@ -84,7 +85,6 @@ const SankeySettings = () => {
84
85
  </Button>
85
86
  </div>
86
87
  ))}
87
- {`Total Story Nodes: ${data?.storyNodeText?.length}`}
88
88
  {data?.storyNodeText?.length < 3 && (
89
89
  <button
90
90
  type='button'
@@ -97,8 +97,7 @@ const SankeySettings = () => {
97
97
  Add StoryNode
98
98
  </button>
99
99
  )}
100
-
101
- <CheckBox value={config.enableTooltips} fieldName='enableTooltips' label='Enable Tooltips' updateField={updateField} />
100
+ {config.enableTooltips && config.data?.tooltips?.length > 0 && <CheckBox value={config.enableTooltips} fieldName='enableTooltips' label='Enable Tooltips' updateField={updateField} />}
102
101
  </AccordionItemPanel>
103
102
  </AccordionItem>
104
103
  )
@@ -22,7 +22,8 @@ const PanelVisual: FC<PanelProps> = props => {
22
22
  const { config, updateConfig, colorPalettes, twoColorPalette } = useContext<ChartContext>(ConfigContext)
23
23
  const { visual } = config
24
24
  const { setLollipopShape, updateField } = useEditorPanelContext()
25
- const { visHasBarBorders, visCanAnimate, visSupportsNonSequentialPallete, headerColors, visSupportsTooltipOpacity, visSupportsTooltipLines, visSupportsBarSpace, visSupportsBarThickness, visHasDataCutoff, visSupportsSequentialPallete, visSupportsReverseColorPalette } = useEditorPermissions()
25
+ const { visHasBarBorders, visCanAnimate, visSupportsNonSequentialPallete, headerColors, visSupportsTooltipOpacity, visSupportsTooltipLines, visSupportsBarSpace, visSupportsBarThickness, visHasDataCutoff, visSupportsSequentialPallete, visSupportsReverseColorPalette, visHasSingleSeriesTooltip } =
26
+ useEditorPermissions()
26
27
  const { twoColorPalettes, sequential, nonSequential } = useColorPalette(config, updateConfig)
27
28
 
28
29
  const updateColor = (property, _value) => {
@@ -312,7 +313,7 @@ const PanelVisual: FC<PanelProps> = props => {
312
313
  />
313
314
  </label>
314
315
  )}
315
- {config.visualizationType === 'Bar' && <CheckBox value={config.tooltips.singleSeries} fieldName='singleSeries' section='tooltips' label='SHOW HOVER FOR SINGLE DATA SERIES' updateField={updateField} />}
316
+ {visHasSingleSeriesTooltip() && <CheckBox value={config.tooltips.singleSeries} fieldName='singleSeries' section='tooltips' label='SHOW HOVER FOR SINGLE DATA SERIES' updateField={updateField} />}
316
317
 
317
318
  <label>
318
319
  <span className='edit-label column-heading'>No Data Message</span>
@@ -5,6 +5,7 @@ import General from './Panel.General'
5
5
  import BoxPlot from './Panel.BoxPlot'
6
6
  import Visual from './Panel.Visual'
7
7
  import Sankey from './Panel.Sankey'
8
+ import Annotate from './Panel.Annotate'
8
9
 
9
10
  const Panels = {
10
11
  ForestPlot: ForestPlotSettings,
@@ -13,7 +14,8 @@ const Panels = {
13
14
  General,
14
15
  BoxPlot,
15
16
  Visual,
16
- Sankey
17
+ Sankey,
18
+ Annotate
17
19
  }
18
20
 
19
21
  export default Panels
@@ -81,3 +81,7 @@
81
81
  margin-top: 0 !important;
82
82
  }
83
83
  }
84
+
85
+ .annotation-group {
86
+ border: 1px solid black;
87
+ }
@@ -12,4 +12,23 @@
12
12
  padding-left: 350px;
13
13
  }
14
14
  }
15
+
16
+ .viewport-overrides {
17
+ button {
18
+ width: 100%;
19
+ padding: 1em;
20
+ margin-top: 1em;
21
+ text-align: left;
22
+
23
+ span {
24
+ display: inline-block;
25
+ float: right;
26
+ }
27
+ }
28
+
29
+ .edit-block {
30
+ margin-top: 0;
31
+ padding: 1em;
32
+ }
33
+ }
15
34
  }
@@ -76,6 +76,11 @@ export const useEditorPermissions = () => {
76
76
  return false
77
77
  }
78
78
 
79
+ const visHasaAdditionalLabelsOnBars = () => {
80
+ if (['Bar', 'Combo', 'Line'].includes(config.visualizationType)) return true
81
+ return false
82
+ }
83
+
79
84
  const visHasAnchors = () => {
80
85
  switch (visualizationType) {
81
86
  case 'Area Chart':
@@ -103,7 +108,7 @@ export const useEditorPermissions = () => {
103
108
  }
104
109
 
105
110
  const visHasBarBorders = () => {
106
- const disabledCharts = ['Box Plot', 'Scatter Plot', 'Pie']
111
+ const disabledCharts = ['Box Plot', 'Scatter Plot', 'Pie', 'Line']
107
112
  if (disabledCharts.includes(visualizationType)) return false
108
113
  return series?.some(series => series.type === 'Bar' || series.type === 'Paired Bar' || series.type === 'Deviation Bar')
109
114
  }
@@ -311,6 +316,16 @@ export const useEditorPermissions = () => {
311
316
  return false
312
317
  }
313
318
 
319
+ const visHasSingleSeriesTooltip = () => {
320
+ if (visualizationType === 'Bar' || visualizationType === 'Line') {
321
+ return true
322
+ }
323
+ if (visualizationType === 'Area Chart' && visualizationSubType === 'stacked') {
324
+ return true
325
+ }
326
+ return false
327
+ }
328
+
314
329
  return {
315
330
  enabledChartTypes,
316
331
  headerColors,
@@ -324,6 +339,7 @@ export const useEditorPermissions = () => {
324
339
  visHasLegendAxisAlign,
325
340
  visHasBrushChart,
326
341
  visHasNumbersOnBars,
342
+ visHasaAdditionalLabelsOnBars,
327
343
  visSupportsBarSpace,
328
344
  visSupportsBarThickness,
329
345
  visSupportsChartHeight,
@@ -355,6 +371,7 @@ export const useEditorPermissions = () => {
355
371
  visSupportsValueAxisTicks,
356
372
  visSupportsReactTooltip,
357
373
  visSupportsValueAxisMax,
358
- visSupportsValueAxisMin
374
+ visSupportsValueAxisMin,
375
+ visHasSingleSeriesTooltip
359
376
  }
360
377
  }