@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.
Files changed (125) hide show
  1. package/dist/cdcchart.js +34606 -32218
  2. package/examples/feature/bar/additional-column-tooltip.json +446 -0
  3. package/examples/feature/bar/example-bar-chart.json +1 -46
  4. package/examples/feature/bar/lollipop.json +156 -0
  5. package/examples/feature/bar/tall-data.json +98 -0
  6. package/examples/feature/combo/planet-combo-example-config.json +99 -9
  7. package/examples/feature/dev-4261.json +399 -0
  8. package/examples/feature/forest-plot/forest-plot.json +63 -19
  9. package/examples/feature/forest-plot/{broken.json → linear.json} +77 -23
  10. package/examples/feature/forest-plot/log.json +26 -0
  11. package/examples/feature/forest-plot/logarithmic.json +271 -0
  12. package/examples/feature/line/line-chart-preliminary.json +346 -0
  13. package/examples/feature/line/line-points.json +340 -0
  14. package/examples/feature/regions/index.json +462 -0
  15. package/examples/feature/scatterplot/scatterplot.json +272 -33
  16. package/examples/gallery/bar-chart-vertical/combo-line-chart.json +181 -48
  17. package/examples/private/chart-t.json +3740 -0
  18. package/examples/private/combo.json +369 -0
  19. package/examples/private/epi-data.csv +13 -0
  20. package/examples/private/epi-data.json +62 -0
  21. package/examples/private/epi.json +403 -0
  22. package/examples/private/occupancy.json +109283 -0
  23. package/examples/private/prod-line-config.json +401 -0
  24. package/examples/private/region-data.json +822 -0
  25. package/examples/private/region-testing.json +312 -0
  26. package/examples/private/scaling.json +45325 -0
  27. package/examples/private/testing-data.json +1739 -0
  28. package/examples/private/testing.json +816 -0
  29. package/examples/sparkline-multilple.json +846 -0
  30. package/index.html +12 -8
  31. package/package.json +3 -3
  32. package/src/CdcChart.tsx +42 -211
  33. package/src/ConfigContext.tsx +6 -0
  34. package/src/_stories/Chart.stories.tsx +188 -0
  35. package/src/_stories/Chart.tooltip.stories.tsx +305 -0
  36. package/src/_stories/ChartBrush.stories.tsx +19 -0
  37. package/src/_stories/ChartEditor.stories.tsx +22 -0
  38. package/src/_stories/ChartLine.preliminary.tsx +19 -0
  39. package/src/_stories/ChartSuppress.stories.tsx +19 -0
  40. package/src/_stories/_mock/brush_mock.json +393 -0
  41. package/src/_stories/_mock/pie_config.json +191 -0
  42. package/src/_stories/_mock/pie_data.json +218 -0
  43. package/src/_stories/_mock/preliminary_mock.json +346 -0
  44. package/src/_stories/_mock/suppress_mock.json +911 -0
  45. package/src/components/{AreaChart.Stacked.jsx → AreaChart/components/AreaChart.Stacked.jsx} +6 -7
  46. package/src/components/{AreaChart.jsx → AreaChart/components/AreaChart.jsx} +7 -36
  47. package/src/components/AreaChart/index.tsx +4 -0
  48. package/src/components/{BarChart.Horizontal.jsx → BarChart/components/BarChart.Horizontal.tsx} +111 -34
  49. package/src/components/{BarChart.StackedHorizontal.jsx → BarChart/components/BarChart.StackedHorizontal.tsx} +55 -20
  50. package/src/components/BarChart/components/BarChart.StackedVertical.tsx +106 -0
  51. package/src/components/{BarChart.Vertical.jsx → BarChart/components/BarChart.Vertical.tsx} +162 -34
  52. package/src/components/BarChart/components/BarChart.jsx +39 -0
  53. package/src/components/{BarChartType.jsx → BarChart/components/BarChartType.jsx} +0 -2
  54. package/src/components/BarChart/components/context.tsx +13 -0
  55. package/src/components/BarChart/index.tsx +3 -0
  56. package/src/components/{BoxPlot.jsx → BoxPlot/BoxPlot.jsx} +1 -1
  57. package/src/components/BoxPlot/index.tsx +3 -0
  58. package/src/components/DeviationBar.jsx +4 -3
  59. package/src/components/{EditorPanel.jsx → EditorPanel/EditorPanel.tsx} +807 -865
  60. package/src/components/EditorPanel/components/Panel.DateHighlighting.tsx +109 -0
  61. package/src/components/{ForestPlotSettings.jsx → EditorPanel/components/Panel.ForestPlotSettings.tsx} +190 -220
  62. package/src/components/EditorPanel/components/Panel.Regions.tsx +168 -0
  63. package/src/components/{Series.jsx → EditorPanel/components/Panel.Series.tsx} +23 -4
  64. package/src/components/EditorPanel/components/PanelProps.ts +3 -0
  65. package/src/components/EditorPanel/components/Panels.tsx +13 -0
  66. package/src/components/EditorPanel/components/panels.scss +72 -0
  67. package/src/components/EditorPanel/editor-panel.scss +751 -0
  68. package/src/components/EditorPanel/index.tsx +3 -0
  69. package/src/{hooks → components/EditorPanel}/useEditorPermissions.js +50 -5
  70. package/src/components/{Forecasting.jsx → Forecasting/Forecasting.jsx} +1 -1
  71. package/src/components/Forecasting/index.tsx +3 -0
  72. package/src/components/ForestPlot/ForestPlot.tsx +254 -0
  73. package/src/components/ForestPlot/ForestPlotProps.ts +18 -0
  74. package/src/components/ForestPlot/index.scss +1 -0
  75. package/src/components/ForestPlot/index.tsx +3 -0
  76. package/src/components/Legend/Legend.tsx +347 -0
  77. package/src/components/Legend/index.tsx +3 -0
  78. package/src/components/LineChart/LineChartProps.ts +46 -0
  79. package/src/components/{LineChart.Circle.tsx → LineChart/components/LineChart.Circle.tsx} +36 -30
  80. package/src/components/LineChart/helpers.ts +45 -0
  81. package/src/components/LineChart/index.scss +1 -0
  82. package/src/components/{LineChart.tsx → LineChart/index.tsx} +83 -42
  83. package/src/components/LinearChart.jsx +125 -82
  84. package/src/components/PairedBarChart.jsx +2 -2
  85. package/src/components/{PieChart.jsx → PieChart/PieChart.tsx} +16 -7
  86. package/src/components/PieChart/index.tsx +3 -0
  87. package/src/components/Regions/components/Regions.tsx +135 -0
  88. package/src/components/Regions/index.tsx +3 -0
  89. package/src/components/{ScatterPlot.jsx → ScatterPlot/ScatterPlot.jsx} +3 -3
  90. package/src/components/ScatterPlot/index.tsx +3 -0
  91. package/src/components/{SparkLine.jsx → Sparkline/SparkLine.jsx} +2 -2
  92. package/src/components/Sparkline/index.tsx +3 -0
  93. package/src/components/ZoomBrush.tsx +168 -0
  94. package/src/data/initial-state.js +30 -16
  95. package/src/helpers/abbreviateNumber.ts +17 -0
  96. package/src/helpers/computeMarginBottom.ts +55 -0
  97. package/src/helpers/filterData.ts +18 -0
  98. package/src/helpers/generateColorsArray.ts +8 -0
  99. package/src/helpers/getQuartiles.ts +30 -0
  100. package/src/helpers/handleChartAriaLabels.ts +19 -0
  101. package/src/helpers/handleLineType.ts +18 -0
  102. package/src/helpers/lineOptions.ts +18 -0
  103. package/src/helpers/sort.ts +7 -0
  104. package/src/helpers/tests/computeMarginBottom.test.ts +20 -0
  105. package/src/hooks/useBarChart.js +72 -7
  106. package/src/hooks/useColorScale.ts +50 -0
  107. package/src/hooks/{useMinMax.js → useMinMax.ts} +75 -23
  108. package/src/hooks/{useRightAxis.js → useRightAxis.ts} +10 -2
  109. package/src/hooks/{useScales.js → useScales.ts} +64 -17
  110. package/src/hooks/{useTooltip.jsx → useTooltip.tsx} +84 -55
  111. package/src/scss/main.scss +70 -38
  112. package/src/types/ChartConfig.ts +178 -0
  113. package/src/types/ChartContext.ts +54 -0
  114. package/src/types/ForestPlot.ts +53 -0
  115. package/examples/feature/scatterplot/scatterplot-continuous.csv +0 -17
  116. package/src/ConfigContext.jsx +0 -5
  117. package/src/components/BarChart.StackedVertical.jsx +0 -95
  118. package/src/components/BarChart.jsx +0 -30
  119. package/src/components/ForestPlot.jsx +0 -191
  120. package/src/components/Legend.jsx +0 -277
  121. package/src/scss/LinearChart.scss +0 -0
  122. package/src/scss/editor-panel.scss +0 -745
  123. package/src/scss/legend.scss +0 -206
  124. package/src/scss/mixins.scss +0 -0
  125. 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 '../ConfigContext'
2
+ import ConfigContext from '../../../ConfigContext'
3
3
  import { useDebounce } from 'use-debounce'
4
- import WarningImage from '../images/warning.svg'
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 Select = memo(({ label, value, options, fieldName, section = null, subsection = null, required = false, tooltip, updateField, initial: initialValue, ...attributes }) => {
9
- let optionsJsx = options.map((optionName, index) => (
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
- updateConfig({
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
- Forest Plot Settings
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
- {/* width in center */}
250
- {/* <label>
251
- <span className='edit-label column-heading'>Forest Plot Width (%)</span>
252
- <input
253
- type='number'
254
- min={0}
255
- max={100}
256
- value={config.forestPlot.width || ''}
257
- onChange={e => {
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
- width: e.target.value
220
+ estimateField: e.target.value
263
221
  }
264
222
  })
265
- }}
266
- />
267
- </label> */}
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
- <Select
346
- value={config.forestPlot.estimateField}
347
- label='Point Estimate Column'
348
- initial={'Select'}
349
- required={true}
350
- onChange={e => {
351
- if (e.target.value !== '' && e.target.value !== 'Select') {
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
- <CheckBox value={config.forestPlot.showZeroLine} section='forestPlot' fieldName='showZeroLine' label='Show Line on Zero' updateField={updateField} />
405
- <Select
406
- value={config.forestPlot.shape}
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='Scale Radius Column'
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={1}
448
- max={5}
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={5}
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
  )