@cdc/chart 4.23.10 → 4.24.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.
- package/dist/cdcchart.js +34606 -32218
- package/examples/feature/bar/additional-column-tooltip.json +446 -0
- package/examples/feature/bar/example-bar-chart.json +1 -46
- package/examples/feature/bar/lollipop.json +156 -0
- package/examples/feature/bar/tall-data.json +98 -0
- package/examples/feature/combo/planet-combo-example-config.json +99 -9
- package/examples/feature/dev-4261.json +399 -0
- package/examples/feature/forest-plot/forest-plot.json +63 -19
- package/examples/feature/forest-plot/{broken.json → linear.json} +77 -23
- package/examples/feature/forest-plot/log.json +26 -0
- package/examples/feature/forest-plot/logarithmic.json +271 -0
- package/examples/feature/line/line-chart-preliminary.json +346 -0
- package/examples/feature/line/line-points.json +340 -0
- package/examples/feature/regions/index.json +462 -0
- package/examples/feature/scatterplot/scatterplot.json +272 -33
- package/examples/gallery/bar-chart-vertical/combo-line-chart.json +181 -48
- package/examples/private/chart-t.json +3740 -0
- package/examples/private/combo.json +369 -0
- package/examples/private/epi-data.csv +13 -0
- package/examples/private/epi-data.json +62 -0
- package/examples/private/epi.json +403 -0
- package/examples/private/occupancy.json +109283 -0
- package/examples/private/prod-line-config.json +401 -0
- package/examples/private/region-data.json +822 -0
- package/examples/private/region-testing.json +312 -0
- package/examples/private/scaling.json +45325 -0
- package/examples/private/testing-data.json +1739 -0
- package/examples/private/testing.json +816 -0
- package/examples/sparkline-multilple.json +846 -0
- package/index.html +12 -8
- package/package.json +3 -3
- package/src/CdcChart.tsx +42 -211
- package/src/ConfigContext.tsx +6 -0
- package/src/_stories/Chart.stories.tsx +188 -0
- package/src/_stories/Chart.tooltip.stories.tsx +305 -0
- package/src/_stories/ChartBrush.stories.tsx +19 -0
- package/src/_stories/ChartEditor.stories.tsx +22 -0
- package/src/_stories/ChartLine.preliminary.tsx +19 -0
- package/src/_stories/ChartSuppress.stories.tsx +19 -0
- package/src/_stories/_mock/brush_mock.json +393 -0
- package/src/_stories/_mock/pie_config.json +191 -0
- package/src/_stories/_mock/pie_data.json +218 -0
- package/src/_stories/_mock/preliminary_mock.json +346 -0
- package/src/_stories/_mock/suppress_mock.json +911 -0
- package/src/components/{AreaChart.Stacked.jsx → AreaChart/components/AreaChart.Stacked.jsx} +6 -7
- package/src/components/{AreaChart.jsx → AreaChart/components/AreaChart.jsx} +7 -36
- package/src/components/AreaChart/index.tsx +4 -0
- package/src/components/{BarChart.Horizontal.jsx → BarChart/components/BarChart.Horizontal.tsx} +111 -34
- package/src/components/{BarChart.StackedHorizontal.jsx → BarChart/components/BarChart.StackedHorizontal.tsx} +55 -20
- package/src/components/BarChart/components/BarChart.StackedVertical.tsx +106 -0
- package/src/components/{BarChart.Vertical.jsx → BarChart/components/BarChart.Vertical.tsx} +162 -34
- package/src/components/BarChart/components/BarChart.jsx +39 -0
- package/src/components/{BarChartType.jsx → BarChart/components/BarChartType.jsx} +0 -2
- package/src/components/BarChart/components/context.tsx +13 -0
- package/src/components/BarChart/index.tsx +3 -0
- package/src/components/{BoxPlot.jsx → BoxPlot/BoxPlot.jsx} +1 -1
- package/src/components/BoxPlot/index.tsx +3 -0
- package/src/components/DeviationBar.jsx +4 -3
- package/src/components/{EditorPanel.jsx → EditorPanel/EditorPanel.tsx} +807 -865
- package/src/components/EditorPanel/components/Panel.DateHighlighting.tsx +109 -0
- package/src/components/{ForestPlotSettings.jsx → EditorPanel/components/Panel.ForestPlotSettings.tsx} +190 -220
- package/src/components/EditorPanel/components/Panel.Regions.tsx +168 -0
- package/src/components/{Series.jsx → EditorPanel/components/Panel.Series.tsx} +23 -4
- package/src/components/EditorPanel/components/PanelProps.ts +3 -0
- package/src/components/EditorPanel/components/Panels.tsx +13 -0
- package/src/components/EditorPanel/components/panels.scss +72 -0
- package/src/components/EditorPanel/editor-panel.scss +751 -0
- package/src/components/EditorPanel/index.tsx +3 -0
- package/src/{hooks → components/EditorPanel}/useEditorPermissions.js +50 -5
- package/src/components/{Forecasting.jsx → Forecasting/Forecasting.jsx} +1 -1
- package/src/components/Forecasting/index.tsx +3 -0
- package/src/components/ForestPlot/ForestPlot.tsx +254 -0
- package/src/components/ForestPlot/ForestPlotProps.ts +18 -0
- package/src/components/ForestPlot/index.scss +1 -0
- package/src/components/ForestPlot/index.tsx +3 -0
- package/src/components/Legend/Legend.tsx +347 -0
- package/src/components/Legend/index.tsx +3 -0
- package/src/components/LineChart/LineChartProps.ts +46 -0
- package/src/components/{LineChart.Circle.tsx → LineChart/components/LineChart.Circle.tsx} +36 -30
- package/src/components/LineChart/helpers.ts +45 -0
- package/src/components/LineChart/index.scss +1 -0
- package/src/components/{LineChart.tsx → LineChart/index.tsx} +83 -42
- package/src/components/LinearChart.jsx +125 -82
- package/src/components/PairedBarChart.jsx +2 -2
- package/src/components/{PieChart.jsx → PieChart/PieChart.tsx} +16 -7
- package/src/components/PieChart/index.tsx +3 -0
- package/src/components/Regions/components/Regions.tsx +135 -0
- package/src/components/Regions/index.tsx +3 -0
- package/src/components/{ScatterPlot.jsx → ScatterPlot/ScatterPlot.jsx} +3 -3
- package/src/components/ScatterPlot/index.tsx +3 -0
- package/src/components/{SparkLine.jsx → Sparkline/SparkLine.jsx} +2 -2
- package/src/components/Sparkline/index.tsx +3 -0
- package/src/components/ZoomBrush.tsx +168 -0
- package/src/data/initial-state.js +30 -16
- package/src/helpers/abbreviateNumber.ts +17 -0
- package/src/helpers/computeMarginBottom.ts +55 -0
- package/src/helpers/filterData.ts +18 -0
- package/src/helpers/generateColorsArray.ts +8 -0
- package/src/helpers/getQuartiles.ts +30 -0
- package/src/helpers/handleChartAriaLabels.ts +19 -0
- package/src/helpers/handleLineType.ts +18 -0
- package/src/helpers/lineOptions.ts +18 -0
- package/src/helpers/sort.ts +7 -0
- package/src/helpers/tests/computeMarginBottom.test.ts +20 -0
- package/src/hooks/useBarChart.js +72 -7
- package/src/hooks/useColorScale.ts +50 -0
- package/src/hooks/{useMinMax.js → useMinMax.ts} +75 -23
- package/src/hooks/{useRightAxis.js → useRightAxis.ts} +10 -2
- package/src/hooks/{useScales.js → useScales.ts} +64 -17
- package/src/hooks/{useTooltip.jsx → useTooltip.tsx} +84 -55
- package/src/scss/main.scss +70 -38
- package/src/types/ChartConfig.ts +178 -0
- package/src/types/ChartContext.ts +54 -0
- package/src/types/ForestPlot.ts +53 -0
- package/examples/feature/scatterplot/scatterplot-continuous.csv +0 -17
- package/src/ConfigContext.jsx +0 -5
- package/src/components/BarChart.StackedVertical.jsx +0 -95
- package/src/components/BarChart.jsx +0 -30
- package/src/components/ForestPlot.jsx +0 -191
- package/src/components/Legend.jsx +0 -277
- package/src/scss/LinearChart.scss +0 -0
- package/src/scss/editor-panel.scss +0 -745
- package/src/scss/legend.scss +0 -206
- package/src/scss/mixins.scss +0 -0
- package/src/scss/variables.scss +0 -1
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import React, { useState, useEffect } from 'react'
|
|
2
|
+
import { AccordionItem, AccordionItemHeading, AccordionItemPanel, AccordionItemButton } from 'react-accessible-accordion'
|
|
3
|
+
import { type PanelProps } from './PanelProps'
|
|
4
|
+
|
|
5
|
+
const days = [
|
|
6
|
+
{ day: 'Sunday', abbr: 'S', status: 'inactive' },
|
|
7
|
+
{ day: 'Monday', abbr: 'M', status: 'inactive' },
|
|
8
|
+
{ day: 'Tuesday', abbr: 'T', status: 'inactive' },
|
|
9
|
+
{ day: 'Wednesday', abbr: 'W', status: 'inactive' },
|
|
10
|
+
{ day: 'Thursday', abbr: 'T', status: 'inactive' },
|
|
11
|
+
{ day: 'Friday', abbr: 'F', status: 'inactive' },
|
|
12
|
+
{ day: 'Saturday', abbr: 'S', status: 'inactive' }
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
const DateHighlighting = ({ name }: PanelProps) => {
|
|
16
|
+
const [interval, setInterval] = useState(0)
|
|
17
|
+
const [isPlural, setIsPlural] = useState(false)
|
|
18
|
+
const [recurrance, setRecurrance] = useState('Days')
|
|
19
|
+
const [firstRecurranceUpdate, setFirstRecurranceUpdate] = useState(false)
|
|
20
|
+
const [daySelections, setDaySelections] = useState(days)
|
|
21
|
+
|
|
22
|
+
const handleDaySelections = e => {
|
|
23
|
+
const incomingDay = e.target.value
|
|
24
|
+
const prev = [...daySelections]
|
|
25
|
+
|
|
26
|
+
const updatedDays = prev.map(day => {
|
|
27
|
+
if (day.day === incomingDay) {
|
|
28
|
+
return { ...day, status: day.status === 'active' ? 'inactive' : 'active' }
|
|
29
|
+
}
|
|
30
|
+
return day
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
setDaySelections(updatedDays)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
if (interval > 7 && !firstRecurranceUpdate) {
|
|
38
|
+
setRecurrance('Weeks')
|
|
39
|
+
}
|
|
40
|
+
}, [interval])
|
|
41
|
+
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
if (interval > 1) {
|
|
44
|
+
setIsPlural(true)
|
|
45
|
+
} else {
|
|
46
|
+
setIsPlural(false)
|
|
47
|
+
}
|
|
48
|
+
}, [interval])
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<AccordionItem>
|
|
52
|
+
<AccordionItemHeading>
|
|
53
|
+
<AccordionItemButton>{name}</AccordionItemButton>
|
|
54
|
+
</AccordionItemHeading>
|
|
55
|
+
<AccordionItemPanel>
|
|
56
|
+
<ul className='date-highlight'>
|
|
57
|
+
<div className='date-highlight__occurance'>
|
|
58
|
+
<label htmlFor=''>Repeat Every</label>
|
|
59
|
+
<input type='number' value={interval} onChange={e => setInterval(Number(e.target.value))} />
|
|
60
|
+
<select value={recurrance} onChange={e => setRecurrance(e.target.value)}>
|
|
61
|
+
<option value='Day'>{isPlural ? 'Days' : 'Day'}</option>
|
|
62
|
+
<option value='Week'>{isPlural ? 'Weeks' : 'Week'}</option>
|
|
63
|
+
<option value='Month'>{isPlural ? 'Months' : 'Month'}</option>
|
|
64
|
+
<option value='Year'>{isPlural ? 'Years' : 'Year'}</option>
|
|
65
|
+
</select>
|
|
66
|
+
</div>
|
|
67
|
+
{recurrance !== 'Days' && (
|
|
68
|
+
<div className='date-highlight__day-selection'>
|
|
69
|
+
<label htmlFor='' style={{ display: 'block', width: '100%' }}>
|
|
70
|
+
Repeat On
|
|
71
|
+
</label>
|
|
72
|
+
{daySelections.map(d => (
|
|
73
|
+
<button className={`week-button week-button--${d.status} ${d.day}`} value={d.day} onClick={handleDaySelections}>
|
|
74
|
+
{d.abbr}
|
|
75
|
+
</button>
|
|
76
|
+
))}
|
|
77
|
+
</div>
|
|
78
|
+
)}
|
|
79
|
+
<div className='date-highlight__end-date'>
|
|
80
|
+
<label htmlFor=''>Ends</label>
|
|
81
|
+
<div className='radio-group'>
|
|
82
|
+
<div className='group'>
|
|
83
|
+
<input type='radio' name='ending' value='Never' id='Never' />
|
|
84
|
+
<label for='Never'>Never</label>
|
|
85
|
+
</div>
|
|
86
|
+
</div>
|
|
87
|
+
<div className='radio-group'>
|
|
88
|
+
<div className='group'>
|
|
89
|
+
<input type='radio' name='ending' value='After' id='After' />
|
|
90
|
+
<label for='After'>After</label>
|
|
91
|
+
</div>
|
|
92
|
+
<input type='number' className='date-highlight__end-date--on' />
|
|
93
|
+
<p>occurances</p>
|
|
94
|
+
</div>
|
|
95
|
+
<div className='radio-group'>
|
|
96
|
+
<div className='group'>
|
|
97
|
+
<input type='radio' name='ending' value='On' id='On' />
|
|
98
|
+
<label for='On'>On</label>
|
|
99
|
+
</div>
|
|
100
|
+
<input type='date' className='date-highlight__end-date--after' />
|
|
101
|
+
</div>
|
|
102
|
+
</div>
|
|
103
|
+
</ul>
|
|
104
|
+
</AccordionItemPanel>
|
|
105
|
+
</AccordionItem>
|
|
106
|
+
)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export default DateHighlighting
|
|
@@ -1,117 +1,17 @@
|
|
|
1
1
|
import React, { useContext, memo, useState, useEffect } from 'react'
|
|
2
|
-
import ConfigContext from '
|
|
2
|
+
import ConfigContext from '../../../ConfigContext'
|
|
3
3
|
import { useDebounce } from 'use-debounce'
|
|
4
|
-
import WarningImage from '
|
|
4
|
+
import WarningImage from '../../../images/warning.svg'
|
|
5
|
+
import Tooltip from '@cdc/core/components/ui/Tooltip'
|
|
6
|
+
import Icon from '@cdc/core/components/ui/Icon'
|
|
7
|
+
import { type ChartContext } from '../../../types/ChartContext'
|
|
8
|
+
import { Select, CheckBox, TextField } from '@cdc/core/components/EditorPanel/Inputs'
|
|
9
|
+
import { type PanelProps } from './PanelProps'
|
|
5
10
|
|
|
6
11
|
import { AccordionItem, AccordionItemHeading, AccordionItemPanel, AccordionItemButton } from 'react-accessible-accordion'
|
|
7
12
|
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
<option value={optionName} key={index}>
|
|
11
|
-
{optionName}
|
|
12
|
-
</option>
|
|
13
|
-
))
|
|
14
|
-
|
|
15
|
-
if (initialValue) {
|
|
16
|
-
optionsJsx.unshift(
|
|
17
|
-
<option value='' key='initial'>
|
|
18
|
-
{initialValue}
|
|
19
|
-
</option>
|
|
20
|
-
)
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
return (
|
|
24
|
-
<label>
|
|
25
|
-
<span className='edit-label'>
|
|
26
|
-
{label}
|
|
27
|
-
{tooltip}
|
|
28
|
-
</span>
|
|
29
|
-
<select
|
|
30
|
-
className={required && !value ? 'warning' : ''}
|
|
31
|
-
name={fieldName}
|
|
32
|
-
value={value}
|
|
33
|
-
onChange={event => {
|
|
34
|
-
updateField(section, subsection, fieldName, event.target.value)
|
|
35
|
-
}}
|
|
36
|
-
{...attributes}
|
|
37
|
-
>
|
|
38
|
-
{optionsJsx}
|
|
39
|
-
</select>
|
|
40
|
-
</label>
|
|
41
|
-
)
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
const CheckBox = memo(({ label, value, fieldName, section = null, subsection = null, tooltip, updateField, ...attributes }) => (
|
|
45
|
-
<label className='checkbox column-heading'>
|
|
46
|
-
<input
|
|
47
|
-
type='checkbox'
|
|
48
|
-
name={fieldName}
|
|
49
|
-
checked={value}
|
|
50
|
-
onChange={e => {
|
|
51
|
-
updateField(section, subsection, fieldName, !value)
|
|
52
|
-
}}
|
|
53
|
-
{...attributes}
|
|
54
|
-
/>
|
|
55
|
-
<span className='edit-label'>
|
|
56
|
-
{label}
|
|
57
|
-
{tooltip}
|
|
58
|
-
</span>
|
|
59
|
-
</label>
|
|
60
|
-
))
|
|
61
|
-
|
|
62
|
-
/* eslint-disable react-hooks/rules-of-hooks */
|
|
63
|
-
const TextField = memo(({ label, tooltip, section = null, subsection = null, fieldName, updateField, value: stateValue, type = 'input', i = null, min = null, ...attributes }) => {
|
|
64
|
-
const [value, setValue] = useState(stateValue)
|
|
65
|
-
|
|
66
|
-
const [debouncedValue] = useDebounce(value, 500)
|
|
67
|
-
|
|
68
|
-
useEffect(() => {
|
|
69
|
-
if ('string' === typeof debouncedValue && stateValue !== debouncedValue) {
|
|
70
|
-
updateField(section, subsection, fieldName, debouncedValue, i)
|
|
71
|
-
}
|
|
72
|
-
}, [debouncedValue]) // eslint-disable-line
|
|
73
|
-
|
|
74
|
-
let name = subsection ? `${section}-${subsection}-${fieldName}` : `${section}-${subsection}-${fieldName}`
|
|
75
|
-
|
|
76
|
-
const onChange = e => {
|
|
77
|
-
if ('number' !== type || min === null) {
|
|
78
|
-
setValue(e.target.value)
|
|
79
|
-
} else {
|
|
80
|
-
if (!e.target.value || min <= parseFloat(e.target.value)) {
|
|
81
|
-
setValue(e.target.value)
|
|
82
|
-
} else {
|
|
83
|
-
setValue(min.toString())
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
let formElement = <input type='text' name={name} onChange={onChange} {...attributes} value={value} />
|
|
89
|
-
|
|
90
|
-
if ('textarea' === type) {
|
|
91
|
-
formElement = <textarea name={name} onChange={onChange} {...attributes} value={value}></textarea>
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
if ('number' === type) {
|
|
95
|
-
formElement = <input type='number' name={name} onChange={onChange} {...attributes} value={value} />
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
if ('date' === type) {
|
|
99
|
-
formElement = <input type='date' name={name} onChange={onChange} {...attributes} value={value} />
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
return (
|
|
103
|
-
<label>
|
|
104
|
-
<span className='edit-label column-heading'>
|
|
105
|
-
{label}
|
|
106
|
-
{tooltip}
|
|
107
|
-
</span>
|
|
108
|
-
{formElement}
|
|
109
|
-
</label>
|
|
110
|
-
)
|
|
111
|
-
})
|
|
112
|
-
|
|
113
|
-
const ForestPlotSettings = () => {
|
|
114
|
-
const { config, rawData: unfilteredData, updateConfig, isDebug } = useContext(ConfigContext)
|
|
13
|
+
const ForestPlotSettings = ({ name }: PanelProps) => {
|
|
14
|
+
const { config, rawData: unfilteredData, updateConfig } = useContext<ChartContext>(ConfigContext)
|
|
115
15
|
|
|
116
16
|
const enforceRestrictions = updatedConfig => {
|
|
117
17
|
if (updatedConfig.orientation === 'horizontal') {
|
|
@@ -180,7 +80,7 @@ const ForestPlotSettings = () => {
|
|
|
180
80
|
}
|
|
181
81
|
|
|
182
82
|
if (section === 'forestPlot' && subsection) {
|
|
183
|
-
|
|
83
|
+
let newConfig = {
|
|
184
84
|
...config,
|
|
185
85
|
[section]: {
|
|
186
86
|
...config[section],
|
|
@@ -189,7 +89,9 @@ const ForestPlotSettings = () => {
|
|
|
189
89
|
[fieldName]: newValue
|
|
190
90
|
}
|
|
191
91
|
}
|
|
192
|
-
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
updateConfig(newConfig)
|
|
193
95
|
return
|
|
194
96
|
}
|
|
195
97
|
|
|
@@ -239,32 +141,179 @@ const ForestPlotSettings = () => {
|
|
|
239
141
|
<AccordionItem>
|
|
240
142
|
<AccordionItemHeading>
|
|
241
143
|
<AccordionItemButton>
|
|
242
|
-
|
|
144
|
+
{name}
|
|
243
145
|
{(!config.forestPlot.estimateField || !config.forestPlot.upper || !config.forestPlot.lower) && <WarningImage width='25' className='warning-icon' />}
|
|
244
146
|
</AccordionItemButton>
|
|
245
147
|
</AccordionItemHeading>
|
|
246
148
|
<AccordionItemPanel>
|
|
149
|
+
<Select
|
|
150
|
+
value={config.xAxis.dataKey || ''}
|
|
151
|
+
section='xAxis'
|
|
152
|
+
fieldName='dataKey'
|
|
153
|
+
label='Study Column'
|
|
154
|
+
initial='Select'
|
|
155
|
+
required={true}
|
|
156
|
+
updateField={updateField}
|
|
157
|
+
options={getColumns(false)}
|
|
158
|
+
tooltip={
|
|
159
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
160
|
+
<Tooltip.Target>
|
|
161
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
162
|
+
</Tooltip.Target>
|
|
163
|
+
<Tooltip.Content>
|
|
164
|
+
<p>Select the column or row containing the categories or dates for this axis. </p>
|
|
165
|
+
</Tooltip.Content>
|
|
166
|
+
</Tooltip>
|
|
167
|
+
}
|
|
168
|
+
/>
|
|
169
|
+
<Select
|
|
170
|
+
value={config.forestPlot.type}
|
|
171
|
+
label='Forest Plot Type'
|
|
172
|
+
initial={'Select'}
|
|
173
|
+
required={true}
|
|
174
|
+
onChange={e => {
|
|
175
|
+
if (e.target.value !== '' && e.target.value !== 'Select') {
|
|
176
|
+
updateConfig({
|
|
177
|
+
...config,
|
|
178
|
+
forestPlot: {
|
|
179
|
+
...config.forestPlot,
|
|
180
|
+
type: e.target.value
|
|
181
|
+
}
|
|
182
|
+
})
|
|
183
|
+
}
|
|
184
|
+
e.target.value = ''
|
|
185
|
+
}}
|
|
186
|
+
options={['Linear', 'Logarithmic']}
|
|
187
|
+
tooltip={
|
|
188
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
189
|
+
<Tooltip.Target>
|
|
190
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
191
|
+
</Tooltip.Target>
|
|
192
|
+
<Tooltip.Content>
|
|
193
|
+
<p>
|
|
194
|
+
Linear - Typically used for continuous outcomes. Line of no effect is positioned on 0 (zero) <br />
|
|
195
|
+
<br /> Logarithmic - Typically used for binary outcomes such as risk ratios and odds ratios. Line of no effect is positioned on 1.
|
|
196
|
+
</p>
|
|
197
|
+
</Tooltip.Content>
|
|
198
|
+
</Tooltip>
|
|
199
|
+
}
|
|
200
|
+
/>
|
|
201
|
+
|
|
247
202
|
<TextField type='text' value={config.forestPlot?.title || ''} updateField={updateField} section='forestPlot' fieldName='title' label='Plot Title' />
|
|
248
203
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
204
|
+
<br />
|
|
205
|
+
<hr />
|
|
206
|
+
<br />
|
|
207
|
+
<h4>Column Settings</h4>
|
|
208
|
+
|
|
209
|
+
<Select
|
|
210
|
+
value={config.forestPlot.estimateField}
|
|
211
|
+
label='Point Estimate Column'
|
|
212
|
+
initial={config.forestPlot.estimateField || 'Select'}
|
|
213
|
+
required={true}
|
|
214
|
+
onChange={e => {
|
|
215
|
+
if (e.target.value !== '' && e.target.value !== 'Select') {
|
|
258
216
|
updateConfig({
|
|
259
217
|
...config,
|
|
260
218
|
forestPlot: {
|
|
261
219
|
...config.forestPlot,
|
|
262
|
-
|
|
220
|
+
estimateField: e.target.value
|
|
263
221
|
}
|
|
264
222
|
})
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
|
|
223
|
+
}
|
|
224
|
+
e.target.value = ''
|
|
225
|
+
}}
|
|
226
|
+
options={getColumns(false)}
|
|
227
|
+
/>
|
|
228
|
+
|
|
229
|
+
<Select
|
|
230
|
+
value={config.forestPlot.shape}
|
|
231
|
+
label='Point Estimate Shape'
|
|
232
|
+
onChange={e => {
|
|
233
|
+
if (e.target.value !== '' && e.target.value !== 'Select') {
|
|
234
|
+
updateConfig({
|
|
235
|
+
...config,
|
|
236
|
+
forestPlot: {
|
|
237
|
+
...config.forestPlot,
|
|
238
|
+
shape: e.target.value
|
|
239
|
+
}
|
|
240
|
+
})
|
|
241
|
+
}
|
|
242
|
+
e.target.value = ''
|
|
243
|
+
}}
|
|
244
|
+
options={['text', 'circle', 'square']}
|
|
245
|
+
/>
|
|
246
|
+
|
|
247
|
+
<Select
|
|
248
|
+
value={config.forestPlot.lower}
|
|
249
|
+
label='Lower CI Column'
|
|
250
|
+
required={true}
|
|
251
|
+
initial={config.forestPlot.lower || 'Select'}
|
|
252
|
+
onChange={e => {
|
|
253
|
+
if (e.target.value !== '' && e.target.value !== 'Select') {
|
|
254
|
+
updateConfig({
|
|
255
|
+
...config,
|
|
256
|
+
forestPlot: {
|
|
257
|
+
...config.forestPlot,
|
|
258
|
+
lower: e.target.value
|
|
259
|
+
}
|
|
260
|
+
})
|
|
261
|
+
}
|
|
262
|
+
e.target.value = ''
|
|
263
|
+
}}
|
|
264
|
+
options={getColumns(false)}
|
|
265
|
+
/>
|
|
266
|
+
|
|
267
|
+
<Select
|
|
268
|
+
value={config.forestPlot.upper}
|
|
269
|
+
label='Upper CI Column'
|
|
270
|
+
initial={config.forestPlot.upper || 'Select'}
|
|
271
|
+
required={true}
|
|
272
|
+
onChange={e => {
|
|
273
|
+
if (e.target.value !== '' && e.target.value !== 'Select') {
|
|
274
|
+
updateConfig({
|
|
275
|
+
...config,
|
|
276
|
+
forestPlot: {
|
|
277
|
+
...config.forestPlot,
|
|
278
|
+
upper: e.target.value
|
|
279
|
+
}
|
|
280
|
+
})
|
|
281
|
+
}
|
|
282
|
+
e.target.value = ''
|
|
283
|
+
}}
|
|
284
|
+
options={getColumns(false)}
|
|
285
|
+
/>
|
|
286
|
+
|
|
287
|
+
<label>
|
|
288
|
+
<span className='edit-label column-heading'>
|
|
289
|
+
Pooled Result Column
|
|
290
|
+
<input
|
|
291
|
+
type='text'
|
|
292
|
+
value={config.forestPlot.pooledResult.column || ''}
|
|
293
|
+
label='Pooled Result Row'
|
|
294
|
+
onChange={e => {
|
|
295
|
+
updateConfig({
|
|
296
|
+
...config,
|
|
297
|
+
forestPlot: {
|
|
298
|
+
...config.forestPlot,
|
|
299
|
+
pooledResult: {
|
|
300
|
+
...config.forestPlot.pooledResult,
|
|
301
|
+
column: e.target.value
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
})
|
|
305
|
+
e.target.value = ''
|
|
306
|
+
}}
|
|
307
|
+
/>
|
|
308
|
+
</span>
|
|
309
|
+
</label>
|
|
310
|
+
|
|
311
|
+
<CheckBox value={config.forestPlot?.lineOfNoEffect?.show || false} section='forestPlot' subsection='lineOfNoEffect' fieldName='show' label='Show Line of No Effect' updateField={updateField} />
|
|
312
|
+
|
|
313
|
+
<br />
|
|
314
|
+
<hr />
|
|
315
|
+
<br />
|
|
316
|
+
<h4>Width Settings</h4>
|
|
268
317
|
|
|
269
318
|
<label>
|
|
270
319
|
<span className='edit-label column-heading'>Chart Offset Left (%)</span>
|
|
@@ -342,87 +391,20 @@ const ForestPlotSettings = () => {
|
|
|
342
391
|
/>
|
|
343
392
|
</label>
|
|
344
393
|
|
|
345
|
-
<
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
updateConfig({
|
|
353
|
-
...config,
|
|
354
|
-
forestPlot: {
|
|
355
|
-
...config.forestPlot,
|
|
356
|
-
estimateField: e.target.value
|
|
357
|
-
}
|
|
358
|
-
})
|
|
359
|
-
}
|
|
360
|
-
e.target.value = ''
|
|
361
|
-
}}
|
|
362
|
-
options={getColumns(false)}
|
|
363
|
-
/>
|
|
364
|
-
|
|
365
|
-
<Select
|
|
366
|
-
value={config.forestPlot.lower}
|
|
367
|
-
label='Lower CI Column'
|
|
368
|
-
required={true}
|
|
369
|
-
initial={'Select'}
|
|
370
|
-
onChange={e => {
|
|
371
|
-
if (e.target.value !== '' && e.target.value !== 'Select') {
|
|
372
|
-
updateConfig({
|
|
373
|
-
...config,
|
|
374
|
-
forestPlot: {
|
|
375
|
-
...config.forestPlot,
|
|
376
|
-
lower: e.target.value
|
|
377
|
-
}
|
|
378
|
-
})
|
|
379
|
-
}
|
|
380
|
-
e.target.value = ''
|
|
381
|
-
}}
|
|
382
|
-
options={getColumns(false)}
|
|
383
|
-
/>
|
|
384
|
-
<Select
|
|
385
|
-
value={config.forestPlot.upper}
|
|
386
|
-
label='Upper CI Column'
|
|
387
|
-
initial={'Select'}
|
|
388
|
-
required={true}
|
|
389
|
-
onChange={e => {
|
|
390
|
-
if (e.target.value !== '' && e.target.value !== 'Select') {
|
|
391
|
-
updateConfig({
|
|
392
|
-
...config,
|
|
393
|
-
forestPlot: {
|
|
394
|
-
...config.forestPlot,
|
|
395
|
-
upper: e.target.value
|
|
396
|
-
}
|
|
397
|
-
})
|
|
398
|
-
}
|
|
399
|
-
e.target.value = ''
|
|
400
|
-
}}
|
|
401
|
-
options={getColumns(false)}
|
|
402
|
-
/>
|
|
394
|
+
<TextField type='number' min={20} max={45} value={config.forestPlot.rowHeight ? config.forestPlot.rowHeight : 10} updateField={updateField} section='forestPlot' fieldName='rowHeight' label='Row Height' placeholder='10' />
|
|
395
|
+
<br />
|
|
396
|
+
<hr />
|
|
397
|
+
<br />
|
|
398
|
+
<h4>Labels Settings</h4>
|
|
399
|
+
<TextField type='text' value={config.forestPlot?.leftLabel || ''} updateField={updateField} section='forestPlot' fieldName='leftLabel' label='Left Label' />
|
|
400
|
+
<TextField type='text' value={config.forestPlot?.rightLabel || ''} updateField={updateField} section='forestPlot' fieldName='rightLabel' label='Right Label' />
|
|
403
401
|
|
|
404
|
-
<
|
|
405
|
-
<
|
|
406
|
-
|
|
407
|
-
label='Point Estimate Shape'
|
|
408
|
-
initial={'Select'}
|
|
409
|
-
onChange={e => {
|
|
410
|
-
if (e.target.value !== '' && e.target.value !== 'Select') {
|
|
411
|
-
updateConfig({
|
|
412
|
-
...config,
|
|
413
|
-
forestPlot: {
|
|
414
|
-
...config.forestPlot,
|
|
415
|
-
shape: e.target.value
|
|
416
|
-
}
|
|
417
|
-
})
|
|
418
|
-
}
|
|
419
|
-
e.target.value = ''
|
|
420
|
-
}}
|
|
421
|
-
options={['text', 'circle', 'square', 'diamond']}
|
|
422
|
-
/>
|
|
402
|
+
<br />
|
|
403
|
+
<hr />
|
|
404
|
+
<br />
|
|
423
405
|
<Select
|
|
424
406
|
value={config.forestPlot.radius.scalingColumn}
|
|
425
|
-
label='
|
|
407
|
+
label='Weight Column'
|
|
426
408
|
initial={'Select'}
|
|
427
409
|
onChange={e => {
|
|
428
410
|
if (e.target.value !== '' && e.target.value !== 'Select') {
|
|
@@ -441,12 +423,13 @@ const ForestPlotSettings = () => {
|
|
|
441
423
|
}}
|
|
442
424
|
options={getColumns(false)}
|
|
443
425
|
/>
|
|
426
|
+
|
|
444
427
|
<label>
|
|
445
428
|
<span className='edit-label column-heading'>Radius Minimum Size</span>
|
|
446
429
|
<input
|
|
447
|
-
min={
|
|
448
|
-
max={
|
|
449
|
-
value={config.forestPlot.radius.min}
|
|
430
|
+
min={3}
|
|
431
|
+
max={6}
|
|
432
|
+
value={config.forestPlot.radius.min || 3}
|
|
450
433
|
onChange={e => {
|
|
451
434
|
updateConfig({
|
|
452
435
|
...config,
|
|
@@ -467,7 +450,7 @@ const ForestPlotSettings = () => {
|
|
|
467
450
|
<label>
|
|
468
451
|
<span className='edit-label column-heading'>Radius Maximum Size</span>
|
|
469
452
|
<input
|
|
470
|
-
min={
|
|
453
|
+
min={7}
|
|
471
454
|
max={10}
|
|
472
455
|
value={config.forestPlot.radius.max}
|
|
473
456
|
onChange={e => {
|
|
@@ -487,19 +470,6 @@ const ForestPlotSettings = () => {
|
|
|
487
470
|
placeholder=' 1'
|
|
488
471
|
/>
|
|
489
472
|
</label>
|
|
490
|
-
<TextField type='number' min={20} max={45} value={config.forestPlot.rowHeight ? config.forestPlot.rowHeight : 10} updateField={updateField} section='forestPlot' fieldName='rowHeight' label='Row Height' placeholder='10' />
|
|
491
|
-
<br />
|
|
492
|
-
<hr />
|
|
493
|
-
<br />
|
|
494
|
-
<h4>Add Regression Line</h4>
|
|
495
|
-
<TextField type='number' value={config.forestPlot?.regression?.upper || ''} updateField={updateField} section='forestPlot' subsection='regression' fieldName='upper' label='Upper Value' />
|
|
496
|
-
<TextField type='number' value={config.forestPlot?.regression?.lower || ''} updateField={updateField} section='forestPlot' subsection='regression' fieldName='lower' label='Lower Value' />
|
|
497
|
-
<TextField type='number' value={config.forestPlot?.regression?.estimateField || ''} updateField={updateField} section='forestPlot' subsection='regression' fieldName='estimateField' label='Estimate Value' />
|
|
498
|
-
<TextField type='text' value={config.forestPlot?.regression?.baseLineColor || 'black'} updateField={updateField} section='forestPlot' subsection='regression' fieldName='baseLineColor' label='Base Color' />
|
|
499
|
-
<CheckBox value={config.forestPlot?.regression?.showBaseLine || false} section='forestPlot' subsection='regression' fieldName='showBaseLine' label='Show base line' updateField={updateField} />
|
|
500
|
-
<CheckBox value={config.forestPlot?.regression?.showDiamond || false} section='forestPlot' subsection='regression' fieldName='showDiamond' label='Show Diamond' updateField={updateField} />
|
|
501
|
-
<CheckBox value={config.forestPlot?.hideDateCategoryCol || false} section='forestPlot' fieldName='hideDateCategoryCol' label='Hide Date Category Column' updateField={updateField} />
|
|
502
|
-
<TextField type='text' value={config.forestPlot?.regression?.description || ''} updateField={updateField} section='forestPlot' subsection='regression' fieldName='description' label='Description' />
|
|
503
473
|
</AccordionItemPanel>
|
|
504
474
|
</AccordionItem>
|
|
505
475
|
)
|