@cdc/chart 4.26.2 → 4.26.4

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 (165) hide show
  1. package/CONFIG.md +169 -0
  2. package/README.md +42 -17
  3. package/dist/cdcchart.js +39419 -35180
  4. package/examples/__data__/data-with-metadata.json +10 -0
  5. package/examples/feature/bar/additional-column-tooltip.json +3 -3
  6. package/examples/feature/deviation/planet-deviation-config.json +2 -2
  7. package/examples/feature/paired-bar/paired-bar-example.json +2 -2
  8. package/examples/feature/pie/planet-pie-example-config.json +2 -1
  9. package/examples/feature/tests-case-rate/case-rate-example-config.json +2 -2
  10. package/examples/feature/tests-covid/covid-confidence-example-config.json +2 -2
  11. package/examples/feature/tests-covid/covid-example-config.json +2 -2
  12. package/examples/feature/tests-cutoff/cutoff-example-config.json +2 -2
  13. package/examples/feature/tests-non-numerics/planet-pie-example-config-nonnumeric.json +2 -2
  14. package/examples/metadata-variables.json +58 -0
  15. package/examples/minimal-example.json +24 -0
  16. package/examples/private/test2.json +35012 -0
  17. package/package.json +4 -4
  18. package/src/CdcChart.tsx +8 -4
  19. package/src/CdcChartComponent.tsx +326 -290
  20. package/src/_stories/Chart.CustomColors.smoke.stories.tsx +97 -0
  21. package/src/_stories/Chart.Defaults.smoke.stories.tsx +95 -0
  22. package/src/_stories/{Chart.HTMLInDataTable.stories.tsx → Chart.HTMLInDataTable.smoke.stories.tsx} +10 -0
  23. package/src/_stories/Chart.Minimal.smoke.stories.tsx +25 -0
  24. package/src/_stories/{Chart.SmallMultiples.stories.tsx → Chart.SmallMultiples.smoke.stories.tsx} +17 -1
  25. package/src/_stories/Chart.SmallestLeftAxisMax.smoke.stories.tsx +64 -0
  26. package/src/_stories/{Chart.stories.tsx → Chart.smoke.stories.tsx} +48 -2
  27. package/src/_stories/{Chart.tooltip.stories.tsx → Chart.tooltip.smoke.stories.tsx} +68 -0
  28. package/src/_stories/ChartBar.Editor.stories.tsx +177 -115
  29. package/src/_stories/ChartBrush.Editor.stories.tsx +11 -25
  30. package/src/_stories/ChartEditor.Editor.stories.tsx +24 -1
  31. package/src/_stories/{Chart.CustomColors.stories.tsx → ChartLine.DashedDates.smoke.stories.tsx} +4 -4
  32. package/src/_stories/_mock/line_chart_dashed_dates.json +276 -0
  33. package/src/_stories/_mock/paired-bar-abbr.json +421 -0
  34. package/src/_stories/_mock/paired-bar.json +1 -1
  35. package/src/_stories/_mock/pie_custom_colors.json +268 -0
  36. package/src/_stories/_mock/smallest_left_axis_max.json +104 -0
  37. package/src/components/Annotations/components/AnnotationDraggable.styles.css +10 -10
  38. package/src/components/Annotations/components/AnnotationDraggable.tsx +1 -1
  39. package/src/components/Annotations/components/AnnotationDropdown.styles.css +1 -1
  40. package/src/components/Annotations/components/AnnotationList.styles.css +11 -11
  41. package/src/components/AreaChart/components/AreaChart.Stacked.jsx +10 -2
  42. package/src/components/Axis/BottomAxis.tsx +10 -3
  43. package/src/components/Axis/LeftAxis.tsx +2 -4
  44. package/src/components/Axis/LeftAxisGridlines.tsx +1 -3
  45. package/src/components/Axis/PairedBarAxis.tsx +10 -4
  46. package/src/components/BarChart/components/BarChart.Horizontal.tsx +21 -33
  47. package/src/components/BarChart/components/BarChart.StackedHorizontal.tsx +21 -35
  48. package/src/components/BarChart/components/BarChart.StackedVertical.tsx +21 -36
  49. package/src/components/BarChart/components/BarChart.Vertical.tsx +21 -34
  50. package/src/components/BarChart/components/BarChart.tsx +2 -6
  51. package/src/components/BarChart/helpers/getPatternUrl.ts +94 -0
  52. package/src/components/BarChart/helpers/tests/getPatternUrl.test.ts +134 -0
  53. package/src/components/BarChart/helpers/useBarChart.ts +4 -1
  54. package/src/components/BoxPlot/BoxPlot.Vertical.tsx +3 -3
  55. package/src/components/Brush/BrushSelector.tsx +2 -1
  56. package/src/components/Brush/MiniChartPreview.tsx +21 -26
  57. package/src/components/EditorPanel/EditorPanel.tsx +692 -954
  58. package/src/components/EditorPanel/EditorPanelContext.ts +1 -1
  59. package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +218 -167
  60. package/src/components/EditorPanel/components/Panels/Panel.ForestPlotSettings.tsx +0 -78
  61. package/src/components/EditorPanel/components/Panels/Panel.General.tsx +39 -1
  62. package/src/components/EditorPanel/components/Panels/Panel.PatternSettings.tsx +169 -135
  63. package/src/components/EditorPanel/components/Panels/Panel.Regions.tsx +154 -109
  64. package/src/components/EditorPanel/components/Panels/Panel.Sankey.tsx +3 -3
  65. package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +95 -28
  66. package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +45 -42
  67. package/src/components/EditorPanel/editor-panel.scss +1 -1
  68. package/src/components/EditorPanel/useEditorPermissions.ts +1 -10
  69. package/src/components/Forecasting/Forecasting.tsx +2 -2
  70. package/src/components/ForestPlot/ForestPlot.tsx +26 -22
  71. package/src/components/HorizonChart/HorizonChart.tsx +10 -2
  72. package/src/components/HoverLine/HoverLine.tsx +6 -8
  73. package/src/components/Legend/Legend.Component.tsx +4 -4
  74. package/src/components/Legend/LegendGroup/LegendGroup.styles.css +9 -4
  75. package/src/components/Legend/LegendGroup/LegendGroup.tsx +3 -1
  76. package/src/components/Legend/helpers/createFormatLabels.tsx +3 -2
  77. package/src/components/Legend/helpers/index.ts +0 -2
  78. package/src/components/LineChart/LineChartProps.ts +1 -0
  79. package/src/components/LineChart/components/LineChart.BumpCircle.tsx +3 -2
  80. package/src/components/LineChart/index.tsx +11 -4
  81. package/src/components/LinearChart/VisualizationRenderer.tsx +11 -1
  82. package/src/components/LinearChart/tests/LinearChart.test.tsx +224 -0
  83. package/src/components/LinearChart/tests/mockConfigContext.ts +2 -0
  84. package/src/components/LinearChart.tsx +124 -47
  85. package/src/components/PairedBarChart.jsx +2 -2
  86. package/src/components/PieChart/PieChart.tsx +30 -13
  87. package/src/components/RadarChart/RadarChart.tsx +1 -1
  88. package/src/components/Regions/components/Regions.tsx +36 -26
  89. package/src/components/Sankey/components/Sankey.tsx +3 -3
  90. package/src/components/Sankey/sankey.scss +1 -1
  91. package/src/components/ScatterPlot/ScatterPlot.jsx +19 -17
  92. package/src/components/SmallMultiples/SmallMultipleTile.tsx +1 -0
  93. package/src/components/SmallMultiples/SmallMultiples.css +5 -5
  94. package/src/components/Sparkline/components/SparkLine.tsx +1 -1
  95. package/src/components/Sparkline/index.scss +4 -2
  96. package/src/components/WarmingStripes/WarmingStripes.tsx +5 -3
  97. package/src/components/WarmingStripes/WarmingStripesGradientLegend.css +8 -8
  98. package/src/data/initial-state.js +24 -14
  99. package/src/data/legacy-defaults.ts +18 -0
  100. package/src/helpers/abbreviateNumber.ts +24 -17
  101. package/src/helpers/calculateLeftYAxisWidth.ts +193 -0
  102. package/src/helpers/getChartPatternId.ts +17 -0
  103. package/src/helpers/getMinMax.ts +16 -2
  104. package/src/helpers/seriesColumnSettings.ts +114 -0
  105. package/src/helpers/tests/countNumOfTicks.test.ts +77 -0
  106. package/src/helpers/tests/seriesColumnSettings.test.ts +84 -0
  107. package/src/helpers/tests/tooltipHelpers.test.ts +151 -0
  108. package/src/helpers/tooltipHelpers.ts +176 -0
  109. package/src/hooks/useHighlightedBars.ts +9 -16
  110. package/src/hooks/useProgrammaticTooltip.ts +16 -2
  111. package/src/hooks/useRightAxis.ts +14 -0
  112. package/src/hooks/useScales.ts +92 -56
  113. package/src/hooks/useSmallMultipleSynchronization.ts +3 -4
  114. package/src/hooks/useTooltip.tsx +186 -40
  115. package/src/scss/main.scss +152 -79
  116. package/src/test/CdcChart.test.jsx +26 -2
  117. package/src/types/ChartConfig.ts +5 -0
  118. package/tests/fixtures/chart-config-with-metadata.json +29 -0
  119. package/tests/fixtures/data-with-metadata.json +10 -0
  120. package/examples/chart-regression-2.json +0 -2360
  121. package/examples/feature/__data__/age-adjusted-rates.json +0 -1486
  122. package/examples/feature/__data__/city-temperature.json +0 -2198
  123. package/examples/feature/bar/Barchart_with_negative.json +0 -34
  124. package/examples/feature/boxplot/box-plot-data.json +0 -71
  125. package/examples/feature/boxplot/boxplot-data.json +0 -156
  126. package/examples/feature/combo/combochart-categories_are_numbers .json +0 -18
  127. package/examples/feature/forest-plot/log.json +0 -26
  128. package/examples/feature/tests-date-exclusions/date-exclusions-data.json +0 -162
  129. package/examples/region-issue.json +0 -2065
  130. package/examples/xaxis.json +0 -493
  131. /package/examples/feature/bar/{tall-data.json → __data__/tall-data.json} +0 -0
  132. /package/examples/feature/deviation/{planet-deviation-data.json → __data__/planet-deviation-data.json} +0 -0
  133. /package/examples/feature/paired-bar/{paired-bar-data.json → __data__/paired-bar-data.json} +0 -0
  134. /package/examples/feature/paired-bar/{paired-bar-formatted.json → __data__/paired-bar-formatted.json} +0 -0
  135. /package/examples/feature/tests-case-rate/{case-rate-example-data.json → __data__/case-rate-example-data.json} +0 -0
  136. /package/examples/feature/tests-covid/{covid-example-data-confidence.json → __data__/covid-example-data-confidence.json} +0 -0
  137. /package/examples/feature/tests-covid/{covid-example-data.json → __data__/covid-example-data.json} +0 -0
  138. /package/examples/feature/tests-cutoff/{cutoff-example-data.json → __data__/cutoff-example-data.json} +0 -0
  139. /package/examples/feature/tests-non-numerics/{planet-example-data-nonnumeric.json → __data__/planet-example-data-nonnumeric.json} +0 -0
  140. /package/src/_stories/{Chart.Anchors.stories.tsx → Chart.Anchors.smoke.stories.tsx} +0 -0
  141. /package/src/_stories/{Chart.BoxPlot.stories.tsx → Chart.BoxPlot.smoke.stories.tsx} +0 -0
  142. /package/src/_stories/{Chart.CI.stories.tsx → Chart.CI.smoke.stories.tsx} +0 -0
  143. /package/src/_stories/{Chart.Combo.stories.tsx → Chart.Combo.smoke.stories.tsx} +0 -0
  144. /package/src/_stories/{Chart.DynamicSeries.stories.tsx → Chart.DynamicSeries.smoke.stories.tsx} +0 -0
  145. /package/src/_stories/{Chart.Filters.stories.tsx → Chart.Filters.smoke.stories.tsx} +0 -0
  146. /package/src/_stories/{Chart.Forecast.stories.tsx → Chart.Forecast.smoke.stories.tsx} +0 -0
  147. /package/src/_stories/{Chart.Legend.Gradient.stories.tsx → Chart.Legend.Gradient.smoke.stories.tsx} +0 -0
  148. /package/src/_stories/{Chart.Patterns.stories.tsx → Chart.Patterns.smoke.stories.tsx} +0 -0
  149. /package/src/_stories/{Chart.PreserveDecimals.stories.tsx → Chart.PreserveDecimals.smoke.stories.tsx} +0 -0
  150. /package/src/_stories/{Chart.Regions.Categorical.stories.tsx → Chart.Regions.Categorical.smoke.stories.tsx} +0 -0
  151. /package/src/_stories/{Chart.Regions.DateScale.stories.tsx → Chart.Regions.DateScale.smoke.stories.tsx} +0 -0
  152. /package/src/_stories/{Chart.Regions.DateTimeScale.stories.tsx → Chart.Regions.DateTimeScale.smoke.stories.tsx} +0 -0
  153. /package/src/_stories/{Chart.ScatterPlot.stories.tsx → Chart.ScatterPlot.smoke.stories.tsx} +0 -0
  154. /package/src/_stories/{ChartAnnotation.stories.tsx → ChartAnnotation.smoke.stories.tsx} +0 -0
  155. /package/src/_stories/{ChartAxisLabels.stories.tsx → ChartAxisLabels.smoke.stories.tsx} +0 -0
  156. /package/src/_stories/{ChartAxisTitles.stories.tsx → ChartAxisTitles.smoke.stories.tsx} +0 -0
  157. /package/src/_stories/{ChartBrush.Matrix.Continuous.stories.tsx → ChartBrush.Matrix.Continuous.smoke.stories.tsx} +0 -0
  158. /package/src/_stories/{ChartBrush.Matrix.Date.stories.tsx → ChartBrush.Matrix.Date.smoke.stories.tsx} +0 -0
  159. /package/src/_stories/{ChartBrush.Matrix.DateTime.stories.tsx → ChartBrush.Matrix.DateTime.smoke.stories.tsx} +0 -0
  160. /package/src/_stories/{ChartBrush.stories.tsx → ChartBrush.smoke.stories.tsx} +0 -0
  161. /package/src/_stories/{ChartLine.QuadrantAngles.stories.tsx → ChartLine.QuadrantAngles.smoke.stories.tsx} +0 -0
  162. /package/src/_stories/{ChartLine.Suppression.stories.tsx → ChartLine.Suppression.smoke.stories.tsx} +0 -0
  163. /package/src/_stories/{ChartLine.Symbols.stories.tsx → ChartLine.Symbols.smoke.stories.tsx} +0 -0
  164. /package/src/_stories/{ChartPrefixSuffix.stories.tsx → ChartPrefixSuffix.smoke.stories.tsx} +0 -0
  165. /package/src/_stories/{TechAdoptionWithLinks.stories.tsx → TechAdoptionWithLinks.smoke.stories.tsx} +0 -0
@@ -19,7 +19,7 @@ export type EditorPanelContext = {
19
19
  handleUpdateHighlightedBarColor?: Function
20
20
  handleUpdateHighlightedBorderWidth?: Function
21
21
  highlightedBarValues?: Function
22
- highlightedSeriesValues?: Function
22
+ getHighlightedSeriesValues?: Function
23
23
  isPaletteReversed?: boolean
24
24
  handleRemoveHighlightedBar?: Function
25
25
  setLollipopShape?: Function
@@ -1,12 +1,22 @@
1
1
  import React, { useContext } from 'react'
2
+ import { Draggable } from '@hello-pangea/dnd'
2
3
  import ConfigContext from '../../../../ConfigContext.js'
3
4
  import { useEditorPermissions } from '../../useEditorPermissions'
4
5
 
5
6
  // CDC Core
6
7
  import Accordion from '@cdc/core/components/ui/Accordion'
7
8
  import Button from '@cdc/core/components/elements/Button'
9
+ import GroupedList from '@cdc/core/components/EditorPanel/GroupedList'
10
+ import Icon from '@cdc/core/components/ui/Icon'
8
11
  import { CheckBox, Select } from '@cdc/core/components/EditorPanel/Inputs'
9
- import _ from 'lodash'
12
+ import cloneDeep from 'lodash/cloneDeep'
13
+ import {
14
+ Accordion as AccessibleAccordion,
15
+ AccordionItem,
16
+ AccordionItemButton,
17
+ AccordionItemHeading,
18
+ AccordionItemPanel
19
+ } from 'react-accessible-accordion'
10
20
 
11
21
  // types
12
22
  import { type PanelProps } from './../PanelProps'
@@ -102,6 +112,16 @@ const PanelAnnotate: React.FC<PanelProps> = props => {
102
112
  })
103
113
  }
104
114
 
115
+ const handleAnnotationReorder = (sourceIndex: number, destinationIndex: number) => {
116
+ const annotations = [...config.annotations]
117
+ const [movedAnnotation] = annotations.splice(sourceIndex, 1)
118
+ annotations.splice(destinationIndex, 0, movedAnnotation)
119
+ updateConfig({
120
+ ...config,
121
+ annotations
122
+ })
123
+ }
124
+
105
125
  return (
106
126
  <Accordion key={props.name}>
107
127
  <Accordion.Section title={props.name} key={props.name}>
@@ -133,190 +153,221 @@ const PanelAnnotate: React.FC<PanelProps> = props => {
133
153
  />
134
154
  </label>
135
155
  )}
136
- {config?.annotations &&
137
- config?.annotations.map((annotation, index) => (
138
- <Accordion key={index}>
139
- <Accordion.Section
140
- title={annotation.text ? annotation.text.substring(0, 15) + '...' : `Annotation ${index + 1}`}
141
- >
142
- <div className='annotation-group'>
143
- <label>
144
- Annotation Text:
145
- <textarea
146
- rows={5}
147
- value={annotation.text}
148
- onChange={e => handleAnnotationUpdate(e.target.value, 'text', index)}
149
- />
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
156
+ <GroupedList
157
+ items={config?.annotations}
158
+ label='Text Annotations'
159
+ droppableId='chart-annotations-order'
160
+ onDragEnd={({ source, destination }) => {
161
+ if (!destination || source.index === destination.index) return
162
+ handleAnnotationReorder(source.index, destination.index)
163
+ }}
164
+ renderItem={(annotation, index) => (
165
+ <Draggable key={`annotation-${index}`} draggableId={`annotation-${index}`} index={index}>
166
+ {(provided, snapshot) => (
167
+ <div
168
+ ref={provided.innerRef}
169
+ {...provided.draggableProps}
170
+ {...provided.dragHandleProps}
171
+ className={snapshot.isDragging ? 'currently-dragging' : ''}
172
+ style={provided.draggableProps.style}
173
+ >
174
+ <AccessibleAccordion allowZeroExpanded preExpanded={['panel']}>
175
+ <AccordionItem uuid='panel' className='series-item series-item--chart'>
176
+ <AccordionItemHeading className='series-item__title'>
177
+ <AccordionItemButton className='accordion__button'>
178
+ <Icon display='move' size={15} style={{ cursor: 'default' }} />
179
+ {annotation.text ? annotation.text.substring(0, 15) + '...' : `Annotation ${index + 1}`}
180
+ </AccordionItemButton>
181
+ </AccordionItemHeading>
182
+ <AccordionItemPanel>
183
+ <div className='series-item__panel-actions'>
184
+ <Button
185
+ type='button'
186
+ variant='danger'
187
+ size='sm'
188
+ className='grouped-list__remove'
189
+ onClick={() => handleRemoveAnnotation(index)}
190
+ >
191
+ Delete Annotation
192
+ </Button>
193
+ </div>
194
+ <label>
195
+ Annotation Text:
196
+ <textarea
197
+ rows={5}
198
+ value={annotation.text}
199
+ onChange={e => handleAnnotationUpdate(e.target.value, 'text', index)}
200
+ />
201
+ </label>
166
202
 
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
- }
203
+ {visSupportsDataAnnotations() && (
204
+ <Select
205
+ label='Position Mode:'
206
+ value={annotation.anchorMode || 'fixed'}
207
+ options={[
208
+ { value: 'fixed', label: 'Fixed position' },
209
+ { value: 'data', label: 'Snap to data' }
210
+ ]}
211
+ section='annotations'
212
+ subsection={null}
213
+ fieldName='anchorMode'
214
+ updateField={(section, subsection, fieldName, value) => {
215
+ const updatedAnnotations = cloneDeep(config?.annotations)
216
+ updatedAnnotations[index].anchorMode = value
176
217
 
177
- updateConfig({
178
- ...config,
179
- annotations: updatedAnnotations
180
- })
181
- }}
182
- />
183
- )}
218
+ // When switching to data mode, ensure seriesKey and dataX are initialized
219
+ if (value === 'data') {
220
+ if (!updatedAnnotations[index].seriesKey) {
221
+ updatedAnnotations[index].seriesKey = config.series?.[0]?.dataKey || ''
222
+ }
223
+ if (!updatedAnnotations[index].dataX) {
224
+ updatedAnnotations[index].dataX = transformedData?.[0]?.[config.xAxis.dataKey] || ''
225
+ }
226
+ }
184
227
 
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
- )}
228
+ updateConfig({
229
+ ...config,
230
+ annotations: updatedAnnotations
231
+ })
232
+ }}
233
+ />
234
+ )}
203
235
 
204
- <label>
205
- Opacity
206
- <br />
207
- <input
208
- type='range'
209
- onChange={e => {
210
- const updatedAnnotations = _.cloneDeep(config?.annotations)
211
- updatedAnnotations[index].opacity = e.target.value
212
- updateConfig({
213
- ...config,
214
- annotations: updatedAnnotations
215
- })
216
- }}
217
- value={config?.annotations?.[index]?.opacity || '100'}
218
- />
219
- </label>
236
+ {visSupportsDataAnnotations() && annotation.anchorMode === 'data' && (
237
+ <Select
238
+ label='Series:'
239
+ value={annotation.seriesKey || config.series?.[0]?.dataKey || ''}
240
+ options={config.series.map(s => s.dataKey)}
241
+ section='annotations'
242
+ subsection={null}
243
+ fieldName='seriesKey'
244
+ updateField={(section, subsection, fieldName, value) => {
245
+ const updatedAnnotations = cloneDeep(config?.annotations)
246
+ updatedAnnotations[index].seriesKey = value || config.series?.[0]?.dataKey
247
+ updateConfig({
248
+ ...config,
249
+ annotations: updatedAnnotations
250
+ })
251
+ }}
252
+ />
253
+ )}
220
254
 
221
- <CheckBox
222
- value={config?.annotations[index]?.edit?.subject || false}
223
- section='annotations'
224
- subsection={null}
225
- fieldName={`${index}.edit.subject`}
226
- label='Edit Subject'
227
- updateField={(section, subsection, fieldName, value) => {
228
- const updatedAnnotations = _.cloneDeep(config?.annotations)
229
- updatedAnnotations[index].edit.subject = value
230
- updateConfig({
231
- ...config,
232
- annotations: updatedAnnotations
233
- })
234
- }}
235
- />
236
- <CheckBox
237
- value={config?.annotations[index]?.edit?.label || false}
238
- section='annotations'
239
- subsection={null}
240
- fieldName={`${index}.edit.label`}
241
- label='Edit Label'
242
- updateField={(section, subsection, fieldName, value) => {
243
- const updatedAnnotations = _.cloneDeep(config?.annotations)
244
- updatedAnnotations[index].edit.label = value
245
- updateConfig({
246
- ...config,
247
- annotations: updatedAnnotations
248
- })
249
- }}
250
- />
255
+ <label>
256
+ Opacity
257
+ <br />
258
+ <input
259
+ type='range'
260
+ onChange={e => {
261
+ const updatedAnnotations = cloneDeep(config?.annotations)
262
+ updatedAnnotations[index].opacity = e.target.value
263
+ updateConfig({
264
+ ...config,
265
+ annotations: updatedAnnotations
266
+ })
267
+ }}
268
+ value={config?.annotations?.[index]?.opacity || '100'}
269
+ />
270
+ </label>
251
271
 
252
- <Select
253
- label='Connection Type:'
254
- value={config?.annotations[index]?.connectionType}
255
- options={['Select', 'curve', 'line', 'elbow', 'none']}
256
- section='annotations'
257
- subsection={null}
258
- fieldName='connectionType'
259
- updateField={(section, subsection, fieldName, value) => {
260
- const updatedAnnotations = _.cloneDeep(config?.annotations)
261
- updatedAnnotations[index].connectionType = value
262
- updateConfig({
263
- ...config,
264
- annotations: updatedAnnotations
265
- })
266
- }}
267
- />
272
+ <CheckBox
273
+ value={config?.annotations[index]?.edit?.subject || false}
274
+ section='annotations'
275
+ subsection={null}
276
+ fieldName={`${index}.edit.subject`}
277
+ label='Edit Subject'
278
+ updateField={(section, subsection, fieldName, value) => {
279
+ const updatedAnnotations = cloneDeep(config?.annotations)
280
+ updatedAnnotations[index].edit.subject = value
281
+ updateConfig({
282
+ ...config,
283
+ annotations: updatedAnnotations
284
+ })
285
+ }}
286
+ />
287
+ <CheckBox
288
+ value={config?.annotations[index]?.edit?.label || false}
289
+ section='annotations'
290
+ subsection={null}
291
+ fieldName={`${index}.edit.label`}
292
+ label='Edit Label'
293
+ updateField={(section, subsection, fieldName, value) => {
294
+ const updatedAnnotations = cloneDeep(config?.annotations)
295
+ updatedAnnotations[index].edit.label = value
296
+ updateConfig({
297
+ ...config,
298
+ annotations: updatedAnnotations
299
+ })
300
+ }}
301
+ />
268
302
 
269
- {annotation.connectionType === 'curve' && (
270
- <>
271
- <label>
272
- Curve Control
273
- {/* create a range input */}
274
- <input
275
- type='range'
276
- min='-20'
277
- max='20'
278
- value={config?.annotations[index]?.bezier || 0}
279
- onChange={e => {
280
- const updatedAnnotations = _.cloneDeep(config?.annotations)
281
- updatedAnnotations[index].bezier = e.target.value
303
+ <Select
304
+ label='Connection Type:'
305
+ value={config?.annotations[index]?.connectionType}
306
+ options={['Select', 'curve', 'line', 'elbow', 'none']}
307
+ section='annotations'
308
+ subsection={null}
309
+ fieldName='connectionType'
310
+ updateField={(section, subsection, fieldName, value) => {
311
+ const updatedAnnotations = cloneDeep(config?.annotations)
312
+ updatedAnnotations[index].connectionType = value
282
313
  updateConfig({
283
314
  ...config,
284
315
  annotations: updatedAnnotations
285
316
  })
286
317
  }}
287
318
  />
288
- </label>
289
- </>
290
- )}
291
319
 
292
- <Select
293
- label='Marker'
294
- value={annotation.marker}
295
- options={['arrow', 'circle']}
296
- section='annotations'
297
- subsection={null}
298
- fieldName='marker'
299
- updateField={(section, subsection, fieldName, value) => {
300
- const updatedAnnotations = _.cloneDeep(config?.annotations)
301
- updatedAnnotations[index].marker = value
302
- updateConfig({
303
- ...config,
304
- annotations: updatedAnnotations
305
- })
306
- }}
307
- />
320
+ {annotation.connectionType === 'curve' && (
321
+ <>
322
+ <label>
323
+ Curve Control
324
+ {/* create a range input */}
325
+ <input
326
+ type='range'
327
+ min='-20'
328
+ max='20'
329
+ value={config?.annotations[index]?.bezier || 0}
330
+ onChange={e => {
331
+ const updatedAnnotations = cloneDeep(config?.annotations)
332
+ updatedAnnotations[index].bezier = e.target.value
333
+ updateConfig({
334
+ ...config,
335
+ annotations: updatedAnnotations
336
+ })
337
+ }}
338
+ />
339
+ </label>
340
+ </>
341
+ )}
308
342
 
309
- <Button className='btn btn-danger full-width' onClick={() => handleRemoveAnnotation(index)}>
310
- Delete Annotation
311
- </Button>
343
+ <Select
344
+ label='Marker'
345
+ value={annotation.marker}
346
+ options={['arrow', 'circle']}
347
+ section='annotations'
348
+ subsection={null}
349
+ fieldName='marker'
350
+ updateField={(section, subsection, fieldName, value) => {
351
+ const updatedAnnotations = cloneDeep(config?.annotations)
352
+ updatedAnnotations[index].marker = value
353
+ updateConfig({
354
+ ...config,
355
+ annotations: updatedAnnotations
356
+ })
357
+ }}
358
+ />
359
+ </AccordionItemPanel>
360
+ </AccordionItem>
361
+ </AccessibleAccordion>
312
362
  </div>
313
- </Accordion.Section>
314
- </Accordion>
315
- ))}
363
+ )}
364
+ </Draggable>
365
+ )}
366
+ />
316
367
  {config?.annotations?.length < 3 && (
317
- <button onClick={handleAddAnnotation} className='btn btn-primary mt-2 full-width'>
368
+ <Button variant='editor-primary' onClick={handleAddAnnotation}>
318
369
  Add Annotation
319
- </button>
370
+ </Button>
320
371
  )}
321
372
  </Accordion.Section>
322
373
  </Accordion>
@@ -320,84 +320,6 @@ const ForestPlotSettings: FC<PanelProps> = ({ name }) => {
320
320
  <br />
321
321
  <hr />
322
322
  <br />
323
- <h4>Width Settings</h4>
324
-
325
- <label>
326
- <span className='edit-label column-heading'>Chart Offset Left (%)</span>
327
- <input
328
- type='number'
329
- min={0}
330
- max={100}
331
- value={config.forestPlot.leftWidthOffset || 0}
332
- onChange={e => {
333
- updateConfig({
334
- ...config,
335
- forestPlot: {
336
- ...config.forestPlot,
337
- leftWidthOffset: e.target.value
338
- }
339
- })
340
- }}
341
- />
342
- </label>
343
-
344
- <label>
345
- <span className='edit-label column-heading'>Chart Offset Left Mobile(%)</span>
346
- <input
347
- type='number'
348
- min={0}
349
- max={100}
350
- value={config.forestPlot.leftWidthOffsetMobile || 0}
351
- onChange={e => {
352
- updateConfig({
353
- ...config,
354
- forestPlot: {
355
- ...config.forestPlot,
356
- leftWidthOffsetMobile: e.target.value
357
- }
358
- })
359
- }}
360
- />
361
- </label>
362
-
363
- <label>
364
- <span className='edit-label column-heading'>Chart Offset Right (%)</span>
365
- <input
366
- type='number'
367
- min={0}
368
- max={100}
369
- value={config.forestPlot.rightWidthOffset || 0}
370
- onChange={e => {
371
- updateConfig({
372
- ...config,
373
- forestPlot: {
374
- ...config.forestPlot,
375
- rightWidthOffset: e.target.value
376
- }
377
- })
378
- }}
379
- />
380
- </label>
381
-
382
- <label>
383
- <span className='edit-label column-heading'>Chart Offset Right Mobile(%)</span>
384
- <input
385
- type='number'
386
- min={0}
387
- max={100}
388
- value={config.forestPlot.rightWidthOffsetMobile || 0}
389
- onChange={e => {
390
- updateConfig({
391
- ...config,
392
- forestPlot: {
393
- ...config.forestPlot,
394
- rightWidthOffsetMobile: e.target.value
395
- }
396
- })
397
- }}
398
- />
399
- </label>
400
-
401
323
  <TextField
402
324
  type='number'
403
325
  min={20}
@@ -47,6 +47,22 @@ const PanelGeneral: FC<PanelProps> = props => {
47
47
  }
48
48
  }
49
49
 
50
+ const handleTitleStyleChange = (newTitleStyle: string) => {
51
+ updateConfig({
52
+ ...config,
53
+ titleStyle: newTitleStyle,
54
+ visual:
55
+ newTitleStyle === 'legacy'
56
+ ? config.visual
57
+ : {
58
+ ...config.visual,
59
+ border: undefined,
60
+ borderColorTheme: undefined,
61
+ accent: undefined
62
+ }
63
+ })
64
+ }
65
+
50
66
  return (
51
67
  <AccordionItem>
52
68
  {' '}
@@ -475,12 +491,12 @@ const PanelGeneral: FC<PanelProps> = props => {
475
491
  value={config.titleStyle}
476
492
  fieldName='titleStyle'
477
493
  label='Title Style'
478
- updateField={updateField}
479
494
  options={[
480
495
  { value: 'small', label: 'Small (h3)' },
481
496
  { value: 'large', label: 'Large (h2)' },
482
497
  { value: 'legacy', label: 'Legacy' }
483
498
  ]}
499
+ onChange={event => handleTitleStyleChange(event.target.value)}
484
500
  tooltip={
485
501
  <Tooltip style={{ textTransform: 'none' }}>
486
502
  <Tooltip.Target>
@@ -579,6 +595,28 @@ const PanelGeneral: FC<PanelProps> = props => {
579
595
  }
580
596
  />
581
597
  )}
598
+ <Select
599
+ value={config.locale}
600
+ fieldName='locale'
601
+ label='Language for dates and numbers'
602
+ updateField={updateField}
603
+ options={[
604
+ { value: 'en-US', label: 'English (en-US)' },
605
+ { value: 'es-MX', label: 'Spanish (es-MX)' }
606
+ ]}
607
+ tooltip={
608
+ <Tooltip style={{ textTransform: 'none' }}>
609
+ <Tooltip.Target>
610
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
611
+ </Tooltip.Target>
612
+ <Tooltip.Content>
613
+ <p>
614
+ Change the language (locale) for this visualization to alter the way dates and numbers are formatted.
615
+ </p>
616
+ </Tooltip.Content>
617
+ </Tooltip>
618
+ }
619
+ />
582
620
  </AccordionItemPanel>
583
621
  </AccordionItem>
584
622
  )