@cdc/core 4.24.2 → 4.24.3

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 (54) hide show
  1. package/assets/icon-sankey.svg +1 -0
  2. package/assets/icon-table.svg +1 -0
  3. package/components/DataTable/DataTable.tsx +28 -10
  4. package/components/DataTable/DataTableStandAlone.tsx +15 -0
  5. package/components/DataTable/components/CellAnchor.tsx +3 -1
  6. package/components/DataTable/components/ChartHeader.tsx +48 -12
  7. package/components/DataTable/components/DataTableEditorPanel.tsx +42 -0
  8. package/components/DataTable/components/MapHeader.tsx +10 -5
  9. package/components/DataTable/helpers/customColumns.ts +4 -2
  10. package/components/DataTable/helpers/getChartCellValue.ts +4 -2
  11. package/components/DataTable/helpers/getDataSeriesColumns.ts +9 -1
  12. package/components/DataTable/types/TableConfig.ts +6 -7
  13. package/components/EditorPanel/ColumnsEditor.tsx +311 -0
  14. package/components/EditorPanel/DataTableEditor.tsx +27 -28
  15. package/components/Filters.jsx +27 -10
  16. package/components/MultiSelect/MultiSelect.tsx +39 -20
  17. package/components/MultiSelect/multiselect.styles.css +44 -27
  18. package/components/NestedDropdown/NestedDropdown.tsx +257 -0
  19. package/components/NestedDropdown/index.ts +1 -0
  20. package/components/NestedDropdown/nesteddropdown.styles.css +70 -0
  21. package/components/Table/Table.tsx +1 -1
  22. package/components/_stories/MultiSelect.stories.tsx +10 -1
  23. package/components/_stories/NestedDropdown.stories.tsx +58 -0
  24. package/components/createBarElement.jsx +117 -0
  25. package/components/elements/ScreenReaderText.tsx +8 -0
  26. package/components/elements/SkipTo.tsx +14 -0
  27. package/components/ui/Icon.tsx +5 -1
  28. package/components/ui/Title/Title.scss +7 -1
  29. package/components/ui/Title/index.tsx +3 -3
  30. package/components/ui/Tooltip.jsx +1 -1
  31. package/data/colorPalettes.js +1 -6
  32. package/helpers/cove/accessibility.ts +23 -0
  33. package/helpers/cove/date.ts +19 -0
  34. package/helpers/coveUpdateWorker.js +4 -0
  35. package/helpers/isDomainExternal.js +14 -0
  36. package/helpers/queryStringUtils.js +26 -0
  37. package/helpers/tests/updateFieldFactory.test.ts +89 -0
  38. package/helpers/updateFieldFactory.ts +38 -0
  39. package/helpers/useDataVizClasses.js +2 -2
  40. package/helpers/ver/4.24.3.js +25 -0
  41. package/package.json +4 -3
  42. package/styles/_data-table.scss +0 -13
  43. package/styles/base.scss +8 -0
  44. package/types/Axis.ts +1 -0
  45. package/types/BaseVisualizationType.ts +1 -0
  46. package/types/ConfidenceInterval.ts +1 -0
  47. package/types/Legend.ts +18 -0
  48. package/types/Region.ts +10 -0
  49. package/types/Runtime.ts +2 -0
  50. package/types/Table.ts +1 -1
  51. package/types/UpdateFieldFunc.ts +1 -1
  52. package/types/Visualization.ts +17 -5
  53. package/components/DataTable/components/SkipNav.tsx +0 -7
  54. package/helpers/cove/date.js +0 -9
@@ -0,0 +1 @@
1
+ <?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 96.31 82.55"><defs><style>.c{stroke-linecap:round;stroke-width:3px;}.c,.d,.e{stroke:#000;}.e{fill:none;}</style></defs><g id="a"/><g id="b"><path class="c" d="M6.88,39.98V5.57"/><path class="c" d="M89.42,22.98V5.57"/><path class="c" d="M89.42,52.79V27.38"/><path class="c" d="M89.42,76v-18.41"/><path class="c" d="M6.88,76v-28.43"/><rect class="e" x="12.3" y="5.98" width="71.62" height="9.69"/><path class="d" d="M83.92,16.67s-11.46,1.07-27.63,11.61-27.1,16.32-35.66,17.97c-4.59,.88-8.34,.72-8.34,.72v5.31s3.75,.17,8.34-.72c8.56-1.65,19.49-7.42,35.66-17.97s27.63-11.61,27.63-11.61v-5.31Z"/><path class="e" d="M12.3,16.67s41.36,10.71,71.62,10.71v8.71s-31.58,1.88-71.62-10.71v-8.71Z"/><path class="d" d="M83.92,53.29s-13.18,1.49-35.77,9.06c0,0-18.05,7.37-35.85,7.37v-15.89c17.8,0,35.85-7.37,35.85-7.37,22.59-7.57,35.77-9.06,35.77-9.06v15.89Z"/><rect class="d" x="12.3" y="71" width="71.62" height="5.44"/><path class="e" d="M83.92,57.58l-8.82-2.38c-6.78-1.93-13.27-4.73-19.33-8.34l-14.69-8.76c-5.94-3.54-12.3-6.31-18.93-8.25l-9.85-2.88v12.14l9.85,2.88c6.64,1.94,13,4.71,18.93,8.25l14.69,8.76c6.05,3.61,12.55,6.41,19.33,8.34l8.82,2.38v-12.14Z"/></g></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 512 512"><!--!Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M64 256V160H224v96H64zm0 64H224v96H64V320zm224 96V320H448v96H288zM448 256H288V160H448v96zM64 32C28.7 32 0 60.7 0 96V416c0 35.3 28.7 64 64 64H448c35.3 0 64-28.7 64-64V96c0-35.3-28.7-64-64-64H64z"/></svg>
@@ -9,7 +9,7 @@ import { customSort } from './helpers/customSort'
9
9
  import ChartHeader from './components/ChartHeader'
10
10
  import BoxplotHeader from './components/BoxplotHeader'
11
11
  import MapHeader from './components/MapHeader'
12
- import SkipNav from './components/SkipNav'
12
+ import SkipTo from '../elements/SkipTo'
13
13
  import ExpandCollapse from './components/ExpandCollapse'
14
14
  import mapCellMatrix from './helpers/mapCellMatrix'
15
15
  import Table from '../Table'
@@ -39,7 +39,7 @@ export type DataTableProps = {
39
39
  navigationHandler?: Function
40
40
  outerContainerRef?: Function
41
41
  rawData: Object[]
42
- runtimeData: Object[] | Record<string, Object> // UNSAFE
42
+ runtimeData: Object[] & Record<string, Object>
43
43
  setFilteredCountryCode?: Function // used for Maps only
44
44
  showDownloadButton?: boolean
45
45
  tabbingId: string
@@ -53,7 +53,6 @@ export type DataTableProps = {
53
53
  /* eslint-disable jsx-a11y/no-noninteractive-tabindex, jsx-a11y/no-static-element-interactions */
54
54
  const DataTable = (props: DataTableProps) => {
55
55
  const { config, dataConfig, tableTitle, vizTitle, rawData, runtimeData, headerColor, expandDataTable, columns, viewport, formatLegendLocation, tabbingId, wrapColumns } = props
56
-
57
56
  const [expanded, setExpanded] = useState(expandDataTable)
58
57
 
59
58
  const [sortBy, setSortBy] = useState<any>({ column: config.type === 'map' ? 'geo' : 'date', asc: false, colIndex: null })
@@ -91,7 +90,7 @@ const DataTable = (props: DataTableProps) => {
91
90
  case 'Box Plot':
92
91
  if (!config.boxplot) return <Loading />
93
92
  break
94
- case 'Line' || 'Bar' || 'Combo' || 'Pie' || 'Deviation Bar' || 'Paired Bar':
93
+ case 'Line' || 'Bar' || 'Combo' || 'Pie' || 'Deviation Bar' || 'Paired Bar' || 'Sankey' || 'Table':
95
94
  if (!runtimeData) return <Loading />
96
95
  break
97
96
  default:
@@ -115,7 +114,7 @@ const DataTable = (props: DataTableProps) => {
115
114
  dataA = _runtimeData[a][sortBy.column]
116
115
  dataB = _runtimeData[b][sortBy.column]
117
116
  }
118
- if (!dataA && !dataB && config.type === 'chart' && config.xAxis && config.xAxis.type === 'date' && config.xAxis.sortDates) {
117
+ if (!dataA && !dataB && config.type === 'chart' && config.xAxis && config.xAxis.type === 'date-time') {
119
118
  dataA = timeParse(config.runtime.xAxis.dateParseFormat)(_runtimeData[a][config.xAxis.dataKey])
120
119
  dataB = timeParse(config.runtime.xAxis.dateParseFormat)(_runtimeData[b][config.xAxis.dataKey])
121
120
  }
@@ -142,12 +141,25 @@ const DataTable = (props: DataTableProps) => {
142
141
  // If a relative region is found we don't want to display the data table.
143
142
  // Takes backwards compatibility into consideration, ie !region.toType || !region.fromType
144
143
  const noRelativeRegions = config?.regions?.every(region => {
145
- return (region.toType === 'Fixed' && region.fromType === 'Fixed') || (!region.toType && !region.fromType) || (!region.toType && region.fromType === 'Fixed') || (!region.fromType && region.toType === 'Fixed')
144
+ const toTypeFixed = region.toType === 'Fixed'
145
+ const fromTypeFixed = region.fromType === 'Fixed'
146
+ const toIsNotSet = !region.toType
147
+ const fromIsNotSet = !region.fromType
148
+ const BothFixed = toTypeFixed && fromTypeFixed
149
+ const NeitherFixed = toIsNotSet && fromIsNotSet
150
+ const ToFixedFromNotSet = toTypeFixed && fromIsNotSet
151
+ const FromFixedToNotSet = fromTypeFixed && toIsNotSet
152
+
153
+ return BothFixed || NeitherFixed || ToFixedFromNotSet || FromFixedToNotSet
146
154
  })
147
155
 
148
156
  // prettier-ignore
149
157
  const tableData = useMemo(() => (
150
- config.visualizationType === 'Pie'
158
+ config.data?.[0]?.tableData
159
+ ? config.data?.[0]?.tableData
160
+ : config.visualizationType === 'Sankey'
161
+ ? config.data?.[0]?.tableData
162
+ : config.visualizationType === 'Pie'
151
163
  ? [config.yAxis.dataKey]
152
164
  : config.visualizationType === 'Box Plot'
153
165
  ? Object.entries(config.boxplot.tableData[0])
@@ -169,10 +181,10 @@ const DataTable = (props: DataTableProps) => {
169
181
  <ErrorBoundary component='DataTable'>
170
182
  <MediaControls.Section classes={['download-links']}>
171
183
  <MediaControls.Link config={config} dashboardDataConfig={dataConfig} />
172
- {(config.table.download || config.general?.showDownloadButton) && <DownloadButton rawData={getDownloadData()} fileName={`${vizTitle || 'data-table'}.csv`} headerColor={headerColor} skipId={skipId} />}
184
+ {(config.table.download || config.general?.showDownloadButton) && <DownloadButton rawData={getDownloadData()} fileName={`${vizTitle || 'data-table'}.csv`} headerColor={headerColor} />}
173
185
  </MediaControls.Section>
174
186
  <section id={tabbingId.replace('#', '')} className={`data-table-container ${viewport}`} aria-label={accessibilityLabel}>
175
- <SkipNav skipId={skipId} />
187
+ <SkipTo skipId={skipId} skipMessage='Skip Data Table' />
176
188
  <ExpandCollapse expanded={expanded} setExpanded={setExpanded} tableTitle={tableTitle} />
177
189
  <div className='table-container' style={limitHeight}>
178
190
  <Table
@@ -205,6 +217,9 @@ const DataTable = (props: DataTableProps) => {
205
217
  )}
206
218
  </div>
207
219
  </section>
220
+ <div id={skipId} className='cdcdataviz-sr-only'>
221
+ Skipped data table.
222
+ </div>
208
223
  </ErrorBoundary>
209
224
  )
210
225
  } else {
@@ -212,7 +227,7 @@ const DataTable = (props: DataTableProps) => {
212
227
  return (
213
228
  <ErrorBoundary component='DataTable'>
214
229
  <section id={tabbingId.replace('#', '')} className={`data-table-container ${viewport}`} aria-label={accessibilityLabel}>
215
- <SkipNav skipId={skipId} />
230
+ <SkipTo skipId={skipId} skipMessage='Skip Data Table' />
216
231
  <ExpandCollapse expanded={expanded} setExpanded={setExpanded} tableTitle={tableTitle} />
217
232
  <div className='table-container' style={limitHeight}>
218
233
  <Table
@@ -226,6 +241,9 @@ const DataTable = (props: DataTableProps) => {
226
241
  />
227
242
  </div>
228
243
  </section>
244
+ <div id={skipId} className='cdcdataviz-sr-only'>
245
+ Skipped data table.
246
+ </div>
229
247
  </ErrorBoundary>
230
248
  )
231
249
  }
@@ -0,0 +1,15 @@
1
+ import { ViewPort } from '../../types/ViewPort'
2
+ import { Visualization } from '../../types/Visualization'
3
+ import DataTable from './DataTable'
4
+
5
+ type StandAloneProps = {
6
+ visualizationKey: string
7
+ config: Visualization
8
+ viewport?: ViewPort
9
+ }
10
+
11
+ const DataTableStandAlone: React.FC<StandAloneProps> = ({ visualizationKey, config, viewport }) => {
12
+ return <DataTable expandDataTable={true} config={config} rawData={config.data} runtimeData={config.formattedData} tabbingId={visualizationKey} tableTitle={config.table.label} viewport={viewport || 'lg'} />
13
+ }
14
+
15
+ export default DataTableStandAlone
@@ -1,4 +1,6 @@
1
1
  import ExternalIcon from '@cdc/core/assets/external-link.svg'
2
+ import isDomainExternal from '@cdc/core/helpers/isDomainExternal'
3
+
2
4
  // Optionally wrap cell with anchor if config defines a navigation url
3
5
  const CellAnchor = ({ markup, row, columns, navigationHandler, mapZoomHandler }) => {
4
6
  if (columns.navigate && row[columns.navigate.name]) {
@@ -16,7 +18,7 @@ const CellAnchor = ({ markup, row, columns, navigationHandler, mapZoomHandler })
16
18
  }}
17
19
  >
18
20
  {markup}
19
- <ExternalIcon className='inline-icon' />
21
+ {isDomainExternal(row[columns.navigate.name]) && <ExternalIcon className='inline-icon' />}
20
22
  </span>
21
23
  )
22
24
  } else if (mapZoomHandler) {
@@ -2,6 +2,7 @@ import { getChartCellValue } from '../helpers/getChartCellValue'
2
2
  import { getSeriesName } from '../helpers/getSeriesName'
3
3
  import { getDataSeriesColumns } from '../helpers/getDataSeriesColumns'
4
4
  import { DownIcon, UpIcon } from './Icons'
5
+ import ScreenReaderText from '@cdc/core/components/elements/ScreenReaderText'
5
6
 
6
7
  type ChartHeaderProps = { data; isVertical; config; setSortBy; sortBy; groupBy?; hasRowType? }
7
8
 
@@ -16,6 +17,45 @@ const ChartHeader = ({ data, isVertical, config, setSortBy, sortBy, groupBy, has
16
17
  dataSeriesColumns = groupHeaderRemoved
17
18
  }
18
19
  }
20
+
21
+ const handleHeaderClasses = (sortBy, text) => {
22
+ let classes = ['sort']
23
+ if (sortBy.column === text && sortBy.asc) {
24
+ classes.push('sort-asc')
25
+ }
26
+ if (sortBy.column === text && sortBy.desc) {
27
+ classes.push('sort-desc')
28
+ }
29
+ return classes.join(' ')
30
+ }
31
+
32
+ const ScreenReaderSortByText = ({ text, config, sortBy }) => {
33
+ const notApplicableText = 'Not Applicable'
34
+ let columnHeaderText = `${text} `
35
+ if (text !== '__series__' || text !== '') {
36
+ columnHeaderText = `${text} `
37
+ }
38
+
39
+ if ((text === '__series__' || text === '') && !config.table.indexLabel) {
40
+ columnHeaderText = notApplicableText
41
+ }
42
+
43
+ if ((text === '__series__' || text === '') && config.table.indexLabel) {
44
+ columnHeaderText = config.table.indexLabel
45
+ }
46
+
47
+ if (columnHeaderText === notApplicableText) return
48
+
49
+ return <span className='cdcdataviz-sr-only'>{`Press command, modifier, or enter key to sort by ${columnHeaderText} in ${sortBy.column !== columnHeaderText ? 'ascending' : sortBy.column === 'desc' ? 'descending' : 'ascending'} order`}</span>
50
+ }
51
+
52
+ const ColumnHeadingText = ({ column, text, config }) => {
53
+ let notApplicableText = 'Not Applicable'
54
+ if (text === '__series__' && config.table.indexLabel) return `${config.table.indexLabel} `
55
+ if (text === '__series__' && !config.table.indexLabel) return <ScreenReaderText as='span'>{notApplicableText}</ScreenReaderText>
56
+ return text
57
+ }
58
+
19
59
  if (isVertical) {
20
60
  if (hasRowType) {
21
61
  // find the row type column and place it at the beginning of the array
@@ -25,6 +65,7 @@ const ChartHeader = ({ data, isVertical, config, setSortBy, sortBy, groupBy, has
25
65
  dataSeriesColumns.splice(rowTypeIndex, 1)
26
66
  }
27
67
  }
68
+
28
69
  return (
29
70
  <tr>
30
71
  {dataSeriesColumns.map((column, index) => {
@@ -35,7 +76,6 @@ const ChartHeader = ({ data, isVertical, config, setSortBy, sortBy, groupBy, has
35
76
  style={{ minWidth: (config.table.cellMinWidth || 0) + 'px' }}
36
77
  key={`col-header-${column}__${index}`}
37
78
  tabIndex={0}
38
- title={text}
39
79
  role='columnheader'
40
80
  scope='col'
41
81
  onClick={() => {
@@ -48,14 +88,12 @@ const ChartHeader = ({ data, isVertical, config, setSortBy, sortBy, groupBy, has
48
88
  setSortBy({ column, asc: sortBy.column === column ? !sortBy.asc : false, colIndex: index })
49
89
  }
50
90
  }}
51
- className={sortBy.column === column ? (sortBy.asc ? 'sort sort-asc' : 'sort sort-desc') : 'sort'}
91
+ className={handleHeaderClasses(sortBy, text)}
52
92
  {...(sortBy.column === column ? (sortBy.asc ? { 'aria-sort': 'ascending' } : { 'aria-sort': 'descending' }) : null)}
53
93
  >
54
- {text}
94
+ <ColumnHeadingText text={text} column={column} config={config} />
55
95
  {column === sortBy.column && <span className={'sort-icon'}>{!sortBy.asc ? <UpIcon /> : <DownIcon />}</span>}
56
- <button>
57
- <span className='cdcdataviz-sr-only'>{`Sort by ${text} in ${sortBy.column === column ? (!sortBy.asc ? 'descending' : 'ascending') : 'descending'} `} order</span>
58
- </button>
96
+ <ScreenReaderSortByText sortBy={sortBy} config={config} text={text} />
59
97
  </th>
60
98
  )
61
99
  })}
@@ -68,12 +106,12 @@ const ChartHeader = ({ data, isVertical, config, setSortBy, sortBy, groupBy, has
68
106
  {['__series__', ...Object.keys(data)].slice(sliceVal).map((row, index) => {
69
107
  let column = config.xAxis?.dataKey
70
108
  let text = row !== '__series__' ? getChartCellValue(row, column, config, data) : '__series__'
109
+
71
110
  return (
72
111
  <th
73
112
  style={{ minWidth: (config.table.cellMinWidth || 0) + 'px' }}
74
113
  key={`col-header-${text}__${index}`}
75
114
  tabIndex={0}
76
- title={text}
77
115
  role='columnheader'
78
116
  scope='col'
79
117
  onClick={() => {
@@ -84,14 +122,12 @@ const ChartHeader = ({ data, isVertical, config, setSortBy, sortBy, groupBy, has
84
122
  setSortBy({ column: text, asc: sortBy.column === text ? !sortBy.asc : false, colIndex: index })
85
123
  }
86
124
  }}
87
- className={sortBy.column === text ? (sortBy.asc ? 'sort sort-asc' : 'sort sort-desc') : 'sort'}
125
+ className={handleHeaderClasses(sortBy, text)}
88
126
  {...(sortBy.column === text ? (sortBy.asc ? { 'aria-sort': 'ascending' } : { 'aria-sort': 'descending' }) : null)}
89
127
  >
90
- {text === '__series__' ? '' : text}
128
+ <ColumnHeadingText text={text} column={column} config={config} />
91
129
  {index === sortBy.colIndex && <span className={'sort-icon'}>{!sortBy.asc ? <UpIcon /> : <DownIcon />}</span>}
92
- <button>
93
- <span className='cdcdataviz-sr-only'>{`Sort by ${text} in ${sortBy.column === text ? (!sortBy.asc ? 'descending' : 'ascending') : 'descending'} `} order</span>
94
- </button>
130
+ <ScreenReaderSortByText text={text} config={config} sortBy={sortBy} />
95
131
  </th>
96
132
  )
97
133
  })}
@@ -0,0 +1,42 @@
1
+ import { AccordionItem, AccordionItemButton, AccordionItemHeading, AccordionItemPanel } from 'react-accessible-accordion'
2
+ import DataTableEditor from '../../EditorPanel/DataTableEditor'
3
+ import { Visualization } from '@cdc/core/types/Visualization'
4
+ import { updateFieldFactory } from '@cdc/core/helpers/updateFieldFactory'
5
+ import { useMemo } from 'react'
6
+ import ColumnsEditor from '../../EditorPanel/ColumnsEditor'
7
+
8
+ type DataTableEditorProps = {
9
+ config: Visualization
10
+ updateConfig: Function
11
+ }
12
+
13
+ const DataTableEditorPanel: React.FC<DataTableEditorProps> = ({ config, updateConfig }) => {
14
+ const updateField = useMemo(() => updateFieldFactory(config, updateConfig), [JSON.stringify(config)])
15
+ const deleteColumn = columnName => {
16
+ const newColumns = config.columns
17
+
18
+ delete newColumns[columnName]
19
+
20
+ updateConfig({
21
+ ...config,
22
+ columns: newColumns
23
+ })
24
+ }
25
+
26
+ const columns = Object.keys(config.columns || {})
27
+ return (
28
+ <>
29
+ <ColumnsEditor config={config} updateField={updateField} deleteColumn={deleteColumn} />
30
+ <AccordionItem>
31
+ <AccordionItemHeading>
32
+ <AccordionItemButton>Data Table</AccordionItemButton>
33
+ </AccordionItemHeading>
34
+ <AccordionItemPanel>
35
+ <DataTableEditor config={config} columns={columns} updateField={updateField} isDashboard={true} />
36
+ </AccordionItemPanel>
37
+ </AccordionItem>
38
+ </>
39
+ )
40
+ }
41
+
42
+ export default DataTableEditorPanel
@@ -1,11 +1,19 @@
1
1
  import { DataTableProps } from '../DataTable'
2
2
  import { DownIcon, UpIcon } from './Icons'
3
+ import ScreenReaderText from '../../elements/ScreenReaderText'
3
4
 
4
5
  type MapHeaderProps = DataTableProps & {
5
6
  sortBy: { column; asc }
6
7
  setSortBy: Function
7
8
  }
8
9
 
10
+ const ColumnHeadingText = ({ column, text, config }) => {
11
+ let notApplicableText = 'Not Applicable'
12
+ if (text === '__series__' && config.table.indexLabel) return `${config.table.indexLabel} `
13
+ if (text === '__series__' && !config.table.indexLabel) return <ScreenReaderText as='span'>{notApplicableText}</ScreenReaderText>
14
+ return text
15
+ }
16
+
9
17
  const MapHeader = ({ columns, config, indexTitle, sortBy, setSortBy }: MapHeaderProps) => {
10
18
  return (
11
19
  <tr>
@@ -27,7 +35,6 @@ const MapHeader = ({ columns, config, indexTitle, sortBy, setSortBy }: MapHeader
27
35
  key={`col-header-${column}__${index}`}
28
36
  id={column}
29
37
  tabIndex={0}
30
- title={text}
31
38
  role='columnheader'
32
39
  scope='col'
33
40
  onClick={() => {
@@ -41,11 +48,9 @@ const MapHeader = ({ columns, config, indexTitle, sortBy, setSortBy }: MapHeader
41
48
  className={sortBy.column === column ? (sortBy.asc ? 'sort sort-asc' : 'sort sort-desc') : 'sort'}
42
49
  {...(sortBy.column === column ? (sortBy.asc ? { 'aria-sort': 'ascending' } : { 'aria-sort': 'descending' }) : null)}
43
50
  >
44
- {text}
51
+ <ColumnHeadingText text={text} config={config} column={column} />
45
52
  {sortBy.column === column && <span className={'sort-icon'}>{!sortBy.asc ? <UpIcon /> : <DownIcon />}</span>}
46
- <button>
47
- <span className='cdcdataviz-sr-only'>{`Sort by ${text} in ${sortBy.column === column ? (!sortBy.asc ? 'descending' : 'ascending') : 'descending'} `} order</span>
48
- </button>
53
+ <span className='cdcdataviz-sr-only'>{`Sort by ${text} in ${sortBy.column === column ? (!sortBy.asc ? 'descending' : 'ascending') : 'descending'} order`}</span>
49
54
  </th>
50
55
  )
51
56
  })}
@@ -1,5 +1,7 @@
1
+ type RuntimeData = Object[] & Record<string, Object>
2
+
1
3
  // removes null and excluded columns
2
- const customColumns = (runtimeData: Object[] | Record<string, Object>, excludeColumns: string[] = []): Object[] | Record<string, Object> => {
4
+ const customColumns = (runtimeData: Object[] | RuntimeData, excludeColumns: string[] = []): RuntimeData => {
3
5
  if (!Array.isArray(runtimeData)) {
4
6
  // currently we don't support Record types
5
7
  return runtimeData
@@ -18,7 +20,7 @@ const customColumns = (runtimeData: Object[] | Record<string, Object>, excludeCo
18
20
  if (runtimeDataMemo[key] === true) row[key] = d[key]
19
21
  })
20
22
  return row
21
- })
23
+ }) as RuntimeData
22
24
  }
23
25
  }
24
26
 
@@ -1,5 +1,6 @@
1
1
  import { parseDate, formatDate } from '@cdc/core/helpers/cove/date'
2
2
  import { formatNumber } from '@cdc/core/helpers/cove/number'
3
+ import { TableConfig } from '../types/TableConfig'
3
4
 
4
5
  // if its additional column, return formatting params
5
6
  const isAdditionalColumn = (column, config) => {
@@ -23,8 +24,9 @@ const isAdditionalColumn = (column, config) => {
23
24
  return formattingParams
24
25
  }
25
26
 
26
- export const getChartCellValue = (row, column, config, runtimeData) => {
27
- if (config.table.customTableConfig) return runtimeData[row][column]
27
+ export const getChartCellValue = (row: string, column: string, config: TableConfig, runtimeData: Object[]) => {
28
+ if (config.table.customTableConfig || config.visualizationType === 'Sankey' || runtimeData?.[0]?.tableData) return runtimeData[row][column]
29
+
28
30
  const rowObj = runtimeData[row]
29
31
  let cellValue // placeholder for formatting below
30
32
  let labelValue = rowObj[column] // just raw X axis string
@@ -1,5 +1,13 @@
1
- export const getDataSeriesColumns = (config, isVertical, runtimeData): string[] => {
1
+ import { TableConfig } from '../types/TableConfig'
2
+
3
+ export const getDataSeriesColumns = (config: TableConfig, isVertical: boolean, runtimeData: Object[]): string[] => {
2
4
  if (config.table.customTableConfig) return runtimeData[0] ? Object.keys(runtimeData[0]) : []
5
+ if (config.type === 'table') {
6
+ const excludeColumns = Object.values(config.columns)
7
+ .filter(column => column.dataTable === false)
8
+ .map(column => column.name)
9
+ return Object.keys(runtimeData[0]).filter(columnName => !excludeColumns.includes(columnName))
10
+ }
3
11
  let tmpSeriesColumns
4
12
  if (config.visualizationType !== 'Pie') {
5
13
  tmpSeriesColumns = isVertical ? [config.xAxis?.dataKey] : [] //, ...config.runtime.seriesLabelsAll
@@ -2,9 +2,11 @@ import { Axis } from '@cdc/core/types/Axis'
2
2
  import { Series } from '@cdc/core/types/Series'
3
3
  import { Runtime } from '@cdc/core/types/Runtime'
4
4
  import { Table } from '@cdc/core/types/Table'
5
+ import { Region } from '@cdc/core/types/Region'
5
6
  import { BoxPlot } from '../../../types/BoxPlot'
6
7
  import { General } from '../../../types/General'
7
8
  import { Column } from '../../../types/Column'
9
+ import { Legend } from '@cdc/core/types/Legend'
8
10
 
9
11
  export type TableConfig = {
10
12
  type?: string
@@ -12,17 +14,14 @@ export type TableConfig = {
12
14
  xAxis?: Axis
13
15
  yAxis?: Axis
14
16
  boxplot?: BoxPlot
15
- visualizationType?: string
17
+ visualizationType: string
16
18
  general?: General
17
19
  columns?: Record<string, Column>
18
- legend?: {
19
- specialClasses?: { key: string; label: string; value: string }[]
20
- hide?: boolean
21
- }
20
+ legend?: Legend
22
21
  series?: Series
23
- regions?: { label: string; from: string; to: string; fromType: 'Fixed' | 'Previous Days'; toType: 'Fixed' | 'Last Date' }[]
22
+ regions?: Region[]
24
23
  runtimeSeriesLabels?: Object
25
24
  dataFormat?: Object
26
- runtime: Runtime
25
+ runtime?: Runtime
27
26
  data: Object[]
28
27
  }