@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
package/src/CdcChart.tsx CHANGED
@@ -29,9 +29,9 @@ import Legend from './components/Legend'
29
29
  import defaults from './data/initial-state'
30
30
  import EditorPanel from './components/EditorPanel'
31
31
  import { abbreviateNumber } from './helpers/abbreviateNumber'
32
+ import { handleChartTabbing } from './helpers/handleChartTabbing'
32
33
  import { getQuartiles } from './helpers/getQuartiles'
33
34
  import { sortAsc, sortDesc } from './helpers/sort'
34
- import { filterData } from './helpers/filterData'
35
35
  import { handleChartAriaLabels } from './helpers/handleChartAriaLabels'
36
36
  import { lineOptions } from './helpers/lineOptions'
37
37
  import { handleLineType } from './helpers/handleLineType'
@@ -39,6 +39,7 @@ import { generateColorsArray } from './helpers/generateColorsArray'
39
39
  import Loading from '@cdc/core/components/Loading'
40
40
  import Filters from '@cdc/core/components/Filters'
41
41
  import MediaControls from '@cdc/core/components/MediaControls'
42
+ import Annotation from './components/Annotations'
42
43
 
43
44
  // Helpers
44
45
  import { publish, subscribe, unsubscribe } from '@cdc/core/helpers/events'
@@ -50,6 +51,7 @@ import cacheBustingString from '@cdc/core/helpers/cacheBustingString'
50
51
  import isNumber from '@cdc/core/helpers/isNumber'
51
52
  import coveUpdateWorker from '@cdc/core/helpers/coveUpdateWorker'
52
53
  import { getQueryStringFilterValue } from '@cdc/core/helpers/queryStringUtils'
54
+ import { isConvertLineToBarGraph } from './helpers/isConvertLineToBarGraph'
53
55
 
54
56
  import './scss/main.scss'
55
57
  // load both then config below determines which to use
@@ -58,8 +60,10 @@ import { getFileExtension } from '@cdc/core/helpers/getFileExtension'
58
60
  import Title from '@cdc/core/components/ui/Title'
59
61
  import { ChartConfig } from './types/ChartConfig'
60
62
  import { Label } from './types/Label'
63
+ import { type ViewportSize } from './types/ChartConfig'
61
64
  import { isSolrCsv, isSolrJson } from '@cdc/core/helpers/isSolr'
62
65
  import SkipTo from '@cdc/core/components/elements/SkipTo'
66
+ import { filterVizData } from '@cdc/core/helpers/filterVizData'
63
67
 
64
68
  export default function CdcChart({ configUrl, config: configObj, isEditor = false, isDebug = false, isDashboard = false, setConfig: setParentConfig, setEditing, hostname, link, setSharedFilter, setSharedFilterValue, dashboardConfig }) {
65
69
  const transform = new DataTransform()
@@ -70,11 +74,12 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
70
74
  const [excludedData, setExcludedData] = useState<Record<string, number>[] | undefined>(undefined)
71
75
  const [filteredData, setFilteredData] = useState<Record<string, any>[] | undefined>(undefined)
72
76
  const [seriesHighlight, setSeriesHighlight] = useState<string[]>(configObj && configObj?.legend?.seriesHighlight?.length ? [...configObj?.legend?.seriesHighlight] : [])
73
- const [currentViewport, setCurrentViewport] = useState('lg')
77
+ const [currentViewport, setCurrentViewport] = useState<ViewportSize>('lg')
74
78
  const [dimensions, setDimensions] = useState<[number?, number?]>([])
75
79
  const [externalFilters, setExternalFilters] = useState<any[]>()
76
80
  const [container, setContainer] = useState()
77
81
  const [coveLoadedEventRan, setCoveLoadedEventRan] = useState(false)
82
+ const [isDraggingAnnotation, setIsDraggingAnnotation] = useState(false)
78
83
  const [dynamicLegendItems, setDynamicLegendItems] = useState<any[]>([])
79
84
  const [imageId] = useState(`cove-${Math.random().toString(16).slice(-4)}`)
80
85
  const [brushConfig, setBrushConfig] = useState({
@@ -87,6 +92,10 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
87
92
  let innerContainerRef = useRef()
88
93
  const legendRef = useRef(null)
89
94
 
95
+ const handleDragStateChange = isDragging => {
96
+ setIsDraggingAnnotation(isDragging)
97
+ }
98
+
90
99
  if (isDebug) console.log('Chart config, isEditor', config, isEditor)
91
100
 
92
101
  // Destructure items from config for more readable JSX
@@ -101,7 +110,10 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
101
110
 
102
111
  const { barBorderClass, lineDatapointClass, contentClasses, sparkLineStyles } = useDataVizClasses(config)
103
112
  const legendId = useId()
104
- const handleChartTabbing = !config.legend?.hide ? legendId : config?.title ? `dataTableSection__${config.title.replace(/\s/g, '')}` : `dataTableSection`
113
+
114
+ const checkLineToBarGraph = () => {
115
+ return isConvertLineToBarGraph(config.visualizationType, filteredData, config.allowLineToBarGraph)
116
+ }
105
117
 
106
118
  const reloadURLData = async () => {
107
119
  if (config.dataUrl) {
@@ -164,7 +176,7 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
164
176
  if (data) {
165
177
  setStateData(data)
166
178
  setExcludedData(data)
167
- setFilteredData(filterData(config.filters, data))
179
+ setFilteredData(filterVizData(config.filters, data))
168
180
  }
169
181
  }
170
182
  }
@@ -251,7 +263,7 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
251
263
  if (!series.axis) series.axis = 'Left'
252
264
  })
253
265
 
254
- if (!newConfig.data && data) {
266
+ if (data) {
255
267
  newConfig.data = data
256
268
  }
257
269
 
@@ -312,17 +324,15 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
312
324
  newConfig.filters[index].values = filterValues
313
325
  // Initial filter should be active
314
326
 
315
- newConfig.filters[index].active = newConfig.filters[index].active || filterValues[0]
327
+ newConfig.filters[index].active = !newConfig.filters[index].active || filterValues.indexOf(newConfig.filters[index].active) === -1 ? filterValues[0] : newConfig.filters[index].active
316
328
  newConfig.filters[index].filterStyle = newConfig.filters[index].filterStyle ? newConfig.filters[index].filterStyle : 'dropdown'
317
329
  })
318
- currentData = filterData(newConfig.filters, newExcludedData)
330
+ currentData = filterVizData(newConfig.filters, newExcludedData)
319
331
  setFilteredData(currentData)
320
332
  }
321
333
 
322
- if (newConfig.xAxis.type === 'date-time' && newConfig.barThickness > 0.1) {
323
- newConfig.barThickness = 0.035
324
- } else if (newConfig.xAxis.type !== 'date-time' && newConfig.barThickness < 0.1) {
325
- newConfig.barThickness = 0.35
334
+ if (newConfig.xAxis.type === 'date-time' && config.orientation === 'horizontal') {
335
+ newConfig.xAxis.type = 'date'
326
336
  }
327
337
 
328
338
  //Enforce default values that need to be calculated at runtime
@@ -487,7 +497,7 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
487
497
 
488
498
  newConfig.runtime.horizontal = false
489
499
  newConfig.orientation = 'horizontal'
490
- } else if (['Box Plot', 'Scatter Plot', 'Area Chart', 'Line', 'Forecasting'].includes(newConfig.visualizationType)) {
500
+ } else if (['Box Plot', 'Scatter Plot', 'Area Chart', 'Line', 'Forecasting'].includes(newConfig.visualizationType) && !checkLineToBarGraph()) {
491
501
  newConfig.runtime.xAxis = newConfig.xAxis
492
502
  newConfig.runtime.yAxis = newConfig.yAxis
493
503
  newConfig.runtime.horizontal = false
@@ -628,14 +638,14 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
628
638
  let configCopy = { ...config }
629
639
  delete configCopy['filters']
630
640
  setConfig(configCopy)
631
- setFilteredData(filterData(externalFilters, excludedData))
641
+ setFilteredData(filterVizData(externalFilters, excludedData))
632
642
  }
633
643
  }
634
644
 
635
645
  if (externalFilters && externalFilters.length > 0 && externalFilters.length > 0 && externalFilters[0].hasOwnProperty('active')) {
636
646
  let newConfigHere = { ...config, filters: externalFilters }
637
647
  setConfig(newConfigHere)
638
- setFilteredData(filterData(externalFilters, excludedData))
648
+ setFilteredData(filterVizData(externalFilters, excludedData))
639
649
  }
640
650
  }, [externalFilters]) // eslint-disable-line
641
651
 
@@ -913,7 +923,7 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
913
923
  }
914
924
 
915
925
  // Select appropriate chart type
916
- const chartComponents = {
926
+ const ChartComponents = {
917
927
  'Paired Bar': <LinearChart />,
918
928
  Forecasting: <LinearChart />,
919
929
  Bar: <LinearChart />,
@@ -1107,17 +1117,33 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
1107
1117
  // Prevent render if loading
1108
1118
  let body = <Loading />
1109
1119
 
1120
+ const makeClassName = string => {
1121
+ if (!string || !string.toLowerCase) return
1122
+ return string.toLowerCase().replaceAll(/ /g, '-')
1123
+ }
1124
+
1110
1125
  const getChartWrapperClasses = () => {
1126
+ const isLegendOnBottom = legend?.position === 'bottom' || ['sm', 'xs', 'xxs'].includes(currentViewport)
1111
1127
  const classes = ['chart-container', 'p-relative']
1112
- if (config.legend.position === 'bottom') classes.push('bottom')
1113
- if (config.legend.hide) classes.push('legend-hidden')
1128
+ if (config.legend?.position === 'bottom') classes.push('bottom')
1129
+ if (config.legend?.hide) classes.push('legend-hidden')
1114
1130
  if (lineDatapointClass) classes.push(lineDatapointClass)
1115
1131
  if (!config.barHasBorder) classes.push('chart-bar--no-border')
1116
- if (isDebug) classes.push('debug')
1132
+ if (config.brush?.active && dashboardConfig?.type === 'dashboard' && (!isLegendOnBottom || config.legend.hide)) classes.push('dashboard-brush')
1117
1133
  classes.push(...contentClasses)
1118
1134
  return classes
1119
1135
  }
1120
1136
 
1137
+ const getChartSubTextClasses = () => {
1138
+ const classes = ['subtext ']
1139
+ const isLegendOnBottom = legend?.position === 'bottom' || ['sm', 'xs', 'xxs'].includes(currentViewport)
1140
+
1141
+ if (config.isResponsiveTicks) classes.push('subtext--responsive-ticks ')
1142
+ if (config.brush?.active && !isLegendOnBottom) classes.push('subtext--brush-active ')
1143
+ if (config.brush?.active && config.legend.hide) classes.push('subtext--brush-active ')
1144
+ return classes
1145
+ }
1146
+
1121
1147
  if (!loading) {
1122
1148
  const tableLink = (
1123
1149
  <a href={`#data-table-${config.dataKey}`} className='margin-left-href'>
@@ -1131,21 +1157,28 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
1131
1157
  {config.newViz && <Confirm />}
1132
1158
  {undefined === config.newViz && isEditor && config.runtime && config.runtime?.editorErrorMessage && <Error />}
1133
1159
  {!missingRequiredSections() && !config.newViz && (
1134
- <div className='cdc-chart-inner-container cove-component__content' aria-label={handleChartAriaLabels(config)} tabIndex={0}>
1160
+ <div className={`cdc-chart-inner-container cove-component__content type-${makeClassName(config.visualizationType)}`} aria-label={handleChartAriaLabels(config)} tabIndex={0}>
1135
1161
  <Title showTitle={config.showTitle} isDashboard={isDashboard} title={title} superTitle={config.superTitle} classes={['chart-title', `${config.theme}`, 'cove-component__header']} style={undefined} />
1136
1162
 
1137
1163
  {/* Filters */}
1138
- {config.filters && !externalFilters && config.visualizationType !== 'Spark Line' && <Filters config={config} setConfig={setConfig} setFilteredData={setFilteredData} filteredData={filteredData} excludedData={excludedData} filterData={filterData} dimensions={dimensions} />}
1139
- <SkipTo skipId={handleChartTabbing} skipMessage='Skip Over Chart Container' />
1164
+ {config.filters && !externalFilters && config.visualizationType !== 'Spark Line' && <Filters config={config} setConfig={setConfig} setFilteredData={setFilteredData} filteredData={filteredData} excludedData={excludedData} filterData={filterVizData} dimensions={dimensions} />}
1165
+ <SkipTo skipId={handleChartTabbing(config, legendId)} skipMessage='Skip Over Chart Container' />
1166
+ {config.annotations?.length > 0 && <SkipTo skipId={handleChartTabbing(config, legendId)} skipMessage={`Skip over annotations`} key={`skip-annotations`} />}
1167
+
1140
1168
  {/* Visualization */}
1141
1169
  {config?.introText && config.visualizationType !== 'Spark Line' && <section className='introText'>{parse(config.introText)}</section>}
1170
+
1142
1171
  <div className={getChartWrapperClasses().join(' ')}>
1143
- {/* All charts except sparkline */}
1144
- {config.visualizationType !== 'Spark Line' && chartComponents[config.visualizationType]}
1172
+ {/* All charts except line and sparkline */}
1173
+ {config.visualizationType !== 'Spark Line' && config.visualizationType !== 'Line' && ChartComponents[config.visualizationType]}
1174
+
1175
+ {/* Line Chart */}
1176
+ {config.visualizationType === 'Line' && (checkLineToBarGraph() ? ChartComponents['Bar'] : ChartComponents['Line'])}
1177
+
1145
1178
  {/* Sparkline */}
1146
1179
  {config.visualizationType === 'Spark Line' && (
1147
1180
  <>
1148
- <Filters config={config} setConfig={setConfig} setFilteredData={setFilteredData} filteredData={filteredData} excludedData={excludedData} filterData={filterData} dimensions={dimensions} />
1181
+ <Filters config={config} setConfig={setConfig} setFilteredData={setFilteredData} filteredData={filteredData} excludedData={excludedData} filterData={filterVizData} dimensions={dimensions} />
1149
1182
  {config?.introText && (
1150
1183
  <section className='introText' style={{ padding: '0px 0 35px' }}>
1151
1184
  {parse(config.introText)}
@@ -1163,12 +1196,15 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
1163
1196
  )}
1164
1197
  {/* Sankey */}
1165
1198
  {config.visualizationType === 'Sankey' && <ParentSize aria-hidden='true'>{parent => <SankeyChart runtime={config.runtime} width={parent.width} height={parent.height} />}</ParentSize>}
1166
- {!config.legend.hide && config.visualizationType !== 'Spark Line' && config.visualizationType !== 'Sankey' && <Legend ref={legendRef} />}
1199
+ {!config.legend.hide && config.visualizationType !== 'Spark Line' && config.visualizationType !== 'Sankey' && <Legend ref={legendRef} skipId={handleChartTabbing(config, legendId)} />}
1167
1200
  </div>
1168
1201
  {/* Link */}
1169
1202
  {isDashboard && config.table && config.table.show && config.table.showDataTableLink ? tableLink : link && link}
1170
1203
  {/* Description */}
1171
- {description && config.visualizationType !== 'Spark Line' && <div className={'column ' + config.isResponsiveTicks ? 'subtext--responsive-ticks' : 'subtext'}>{parse(description)}</div>}
1204
+
1205
+ {description && config.visualizationType !== 'Spark Line' && <div className={getChartSubTextClasses().join('')}>{parse(description)}</div>}
1206
+ {false && <Annotation.List />}
1207
+
1172
1208
  {/* buttons */}
1173
1209
  <MediaControls.Section classes={['download-buttons']}>
1174
1210
  {config.table.showDownloadImgButton && <MediaControls.Button text='Download Image' title='Download Chart as Image' type='image' state={config} elementToCapture={imageId} />}
@@ -1178,7 +1214,7 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
1178
1214
  {((config.xAxis.dataKey && config.table.show && config.visualizationType !== 'Spark Line' && config.visualizationType !== 'Sankey') || (config.visualizationType === 'Sankey' && config.table.show)) && (
1179
1215
  <DataTable
1180
1216
  config={config}
1181
- rawData={config.visualizationType === 'Sankey' ? config?.data?.[0]?.tableData : config.table.customTableConfig ? filterData(config.filters, config.data) : config.data}
1217
+ rawData={config.visualizationType === 'Sankey' ? config?.data?.[0]?.tableData : config.table.customTableConfig ? filterVizData(config.filters, config.data) : config.data}
1182
1218
  runtimeData={config.visualizationType === 'Sankey' ? config?.data?.[0]?.tableData : filteredData || excludedData}
1183
1219
  expandDataTable={config.table.expanded}
1184
1220
  columns={config.columns}
@@ -1189,10 +1225,11 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
1189
1225
  indexTitle={config.table.indexLabel}
1190
1226
  vizTitle={title}
1191
1227
  viewport={currentViewport}
1192
- tabbingId={handleChartTabbing}
1228
+ tabbingId={handleChartTabbing(config, legendId)}
1193
1229
  colorScale={colorScale}
1194
1230
  />
1195
1231
  )}
1232
+ {config?.annotations?.length > 0 && <Annotation.Dropdown />}
1196
1233
  {config?.footnotes && <section className='footnotes'>{parse(config.footnotes)}</section>}
1197
1234
  {/* show pdf or image button */}
1198
1235
  </div>
@@ -1211,54 +1248,57 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
1211
1248
 
1212
1249
  const contextValues = {
1213
1250
  brushConfig,
1214
- setBrushConfig,
1215
1251
  capitalize,
1216
- getXAxisData,
1217
- getYAxisData,
1218
- config,
1219
- setConfig,
1220
- rawData: stateData ?? {},
1221
- excludedData: excludedData,
1222
- transformedData: clean(filteredData || excludedData), // do this right before passing to components
1223
- tableData: filteredData || excludedData, // do not clean table data
1224
- unfilteredData: stateData,
1225
- seriesHighlight,
1252
+ clean,
1253
+ colorPalettes,
1226
1254
  colorScale,
1227
- dimensions,
1255
+ config,
1228
1256
  currentViewport,
1229
- parseDate,
1257
+ dashboardConfig,
1258
+ debugSvg: isDebug,
1259
+ dimensions,
1260
+ dynamicLegendItems,
1261
+ excludedData: excludedData,
1230
1262
  formatDate,
1231
- formatTooltipsDate,
1232
1263
  formatNumber,
1233
- loading,
1234
- updateConfig,
1235
- colorPalettes,
1236
- isDashboard,
1237
- setParentConfig,
1238
- missingRequiredSections,
1239
- setEditing,
1240
- setFilteredData,
1264
+ formatTooltipsDate,
1265
+ getTextWidth,
1266
+ getXAxisData,
1267
+ getYAxisData,
1241
1268
  handleChartAriaLabels,
1269
+ handleLineType,
1242
1270
  highlight,
1243
1271
  highlightReset,
1244
- legend,
1245
- setSeriesHighlight,
1246
- dynamicLegendItems,
1247
- setDynamicLegendItems,
1248
- filterData,
1249
1272
  imageId,
1250
- handleLineType,
1251
- lineOptions,
1252
- isNumber,
1253
- getTextWidth,
1254
- twoColorPalette,
1255
- isEditor,
1273
+ isDashboard,
1274
+ isLegendBottom: legend?.position === 'bottom' || ['sm', 'xs', 'xxs'].includes(currentViewport),
1256
1275
  isDebug,
1276
+ isDraggingAnnotation,
1277
+ handleDragStateChange,
1278
+ isEditor,
1279
+ isNumber,
1280
+ legend,
1281
+ lineOptions,
1282
+ loading,
1283
+ missingRequiredSections,
1284
+ outerContainerRef,
1285
+ parseDate,
1286
+ rawData: stateData ?? {},
1287
+ seriesHighlight,
1288
+ setBrushConfig,
1289
+ setConfig,
1290
+ setDynamicLegendItems,
1291
+ setEditing,
1292
+ setFilteredData,
1293
+ setParentConfig,
1294
+ setSeriesHighlight,
1257
1295
  setSharedFilter,
1258
1296
  setSharedFilterValue,
1259
- dashboardConfig,
1260
- debugSvg: isDebug,
1261
- clean
1297
+ tableData: filteredData || excludedData, // do not clean table data
1298
+ transformedData: clean(filteredData || excludedData), // do this right before passing to components
1299
+ twoColorPalette,
1300
+ unfilteredData: stateData,
1301
+ updateConfig
1262
1302
  }
1263
1303
 
1264
1304
  return (
@@ -2,6 +2,9 @@ import type { Meta, StoryObj } from '@storybook/react'
2
2
  import SuppressedConfig from './_mock/bar-chart-suppressed.json'
3
3
 
4
4
  import Chart from '../CdcChart'
5
+ import lineChartTwoPointsRegressionTest from './_mock/line_chart_two_points_regression_test.json'
6
+ import lineChartTwoPointsNewChart from './_mock/line_chart_two_points_new_chart.json'
7
+ import lollipop from './_mock/lollipop.json'
5
8
 
6
9
  const meta: Meta<typeof Chart> = {
7
10
  title: 'Components/Templates/Chart',
@@ -10,179 +13,23 @@ const meta: Meta<typeof Chart> = {
10
13
 
11
14
  type Story = StoryObj<typeof Chart>
12
15
 
16
+ export const line_Chart_Two_Points_Regression_Test: Story = {
17
+ args: {
18
+ config: lineChartTwoPointsRegressionTest,
19
+ isEditor: false
20
+ }
21
+ }
22
+ export const line_Chart_Two_Points_New_Chart: Story = {
23
+ args: {
24
+ config: lineChartTwoPointsNewChart,
25
+ isEditor: false
26
+ }
27
+ }
28
+
13
29
  export const Lollipop: Story = {
14
30
  args: {
15
- config: {
16
- type: 'chart',
17
- title: 'Lollipop Style Horizontal Bar Chart - Number of Spills Occurring in the Home',
18
- showTitle: true,
19
- showDownloadMediaButton: false,
20
- theme: 'theme-blue',
21
- animate: true,
22
- fontSize: 'medium',
23
- lineDatapointStyle: 'hover',
24
- barHasBorder: 'false',
25
- isLollipopChart: true,
26
- lollipopShape: 'circle',
27
- lollipopColorStyle: 'two-tone',
28
- visualizationSubType: 'horizontal',
29
- barStyle: '',
30
- roundingStyle: 'standard',
31
- tipRounding: 'top',
32
- isResponsiveTicks: false,
33
- general: { showDownloadButton: false },
34
- padding: { left: 5, right: 5 },
35
- yAxis: {
36
- hideAxis: true,
37
- displayNumbersOnBar: true,
38
- hideLabel: false,
39
- hideTicks: false,
40
- size: '13',
41
- gridLines: false,
42
- enablePadding: false,
43
- min: '',
44
- max: '',
45
- labelColor: '#333',
46
- tickLabelColor: '#333',
47
- tickColor: '#333',
48
- rightHideAxis: true,
49
- rightAxisSize: 50,
50
- rightLabel: '',
51
- rightLabelOffsetSize: 0,
52
- rightAxisLabelColor: '#333',
53
- rightAxisTickLabelColor: '#333',
54
- rightAxisTickColor: '#333',
55
- numTicks: '9',
56
- axisPadding: 0,
57
- tickRotation: 0,
58
- anchors: [],
59
- type: 'chart',
60
- title: 'Lollipop Style Horizontal Bar Chart',
61
- theme: 'theme-blue',
62
- fontSize: 'medium',
63
- lineDatapointStyle: 'hover',
64
- barHasBorder: 'false',
65
- isLollipopChart: false,
66
- lollipopShape: 'circle',
67
- lollipopColorStyle: 'two-tone',
68
- visualizationSubType: 'horizontal',
69
- padding: { left: 5, right: 5 },
70
- yAxis: { size: 50, gridLines: false },
71
- barThickness: 0.35,
72
- height: 260,
73
- xAxis: { type: 'categorical', size: 75, tickRotation: 0, dataKey: 'Vehicle' },
74
- table: { label: 'Data Table', expanded: true, show: true },
75
- legend: { behavior: 'isolate', position: 'right' },
76
- exclusions: { active: false, keys: [] },
77
- palette: 'qualitative-bold',
78
- labels: false,
79
- dataFormat: {},
80
- confidenceKeys: {},
81
- data: [
82
- { Group: 'Combined Total of Group A', Vehicle: '100', Home: '120', Work: '140', Office: '120' },
83
- { Group: 'Combined Total of Group B', Vehicle: '150', Home: '140', Work: '100', Office: '90' },
84
- { Group: 'Combined Total of Group C', Vehicle: '90', Home: '90', Work: '80', Office: '80' },
85
- { Group: 'Combined Total of Group D', Vehicle: '70', Home: '60', Work: '50', Office: '70' }
86
- ],
87
- dataFileName: 'CSV_Source_Example_for_Horizontal_Bar_viz-cdcwp1619811744363.csv',
88
- dataFileSourceType: 'file',
89
- visualizationType: 'Bar',
90
- runtime: {
91
- seriesLabels: { Vehicle: 'Vehicle' },
92
- seriesLabelsAll: ['Vehicle'],
93
- originalXAxis: { type: 'categorical', size: 75, tickRotation: 0, dataKey: 'Vehicle' },
94
- seriesKeys: ['Vehicle'],
95
- xAxis: { size: 50, gridLines: false },
96
- yAxis: { type: 'categorical', size: 75, tickRotation: 0, dataKey: 'Vehicle' },
97
- horizontal: true,
98
- uniqueId: 1651765968212,
99
- editorErrorMessage: ''
100
- },
101
- description: 'Subtext can be added here for options like citing data sources or insight into reading the bar chart.',
102
- series: [{ dataKey: 'Vehicle', type: 'Bar' }],
103
- barHeight: 25,
104
- barPadding: 40,
105
- labelPlacement: 'Below Bar',
106
- label: 'Number of Accidents'
107
- },
108
- boxplot: [],
109
- topAxis: { hasLine: false },
110
- isLegendValue: false,
111
- barThickness: 0.35,
112
- barHeight: 6,
113
- barSpace: 15,
114
- heights: { vertical: 300, horizontal: 170.39999999999998 },
115
- xAxis: {
116
- anchors: [],
117
- type: 'categorical',
118
- showTargetLabel: true,
119
- targetLabel: 'Target',
120
- hideAxis: true,
121
- hideLabel: true,
122
- hideTicks: true,
123
- size: '16',
124
- tickRotation: 0,
125
- min: '',
126
- max: '160',
127
- labelColor: '#333',
128
- tickLabelColor: '#333',
129
- tickColor: '#333',
130
- numTicks: '',
131
- labelOffset: 65,
132
- axisPadding: 0,
133
- target: 0,
134
- maxTickRotation: 0,
135
- dataKey: 'Group'
136
- },
137
- table: { label: 'Data Table', expanded: false, limitHeight: false, height: '', caption: '', showDownloadUrl: false, showDataTableLink: true, indexLabel: 'Group', download: false, showVertical: true, show: true },
138
- orientation: 'horizontal',
139
- color: 'pinkpurple',
140
- columns: {},
141
- legend: {
142
- behavior: 'isolate',
143
- singleRow: false,
144
- colorCode: '',
145
- reverseLabelOrder: false,
146
- description: '',
147
- dynamicLegend: false,
148
- dynamicLegendDefaultText: 'Show All',
149
- dynamicLegendItemLimit: 5,
150
- dynamicLegendItemLimitMessage: 'Dynamic Legend Item Limit Hit.',
151
- dynamicLegendChartMessage: 'Select Options from the Legend',
152
- position: 'right',
153
- hide: true,
154
- label: 'Accident Location'
155
- },
156
- exclusions: { active: false, keys: [] },
157
- palette: 'qualitative-bold',
158
- isPaletteReversed: false,
159
- twoColor: { palette: 'monochrome-1', isPaletteReversed: false },
160
- labels: false,
161
- dataFormat: { commas: false, prefix: '', suffix: '', abbreviated: false, bottomSuffix: '', bottomPrefix: '', bottomAbbreviated: false },
162
- confidenceKeys: {},
163
- visual: { border: true, accent: true, background: true, verticalHoverLine: false, horizontalHoverLine: false },
164
- useLogScale: false,
165
- filterBehavior: 'Filter Change',
166
- highlightedBarValues: [],
167
- series: [{ dataKey: 'Home', type: 'Bar', tooltip: true }],
168
- tooltips: { opacity: 90 },
169
- height: 212,
170
- data: [
171
- { Group: 'Combined Total of Group A', Vehicle: '100', Home: '120', Work: '140', Office: '120' },
172
- { Group: 'Combined Total of Group B', Vehicle: '150', Home: '140', Work: '100', Office: '90' },
173
- { Group: 'Combined Total of Group C', Vehicle: '90', Home: '90', Work: '80', Office: '80' },
174
- { Group: 'Combined Total of Group D', Vehicle: '70', Home: '60', Work: '50', Office: '70' }
175
- ],
176
- dataFileName: 'CSV_Source_Example_for_Horizontal_Bar_viz-cdcwp1619811744363.csv',
177
- dataFileSourceType: 'file',
178
- visualizationType: 'Bar',
179
- description: 'Subtext can be added here for options like citing data sources or insight into reading the bar chart.',
180
- barPadding: 47,
181
- filters: [],
182
- lollipopSize: 'medium',
183
- validated: 4.23,
184
- dynamicMarginTop: 0
185
- }
31
+ config: lollipop,
32
+ isEditor: false
186
33
  }
187
34
  }
188
35
 
@@ -0,0 +1,32 @@
1
+ import type { Meta, StoryObj } from '@storybook/react'
2
+ import annotationConfig from './_mock/annotation_category_mock.json'
3
+ import annotationConfigDateLinear from './_mock/annotation_date-linear_mock.json'
4
+ import annotationConfigDateTime from './_mock/annotation_date-time_mock.json'
5
+ import Chart from '../CdcChart'
6
+
7
+ const meta: Meta<typeof Chart> = {
8
+ title: 'Components/Templates/Chart/Annotation',
9
+ component: Chart
10
+ }
11
+
12
+ type Story = StoryObj<typeof Chart>
13
+
14
+ export const Chart_Annotation_Categorical: Story = {
15
+ args: {
16
+ config: annotationConfig
17
+ }
18
+ }
19
+
20
+ export const Chart_Annotation_Date_Linear: Story = {
21
+ args: {
22
+ config: annotationConfigDateLinear
23
+ }
24
+ }
25
+
26
+ export const Chart_Annotation_Date_Time: Story = {
27
+ args: {
28
+ config: annotationConfigDateTime
29
+ }
30
+ }
31
+
32
+ export default meta