@cdc/chart 4.26.4 → 4.26.5
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.
- package/CONFIG.md +349 -29
- package/LICENSE +201 -0
- package/dist/cdcchart.js +34247 -32805
- package/examples/feature/heatmap/average-age-categorical.json +313 -0
- package/examples/feature/heatmap/calendar-heatmap.json +134 -0
- package/examples/feature/heatmap/cell-values-bottom-axis.json +181 -0
- package/examples/feature/heatmap/sparse-aggregation.json +158 -0
- package/examples/private/bump-chart.json +1116 -0
- package/examples/private/test-123.json +624 -0
- package/package.json +4 -3
- package/src/CdcChartComponent.tsx +135 -54
- package/src/_stories/Chart.AltText.stories.tsx +136 -0
- package/src/_stories/Chart.HeatMap.stories.tsx +187 -0
- package/src/_stories/Chart.Sankey.smoke.stories.tsx +62 -0
- package/src/_stories/Chart.SmallMultiples.smoke.stories.tsx +29 -0
- package/src/_stories/ChartAxisTitles.smoke.stories.tsx +13 -0
- package/src/_stories/ChartBar.Editor.stories.tsx +63 -0
- package/src/_stories/ChartBrush.Interaction.stories.tsx +112 -0
- package/src/_stories/ChartBrush.smoke.stories.tsx +13 -4
- package/src/_stories/_mock/alt_text_metadata.json +38 -0
- package/src/_stories/_mock/heatmap-average-age-categorical.json +315 -0
- package/src/_stories/_mock/heatmap.json +156 -0
- package/src/_stories/_mock/reported_pertussis_cases.json +1643 -0
- package/src/_stories/_mock/sankey_mock.json +78 -0
- package/src/_stories/_mock/small_multiples/small_multiples_lines.json +1 -1
- package/src/components/Annotations/components/AnnotationDraggable.tsx +1 -1
- package/src/components/Annotations/components/AnnotationDropdown.tsx +5 -2
- package/src/components/Axis/LeftAxis.tsx +14 -11
- package/src/components/Axis/LeftAxisGridlines.tsx +14 -11
- package/src/components/Brush/BrushSelector.tsx +88 -187
- package/src/components/Brush/brushInteraction.ts +22 -0
- package/src/components/Brush/tests/brushInteraction.test.ts +38 -0
- package/src/components/EditorPanel/EditorPanel.tsx +310 -49
- package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +13 -0
- package/src/components/EditorPanel/components/Panels/Panel.General.tsx +105 -13
- package/src/components/EditorPanel/components/Panels/Panel.PatternSettings.tsx +1 -0
- package/src/components/EditorPanel/components/Panels/Panel.Regions.tsx +5 -0
- package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +2 -2
- package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +1 -1
- package/src/components/EditorPanel/helpers/getVisualizationTypeConfigUpdate.ts +57 -0
- package/src/components/EditorPanel/helpers/tests/getVisualizationTypeConfigUpdate.test.ts +56 -0
- package/src/components/EditorPanel/useEditorPermissions.test.tsx +70 -0
- package/src/components/EditorPanel/useEditorPermissions.ts +42 -22
- package/src/components/HeatMap/components/HeatMap.tsx +762 -0
- package/src/components/HeatMap/components/HeatMapGradientLegend.tsx +114 -0
- package/src/components/HeatMap/heatmap.constants.ts +13 -0
- package/src/components/HeatMap/heatmap.css +71 -0
- package/src/components/HeatMap/helpers/index.ts +261 -0
- package/src/components/HeatMap/index.tsx +5 -0
- package/src/components/HeatMap/tests/HeatMap.test.tsx +1040 -0
- package/src/components/HeatMap/tests/helpers.test.ts +167 -0
- package/src/components/LineChart/components/LineChart.BumpCircle.tsx +19 -22
- package/src/components/LineChart/helpers.test.ts +345 -0
- package/src/components/LineChart/helpers.ts +15 -5
- package/src/components/LineChart/index.tsx +7 -1
- package/src/components/LinearChart/tests/LinearChart.test.tsx +107 -33
- package/src/components/LinearChart/tests/mockConfigContext.ts +1 -0
- package/src/components/LinearChart.tsx +58 -37
- package/src/components/PieChart/PieChart.tsx +4 -1
- package/src/components/RadarChart/RadarChart.tsx +3 -1
- package/src/components/Regions/components/Regions.tsx +195 -41
- package/src/components/Sankey/components/Sankey.tsx +7 -3
- package/src/components/Sankey/helpers/getSankeyTooltip.tsx +7 -6
- package/src/components/SmallMultiples/SmallMultipleTile.tsx +30 -3
- package/src/components/SmallMultiples/SmallMultiples.css +12 -0
- package/src/components/SmallMultiples/SmallMultiples.tsx +15 -9
- package/src/components/SmallMultiples/tests/SmallMultipleTile.test.tsx +152 -0
- package/src/components/Sparkline/components/SparkLine.tsx +4 -9
- package/src/components/WarmingStripes/WarmingStripesGradientLegend.css +1 -1
- package/src/components/WarmingStripes/WarmingStripesGradientLegend.tsx +2 -2
- package/src/data/initial-state.js +11 -0
- package/src/helpers/axisLabelFontSize.ts +8 -0
- package/src/helpers/bumpChartTooltip.ts +54 -0
- package/src/helpers/calculateLeftYAxisWidth.ts +4 -0
- package/src/helpers/ensureSpecialChartAxisTypes.ts +11 -0
- package/src/helpers/getMinMax.ts +2 -3
- package/src/helpers/getYAxisAutoPadding.ts +8 -6
- package/src/helpers/getYAxisAutoPaddingMode.ts +17 -0
- package/src/helpers/handleChartAriaLabels.ts +23 -10
- package/src/helpers/seriesHighlight.ts +26 -0
- package/src/helpers/tests/axisLabelFontSize.test.ts +15 -0
- package/src/helpers/tests/bumpChartTooltip.test.ts +75 -0
- package/src/helpers/tests/ensureSpecialChartAxisTypes.test.ts +30 -0
- package/src/helpers/tests/getYAxisAutoPadding.test.ts +37 -0
- package/src/helpers/tests/getYAxisAutoPaddingMode.test.ts +90 -0
- package/src/helpers/tests/handleChartAriaLabels.test.ts +71 -0
- package/src/helpers/tests/seriesHighlight.test.ts +61 -0
- package/src/hooks/tests/useScales.test.tsx +105 -0
- package/src/hooks/useScales.ts +19 -9
- package/src/index.jsx +5 -2
- package/src/scss/main.scss +32 -49
- package/src/types/ChartConfig.ts +18 -0
- package/src/types/ChartContext.ts +2 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import { classifyBrushInteraction } from '../brushInteraction'
|
|
3
|
+
|
|
4
|
+
describe('classifyBrushInteraction', () => {
|
|
5
|
+
const extent = { x0: 100, x1: 300 }
|
|
6
|
+
const handleHitWidth = 24
|
|
7
|
+
|
|
8
|
+
it('allows interactions inside the selection', () => {
|
|
9
|
+
expect(classifyBrushInteraction(200, extent, handleHitWidth)).toBe('selection')
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
it('allows interactions within the left handle hit area', () => {
|
|
13
|
+
expect(classifyBrushInteraction(82, extent, handleHitWidth)).toBe('left-handle')
|
|
14
|
+
expect(classifyBrushInteraction(124, extent, handleHitWidth)).toBe('left-handle')
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
it('allows interactions within the right handle hit area', () => {
|
|
18
|
+
expect(classifyBrushInteraction(276, extent, handleHitWidth)).toBe('right-handle')
|
|
19
|
+
expect(classifyBrushInteraction(318, extent, handleHitWidth)).toBe('right-handle')
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
it('blocks interactions outside the selection and handle hit areas', () => {
|
|
23
|
+
expect(classifyBrushInteraction(50, extent, handleHitWidth)).toBe('outside')
|
|
24
|
+
expect(classifyBrushInteraction(350, extent, handleHitWidth)).toBe('outside')
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
it('handles reversed extents', () => {
|
|
28
|
+
expect(classifyBrushInteraction(200, { x0: 300, x1: 100 }, handleHitWidth)).toBe('selection')
|
|
29
|
+
expect(classifyBrushInteraction(82, { x0: 300, x1: 100 }, handleHitWidth)).toBe('left-handle')
|
|
30
|
+
expect(classifyBrushInteraction(318, { x0: 300, x1: 100 }, handleHitWidth)).toBe('right-handle')
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
it('blocks interactions for uninitialized or invalid extents', () => {
|
|
34
|
+
expect(classifyBrushInteraction(100, null, handleHitWidth)).toBe('outside')
|
|
35
|
+
expect(classifyBrushInteraction(100, { x0: -1, x1: -1 }, handleHitWidth)).toBe('outside')
|
|
36
|
+
expect(classifyBrushInteraction(100, { x0: Number.NaN, x1: 200 }, handleHitWidth)).toBe('outside')
|
|
37
|
+
})
|
|
38
|
+
})
|
|
@@ -61,6 +61,11 @@ import { paletteMigrationMap, twoColorPaletteMigrationMap } from '@cdc/core/help
|
|
|
61
61
|
import { isV1Palette, migratePaletteWithMap } from '@cdc/core/helpers/palettes/utils'
|
|
62
62
|
import { USE_V2_MIGRATION } from '@cdc/core/helpers/constants'
|
|
63
63
|
import { getSeriesOwnedColumnNames } from '../../helpers/seriesColumnSettings'
|
|
64
|
+
import {
|
|
65
|
+
HEATMAP_CONFIG_DEFAULTS,
|
|
66
|
+
MAX_HEATMAP_COLOR_BUCKETS,
|
|
67
|
+
MIN_HEATMAP_COLOR_BUCKETS
|
|
68
|
+
} from '../HeatMap/heatmap.constants'
|
|
64
69
|
|
|
65
70
|
interface PreliminaryProps {
|
|
66
71
|
config: ChartConfig
|
|
@@ -1189,12 +1194,23 @@ const EditorPanel: React.FC<ChartEditorPanelProps> = ({ datasets }) => {
|
|
|
1189
1194
|
return filter ? filteredColumns : allColumns
|
|
1190
1195
|
}
|
|
1191
1196
|
|
|
1197
|
+
const isHeatMap = config.visualizationType === 'HeatMap'
|
|
1198
|
+
const heatMapOwnedColumnNames = useMemo(
|
|
1199
|
+
() => [config.xAxis?.dataKey, ...(config.series || []).map(series => series.dataKey)].filter(Boolean),
|
|
1200
|
+
[config.xAxis?.dataKey, config.series]
|
|
1201
|
+
)
|
|
1202
|
+
|
|
1192
1203
|
const getLegendStyleOptions = (option: 'style' | 'subStyle' | 'shapes' | 'groupBy'): string[] => {
|
|
1193
1204
|
const options: string[] = []
|
|
1194
1205
|
|
|
1195
1206
|
switch (option) {
|
|
1196
1207
|
case 'style':
|
|
1197
1208
|
options.push('circles', 'boxes')
|
|
1209
|
+
if (config.visualizationType === 'HeatMap') {
|
|
1210
|
+
if (!['right', 'left'].includes(config.legend.position) && config.legend.position) {
|
|
1211
|
+
options.push('gradient')
|
|
1212
|
+
}
|
|
1213
|
+
}
|
|
1198
1214
|
if (
|
|
1199
1215
|
config.visualizationType === 'Bar' &&
|
|
1200
1216
|
(!['right', 'left'].includes(config.legend.position) || !config.legend.position)
|
|
@@ -1338,6 +1354,15 @@ const EditorPanel: React.FC<ChartEditorPanelProps> = ({ datasets }) => {
|
|
|
1338
1354
|
if (config.isLollipopChart && config?.series?.length === 0) {
|
|
1339
1355
|
config.runtime.editorErrorMessage = 'Add a data series'
|
|
1340
1356
|
}
|
|
1357
|
+
if (config.visualizationType === 'HeatMap') {
|
|
1358
|
+
const missingMappings = [
|
|
1359
|
+
!config.xAxis?.dataKey && 'Date/Category Axis',
|
|
1360
|
+
(!config.series || config.series.length === 0) && 'Data Series'
|
|
1361
|
+
].filter(Boolean)
|
|
1362
|
+
|
|
1363
|
+
config.runtime.editorErrorMessage =
|
|
1364
|
+
missingMappings.length > 0 ? `${missingMappings.join(', ')} must be set for heatmaps.` : ''
|
|
1365
|
+
}
|
|
1341
1366
|
|
|
1342
1367
|
const section = config.orientation === 'horizontal' ? 'xAxis' : 'yAxis'
|
|
1343
1368
|
const [warningMsg, setWarningMsg] = useState({ maxMsg: '', minMsg: '', rightMaxMessage: '', minMsgRight: '' })
|
|
@@ -1737,6 +1762,7 @@ const EditorPanel: React.FC<ChartEditorPanelProps> = ({ datasets }) => {
|
|
|
1737
1762
|
'Bump Chart',
|
|
1738
1763
|
'Area Chart',
|
|
1739
1764
|
'Combo',
|
|
1765
|
+
'HeatMap',
|
|
1740
1766
|
'Line',
|
|
1741
1767
|
'Bar',
|
|
1742
1768
|
'Forecasting',
|
|
@@ -1920,6 +1946,76 @@ const EditorPanel: React.FC<ChartEditorPanelProps> = ({ datasets }) => {
|
|
|
1920
1946
|
return strippedState
|
|
1921
1947
|
}
|
|
1922
1948
|
|
|
1949
|
+
const renderHeatMapSettingsAccordion = () => {
|
|
1950
|
+
if (config.visualizationType !== 'HeatMap') return null
|
|
1951
|
+
|
|
1952
|
+
return (
|
|
1953
|
+
<AccordionItem>
|
|
1954
|
+
<AccordionItemHeading>
|
|
1955
|
+
<AccordionItemButton>HeatMap Settings</AccordionItemButton>
|
|
1956
|
+
</AccordionItemHeading>
|
|
1957
|
+
<AccordionItemPanel>
|
|
1958
|
+
<p className='helper-text'>Selected data series columns provide the heatmap cell values.</p>
|
|
1959
|
+
<CheckBox
|
|
1960
|
+
value={Boolean(config.heatmap?.showCellValues ?? HEATMAP_CONFIG_DEFAULTS.showCellValues)}
|
|
1961
|
+
section='heatmap'
|
|
1962
|
+
fieldName='showCellValues'
|
|
1963
|
+
label='Show Cell Values'
|
|
1964
|
+
updateField={updateFieldDeprecated}
|
|
1965
|
+
/>
|
|
1966
|
+
<TextField
|
|
1967
|
+
value={config.heatmap?.cellPadding ?? HEATMAP_CONFIG_DEFAULTS.cellPadding}
|
|
1968
|
+
type='number'
|
|
1969
|
+
min={0}
|
|
1970
|
+
section='heatmap'
|
|
1971
|
+
fieldName='cellPadding'
|
|
1972
|
+
label='Cell Padding'
|
|
1973
|
+
updateField={updateFieldDeprecated}
|
|
1974
|
+
/>
|
|
1975
|
+
<TextField
|
|
1976
|
+
value={config.heatmap?.rowLabelGap ?? HEATMAP_CONFIG_DEFAULTS.rowLabelGap}
|
|
1977
|
+
type='number'
|
|
1978
|
+
min={0}
|
|
1979
|
+
section='heatmap'
|
|
1980
|
+
fieldName='rowLabelGap'
|
|
1981
|
+
label='Row Label Gap'
|
|
1982
|
+
updateField={updateFieldDeprecated}
|
|
1983
|
+
/>
|
|
1984
|
+
<TextField
|
|
1985
|
+
value={config.heatmap?.columnLabelGap ?? HEATMAP_CONFIG_DEFAULTS.columnLabelGap}
|
|
1986
|
+
type='number'
|
|
1987
|
+
min={0}
|
|
1988
|
+
section='heatmap'
|
|
1989
|
+
fieldName='columnLabelGap'
|
|
1990
|
+
label='Column Label Gap'
|
|
1991
|
+
updateField={updateFieldDeprecated}
|
|
1992
|
+
/>
|
|
1993
|
+
<TextField
|
|
1994
|
+
value={config.heatmap?.colorBucketCount ?? HEATMAP_CONFIG_DEFAULTS.colorBucketCount}
|
|
1995
|
+
type='number'
|
|
1996
|
+
min={MIN_HEATMAP_COLOR_BUCKETS}
|
|
1997
|
+
max={MAX_HEATMAP_COLOR_BUCKETS}
|
|
1998
|
+
step={1}
|
|
1999
|
+
section='heatmap'
|
|
2000
|
+
fieldName='colorBucketCount'
|
|
2001
|
+
label='Data Grouping'
|
|
2002
|
+
updateField={updateFieldDeprecated}
|
|
2003
|
+
tooltip={
|
|
2004
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
2005
|
+
<Tooltip.Target>
|
|
2006
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
2007
|
+
</Tooltip.Target>
|
|
2008
|
+
<Tooltip.Content>
|
|
2009
|
+
Choose the number of value groups used to color the heatmap. Values are limited to 1-9.
|
|
2010
|
+
</Tooltip.Content>
|
|
2011
|
+
</Tooltip>
|
|
2012
|
+
}
|
|
2013
|
+
/>
|
|
2014
|
+
</AccordionItemPanel>
|
|
2015
|
+
</AccordionItem>
|
|
2016
|
+
)
|
|
2017
|
+
}
|
|
2018
|
+
|
|
1923
2019
|
return (
|
|
1924
2020
|
<EditorPanelContext.Provider value={editorContextValues}>
|
|
1925
2021
|
<BaseEditorPanel
|
|
@@ -1950,7 +2046,10 @@ const EditorPanel: React.FC<ChartEditorPanelProps> = ({ datasets }) => {
|
|
|
1950
2046
|
{(!config.series ||
|
|
1951
2047
|
config.series.length === 0 ||
|
|
1952
2048
|
(config.visualizationType === 'Paired Bar' && config.series.length < 2)) &&
|
|
1953
|
-
!config.dynamicSeries &&
|
|
2049
|
+
!config.dynamicSeries &&
|
|
2050
|
+
config.visualizationType !== 'HeatMap' && (
|
|
2051
|
+
<WarningImage width='25' className='warning-icon' />
|
|
2052
|
+
)}
|
|
1954
2053
|
</AccordionItemButton>
|
|
1955
2054
|
</AccordionItemHeading>
|
|
1956
2055
|
<AccordionItemPanel>
|
|
@@ -1987,9 +2086,21 @@ const EditorPanel: React.FC<ChartEditorPanelProps> = ({ datasets }) => {
|
|
|
1987
2086
|
)}
|
|
1988
2087
|
{(!visSupportsDynamicSeries() || !config.dynamicSeries) && (
|
|
1989
2088
|
<>
|
|
2089
|
+
{config.visualizationType === 'HeatMap' && (
|
|
2090
|
+
<p className='helper-text'>
|
|
2091
|
+
Add one or more data series to create heatmap rows. Each selected series becomes a row
|
|
2092
|
+
in the heatmap, while the Date/Category Axis provides the columns.
|
|
2093
|
+
</p>
|
|
2094
|
+
)}
|
|
1990
2095
|
{(!config.series || config.series.length === 0) &&
|
|
1991
2096
|
!config.dynamicSeries &&
|
|
1992
|
-
config.visualizationType !== 'Paired Bar' &&
|
|
2097
|
+
config.visualizationType !== 'Paired Bar' &&
|
|
2098
|
+
config.visualizationType !== 'HeatMap' && (
|
|
2099
|
+
<p className='warning'>At least one series is required</p>
|
|
2100
|
+
)}
|
|
2101
|
+
{(!config.series || config.series.length === 0) &&
|
|
2102
|
+
!config.dynamicSeries &&
|
|
2103
|
+
config.visualizationType === 'HeatMap' && (
|
|
1993
2104
|
<p className='warning'>At least one series is required</p>
|
|
1994
2105
|
)}
|
|
1995
2106
|
{(!config.series || config.series.length === 0 || config.series.length < 2) &&
|
|
@@ -2010,7 +2121,7 @@ const EditorPanel: React.FC<ChartEditorPanelProps> = ({ datasets }) => {
|
|
|
2010
2121
|
}
|
|
2011
2122
|
e.target.value = ''
|
|
2012
2123
|
}}
|
|
2013
|
-
options={getColumns()}
|
|
2124
|
+
options={getColumns().filter(column => column !== config.xAxis?.dataKey)}
|
|
2014
2125
|
/>
|
|
2015
2126
|
{config.series && config.series.length !== 0 && (
|
|
2016
2127
|
<Panels.Series.Wrapper
|
|
@@ -2022,16 +2133,23 @@ const EditorPanel: React.FC<ChartEditorPanelProps> = ({ datasets }) => {
|
|
|
2022
2133
|
droppableId='chart-series-order'
|
|
2023
2134
|
label={
|
|
2024
2135
|
<>
|
|
2025
|
-
Displaying
|
|
2136
|
+
{config.visualizationType === 'HeatMap' ? 'Displaying Rows' : 'Displaying'}
|
|
2026
2137
|
<Tooltip style={{ textTransform: 'none' }}>
|
|
2027
2138
|
<Tooltip.Target>
|
|
2028
2139
|
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
2029
2140
|
</Tooltip.Target>
|
|
2030
2141
|
<Tooltip.Content>
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2142
|
+
{config.visualizationType === 'HeatMap' ? (
|
|
2143
|
+
<p>
|
|
2144
|
+
Each selected data series becomes a row in the heatmap. Reorder these
|
|
2145
|
+
entries to change the row order shown in the visualization.
|
|
2146
|
+
</p>
|
|
2147
|
+
) : (
|
|
2148
|
+
<p>
|
|
2149
|
+
A data series is a set of related data points plotted in a chart and
|
|
2150
|
+
typically represented in the chart legend.
|
|
2151
|
+
</p>
|
|
2152
|
+
)}
|
|
2035
2153
|
</Tooltip.Content>
|
|
2036
2154
|
</Tooltip>
|
|
2037
2155
|
</>
|
|
@@ -2108,9 +2226,9 @@ const EditorPanel: React.FC<ChartEditorPanelProps> = ({ datasets }) => {
|
|
|
2108
2226
|
: config.orientation === 'vertical'
|
|
2109
2227
|
? 'Left Value Axis'
|
|
2110
2228
|
: 'Value Axis'}
|
|
2111
|
-
{config.visualizationType === 'Pie' && !config.yAxis.dataKey
|
|
2229
|
+
{config.visualizationType === 'Pie' && !config.yAxis.dataKey ? (
|
|
2112
2230
|
<WarningImage width='25' className='warning-icon' />
|
|
2113
|
-
)}
|
|
2231
|
+
) : null}
|
|
2114
2232
|
</AccordionItemButton>
|
|
2115
2233
|
</AccordionItemHeading>
|
|
2116
2234
|
<AccordionItemPanel>
|
|
@@ -2158,7 +2276,86 @@ const EditorPanel: React.FC<ChartEditorPanelProps> = ({ datasets }) => {
|
|
|
2158
2276
|
/>
|
|
2159
2277
|
</>
|
|
2160
2278
|
)}
|
|
2161
|
-
{config.visualizationType
|
|
2279
|
+
{config.visualizationType === 'HeatMap' && (
|
|
2280
|
+
<>
|
|
2281
|
+
<TextField
|
|
2282
|
+
value={config.yAxis.label}
|
|
2283
|
+
section='yAxis'
|
|
2284
|
+
fieldName='label'
|
|
2285
|
+
label='Label'
|
|
2286
|
+
updateField={updateFieldDeprecated}
|
|
2287
|
+
maxLength={35}
|
|
2288
|
+
tooltip={
|
|
2289
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
2290
|
+
<Tooltip.Target>
|
|
2291
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
2292
|
+
</Tooltip.Target>
|
|
2293
|
+
<Tooltip.Content>
|
|
2294
|
+
<p>35 character limit</p>
|
|
2295
|
+
</Tooltip.Content>
|
|
2296
|
+
</Tooltip>
|
|
2297
|
+
}
|
|
2298
|
+
/>
|
|
2299
|
+
<Select
|
|
2300
|
+
value={config.yAxis.titlePlacement || 'side'}
|
|
2301
|
+
section='yAxis'
|
|
2302
|
+
fieldName='titlePlacement'
|
|
2303
|
+
label='Label Placement'
|
|
2304
|
+
updateField={updateFieldDeprecated}
|
|
2305
|
+
options={[
|
|
2306
|
+
{ value: 'side', label: 'Side' },
|
|
2307
|
+
{ value: 'top', label: 'Top' }
|
|
2308
|
+
]}
|
|
2309
|
+
/>
|
|
2310
|
+
<TextField
|
|
2311
|
+
value={config.yAxis.size}
|
|
2312
|
+
type='number'
|
|
2313
|
+
section='yAxis'
|
|
2314
|
+
fieldName='size'
|
|
2315
|
+
label='Size (Width)'
|
|
2316
|
+
className='number-narrow'
|
|
2317
|
+
updateField={updateFieldDeprecated}
|
|
2318
|
+
tooltip={
|
|
2319
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
2320
|
+
<Tooltip.Target>
|
|
2321
|
+
<Icon
|
|
2322
|
+
display='question'
|
|
2323
|
+
style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }}
|
|
2324
|
+
/>
|
|
2325
|
+
</Tooltip.Target>
|
|
2326
|
+
<Tooltip.Content>
|
|
2327
|
+
<p>Increase the size if month labels are crowded or overlap the chart area.</p>
|
|
2328
|
+
</Tooltip.Content>
|
|
2329
|
+
</Tooltip>
|
|
2330
|
+
}
|
|
2331
|
+
/>
|
|
2332
|
+
<CheckBox
|
|
2333
|
+
value={config.yAxis.hideAxis}
|
|
2334
|
+
section='yAxis'
|
|
2335
|
+
fieldName='hideAxis'
|
|
2336
|
+
label='Hide Axis'
|
|
2337
|
+
updateField={updateFieldDeprecated}
|
|
2338
|
+
/>
|
|
2339
|
+
<CheckBox
|
|
2340
|
+
value={config.yAxis.hideTicks}
|
|
2341
|
+
section='yAxis'
|
|
2342
|
+
fieldName='hideTicks'
|
|
2343
|
+
label='Hide Ticks'
|
|
2344
|
+
updateField={updateFieldDeprecated}
|
|
2345
|
+
/>
|
|
2346
|
+
<TextField
|
|
2347
|
+
value={config.yAxis.tickRotation || 0}
|
|
2348
|
+
type='number'
|
|
2349
|
+
min={0}
|
|
2350
|
+
section='yAxis'
|
|
2351
|
+
fieldName='tickRotation'
|
|
2352
|
+
label='Tick rotation (Degrees)'
|
|
2353
|
+
className='number-narrow'
|
|
2354
|
+
updateField={updateFieldDeprecated}
|
|
2355
|
+
/>
|
|
2356
|
+
</>
|
|
2357
|
+
)}
|
|
2358
|
+
{config.visualizationType !== 'Pie' && config.visualizationType !== 'HeatMap' && (
|
|
2162
2359
|
<>
|
|
2163
2360
|
<Select
|
|
2164
2361
|
label='Axis Type'
|
|
@@ -2209,18 +2406,30 @@ const EditorPanel: React.FC<ChartEditorPanelProps> = ({ datasets }) => {
|
|
|
2209
2406
|
fieldName='label'
|
|
2210
2407
|
label='Label'
|
|
2211
2408
|
updateField={updateFieldDeprecated}
|
|
2212
|
-
maxLength={35}
|
|
2409
|
+
maxLength={config.yAxis.titlePlacement === 'side' ? 35 : undefined}
|
|
2213
2410
|
tooltip={
|
|
2214
2411
|
<Tooltip style={{ textTransform: 'none' }}>
|
|
2215
2412
|
<Tooltip.Target>
|
|
2216
2413
|
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
2217
2414
|
</Tooltip.Target>
|
|
2218
2415
|
<Tooltip.Content>
|
|
2219
|
-
<p>35 character limit</p>
|
|
2416
|
+
<p>35 character limit when Label Placement is Side</p>
|
|
2220
2417
|
</Tooltip.Content>
|
|
2221
2418
|
</Tooltip>
|
|
2222
2419
|
}
|
|
2223
2420
|
/>
|
|
2421
|
+
<Select
|
|
2422
|
+
display={!visHasCategoricalAxis()}
|
|
2423
|
+
value={config.yAxis.titlePlacement}
|
|
2424
|
+
section='yAxis'
|
|
2425
|
+
fieldName='titlePlacement'
|
|
2426
|
+
label='Label Placement'
|
|
2427
|
+
updateField={updateField}
|
|
2428
|
+
options={[
|
|
2429
|
+
{ value: 'side', label: 'Side' },
|
|
2430
|
+
{ value: 'top', label: 'Top' }
|
|
2431
|
+
]}
|
|
2432
|
+
/>
|
|
2224
2433
|
<TextField
|
|
2225
2434
|
display={!visHasCategoricalAxis()}
|
|
2226
2435
|
value={config.yAxis.inlineLabel}
|
|
@@ -2604,7 +2813,8 @@ const EditorPanel: React.FC<ChartEditorPanelProps> = ({ datasets }) => {
|
|
|
2604
2813
|
)}
|
|
2605
2814
|
</>
|
|
2606
2815
|
) : (
|
|
2607
|
-
config.visualizationType !== 'Pie' &&
|
|
2816
|
+
config.visualizationType !== 'Pie' &&
|
|
2817
|
+
config.visualizationType !== 'HeatMap' && (
|
|
2608
2818
|
<>
|
|
2609
2819
|
<CheckBox
|
|
2610
2820
|
display={!visHasCategoricalAxis()}
|
|
@@ -3060,6 +3270,16 @@ const EditorPanel: React.FC<ChartEditorPanelProps> = ({ datasets }) => {
|
|
|
3060
3270
|
</Tooltip>
|
|
3061
3271
|
}
|
|
3062
3272
|
/>
|
|
3273
|
+
{config.visualizationType === 'HeatMap' && (
|
|
3274
|
+
<Select
|
|
3275
|
+
value={config.heatmap?.xAxisPosition ?? HEATMAP_CONFIG_DEFAULTS.xAxisPosition}
|
|
3276
|
+
section='heatmap'
|
|
3277
|
+
fieldName='xAxisPosition'
|
|
3278
|
+
label='X-Axis Position'
|
|
3279
|
+
updateField={updateFieldDeprecated}
|
|
3280
|
+
options={['top', 'bottom']}
|
|
3281
|
+
/>
|
|
3282
|
+
)}
|
|
3063
3283
|
|
|
3064
3284
|
{config.xAxis.type === 'continuous' && (
|
|
3065
3285
|
<>
|
|
@@ -3319,38 +3539,71 @@ const EditorPanel: React.FC<ChartEditorPanelProps> = ({ datasets }) => {
|
|
|
3319
3539
|
}
|
|
3320
3540
|
/>
|
|
3321
3541
|
{config.xAxis.brushActive && (
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3542
|
+
<>
|
|
3543
|
+
<CheckBox
|
|
3544
|
+
value={!!config.xAxis.brushDynamicYAxis}
|
|
3545
|
+
section='xAxis'
|
|
3546
|
+
fieldName='brushDynamicYAxis'
|
|
3547
|
+
label='Dynamic Y-Axis'
|
|
3548
|
+
className='ms-4'
|
|
3549
|
+
updateField={updateFieldDeprecated}
|
|
3550
|
+
tooltip={
|
|
3551
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
3552
|
+
<Tooltip.Target>
|
|
3553
|
+
<Icon
|
|
3554
|
+
display='question'
|
|
3555
|
+
style={{
|
|
3556
|
+
marginLeft: '0.5rem',
|
|
3557
|
+
display: 'inline-block',
|
|
3558
|
+
whiteSpace: 'nowrap'
|
|
3559
|
+
}}
|
|
3560
|
+
/>
|
|
3561
|
+
</Tooltip.Target>
|
|
3562
|
+
<Tooltip.Content>
|
|
3563
|
+
<p>
|
|
3564
|
+
When enabled, the Y-axis rescales to fit only the data visible in the
|
|
3565
|
+
current brush selection. When disabled, the Y-axis shows the full data
|
|
3566
|
+
range.
|
|
3567
|
+
</p>
|
|
3568
|
+
</Tooltip.Content>
|
|
3569
|
+
</Tooltip>
|
|
3570
|
+
}
|
|
3571
|
+
/>
|
|
3572
|
+
<div className='ms-4 mt-2'>
|
|
3573
|
+
<TextField
|
|
3574
|
+
value={config.xAxis.brushDefaultRecentDateCount ?? ''}
|
|
3575
|
+
placeholder='Default (35%)'
|
|
3576
|
+
type='number'
|
|
3577
|
+
min={1}
|
|
3578
|
+
section='xAxis'
|
|
3579
|
+
fieldName='brushDefaultRecentDateCount'
|
|
3580
|
+
label='Show Last X Dates by Default'
|
|
3581
|
+
className='number-narrow'
|
|
3582
|
+
updateField={updateFieldDeprecated}
|
|
3583
|
+
tooltip={
|
|
3584
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
3585
|
+
<Tooltip.Target>
|
|
3586
|
+
<Icon
|
|
3587
|
+
display='question'
|
|
3588
|
+
style={{
|
|
3589
|
+
marginLeft: '0.5rem',
|
|
3590
|
+
display: 'inline-block',
|
|
3591
|
+
whiteSpace: 'nowrap'
|
|
3592
|
+
}}
|
|
3593
|
+
/>
|
|
3594
|
+
</Tooltip.Target>
|
|
3595
|
+
<Tooltip.Content>
|
|
3596
|
+
<p>
|
|
3597
|
+
When set, the brush slider will initially select this many recent data
|
|
3598
|
+
points instead of the default 35%. Leave empty to use the default
|
|
3599
|
+
percentage-based selection.
|
|
3600
|
+
</p>
|
|
3601
|
+
</Tooltip.Content>
|
|
3602
|
+
</Tooltip>
|
|
3603
|
+
}
|
|
3604
|
+
/>
|
|
3605
|
+
</div>
|
|
3606
|
+
</>
|
|
3354
3607
|
)}
|
|
3355
3608
|
</>
|
|
3356
3609
|
)}
|
|
@@ -3866,6 +4119,7 @@ const EditorPanel: React.FC<ChartEditorPanelProps> = ({ datasets }) => {
|
|
|
3866
4119
|
</AccordionItemPanel>
|
|
3867
4120
|
</AccordionItem>
|
|
3868
4121
|
)}
|
|
4122
|
+
{renderHeatMapSettingsAccordion()}
|
|
3869
4123
|
<Panels.Regions name='Regions' />
|
|
3870
4124
|
|
|
3871
4125
|
{/* Columns */}
|
|
@@ -3879,7 +4133,9 @@ const EditorPanel: React.FC<ChartEditorPanelProps> = ({ datasets }) => {
|
|
|
3879
4133
|
config={config}
|
|
3880
4134
|
updateField={updateFieldDeprecated}
|
|
3881
4135
|
deleteColumn={removeAdditionalColumn}
|
|
3882
|
-
hiddenColumnNames={
|
|
4136
|
+
hiddenColumnNames={
|
|
4137
|
+
isHeatMap ? [...seriesOwnedColumnNames, ...heatMapOwnedColumnNames] : seriesOwnedColumnNames
|
|
4138
|
+
}
|
|
3883
4139
|
/>{' '}
|
|
3884
4140
|
</AccordionItemPanel>
|
|
3885
4141
|
</AccordionItem>
|
|
@@ -3898,7 +4154,11 @@ const EditorPanel: React.FC<ChartEditorPanelProps> = ({ datasets }) => {
|
|
|
3898
4154
|
label='Position'
|
|
3899
4155
|
updateField={updateFieldDeprecated}
|
|
3900
4156
|
options={
|
|
3901
|
-
config.visualizationType === '
|
|
4157
|
+
config.visualizationType === 'HeatMap'
|
|
4158
|
+
? config.legend.style === 'gradient'
|
|
4159
|
+
? ['bottom', 'top']
|
|
4160
|
+
: ['right', 'left', 'bottom', 'top']
|
|
4161
|
+
: config.visualizationType === 'Warming Stripes'
|
|
3902
4162
|
? ['bottom']
|
|
3903
4163
|
: ['right', 'left', 'bottom', 'top']
|
|
3904
4164
|
}
|
|
@@ -3938,7 +4198,7 @@ const EditorPanel: React.FC<ChartEditorPanelProps> = ({ datasets }) => {
|
|
|
3938
4198
|
options={getLegendStyleOptions('style')}
|
|
3939
4199
|
/>
|
|
3940
4200
|
|
|
3941
|
-
{config.visualizationType !== 'Warming Stripes' && (
|
|
4201
|
+
{config.visualizationType !== 'Warming Stripes' && config.visualizationType !== 'HeatMap' && (
|
|
3942
4202
|
<Select
|
|
3943
4203
|
value={config.legend.groupBy}
|
|
3944
4204
|
section='legend'
|
|
@@ -4347,6 +4607,7 @@ const EditorPanel: React.FC<ChartEditorPanelProps> = ({ datasets }) => {
|
|
|
4347
4607
|
loadConfig={updateConfig}
|
|
4348
4608
|
config={config}
|
|
4349
4609
|
convertStateToConfig={chartConvertStateToConfig}
|
|
4610
|
+
defaultExpanded={config.visualizationType === 'HeatMap'}
|
|
4350
4611
|
/>
|
|
4351
4612
|
)}
|
|
4352
4613
|
</>
|
|
@@ -134,6 +134,19 @@ const PanelAnnotate: React.FC<PanelProps> = props => {
|
|
|
134
134
|
updateField={updateField}
|
|
135
135
|
/>
|
|
136
136
|
|
|
137
|
+
<Select
|
|
138
|
+
label='Mobile Annotations'
|
|
139
|
+
value={config?.general?.mobileAnnotationDisplay || 'symbol'}
|
|
140
|
+
options={[
|
|
141
|
+
{ value: 'symbol', label: 'Show Symbol' },
|
|
142
|
+
{ value: 'text', label: 'Show Text' }
|
|
143
|
+
]}
|
|
144
|
+
section='general'
|
|
145
|
+
subsection={null}
|
|
146
|
+
fieldName='mobileAnnotationDisplay'
|
|
147
|
+
updateField={updateField}
|
|
148
|
+
/>
|
|
149
|
+
|
|
137
150
|
{config.general.showAnnotationDropdown && (
|
|
138
151
|
<label key={`key-2`}>
|
|
139
152
|
Annotation Dropdown Title:
|