@cdc/core 4.25.3 → 4.25.6-1

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 (89) hide show
  1. package/assets/icon-close.svg +1 -1
  2. package/components/Alert/components/Alert.tsx +1 -1
  3. package/components/DataTable/DataTable.tsx +18 -16
  4. package/components/DataTable/DataTableStandAlone.tsx +15 -9
  5. package/components/DataTable/components/CellAnchor.tsx +1 -1
  6. package/components/DataTable/components/ChartHeader.tsx +8 -5
  7. package/components/DataTable/components/DataTableEditorPanel.tsx +25 -3
  8. package/components/DataTable/components/MapHeader.tsx +1 -0
  9. package/components/DataTable/helpers/chartCellMatrix.tsx +14 -10
  10. package/components/DataTable/helpers/getChartCellValue.ts +42 -26
  11. package/components/DataTable/helpers/mapCellMatrix.tsx +25 -7
  12. package/components/DownloadButton.tsx +17 -2
  13. package/components/EditorPanel/DataTableEditor.tsx +1 -1
  14. package/components/EditorPanel/FootnotesEditor.tsx +76 -22
  15. package/components/EditorPanel/Inputs.tsx +12 -4
  16. package/components/EditorPanel/VizFilterEditor/NestedDropdownEditor.tsx +3 -2
  17. package/components/EditorPanel/VizFilterEditor/VizFilterEditor.tsx +51 -35
  18. package/components/Filters/Filters.tsx +158 -461
  19. package/components/Filters/components/Dropdown.tsx +39 -0
  20. package/components/Filters/components/Tabs.tsx +82 -0
  21. package/components/Filters/helpers/getChangedFilters.ts +31 -0
  22. package/components/Filters/helpers/getNestedOptions.ts +2 -2
  23. package/components/Filters/helpers/handleSorting.ts +2 -2
  24. package/components/Filters/helpers/tests/getChangedFilters.test.ts +92 -0
  25. package/components/Filters/helpers/tests/getNestedOptions.test.ts +31 -0
  26. package/components/Filters/index.ts +1 -1
  27. package/components/Footnotes/Footnotes.tsx +1 -1
  28. package/components/Footnotes/FootnotesStandAlone.tsx +8 -33
  29. package/components/Layout/components/Visualization/index.tsx +4 -3
  30. package/components/Legend/Legend.Gradient.tsx +68 -24
  31. package/components/MultiSelect/MultiSelect.tsx +3 -6
  32. package/components/MultiSelect/multiselect.styles.css +2 -0
  33. package/components/NestedDropdown/NestedDropdown.tsx +21 -21
  34. package/components/RichTooltip/RichTooltip.tsx +37 -0
  35. package/components/RichTooltip/richTooltip.css +16 -0
  36. package/components/Table/Table.tsx +142 -142
  37. package/components/Table/components/Row.tsx +1 -1
  38. package/components/Table/table.styles.css +10 -0
  39. package/components/_stories/DataTable.stories.tsx +9 -2
  40. package/components/_stories/Table.stories.tsx +1 -1
  41. package/components/_stories/styles.scss +0 -4
  42. package/components/ui/Accordion.jsx +8 -1
  43. package/components/ui/Title/index.tsx +4 -1
  44. package/components/ui/Title/{Title.scss → title.styles.css} +0 -2
  45. package/components/ui/_stories/Colors.stories.mdx +220 -0
  46. package/components/ui/_stories/IconGallery.stories.mdx +14 -0
  47. package/components/ui/_stories/Title.stories.tsx +29 -4
  48. package/components/ui/accordion.styles.css +3 -0
  49. package/data/colorPalettes.js +0 -1
  50. package/dist/cove-main.css +3 -8
  51. package/dist/cove-main.css.map +1 -1
  52. package/helpers/constants.ts +6 -0
  53. package/helpers/cove/accessibility.ts +7 -8
  54. package/helpers/cove/number.ts +5 -3
  55. package/helpers/coveUpdateWorker.ts +9 -1
  56. package/helpers/filterOrderOptions.ts +17 -0
  57. package/helpers/formatConfigBeforeSave.ts +19 -32
  58. package/helpers/isNumber.ts +20 -0
  59. package/helpers/isRightAlignedTableValue.js +1 -1
  60. package/helpers/pivotData.ts +16 -11
  61. package/helpers/tests/pivotData.test.ts +74 -0
  62. package/helpers/updateFieldFactory.ts +1 -0
  63. package/helpers/ver/4.25.3.ts +25 -2
  64. package/helpers/ver/4.25.4.ts +110 -0
  65. package/helpers/ver/4.25.6.ts +36 -0
  66. package/helpers/ver/4.25.7.ts +26 -0
  67. package/helpers/ver/tests/4.25.4.test.ts +89 -0
  68. package/helpers/ver/tests/4.25.6.test.ts +84 -0
  69. package/helpers/viewports.ts +4 -0
  70. package/package.json +7 -6
  71. package/styles/_global-variables.scss +3 -0
  72. package/styles/_global.scss +0 -4
  73. package/styles/_reset.scss +0 -6
  74. package/styles/filters.scss +0 -4
  75. package/styles/v2/main.scss +0 -5
  76. package/types/Axis.ts +2 -0
  77. package/types/DataSet.ts +14 -0
  78. package/types/Footnotes.ts +5 -2
  79. package/types/General.ts +1 -0
  80. package/types/Legend.ts +1 -0
  81. package/types/Table.ts +1 -0
  82. package/types/Visualization.ts +3 -12
  83. package/types/VizFilter.ts +3 -0
  84. package/components/ui/_stories/Colors.stories.tsx +0 -92
  85. package/components/ui/_stories/Icon.stories.tsx +0 -29
  86. package/helpers/cove/fontSettings.ts +0 -2
  87. package/helpers/isNumber.js +0 -24
  88. package/helpers/isNumberLog.js +0 -18
  89. /package/helpers/{fetchRemoteData.js → fetchRemoteData.ts} +0 -0
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Checks whether the given input is a valid number.
3
+ *
4
+ * Handles both numeric types and numeric strings, including negative values.
5
+ *
6
+ * @param value - The value to check. Can be of any type.
7
+ * @returns boolean - True if the value is a number or a numeric string.
8
+ */
9
+ export default function isNumber(value: unknown = ''): boolean {
10
+ if (typeof value === 'number') {
11
+ return !Number.isNaN(value)
12
+ }
13
+
14
+ if (typeof value === 'string') {
15
+ return value.trim() !== '' && /^-?\d+(\.\d+)?$/.test(value.trim())
16
+ // Matches optional leading "-", integers, or decimals (e.g., "-123", "123.45")
17
+ }
18
+
19
+ return false
20
+ }
@@ -12,7 +12,7 @@ export default function isRightAlignedTableValue(value = '') {
12
12
  if (/^\d{4}-\d{1,2}-\d{1,2}$/.test(value)) {
13
13
  return false
14
14
  }
15
- return numericStrings.includes(value) || /^[\$\d\.\%\,\-\s\(\)CI]*$/.test(value)
15
+ return numericStrings.includes(value) || /^[\$\d\.\%\,\-\s\(\)CI<>]*$/.test(value)
16
16
  }
17
17
  return false
18
18
  }
@@ -1,9 +1,5 @@
1
1
  import _ from 'lodash'
2
2
 
3
- const getKeyFromRow = (row: Record<string, any>, columns: string[]) => {
4
- return columns.map(column => row[column] || '').join(':')
5
- }
6
-
7
3
  const getColumns = (data: Record<string, any>[], columnName: string, pivot: string[], excludeColumns: string[]) => {
8
4
  const excludedColumns = [columnName, ...pivot, ...excludeColumns]
9
5
  return _.uniq(data.flatMap(row => Object.keys(row))).filter(col => !excludedColumns.includes(col))
@@ -18,18 +14,29 @@ export const pivotData = (
18
14
  excludeColumns: string[]
19
15
  ): Record<string, any>[] => {
20
16
  const columns = getColumns(data, columnName, pivot, excludeColumns)
21
- const newColumns = {}
17
+ const newColumns = data.reduce((acc, row) => {
18
+ acc[row[columnName]] = ''
19
+ return acc
20
+ }, {})
21
+
22
+ const getKeyFromRow = (row: Record<string, any>, columns: string[], index) => {
23
+ // if there is only one column header, we need to avoid duplicate values overwriting each other other values in the row
24
+ const isSingleColumn = Object.keys(newColumns).length === 1
25
+ const keyIndex = isSingleColumn ? index : ''
26
+ return columns.map(column => row[column] || '').join(':') + keyIndex
27
+ }
28
+
22
29
  // there should be one row for every aggregate row
23
- const aggregateRows = data.reduce((acc, row) => {
24
- const key = getKeyFromRow(row, columns)
30
+ const aggregateRows = data.reduce((acc, row, index) => {
31
+ const key = getKeyFromRow(row, columns, index)
25
32
  if (!acc[key]) {
26
33
  acc[key] = {}
27
34
  }
28
35
  return acc
29
36
  }, {})
30
37
 
31
- data.forEach(row => {
32
- const key = getKeyFromRow(row, columns)
38
+ data.forEach((row, index) => {
39
+ const key = getKeyFromRow(row, columns, index)
33
40
  if (pivot.length > 1) {
34
41
  pivot.forEach(pivotColumn => {
35
42
  const toAdd = _.omit(row, [columnName, ...pivot])
@@ -50,8 +57,6 @@ export const pivotData = (
50
57
  _pivotedFrom: _pivot
51
58
  }
52
59
  }
53
-
54
- newColumns[row[columnName]] = ''
55
60
  })
56
61
 
57
62
  if (pivot.length > 1) {
@@ -51,4 +51,78 @@ describe('pivotData', () => {
51
51
  { city: 'San Francisco', Jane: 'yellow', John: 'green', _pivotedFrom: 'color' }
52
52
  ])
53
53
  })
54
+ it('should allow for duplicate data when there is 1 Column Header but different columnName data', () => {
55
+ // when there are multiple pivot value columns, if any other data is present it will break the pivot.
56
+ // so we need to tell it which columns to exclude from the pivot.
57
+ // 'other' is added here as an example.
58
+ const data = [
59
+ { name: 'John', age: 27, color: 'blue', city: 'New York', other: 'yes' },
60
+ { name: 'Jane', age: 27, color: 'red', city: 'New York', other: 'no' },
61
+ { name: 'Bob', age: 31, color: 'yellow', city: 'New York', other: 'yes' },
62
+ { name: 'Betty', age: 31, color: 'green', city: 'New York', other: 'no' },
63
+ { name: 'Jane', age: 31, color: 'yellow', city: 'New York', other: 'yes' },
64
+ { name: 'John', age: 31, color: 'green', city: 'New York', other: 'no' },
65
+ { name: 'Bob', age: 27, color: 'blue', city: 'New York', other: 'yes' },
66
+ { name: 'Betty', age: 27, color: 'red', city: 'New York', other: 'no' }
67
+ ]
68
+ const result = pivotData(data, 'city', ['name'], [])
69
+ expect(result).toEqual([
70
+ {
71
+ 'New York': 'John',
72
+ age: 27,
73
+ color: 'blue',
74
+ other: 'yes',
75
+ _pivotedFrom: 'name'
76
+ },
77
+ {
78
+ 'New York': 'Jane',
79
+ age: 27,
80
+ color: 'red',
81
+ other: 'no',
82
+ _pivotedFrom: 'name'
83
+ },
84
+ {
85
+ 'New York': 'Bob',
86
+ age: 31,
87
+ color: 'yellow',
88
+ other: 'yes',
89
+ _pivotedFrom: 'name'
90
+ },
91
+ {
92
+ 'New York': 'Betty',
93
+ age: 31,
94
+ color: 'green',
95
+ other: 'no',
96
+ _pivotedFrom: 'name'
97
+ },
98
+ {
99
+ 'New York': 'Jane',
100
+ age: 31,
101
+ color: 'yellow',
102
+ other: 'yes',
103
+ _pivotedFrom: 'name'
104
+ },
105
+ {
106
+ 'New York': 'John',
107
+ age: 31,
108
+ color: 'green',
109
+ other: 'no',
110
+ _pivotedFrom: 'name'
111
+ },
112
+ {
113
+ 'New York': 'Bob',
114
+ age: 27,
115
+ color: 'blue',
116
+ other: 'yes',
117
+ _pivotedFrom: 'name'
118
+ },
119
+ {
120
+ 'New York': 'Betty',
121
+ age: 27,
122
+ color: 'red',
123
+ other: 'no',
124
+ _pivotedFrom: 'name'
125
+ }
126
+ ])
127
+ })
54
128
  })
@@ -18,6 +18,7 @@ export const updateFieldFactory =
18
18
  const isArray = Array.isArray(config[section])
19
19
 
20
20
  let sectionValue = isArray ? [...config[section], newValue] : { ...config[section], [fieldName]: newValue }
21
+ if (!fieldName && !legacy) sectionValue = newValue
21
22
 
22
23
  if (null !== subsection) {
23
24
  if (isArray) {
@@ -2,17 +2,40 @@ import _ from 'lodash'
2
2
 
3
3
  const remapTableDownloadCSV = config => {
4
4
  if (config.general?.showDownloadButton !== undefined) {
5
- const download = config.general.showDownloadButton
5
+ let download = config.general.showDownloadButton
6
+ if (config.type === 'chart') {
7
+ download = config.table.download || config.general.showDownloadButton
8
+ }
6
9
  delete config.general.showDownloadButton
7
10
  config.table.download = download
8
11
  }
9
12
  return config
10
13
  }
11
14
 
15
+ const handleVisualizations = newConfig => {
16
+ if (newConfig.type === 'dashboard') {
17
+ Object.keys(newConfig.visualizations).forEach(key => {
18
+ const currentViz = newConfig.visualizations[key]
19
+ remapTableDownloadCSV(currentViz)
20
+ })
21
+ }
22
+ remapTableDownloadCSV(newConfig)
23
+ }
24
+
25
+ const migrateAreaChart = config => {
26
+ // Migrate regular Area Chart to Stacked
27
+ if (config.visualizationType === 'Area Chart' && config.visualizationSubType === 'regular') {
28
+ config.visualizationSubType = 'stacked'
29
+ }
30
+ return config
31
+ }
32
+
12
33
  const update_4_25_3 = config => {
13
34
  const ver = '4.25.3'
14
35
  const newConfig = _.cloneDeep(config)
15
- remapTableDownloadCSV
36
+ handleVisualizations(newConfig)
37
+ remapTableDownloadCSV(newConfig)
38
+ migrateAreaChart(newConfig)
16
39
  newConfig.version = ver
17
40
  return newConfig
18
41
  }
@@ -0,0 +1,110 @@
1
+ import _ from 'lodash'
2
+
3
+ export const makeChartLegendsUnified = config => {
4
+ if (config.type === 'chart') {
5
+ config.legend = config.legend || {}
6
+ config.legend.unified = true
7
+ } else if (config.type === 'dashboard') {
8
+ Object.values(config.visualizations).forEach(visualization => {
9
+ makeChartLegendsUnified(visualization)
10
+ })
11
+ }
12
+ }
13
+
14
+ const migrateTableGeneralSettings = config => {
15
+ if (config.type === 'map') {
16
+ if (config.general.showFullGeoNameInCSV) {
17
+ config.table.showFullGeoNameInCSV = config.general.showFullGeoNameInCSV
18
+ }
19
+ delete config.general.showFullGeoNameInCSV
20
+ return config
21
+ }
22
+ }
23
+
24
+ const hasMultipleWidgetColumns = row => {
25
+ const multipleColumns = row.columns.filter(column => column.widget).length > 1
26
+ return multipleColumns && !row.toggle
27
+ }
28
+
29
+ const newMarkupIncludeVisualization = (uid, footnotes) => {
30
+ return {
31
+ filters: [],
32
+ filterBehavior: 'Filter Change',
33
+ footnotes,
34
+ uid,
35
+ type: 'markup-include',
36
+ visualizationType: 'markup-include',
37
+ contentEditor: {
38
+ inlineHTML: '',
39
+ markupVariables: [],
40
+ showHeader: false,
41
+ srcUrl: '',
42
+ title: '',
43
+ useInlineHTML: false
44
+ },
45
+ theme: 'theme-blue',
46
+ visual: {
47
+ border: false,
48
+ accent: false,
49
+ background: false,
50
+ hideBackgroundColor: false,
51
+ borderColorTheme: false
52
+ }
53
+ }
54
+ }
55
+
56
+ const makeNewRow = uuid => {
57
+ return { columns: [{ width: 12, widget: uuid }] }
58
+ }
59
+
60
+ export const moveFootnotesToVizLevel = config => {
61
+ if (config.type === 'dashboard') {
62
+ const newRowsToAdd = [
63
+ /*old row index*/
64
+ /*new row object*/
65
+ ]
66
+ config.rows.forEach((row, index) => {
67
+ if (!row.footnotesId) return
68
+ const makeNewFootnotesRow = hasMultipleWidgetColumns(row)
69
+ const footnotesId = row.footnotesId
70
+ const footnote = _.pick(config.visualizations[footnotesId], ['dataKey', 'dynamicFootnotes', 'staticFootnotes'])
71
+ if (makeNewFootnotesRow) {
72
+ const uuid = `markup-include-${Date.now()}${index}`
73
+ const newRow = makeNewRow(uuid)
74
+ const newFootnotesViz = newMarkupIncludeVisualization(uuid, footnote)
75
+ config.visualizations[uuid] = newFootnotesViz
76
+ newRowsToAdd.push([index, newRow])
77
+ } else {
78
+ row.columns.forEach(column => {
79
+ if (!column.widget) return
80
+ const footnotes = config.visualizations[column.widget].footnotes
81
+ if (typeof footnotes === 'string') {
82
+ // move legacy footnotes
83
+ config.visualizations[column.widget].legacyFootnotes = footnotes
84
+ }
85
+ config.visualizations[column.widget].footnotes = footnote
86
+ })
87
+ }
88
+
89
+ delete config.visualizations[footnotesId]
90
+ delete row.footnotesId
91
+ })
92
+ if (newRowsToAdd.length) {
93
+ newRowsToAdd.forEach(([oldRowIndex, newRow]) => {
94
+ config.rows.splice(oldRowIndex + 1, 0, newRow)
95
+ })
96
+ }
97
+ }
98
+ }
99
+
100
+ const update_4_25_4 = config => {
101
+ const ver = '4.25.4'
102
+ const newConfig = _.cloneDeep(config)
103
+ makeChartLegendsUnified(newConfig)
104
+ migrateTableGeneralSettings(newConfig)
105
+ moveFootnotesToVizLevel(newConfig)
106
+ newConfig.version = ver
107
+ return newConfig
108
+ }
109
+
110
+ export default update_4_25_4
@@ -0,0 +1,36 @@
1
+ import _ from 'lodash'
2
+
3
+ // *NOTE: This ends support for only showing the top prefix
4
+ export const changeOnlyShowTopSuffixToInlineLabel = config => {
5
+ if (config.type === 'chart') {
6
+ if (!config.dataFormat?.suffix) return config
7
+ if (!config.dataFormat.onlyShowTopPrefixSuffix) return config
8
+
9
+ delete config.dataFormat.onlyShowTopPrefixSuffix
10
+
11
+ if (!config.yAxis) config.yAxis = {}
12
+
13
+ if (!config.yAxis?.inlineLabel) {
14
+ config.yAxis.inlineLabel = config.dataFormat.suffix
15
+ }
16
+
17
+ config.dataFormat.suffix = ''
18
+
19
+ return config
20
+ } else if (config.type === 'dashboard') {
21
+ Object.values(config.visualizations).forEach(visualization => {
22
+ changeOnlyShowTopSuffixToInlineLabel(visualization)
23
+ })
24
+ return config
25
+ }
26
+ }
27
+
28
+ const update_4_25_6 = config => {
29
+ const ver = '4.25.6'
30
+ const newConfig = _.cloneDeep(config)
31
+ changeOnlyShowTopSuffixToInlineLabel(newConfig)
32
+ newConfig.version = ver
33
+ return newConfig
34
+ }
35
+
36
+ export default update_4_25_6
@@ -0,0 +1,26 @@
1
+ import _ from 'lodash'
2
+
3
+ export const updatePreliminaryDataSeriesKeys = config => {
4
+ if (config.type === 'chart') {
5
+ ;(config.preliminaryData || []).forEach(pd => {
6
+ if (!pd.seriesKeys) {
7
+ pd.seriesKeys = pd.seriesKey ? [pd.seriesKey] : []
8
+ delete pd.seriesKey
9
+ }
10
+ })
11
+ } else if (config.type === 'dashboard') {
12
+ Object.values(config.visualizations).forEach(visualization => {
13
+ updatePreliminaryDataSeriesKeys(visualization)
14
+ })
15
+ }
16
+ }
17
+
18
+ const update_4_25_7 = config => {
19
+ const ver = '4.25.7'
20
+ const newConfig = _.cloneDeep(config)
21
+ updatePreliminaryDataSeriesKeys(newConfig)
22
+ newConfig.version = ver
23
+ return newConfig
24
+ }
25
+
26
+ export default update_4_25_7
@@ -0,0 +1,89 @@
1
+ import { expect, describe, it } from 'vitest'
2
+ import { makeChartLegendsUnified, moveFootnotesToVizLevel } from '../4.25.4'
3
+ import { ChartConfig } from '@cdc/chart/src/types/ChartConfig'
4
+ import { DashboardConfig } from '@cdc/dashboard/src/types/DashboardConfig'
5
+
6
+ describe('makeChartLegendsUnified(config) ', () => {
7
+ it('sets chart legends unified to true', () => {
8
+ const mockConfig = { type: 'chart', legend: { unified: false } } as Partial<ChartConfig>
9
+ makeChartLegendsUnified(mockConfig)
10
+ expect(mockConfig.legend?.unified).toBe(true)
11
+ })
12
+ it('sets dashboard nested chart legends unified to true', () => {
13
+ const mockConfig = {
14
+ type: 'dashboard',
15
+ visualizations: {
16
+ '1': { type: 'chart', legend: { unified: false } } as ChartConfig,
17
+ '2': { type: 'chart', legend: { unified: false } } as ChartConfig
18
+ }
19
+ } as Partial<DashboardConfig>
20
+ makeChartLegendsUnified(mockConfig)
21
+ expect(mockConfig.visualizations['1'].legend?.unified).toBe(true)
22
+ expect(mockConfig.visualizations['2'].legend?.unified).toBe(true)
23
+ })
24
+ })
25
+
26
+ describe('moveFootnotesToVizLevel', () => {
27
+ it('moves footnotes to visualization level', () => {
28
+ const toMigrate = {
29
+ rows: [
30
+ {
31
+ columns: [
32
+ {
33
+ width: 12,
34
+ widget: 'table123'
35
+ },
36
+ {},
37
+ {}
38
+ ],
39
+ footnotesId: 'footnotes123'
40
+ }
41
+ ],
42
+ visualizations: {
43
+ table123: {},
44
+ footnotes123: {
45
+ uid: 'footnotes123',
46
+ type: 'footnotes',
47
+ visualizationType: 'footnotes',
48
+ dataKey: 'valid-data-chart.csv',
49
+ dynamicFootnotes: {
50
+ symbolColumn: 'Race',
51
+ textColumn: 'Age-adjusted rate'
52
+ }
53
+ }
54
+ },
55
+ type: 'dashboard',
56
+ version: '4.25.4'
57
+ }
58
+
59
+ const expectedMigration = {
60
+ rows: [
61
+ {
62
+ columns: [
63
+ {
64
+ width: 12,
65
+ widget: 'table123'
66
+ },
67
+ {},
68
+ {}
69
+ ]
70
+ }
71
+ ],
72
+ visualizations: {
73
+ table123: {
74
+ footnotes: {
75
+ dataKey: 'valid-data-chart.csv',
76
+ dynamicFootnotes: {
77
+ symbolColumn: 'Race',
78
+ textColumn: 'Age-adjusted rate'
79
+ }
80
+ }
81
+ }
82
+ },
83
+ type: 'dashboard',
84
+ version: '4.25.4'
85
+ }
86
+ moveFootnotesToVizLevel(toMigrate)
87
+ expect(toMigrate).toEqual(expectedMigration)
88
+ })
89
+ })
@@ -0,0 +1,84 @@
1
+ import { expect, describe, it } from 'vitest'
2
+ import { changeOnlyShowTopSuffixToInlineLabel } from '../4.25.6'
3
+
4
+ describe('changeOnlyShowTopSuffixToInlineLabel(config) ', () => {
5
+ it("should'nt change config if no suffix", () => {
6
+ const config = {
7
+ type: 'chart',
8
+ dataFormat: {
9
+ onlyShowTopPrefixSuffix: true,
10
+ suffix: ''
11
+ }
12
+ }
13
+ const newConfig = changeOnlyShowTopSuffixToInlineLabel(config)
14
+ expect(newConfig).toEqual(config)
15
+ })
16
+ it("should't change suffix if onlyShowTopPrefixSuffix is false", () => {
17
+ const config = {
18
+ type: 'chart',
19
+ dataFormat: {
20
+ onlyShowTopPrefixSuffix: false,
21
+ suffix: 'test'
22
+ }
23
+ }
24
+ const newConfig = changeOnlyShowTopSuffixToInlineLabel(config)
25
+ expect(newConfig).toEqual(config)
26
+ })
27
+ it('should change suffix to inlineLabel if onlyShowTopPrefixSuffix is true', () => {
28
+ const config = {
29
+ type: 'chart',
30
+ dataFormat: {
31
+ onlyShowTopPrefixSuffix: true,
32
+ suffix: 'test'
33
+ }
34
+ }
35
+ const newConfig = changeOnlyShowTopSuffixToInlineLabel(config)
36
+ expect(newConfig.yAxis.inlineLabel).toBe('test')
37
+ expect(newConfig.dataFormat.onlyShowTopPrefixSuffix).toBe(undefined)
38
+ expect(newConfig.dataFormat.suffix).toBe('')
39
+ })
40
+ it("should't overwrite existing yAxis inlineLabel", () => {
41
+ const config = {
42
+ type: 'chart',
43
+ dataFormat: {
44
+ onlyShowTopPrefixSuffix: true,
45
+ suffix: 'test'
46
+ },
47
+ yAxis: {
48
+ inlineLabel: 'test2'
49
+ }
50
+ }
51
+ const newConfig = changeOnlyShowTopSuffixToInlineLabel(config)
52
+ expect(newConfig.yAxis.inlineLabel).toBe('test2')
53
+ expect(newConfig.dataFormat.onlyShowTopPrefixSuffix).toBe(undefined)
54
+ expect(newConfig.dataFormat.suffix).toBe('')
55
+ })
56
+ it('should change suffix to inlineLabel for dashboard visualizations', () => {
57
+ const config = {
58
+ type: 'dashboard',
59
+ visualizations: [
60
+ {
61
+ type: 'chart',
62
+ dataFormat: {
63
+ onlyShowTopPrefixSuffix: true,
64
+ suffix: 'test'
65
+ }
66
+ },
67
+ {
68
+ type: 'chart',
69
+ dataFormat: {
70
+ onlyShowTopPrefixSuffix: true,
71
+ suffix: 'test2'
72
+ }
73
+ }
74
+ ]
75
+ }
76
+ const newConfig = changeOnlyShowTopSuffixToInlineLabel(config)
77
+ expect(newConfig.visualizations[0].yAxis.inlineLabel).toBe('test')
78
+ expect(newConfig.visualizations[0].dataFormat.onlyShowTopPrefixSuffix).toBe(undefined)
79
+ expect(newConfig.visualizations[0].dataFormat.suffix).toBe('')
80
+ expect(newConfig.visualizations[1].yAxis.inlineLabel).toBe('test2')
81
+ expect(newConfig.visualizations[1].dataFormat.onlyShowTopPrefixSuffix).toBe(undefined)
82
+ expect(newConfig.visualizations[1].dataFormat.suffix).toBe('')
83
+ })
84
+ })
@@ -8,3 +8,7 @@ export const isBelowBreakpoint = (breakpoint: ViewportSize, currentViewport: Vie
8
8
  export const isLegendWrapViewport = currentViewport => isBelowBreakpoint('sm', currentViewport)
9
9
 
10
10
  export const isMobileHeightViewport = currentViewport => isBelowBreakpoint('sm', currentViewport)
11
+
12
+ export const isMobileStateLabelViewport = currentViewport => isBelowBreakpoint('md', currentViewport)
13
+
14
+ export const isMobileTerritoryViewport = currentViewport => isBelowBreakpoint('sm', currentViewport)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cdc/core",
3
- "version": "4.25.3",
3
+ "version": "4.25.6-1",
4
4
  "description": "Core components, styles, hooks, and helpers, for the CDC Open Visualization project",
5
5
  "moduleName": "CdcCore",
6
6
  "main": "dist/cdccore",
@@ -21,20 +21,21 @@
21
21
  },
22
22
  "license": "Apache-2.0",
23
23
  "dependencies": {
24
+ "dompurify": "^3.2.6",
24
25
  "html2canvas": "^1.4.1",
25
- "json-edit-react": "^1.12.0",
26
- "papaparse": "^5.3.0",
26
+ "json-edit-react": "^1.27.0",
27
27
  "prop-types": "^15.8.1",
28
- "react-accessible-accordion": "^5.0.0",
28
+ "react-accessible-accordion": "^5.0.1",
29
29
  "react-select": "^5.3.1",
30
30
  "react-tooltip": "5.8.2-beta.3",
31
- "use-debounce": "^6.0.1"
31
+ "sass": "^1.89.2",
32
+ "use-debounce": "^10.0.5"
32
33
  },
33
34
  "peerDependencies": {
34
35
  "react": "^18.2.0",
35
36
  "react-dom": "^18.2.0"
36
37
  },
37
- "gitHead": "b09566f5a7d57c8d0109e5f407257729d6b36846",
38
+ "gitHead": "ac45ee0f1d6a4045648c4e083992fc091795e084",
38
39
  "devDependencies": {
39
40
  "sass": "^1.79.4"
40
41
  }
@@ -8,6 +8,7 @@ $colors: (
8
8
  'darkGray': #333,
9
9
  'red': #d8000c,
10
10
  'white': #fff,
11
+ 'silver': #eee,
11
12
 
12
13
  'primary': #005eaa,
13
14
  'secondary': #88c3ea,
@@ -106,4 +107,6 @@ $colors: (
106
107
  --filter-buttons-font-size: 0.889rem;
107
108
  --superTitle-font-size: 0.833rem;
108
109
  --title-font-size: 1.222rem;
110
+ --territory-label-font-size: 0.809rem;
111
+ --territory-label-font-size-mobile: 0.556rem;
109
112
  }
@@ -193,8 +193,4 @@ section.footnotes {
193
193
  -webkit-appearance: none;
194
194
  -moz-appearance: none;
195
195
  cursor: pointer;
196
- &:focus-visible {
197
- outline: 2px dashed var(--colors-blue-vivid-60, #005ea2) !important;
198
- outline-offset: 2px;
199
- }
200
196
  }
@@ -7,12 +7,6 @@
7
7
  font-style: normal;
8
8
  text-rendering: optimizeLegibility;
9
9
 
10
- // match cdc site outline
11
- :focus,
12
- [tabindex]:focus-visible {
13
- outline: 2px solid rgba(255, 102, 1, 0.9) !important;
14
- }
15
-
16
10
  .outline-none {
17
11
  outline: none !important;
18
12
  }
@@ -93,10 +93,6 @@ div.single-filters {
93
93
  &:focus:not(:focus-visible) {
94
94
  outline: none !important;
95
95
  }
96
- &:focus-visible {
97
- outline: 2px dashed var(--colors-blue-vivid-60, #005ea2) !important;
98
- outline-offset: 3px;
99
- }
100
96
 
101
97
  &.tab--active {
102
98
  font-weight: 500;
@@ -6,11 +6,6 @@
6
6
  font-size: 16px;
7
7
  line-height: 1.4;
8
8
 
9
- :focus,
10
- [tabindex]:focus-visible {
11
- outline: 2px solid rgba(255, 102, 1, 0.9);
12
- }
13
-
14
9
  margin: 0;
15
10
  font-family: var(--app-font-main);
16
11
  font-size: 1em;
package/types/Axis.ts CHANGED
@@ -17,6 +17,7 @@ export type Axis = {
17
17
  hideAxis?: boolean
18
18
  hideLabel?: boolean
19
19
  hideTicks?: boolean
20
+ inlineLabel?: string
20
21
  label?: string
21
22
  labelOffset?: number
22
23
  labelPlacement?: string
@@ -50,4 +51,5 @@ export type Axis = {
50
51
  axisBBox: number
51
52
  maxValue: string
52
53
  sortByRecentDate: boolean
54
+ brushActive: boolean
53
55
  }