@cdc/core 4.25.8 → 4.25.11

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 (163) hide show
  1. package/_stories/StoryRenderingTests.stories.tsx +164 -0
  2. package/components/AdvancedEditor/AdvancedEditor.tsx +32 -9
  3. package/components/CustomColorsEditor/CustomColorsEditor.css +299 -0
  4. package/components/CustomColorsEditor/CustomColorsEditor.tsx +209 -0
  5. package/components/CustomColorsEditor/index.ts +1 -0
  6. package/components/DataTable/DataTable.tsx +56 -38
  7. package/components/DataTable/DataTableStandAlone.tsx +8 -3
  8. package/components/DataTable/components/ChartHeader.tsx +44 -14
  9. package/components/DataTable/components/DataTableEditorPanel.tsx +12 -2
  10. package/components/DataTable/components/ExpandCollapse.tsx +10 -1
  11. package/components/DataTable/components/MapHeader.tsx +24 -13
  12. package/components/DataTable/data-table.css +12 -0
  13. package/components/DataTable/helpers/chartCellMatrix.tsx +11 -8
  14. package/components/DataTable/helpers/mapCellMatrix.tsx +33 -4
  15. package/components/DataTable/helpers/standardizeState.js +2 -2
  16. package/components/DataTable/helpers/tests/standardizeState.test.js +54 -0
  17. package/components/DownloadButton.tsx +40 -14
  18. package/components/EditorPanel/DataTableEditor.tsx +3 -3
  19. package/components/EditorPanel/EditorPanel.styles.css +423 -0
  20. package/components/EditorPanel/FootnotesEditor.tsx +44 -37
  21. package/components/EditorPanel/Inputs.tsx +12 -2
  22. package/components/EditorPanel/VizFilterEditor/NestedDropdownEditor.tsx +35 -62
  23. package/components/EditorPanel/VizFilterEditor/VizFilterEditor.tsx +12 -2
  24. package/components/EditorPanel/components/MarkupHighlightedTextField.tsx +227 -0
  25. package/components/EditorPanel/components/MarkupVariablesEditor.tsx +450 -0
  26. package/components/EditorPanel/components/PanelMarkup.tsx +59 -0
  27. package/components/ErrorBoundary.jsx +3 -1
  28. package/components/Filters/Filters.tsx +52 -24
  29. package/components/Filters/components/Dropdown.tsx +6 -1
  30. package/components/Filters/components/Tabs.tsx +1 -0
  31. package/components/Footnotes/Footnotes.tsx +35 -25
  32. package/components/Footnotes/FootnotesStandAlone.tsx +42 -6
  33. package/components/HeaderThemeSelector/HeaderThemeSelector.css +43 -0
  34. package/components/HeaderThemeSelector/HeaderThemeSelector.stories.tsx +74 -0
  35. package/components/HeaderThemeSelector/HeaderThemeSelector.tsx +61 -0
  36. package/components/HeaderThemeSelector/index.ts +2 -0
  37. package/components/Layout/styles/editor.scss +2 -1
  38. package/components/Legend/Legend.Gradient.tsx +3 -6
  39. package/components/LegendShape.tsx +121 -3
  40. package/components/Loader/Loader.tsx +1 -1
  41. package/components/MediaControls.tsx +72 -21
  42. package/components/PaletteConversionModal.tsx +90 -0
  43. package/components/PaletteSelector/DeveloperPaletteRollback.tsx +114 -0
  44. package/components/PaletteSelector/PaletteSelector.css +94 -0
  45. package/components/PaletteSelector/PaletteSelector.tsx +112 -0
  46. package/components/PaletteSelector/index.ts +2 -0
  47. package/components/RichTooltip/RichTooltip.tsx +1 -0
  48. package/components/Table/Table.tsx +3 -1
  49. package/components/Table/components/Cell.tsx +23 -2
  50. package/components/Table/components/Row.tsx +5 -3
  51. package/components/_stories/BlurStrokeTest.stories.tsx +1 -1
  52. package/components/_stories/DataTable.stories.tsx +1 -1
  53. package/components/_stories/Filters.stories.tsx +21 -2
  54. package/components/_stories/Footnotes.CSV.stories.tsx +247 -0
  55. package/components/_stories/Footnotes.stories.tsx +769 -4
  56. package/components/_stories/Inputs.stories.tsx +3 -3
  57. package/components/_stories/MultiSelect.stories.tsx +3 -3
  58. package/components/_stories/NestedDropdown.stories.tsx +1 -1
  59. package/components/_stories/Table.stories.tsx +1 -1
  60. package/components/_stories/styles.scss +0 -1
  61. package/components/elements/_stories/Button.stories.tsx +1 -1
  62. package/components/elements/_stories/Card.stories.tsx +1 -1
  63. package/components/inputs/InputToggle.tsx +2 -0
  64. package/components/managers/DataDesigner.tsx +10 -9
  65. package/components/managers/_stories/DataDesigner.stories.tsx +1 -1
  66. package/components/ui/Accordion.jsx +1 -1
  67. package/components/ui/Tooltip.tsx +2 -1
  68. package/components/ui/_stories/Accordion.stories.tsx +1 -1
  69. package/components/ui/_stories/ColorPaletteMigration.stories.mdx +275 -0
  70. package/components/ui/_stories/Colors.stories.tsx +330 -0
  71. package/components/ui/_stories/IconGallery.stories.tsx +316 -0
  72. package/components/ui/_stories/Title.stories.tsx +1 -1
  73. package/components/ui/accordion.styles.css +57 -0
  74. package/contexts/EditorContext.ts +18 -0
  75. package/contexts/editor.actions.ts +28 -0
  76. package/contexts/editor.reducer.ts +94 -0
  77. package/data/chartColorPalettes.ts +118 -0
  78. package/data/colorPalettes.ts +9 -0
  79. package/data/mapColorPalettes.ts +45 -0
  80. package/data/sharedPalettes.ts +50 -0
  81. package/dist/cove-main.css +63 -14
  82. package/dist/cove-main.css.map +1 -1
  83. package/generateViteConfig.js +80 -0
  84. package/helpers/addValuesToFilters.ts +7 -3
  85. package/helpers/cloneConfig.ts +31 -0
  86. package/helpers/configDataHelpers.ts +128 -0
  87. package/helpers/configHelpers.ts +27 -0
  88. package/helpers/constants.ts +42 -2
  89. package/helpers/cove/number.ts +33 -12
  90. package/helpers/coveUpdateWorker.ts +15 -3
  91. package/helpers/fetchRemoteData.ts +3 -15
  92. package/helpers/filterColorPalettes.ts +152 -0
  93. package/helpers/generateColorsArray.ts +13 -0
  94. package/helpers/getColorPaletteVersion.ts +33 -0
  95. package/helpers/getPaletteAccessor.ts +18 -0
  96. package/helpers/markupProcessor.ts +220 -0
  97. package/helpers/mergeCustomOrderValues.ts +37 -0
  98. package/helpers/metrics/helpers.ts +42 -19
  99. package/helpers/metrics/types.ts +48 -9
  100. package/helpers/metrics/utils.ts +34 -0
  101. package/helpers/palettes/colorDistributions.ts +56 -0
  102. package/helpers/palettes/migratePaletteName.ts +150 -0
  103. package/helpers/palettes/standardizePaletteNames.ts +77 -0
  104. package/helpers/palettes/utils.ts +267 -0
  105. package/helpers/parseCsvWithQuotes.ts +65 -0
  106. package/helpers/queryStringUtils.ts +13 -0
  107. package/helpers/testing.ts +358 -0
  108. package/helpers/tests/addValuesToFilters.test.ts +1 -2
  109. package/helpers/tests/generateColorsArray.test.ts +24 -0
  110. package/helpers/tests/markupProcessor.test.ts +538 -0
  111. package/helpers/tests/testStandaloneBuild.ts +44 -0
  112. package/helpers/useMarkupVariables.ts +31 -0
  113. package/helpers/vegaConfig.ts +0 -1
  114. package/helpers/ver/4.24.10.ts +2 -1
  115. package/helpers/ver/4.24.11.ts +2 -1
  116. package/helpers/ver/4.24.3.ts +2 -1
  117. package/helpers/ver/4.24.4.ts +2 -1
  118. package/helpers/ver/4.24.5.ts +2 -1
  119. package/helpers/ver/4.24.7.ts +2 -1
  120. package/helpers/ver/4.24.9.ts +2 -1
  121. package/helpers/ver/4.25.1.ts +2 -1
  122. package/helpers/ver/4.25.10.ts +36 -0
  123. package/helpers/ver/4.25.11.ts +13 -0
  124. package/helpers/ver/4.25.3.ts +2 -1
  125. package/helpers/ver/4.25.4.ts +2 -1
  126. package/helpers/ver/4.25.6.ts +2 -1
  127. package/helpers/ver/4.25.7.ts +2 -1
  128. package/helpers/ver/4.25.8.ts +2 -1
  129. package/helpers/ver/4.25.9.ts +293 -0
  130. package/helpers/ver/tests/4.25.10.test.ts +204 -0
  131. package/helpers/ver/tests/4.25.8.test.ts +1 -1
  132. package/helpers/ver/tests/4.25.9.test.ts +51 -0
  133. package/helpers/viewports.ts +2 -0
  134. package/hooks/useColorPalette.ts +79 -0
  135. package/package.json +13 -4
  136. package/styles/_common-components.css +73 -0
  137. package/styles/_global.scss +32 -10
  138. package/styles/base.scss +8 -55
  139. package/styles/cove-main.scss +3 -1
  140. package/styles/filters.scss +10 -3
  141. package/styles/v2/base/index.scss +0 -1
  142. package/styles/v2/components/button.scss +4 -3
  143. package/styles/v2/components/editor.scss +16 -7
  144. package/styles/v2/layout/_data-table.scss +3 -2
  145. package/styles/v2/themes/_color-definitions.scss +18 -17
  146. package/styles/v2/utils/_breakpoints.scss +1 -1
  147. package/styles/v2/utils/index.scss +0 -1
  148. package/styles/waiting.scss +1 -1
  149. package/testing-setup.js +32 -0
  150. package/types/MarkupInclude.ts +8 -2
  151. package/types/MarkupVariable.ts +19 -0
  152. package/types/VizFilter.ts +2 -0
  153. package/vitest.config.ts +16 -0
  154. package/components/ui/_stories/Colors.stories.mdx +0 -220
  155. package/components/ui/_stories/IconGallery.stories.mdx +0 -14
  156. package/data/colorPalettes.js +0 -171
  157. package/helpers/formatConfigBeforeSave.ts +0 -135
  158. package/helpers/tests/formatConfigBeforeSave.test.ts +0 -68
  159. package/styles/_mixins.scss +0 -13
  160. package/styles/v2/base/_typography.scss +0 -0
  161. package/styles/v2/components/guidance-block.scss +0 -74
  162. package/styles/v2/utils/_functions.scss +0 -0
  163. /package/{styles/_typography.scss → testBuild.js} +0 -0
@@ -31,7 +31,6 @@ const chartCellArray = ({
31
31
  const groupBy = config.table?.groupBy
32
32
  const dataSeriesColumns = getDataSeriesColumns(config, isVertical, runtimeData)
33
33
 
34
-
35
34
  const dataSeriesColumnsSorted = () => {
36
35
  if (!sortBy && sortBy.colIndex === null) return dataSeriesColumns
37
36
  return dataSeriesColumns.sort((a, b) => {
@@ -73,10 +72,14 @@ const chartCellArray = ({
73
72
  return rows.map(row => {
74
73
  if (hasRowType) {
75
74
  const rowType = getRowType(runtimeData[row])
76
- const rowValues = dataSeriesColumns.map(column => getChartCellValue(row, column, config, runtimeData, rightAxisItemsMap))
75
+ const rowValues = dataSeriesColumns.map(column =>
76
+ getChartCellValue(row, column, config, runtimeData, rightAxisItemsMap)
77
+ )
77
78
  return [rowType, ...rowValues]
78
79
  } else {
79
- return dataSeriesColumns.map((column, j) => getChartCellValue(row, column, config, runtimeData, rightAxisItemsMap))
80
+ return dataSeriesColumns.map((column, j) =>
81
+ getChartCellValue(row, column, config, runtimeData, rightAxisItemsMap)
82
+ )
80
83
  }
81
84
  })
82
85
  }
@@ -86,11 +89,11 @@ const chartCellArray = ({
86
89
  let nodes: ReactNode[] =
87
90
  config.visualizationType !== 'Pie'
88
91
  ? [
89
- <>
90
- {colorScale && colorScale(seriesName) && <LegendShape fill={colorScale(seriesName)} />}
91
- {parse(seriesName)}
92
- </>
93
- ]
92
+ <>
93
+ {colorScale && colorScale(seriesName) && <LegendShape fill={colorScale(seriesName)} />}
94
+ {parse(String(seriesName))}
95
+ </>
96
+ ]
94
97
  : []
95
98
  return nodes.concat(rows.map((row, i) => getChartCellValue(row, column, config, runtimeData, rightAxisItemsMap)))
96
99
  })
@@ -6,16 +6,28 @@ import { displayDataAsText } from '@cdc/core/helpers/displayDataAsText'
6
6
  import _ from 'lodash'
7
7
  import { applyLegendToRow } from '@cdc/map/src/helpers/applyLegendToRow'
8
8
  import { hashObj } from '@cdc/map/src/helpers'
9
+ import { getPatternForRow } from '@cdc/map/src/helpers/getPatternForRow'
9
10
 
10
11
  type MapRowsProps = DataTableProps & {
11
12
  rows: string[]
12
13
  }
13
14
 
14
- const getGeoLabel = (config, row, formatLegendLocation, displayGeoName) => {
15
+ const getGeoLabel = (config, row, formatLegendLocation, displayGeoName, runtimeData = null) => {
15
16
  const { geoType, type } = config.general
17
+
16
18
  let labelValue
17
19
  if (!['single-state', 'us-county'].includes(geoType) || type === 'us-geocode') {
20
+ // Use the row (UID) for lookup - this allows "US-AL" to become "Alabama"
18
21
  labelValue = displayGeoName(row)
22
+
23
+ // If displayGeoName returned the same value (not found in lookups), use the raw imported data
24
+ if (labelValue === row && runtimeData && config.columns?.geo?.name) {
25
+ const rawGeoValue = runtimeData[row]?.[config.columns.geo.name]
26
+ if (rawGeoValue && rawGeoValue !== row) {
27
+ labelValue = rawGeoValue
28
+ }
29
+ }
30
+
19
31
  labelValue = String(labelValue).startsWith('region') ? _.capitalize(labelValue) : labelValue
20
32
  } else {
21
33
  labelValue = formatLegendLocation(row)
@@ -57,7 +69,7 @@ export const getMapRowData = (
57
69
  ].map(column => {
58
70
  const label = columns[column]?.label || columns[column]?.name || column
59
71
  if (column === 'geo') {
60
- dataRow[label] = getGeoLabel(config, row, formatLegendLocation, displayGeoName)
72
+ dataRow[label] = getGeoLabel(config, row, formatLegendLocation, displayGeoName, runtimeData)
61
73
  } else if (filterColumns.includes(column)) {
62
74
  dataRow[label] = runtimeData[row][column]
63
75
  } else {
@@ -99,15 +111,32 @@ const mapCellArray = ({
99
111
  if (!legendColor) {
100
112
  console.error('No legend color found') // eslint-disable-line no-console
101
113
  }
102
- const labelValue = getGeoLabel(config, row, formatLegendLocation, displayGeoName)
114
+ const labelValue = getGeoLabel(config, row, formatLegendLocation, displayGeoName, runtimeData)
103
115
  const mapZoomHandler =
104
116
  type === 'bubble' && allowMapZoom && geoType === 'world' ? () => setFilteredCountryCode(row) : undefined
105
117
 
106
118
  const validColor = legendColor && legendColor.length > 0 && !noColor
119
+
120
+ // Check for pattern information
121
+ const patternInfo = getPatternForRow(rowObj, config)
122
+ const mapId = config.runtime?.uniqueId || 'map'
123
+
107
124
  return (
108
125
  <div className='col-12'>
109
126
  {validColor ? (
110
- <LegendShape fill={legendColor[0]} />
127
+ patternInfo ? (
128
+ <LegendShape
129
+ fill={legendColor[0]}
130
+ patternInfo={{
131
+ pattern: patternInfo.pattern,
132
+ patternId: `${mapId}--${patternInfo.dataKey}--${patternInfo.patternIndex}--table`,
133
+ size: patternInfo.size,
134
+ color: patternInfo.color
135
+ }}
136
+ />
137
+ ) : (
138
+ <LegendShape fill={legendColor[0]} />
139
+ )
111
140
  ) : (
112
141
  <div className='d-inline-block me-2' style={{ width: '1rem', height: '1rem' }} />
113
142
  )}
@@ -8,8 +8,8 @@ const states = {
8
8
  CO: 'Colorado',
9
9
  CT: 'Connecticut',
10
10
  DE: 'Delaware',
11
- DC: 'District Of Columbia',
12
- FM: 'Federated States Of Micronesia',
11
+ DC: 'District of Columbia',
12
+ FM: 'Federated States of Micronesia',
13
13
  FL: 'Florida',
14
14
  GA: 'Georgia',
15
15
  GU: 'Guam',
@@ -0,0 +1,54 @@
1
+ import { standardizeStateName } from '../standardizeState'
2
+
3
+ describe('standardizeStateName', () => {
4
+ it('should return non-string values unchanged', () => {
5
+ expect(standardizeStateName(123)).toBe(123)
6
+ expect(standardizeStateName(null)).toBe(null)
7
+ expect(standardizeStateName(undefined)).toBe(undefined)
8
+ expect(standardizeStateName(true)).toBe(true)
9
+ })
10
+
11
+ it('should return numeric strings unchanged', () => {
12
+ expect(standardizeStateName('123')).toBe('123')
13
+ expect(standardizeStateName('456.78')).toBe('456.78')
14
+ })
15
+
16
+ it('should convert state abbreviations to full names', () => {
17
+ expect(standardizeStateName('DC')).toBe('District of Columbia')
18
+ expect(standardizeStateName('dc')).toBe('District of Columbia')
19
+ expect(standardizeStateName('CA')).toBe('California')
20
+ expect(standardizeStateName('ca')).toBe('California')
21
+ expect(standardizeStateName('FM')).toBe('Federated States of Micronesia')
22
+ expect(standardizeStateName('fm')).toBe('Federated States of Micronesia')
23
+ })
24
+
25
+ it('should handle Virgin Islands variations', () => {
26
+ expect(standardizeStateName('VI')).toBe('U.S. VIRGIN ISLANDS')
27
+ expect(standardizeStateName('vi')).toBe('U.S. VIRGIN ISLANDS')
28
+ expect(standardizeStateName('Virgin Islands')).toBe('U.S. VIRGIN ISLANDS')
29
+ expect(standardizeStateName('VIRGIN ISLANDS')).toBe('U.S. VIRGIN ISLANDS')
30
+ expect(standardizeStateName('U.S. Virgin Islands')).toBe('U.S. VIRGIN ISLANDS')
31
+ expect(standardizeStateName('US VIRGIN ISLANDS')).toBe('U.S. VIRGIN ISLANDS')
32
+ })
33
+
34
+ it('should verify "of" is lowercase in state names', () => {
35
+ const dcName = standardizeStateName('DC')
36
+ expect(dcName).toContain('of')
37
+ expect(dcName).not.toContain('Of')
38
+
39
+ const fmName = standardizeStateName('FM')
40
+ expect(fmName).toContain('of')
41
+ expect(fmName).not.toContain('Of')
42
+ })
43
+
44
+ it('should return original value for unknown state codes', () => {
45
+ expect(standardizeStateName('ZZ')).toBe('ZZ')
46
+ expect(standardizeStateName('Unknown State')).toBe('Unknown State')
47
+ })
48
+
49
+ it('should handle mixed case state names', () => {
50
+ expect(standardizeStateName('California')).toBe('California')
51
+ expect(standardizeStateName('CALIFORNIA')).toBe('CALIFORNIA')
52
+ expect(standardizeStateName('cAlIfOrNiA')).toBe('cAlIfOrNiA')
53
+ })
54
+ })
@@ -1,43 +1,69 @@
1
+ import { useRef } from 'react'
1
2
  import Papa from 'papaparse'
2
3
  import { publishAnalyticsEvent } from '../helpers/metrics/helpers'
4
+ import { getVizTitle, getVizSubType } from '@cdc/core/helpers/metrics/utils'
3
5
 
4
6
  type DownloadButtonProps = {
5
- rawData: Object
7
+ rawData: any[]
6
8
  fileName: string
7
9
  headerColor: string
8
10
  skipId: string | number
9
11
  configUrl?: string
12
+ interactionLabel?: string
13
+ title?: string
10
14
  }
11
15
 
12
- const DownloadButton = ({ rawData, fileName, headerColor, skipId, configUrl }: DownloadButtonProps) => {
13
- const csvData = Papa.unparse(rawData)
14
- // Prepend a Byte Order Mark (BOM) to the CSV data.
15
- // The BOM is a special marker that helps applications like Excel recognize the file as UTF-8 encoded.
16
- // Adding the BOM ensures that Excel interprets special characters correctly.
17
- const bom = '\uFEFF'
18
- const utf8EncodedCsvData = new TextEncoder().encode(bom + csvData)
19
- const blob = new Blob([utf8EncodedCsvData], { type: 'text/csv;charset=utf-8;' })
16
+ const DownloadButton = ({ rawData, fileName, headerColor, skipId, interactionLabel, configUrl, title, config }: DownloadButtonProps) => {
17
+ const linkRef = useRef<HTMLAnchorElement>(null)
18
+
19
+ const handleDownload = (event: React.MouseEvent<HTMLAnchorElement>) => {
20
+ event.preventDefault()
21
+
22
+ const csvData = Papa.unparse(rawData)
23
+
24
+ // Prepend a Byte Order Mark (BOM) to the CSV data.
25
+ // The BOM is a special marker that helps applications like Excel recognize the file as UTF-8 encoded.
26
+ // Adding the BOM ensures that Excel interprets special characters correctly.
27
+ const bom = '\uFEFF'
28
+ const utf8EncodedCsvData = new TextEncoder().encode(bom + csvData)
29
+ const blob = new Blob([utf8EncodedCsvData], { type: 'text/csv;charset=utf-8;' })
30
+
31
+ const url = URL.createObjectURL(blob)
20
32
 
21
- const saveBlob = () => {
22
33
  //@ts-ignore
23
34
  if (typeof window.navigator.msSaveBlob === 'function') {
24
35
  //@ts-ignore
25
36
  navigator.msSaveBlob(blob, fileName)
37
+ } else {
38
+ const downloadLink = document.createElement('a')
39
+ downloadLink.href = url
40
+ downloadLink.download = fileName
41
+ document.body.appendChild(downloadLink)
42
+ downloadLink.click()
43
+ document.body.removeChild(downloadLink)
26
44
  }
27
- publishAnalyticsEvent('data_downloaded', 'click', configUrl)
45
+ URL.revokeObjectURL(url)
46
+ publishAnalyticsEvent({
47
+ vizType: config.type,
48
+ vizSubType: getVizSubType(config),
49
+ eventType: 'data_downloaded',
50
+ eventAction: 'click',
51
+ eventLabel: interactionLabel || configUrl,
52
+ vizTitle: getVizTitle(config)
53
+ })
28
54
  }
29
55
 
30
56
  return (
31
57
  <a
32
- download={fileName}
58
+ ref={linkRef}
33
59
  type='button'
34
- onClick={saveBlob}
35
- href={URL.createObjectURL(blob)}
60
+ onClick={handleDownload}
36
61
  aria-label='Download this data in a CSV file format.'
37
62
  className={`${headerColor} no-border`}
38
63
  id={`${skipId}`}
39
64
  data-html2canvas-ignore
40
65
  role='button'
66
+ style={{ cursor: 'pointer' }}
41
67
  >
42
68
  Download Data (CSV)
43
69
  </a>
@@ -21,9 +21,9 @@ const DataTableEditor: React.FC<DataTableProps> = ({ config, updateField, isDash
21
21
  const isLoadedFromUrl = config.dataKey?.includes('http://') || config?.dataKey?.includes('https://')
22
22
  const excludedColumns = useMemo(() => {
23
23
  return Object.keys(config.columns)
24
- .map<[string, boolean]>(key => [key, config.columns[key].dataTable])
25
- .filter(([key, dataTable]) => !dataTable)
26
- .map(([key]) => key)
24
+ .map<[string, boolean]>(key => [config.columns[key].name, config.columns[key].dataTable])
25
+ .filter(([columnName, dataTable]) => !dataTable && columnName) // also filter out undefined names
26
+ .map(([columnName]) => columnName)
27
27
  }, [config.columns])
28
28
 
29
29
  const groupPivotColumns = useMemo(() => {
@@ -0,0 +1,423 @@
1
+ /* EditorPanel component styles */
2
+ /* Shared editor panel component styles used across all visualization packages */
3
+
4
+ /* Color palette in editor panel context */
5
+ .editor-panel .header .color-palette li {
6
+ width: 1.5em;
7
+ height: 1.5em;
8
+ display: inline-block;
9
+ }
10
+
11
+ .editor-panel .color-palette {
12
+ display: flex;
13
+ }
14
+
15
+ .editor-panel .color-palette li {
16
+ width: 1.5em;
17
+ height: 1.5em;
18
+ display: inline-block;
19
+ margin-right: 0.5em;
20
+ cursor: pointer;
21
+ border: rgba(0, 0, 0, 0.3) 3px solid;
22
+ }
23
+
24
+ .editor-panel .color-palette li.active {
25
+ border: rgba(0, 0, 0, 0.8) 3px solid;
26
+ }
27
+
28
+ .editor-panel .color-palette a {
29
+ display: inline-block;
30
+ border-bottom: 1px solid rgba(0, 0, 0, 0.8);
31
+ }
32
+
33
+ .editor-panel .color-palette.series-list {
34
+ flex-direction: column;
35
+ padding: 0;
36
+ border: none;
37
+ }
38
+
39
+ .editor-panel .color-palette.series-list li {
40
+ padding: 0.3em 0.5em;
41
+ display: flex;
42
+ align-items: center;
43
+ justify-content: space-between;
44
+ width: auto;
45
+ height: auto;
46
+ border: 0;
47
+ }
48
+
49
+ .editor-panel .color-palette.series-list li:not(:last-child) {
50
+ border-bottom: rgba(0, 0, 0, 0.2) 1px solid;
51
+ }
52
+
53
+ .editor-panel .form-container {
54
+ border-right: var(--lightGray) 1px solid;
55
+ flex-grow: 1;
56
+ }
57
+
58
+ .editor-panel .guidance-link {
59
+ margin: 2em 1em 0;
60
+ padding: 0.75em 1em;
61
+ }
62
+
63
+ .editor-panel .guidance-link svg {
64
+ width: 60px;
65
+ color: var(--blue);
66
+ margin-right: 1rem;
67
+ height: 60px;
68
+ }
69
+
70
+ .editor-panel .guidance-link svg path {
71
+ fill: currentColor;
72
+ }
73
+
74
+ .editor-panel .warning {
75
+ color: #d8000c;
76
+ background-color: #ffd2d2;
77
+ padding: 0.75em 1em;
78
+ margin: 1em 0;
79
+ font-size: 0.8em;
80
+ border: #d8000c 1px solid;
81
+ border-radius: 0.4em;
82
+ }
83
+
84
+ .editor-panel .warning strong {
85
+ font-weight: 600;
86
+ display: block;
87
+ }
88
+
89
+ .editor-panel .advanced {
90
+ padding: 0 1em 1em;
91
+ text-align: left;
92
+ }
93
+
94
+ .editor-panel .advanced p {
95
+ font-size: 0.8rem;
96
+ }
97
+
98
+ .editor-panel .advanced .advanced-toggle-link {
99
+ padding-top: 1em;
100
+ display: block;
101
+ text-align: left;
102
+ cursor: pointer;
103
+ text-decoration: underline;
104
+ }
105
+
106
+ .editor-panel .advanced .advanced-toggle-link span {
107
+ text-decoration: none;
108
+ display: inline-block;
109
+ font-family: monospace;
110
+ padding-right: 5px;
111
+ }
112
+
113
+ .editor-panel .advanced .advanced-toggle-link:hover {
114
+ color: rgba(0, 0, 0, 0.7);
115
+ }
116
+
117
+ .editor-panel .advanced textarea {
118
+ height: 400px;
119
+ width: 100%;
120
+ font-size: 0.9em;
121
+ padding: 0.5em;
122
+ font-family: monospace;
123
+ box-sizing: border-box;
124
+ }
125
+
126
+ .editor-panel .heading-2 {
127
+ background: #565656;
128
+ color: #fff;
129
+ font-size: 1.1em;
130
+ padding: 0.6em 1em;
131
+ position: relative;
132
+ border-bottom: #565656 3px solid;
133
+ z-index: 3;
134
+ }
135
+
136
+ .editor-panel label {
137
+ text-transform: uppercase;
138
+ display: block;
139
+ font-size: 0.8em;
140
+ font-weight: 600;
141
+ }
142
+
143
+ .editor-panel label:not(:first-child) {
144
+ margin-top: 1em;
145
+ }
146
+
147
+ .editor-panel label span.edit-label {
148
+ margin-bottom: 0.3em;
149
+ display: block;
150
+ }
151
+
152
+ .editor-panel label span.column-heading {
153
+ font-size: 1em;
154
+ }
155
+
156
+ .editor-panel label.checkbox {
157
+ display: flex;
158
+ }
159
+
160
+ .editor-panel label.checkbox span {
161
+ text-transform: none;
162
+ font-size: 1em;
163
+ font-weight: 400;
164
+ }
165
+
166
+ .editor-panel label.checkbox input {
167
+ margin-top: 0;
168
+ margin-right: 0.5em;
169
+ }
170
+
171
+ .editor-panel input[type='checkbox'],
172
+ .editor-panel input[type='radio'] {
173
+ display: inline-block;
174
+ width: auto !important;
175
+ height: auto !important;
176
+ padding: 0;
177
+ margin-right: 0.5em;
178
+ cursor: pointer;
179
+ user-select: none;
180
+ }
181
+
182
+ .editor-panel input[type='text'],
183
+ .editor-panel input[role='combobox'],
184
+ .editor-panel input[type='number'],
185
+ .editor-panel textarea {
186
+ padding: 0.5em;
187
+ width: 100%;
188
+ }
189
+
190
+ .editor-panel fieldset {
191
+ padding-left: 0;
192
+ }
193
+
194
+ .editor-panel .primary-fieldset {
195
+ border-top: rgba(0, 0, 0, 0.3) 2px solid;
196
+ padding-top: 2em;
197
+ margin-top: 2em;
198
+ }
199
+
200
+ .editor-panel ul.column-edit {
201
+ list-style: none;
202
+ }
203
+
204
+ .editor-panel ul.column-edit li {
205
+ display: flex;
206
+ flex-wrap: wrap;
207
+ justify-content: space-between;
208
+ padding: 0.3em 0;
209
+ }
210
+
211
+ .editor-panel ul.column-edit li label {
212
+ display: inline-block;
213
+ width: 48%;
214
+ }
215
+
216
+ .editor-panel ul.column-edit li label:nth-child(odd) {
217
+ margin-top: 1em;
218
+ }
219
+
220
+ .editor-panel ul.column-edit.three-col li label {
221
+ width: 31%;
222
+ }
223
+
224
+ .editor-panel .edit-block {
225
+ border: 1px solid rgba(0, 0, 0, 0.3);
226
+ padding: 1em;
227
+ margin-top: 1em;
228
+ position: relative;
229
+ }
230
+
231
+ .editor-panel .edit-block .remove-column {
232
+ position: absolute;
233
+ top: 0;
234
+ right: 0;
235
+ border: 0;
236
+ background: rgba(0, 0, 0, 0.1);
237
+ color: #000;
238
+ font-size: 0.8em;
239
+ padding: 0.3em;
240
+ cursor: pointer;
241
+ }
242
+
243
+ .editor-panel span.subtext {
244
+ text-transform: none;
245
+ display: block;
246
+ font-size: 0.8em;
247
+ font-weight: 400;
248
+ }
249
+
250
+ .editor-panel .sort-list {
251
+ list-style: none;
252
+ }
253
+
254
+ .editor-panel .sort-list li {
255
+ border: 1px solid rgba(0, 0, 0, 0.2);
256
+ padding: 0.3em;
257
+ display: flex;
258
+ align-items: center;
259
+ cursor: move;
260
+ margin-bottom: 0.3em;
261
+ }
262
+
263
+ .editor-panel .sort-list li svg {
264
+ margin-right: 0.5em;
265
+ }
266
+
267
+ .editor-panel .info {
268
+ margin-top: 1em;
269
+ font-size: 0.9em;
270
+ }
271
+
272
+ /* React Tags Component styles (third-party library) */
273
+ .editor-panel .react-tags__search {
274
+ width: 100%;
275
+ }
276
+
277
+ .editor-panel .react-tags {
278
+ position: relative;
279
+ cursor: text;
280
+ }
281
+
282
+ .editor-panel .react-tags input.react-tags__search-input {
283
+ font-size: 0.8rem;
284
+ }
285
+
286
+ .editor-panel .react-tags span {
287
+ display: inline;
288
+ }
289
+
290
+ .editor-panel .react-tags.is-focused {
291
+ border-color: rgba(0, 0, 0, 0.7);
292
+ }
293
+
294
+ .editor-panel .react-tags__selected {
295
+ display: inline;
296
+ }
297
+
298
+ .editor-panel .react-tags__selected-tag {
299
+ display: inline-block;
300
+ box-sizing: border-box;
301
+ border: 1px solid #d1d1d1;
302
+ border-radius: 2px;
303
+ background: #f1f1f1;
304
+ padding: 0.4em 0.6em;
305
+ font-size: 0.8em;
306
+ margin-right: 0.3em;
307
+ margin-bottom: 0.3em;
308
+ }
309
+
310
+ .editor-panel .react-tags__selected-tag:after {
311
+ content: '\2715';
312
+ color: #aaa;
313
+ margin-left: 8px;
314
+ }
315
+
316
+ .editor-panel .react-tags__selected-tag:hover,
317
+ .editor-panel .react-tags__selected-tag:focus {
318
+ border-color: #b1b1b1;
319
+ }
320
+
321
+ .editor-panel .react-tags__search {
322
+ display: inline-block;
323
+ max-width: 100%;
324
+ }
325
+
326
+ @media screen and (min-width: 30em) {
327
+ .editor-panel .react-tags__search {
328
+ position: relative;
329
+ }
330
+ }
331
+
332
+ .editor-panel .react-tags__search input {
333
+ max-width: 100%;
334
+ margin: 0;
335
+ outline: none;
336
+ padding: 0.5em 0.3em;
337
+ font-size: inherit;
338
+ line-height: inherit;
339
+ }
340
+
341
+ .editor-panel .react-tags__search input::-ms-clear {
342
+ display: none;
343
+ }
344
+
345
+ .editor-panel .react-tags__suggestions {
346
+ position: absolute;
347
+ top: 100%;
348
+ left: 0;
349
+ width: 100%;
350
+ }
351
+
352
+ @media screen and (min-width: 30em) {
353
+ .editor-panel .react-tags__suggestions {
354
+ width: 240px;
355
+ }
356
+ }
357
+
358
+ .editor-panel .react-tags__suggestions ul {
359
+ margin: 4px -1px;
360
+ padding: 0;
361
+ list-style: none;
362
+ background: white;
363
+ border: 1px solid #d1d1d1;
364
+ border-radius: 2px;
365
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
366
+ }
367
+
368
+ .editor-panel .react-tags__suggestions li {
369
+ border-bottom: 1px solid #ddd;
370
+ padding: 6px 8px;
371
+ }
372
+
373
+ .editor-panel .react-tags__suggestions li mark {
374
+ text-decoration: underline;
375
+ background: none;
376
+ font-weight: 600;
377
+ }
378
+
379
+ .editor-panel .react-tags__suggestions li:hover {
380
+ cursor: pointer;
381
+ background: #eee;
382
+ }
383
+
384
+ .editor-panel .react-tags__suggestions li.is-active {
385
+ background: #b7cfe0;
386
+ }
387
+
388
+ .editor-panel .react-tags__suggestions li.is-disabled {
389
+ opacity: 0.5;
390
+ cursor: auto;
391
+ }
392
+
393
+ .editor-toggle {
394
+ position: fixed;
395
+ top: 1em;
396
+ right: 1em;
397
+ background: var(--blue);
398
+ color: white;
399
+ border: 0;
400
+ border-radius: 0.5em;
401
+ padding: 0.5em 1em;
402
+ font-size: 1em;
403
+ cursor: pointer;
404
+ z-index: 9999999999;
405
+ display: none;
406
+ }
407
+
408
+ .editor-toggle.active {
409
+ display: block;
410
+ }
411
+
412
+ .editor-toggle:hover {
413
+ background: var(--darkBlue);
414
+ }
415
+
416
+ .editor-toggle svg {
417
+ height: 1em;
418
+ width: 1em;
419
+ }
420
+
421
+ .editor-toggle svg path {
422
+ fill: currentColor;
423
+ }