@cdc/core 4.24.5 → 4.24.9

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 (109) hide show
  1. package/assets/icon-gear-multi.svg +23 -0
  2. package/components/AdvancedEditor/AdvancedEditor.tsx +93 -0
  3. package/components/AdvancedEditor/advanced-editor-styles.css +3 -0
  4. package/components/AdvancedEditor/index.ts +1 -0
  5. package/components/Alert/components/Alert.styles.css +15 -0
  6. package/components/Alert/components/Alert.tsx +39 -0
  7. package/components/Alert/index.tsx +3 -0
  8. package/components/DataTable/DataTable.tsx +127 -32
  9. package/components/DataTable/DataTableStandAlone.tsx +4 -25
  10. package/components/DataTable/components/DataTableEditorPanel.tsx +4 -4
  11. package/components/DataTable/components/ExpandCollapse.tsx +1 -1
  12. package/components/DataTable/helpers/chartCellMatrix.tsx +6 -12
  13. package/components/DataTable/helpers/getChartCellValue.ts +9 -5
  14. package/components/DataTable/helpers/getDataSeriesColumns.ts +10 -7
  15. package/components/DataTable/helpers/getRowType.ts +6 -0
  16. package/components/DataTable/helpers/mapCellMatrix.tsx +3 -3
  17. package/components/DataTable/types/TableConfig.ts +2 -1
  18. package/components/EditorPanel/ColumnsEditor.tsx +3 -30
  19. package/components/EditorPanel/DataTableEditor.tsx +66 -22
  20. package/components/EditorPanel/FieldSetWrapper.tsx +51 -0
  21. package/components/EditorPanel/FootnotesEditor.tsx +77 -0
  22. package/components/EditorPanel/Inputs.tsx +13 -4
  23. package/components/EditorPanel/VizFilterEditor/NestedDropdownEditor.tsx +268 -0
  24. package/components/EditorPanel/VizFilterEditor/VizFilterEditor.tsx +306 -0
  25. package/components/EditorPanel/VizFilterEditor/components/FilterOrder.tsx +40 -0
  26. package/components/EditorPanel/VizFilterEditor/index.ts +1 -0
  27. package/components/EditorWrapper/EditorWrapper.tsx +3 -4
  28. package/components/EditorWrapper/index.ts +1 -0
  29. package/components/Filters.tsx +520 -0
  30. package/components/Footnotes/Footnotes.tsx +25 -0
  31. package/components/Footnotes/FootnotesStandAlone.tsx +45 -0
  32. package/components/Footnotes/footnotes.css +5 -0
  33. package/components/Footnotes/index.ts +1 -0
  34. package/components/Layout/components/Responsive.tsx +14 -4
  35. package/components/Layout/components/Sidebar/components/Sidebar.tsx +14 -5
  36. package/components/Layout/components/Sidebar/components/sidebar.styles.scss +23 -20
  37. package/components/Layout/components/Visualization/index.tsx +19 -6
  38. package/components/Layout/components/Visualization/visualizations.scss +32 -26
  39. package/components/Layout/styles/editor.scss +0 -8
  40. package/components/Legend/Legend.Gradient.tsx +133 -0
  41. package/components/LegendShape.tsx +28 -0
  42. package/components/MultiSelect/MultiSelect.tsx +41 -11
  43. package/components/MultiSelect/multiselect.styles.css +0 -3
  44. package/components/NestedDropdown/NestedDropdown.tsx +47 -52
  45. package/components/NestedDropdown/nesteddropdown.styles.css +19 -25
  46. package/components/Table/Table.tsx +8 -5
  47. package/components/Table/components/Cell.tsx +2 -2
  48. package/components/Table/components/Row.tsx +25 -7
  49. package/components/_stories/Footnotes.stories.tsx +17 -0
  50. package/components/_stories/Layout.Debug.stories.tsx +91 -0
  51. package/components/_stories/_mocks/bar-chart-suppressed.json +474 -0
  52. package/components/_stories/styles.scss +14 -1
  53. package/components/createBarElement.jsx +4 -4
  54. package/components/inputs/InputSelect.tsx +17 -6
  55. package/components/ui/Icon.tsx +22 -16
  56. package/components/ui/Title/Title.scss +0 -8
  57. package/helpers/DataTransform.ts +2 -2
  58. package/helpers/addValuesToFilters.ts +135 -0
  59. package/helpers/cove/accessibility.ts +17 -4
  60. package/helpers/cove/fontSettings.ts +2 -0
  61. package/helpers/coveUpdateWorker.ts +30 -9
  62. package/helpers/filterVizData.ts +49 -0
  63. package/helpers/formatConfigBeforeSave.ts +95 -0
  64. package/helpers/gatherQueryParams.ts +14 -7
  65. package/helpers/getGradientLegendWidth.ts +15 -0
  66. package/helpers/getTextWidth.ts +18 -0
  67. package/helpers/lineChartHelpers.js +2 -1
  68. package/helpers/pivotData.ts +18 -0
  69. package/helpers/queryStringUtils.ts +29 -0
  70. package/helpers/scaling.ts +7 -0
  71. package/helpers/tests/addValuesToFilters.test.ts +55 -0
  72. package/helpers/tests/filterVizData.test.ts +31 -0
  73. package/helpers/tests/invertValue.test.ts +35 -0
  74. package/helpers/tests/updateFieldFactory.test.ts +1 -0
  75. package/helpers/updateFieldFactory.ts +1 -1
  76. package/helpers/updatePaletteNames.ts +19 -0
  77. package/helpers/{useDataVizClasses.js → useDataVizClasses.ts} +3 -2
  78. package/helpers/ver/4.24.5.ts +3 -3
  79. package/helpers/ver/4.24.7.ts +123 -0
  80. package/helpers/ver/4.24.9.ts +63 -0
  81. package/helpers/ver/tests/4.24.9.test.ts +22 -0
  82. package/helpers/ver/versionNeedsUpdate.ts +9 -0
  83. package/package.json +6 -4
  84. package/styles/_button-section.scss +7 -2
  85. package/styles/_data-table.scss +0 -1
  86. package/styles/_global.scss +6 -2
  87. package/styles/base.scss +4 -0
  88. package/styles/filters.scss +4 -0
  89. package/styles/v2/themes/_color-definitions.scss +1 -0
  90. package/types/Annotation.ts +46 -0
  91. package/types/Axis.ts +3 -2
  92. package/types/ConfigureData.ts +1 -1
  93. package/types/Dimensions.ts +1 -0
  94. package/types/Footnotes.ts +17 -0
  95. package/types/General.ts +5 -0
  96. package/types/Runtime.ts +2 -7
  97. package/types/Table.ts +6 -0
  98. package/types/Visualization.ts +31 -9
  99. package/types/VizFilter.ts +39 -7
  100. package/LICENSE +0 -201
  101. package/components/AdvancedEditor.jsx +0 -74
  102. package/components/EditorPanel/VizFilterEditor.tsx +0 -234
  103. package/components/Filters.jsx +0 -461
  104. package/components/LegendCircle.jsx +0 -17
  105. package/helpers/queryStringUtils.js +0 -26
  106. package/helpers/updatePaletteNames.js +0 -16
  107. package/types/BaseVisualizationType.ts +0 -1
  108. /package/components/{Waiting.jsx → Waiting.tsx} +0 -0
  109. /package/helpers/ver/{4.23.4.ts → 4.24.4.ts} +0 -0
@@ -1,4 +1,4 @@
1
- import LegendCircle from '@cdc/core/components/LegendCircle'
1
+ import LegendShape from '@cdc/core/components/LegendShape'
2
2
  import CellAnchor from '../components/CellAnchor'
3
3
  import { DataTableProps } from '../DataTable'
4
4
  import { ReactNode } from 'react'
@@ -7,7 +7,7 @@ type MapRowsProps = DataTableProps & {
7
7
  rows: string[]
8
8
  }
9
9
 
10
- const mapCellArray = ({ rows, columns, runtimeData, config, applyLegendToRow, displayGeoName, formatLegendLocation, displayDataAsText, navigationHandler, setFilteredCountryCode, viewport }: MapRowsProps): ReactNode[][] => {
10
+ const mapCellArray = ({ rows, columns, runtimeData, config, applyLegendToRow, displayGeoName, formatLegendLocation, displayDataAsText, navigationHandler, setFilteredCountryCode }: MapRowsProps): ReactNode[][] => {
11
11
  return rows.map(row =>
12
12
  Object.keys(columns)
13
13
  .filter(column => columns[column].dataTable === true && columns[column].name)
@@ -31,7 +31,7 @@ const mapCellArray = ({ rows, columns, runtimeData, config, applyLegendToRow, di
31
31
  }
32
32
  cellValue = (
33
33
  <div className='col-12'>
34
- <LegendCircle viewport={viewport} fill={legendColor[0]} />
34
+ <LegendShape fill={legendColor[0]} />
35
35
  <CellAnchor markup={labelValue} row={rowObj} columns={columns} navigationHandler={navigationHandler} mapZoomHandler={mapZoomHandler} />
36
36
  </div>
37
37
  )
@@ -2,7 +2,7 @@ import { Axis } from '../../../types/Axis'
2
2
  import { Runtime } from '../../../types/Runtime'
3
3
  import { Region } from '../../../types/Region'
4
4
  import { BoxPlot } from '../../../types/BoxPlot'
5
- import { PreliminaryDataItem } from '@cdc/chart/src/components/LineChart/LineChartProps'
5
+ import { type PreliminaryDataItem } from '@cdc/chart/src/types/ChartConfig'
6
6
  import { Visualization } from '../../../types/Visualization'
7
7
 
8
8
  export type TableConfig = Visualization & {
@@ -14,4 +14,5 @@ export type TableConfig = Visualization & {
14
14
  xAxis?: Axis
15
15
  yAxis?: Axis
16
16
  preliminaryData: PreliminaryDataItem[]
17
+ brush: { active: boolean }
17
18
  }
@@ -1,4 +1,3 @@
1
- import { AccordionItem, AccordionItemButton, AccordionItemHeading, AccordionItemPanel } from 'react-accessible-accordion'
2
1
  import Tooltip from '../ui/Tooltip'
3
2
  import Icon from '../ui/Icon'
4
3
  import { TextField } from './Inputs'
@@ -7,6 +6,7 @@ import { UpdateFieldFunc } from '../../types/UpdateFieldFunc'
7
6
  import { Column } from '../../types/Column'
8
7
  import _ from 'lodash'
9
8
  import React, { useState } from 'react'
9
+ import FieldSetWrapper from './FieldSetWrapper'
10
10
 
11
11
  interface ColumnsEditorProps {
12
12
  config: Partial<Visualization>
@@ -18,10 +18,6 @@ type OpenControls = [Record<string, boolean>, Function] // useState type
18
18
 
19
19
  const FieldSet: React.FC<ColumnsEditorProps & { colKey: string; controls: OpenControls }> = ({ config, deleteColumn, updateField, colKey, controls }) => {
20
20
  const [openControls, setOpenControls] = controls
21
- const show = openControls[colKey]
22
- const setShow = (key, value) => {
23
- setOpenControls({ ...openControls, [key]: value })
24
- }
25
21
 
26
22
  const editColumn = (key, value) => {
27
23
  if (key === 'dataTable' && value === true) {
@@ -66,31 +62,8 @@ const FieldSet: React.FC<ColumnsEditorProps & { colKey: string; controls: OpenCo
66
62
 
67
63
  const colName = config.columns[colKey]?.name
68
64
 
69
- if (!show)
70
- return (
71
- <div className='mb-1'>
72
- <button onClick={() => setShow(colKey, true)}>
73
- <Icon display='caretDown' />
74
- </button>
75
- <span> {colName ? `${colName}` : 'New Column'}</span>
76
- </div>
77
- )
78
65
  return (
79
- <fieldset className='edit-block mb-1' key={colKey}>
80
- <div className='d-flex justify-content-between'>
81
- <button onClick={() => setShow(colKey, false)}>
82
- <Icon display='caretUp' />
83
- </button>
84
- <button
85
- className='btn btn-danger btn-sm'
86
- onClick={event => {
87
- event.preventDefault()
88
- deleteColumn(colKey)
89
- }}
90
- >
91
- Remove
92
- </button>
93
- </div>
66
+ <FieldSetWrapper fieldName={colName} fieldKey={colKey} fieldType='Column' controls={controls} deleteField={() => deleteColumn(colKey)}>
94
67
  <label>
95
68
  <span className='edit-label column-heading'>Column</span>
96
69
  <select
@@ -231,7 +204,7 @@ const FieldSet: React.FC<ColumnsEditorProps & { colKey: string; controls: OpenCo
231
204
  <span className='edit-label column-heading'>Order</span>
232
205
  <input onWheel={e => e.currentTarget.blur()} type='number' min='1' value={config.columns[colKey].order} onChange={e => updateField('columns', colKey, 'order', parseInt(e.target.value))} />
233
206
  </label>
234
- </fieldset>
207
+ </FieldSetWrapper>
235
208
  )
236
209
  }
237
210
 
@@ -1,7 +1,7 @@
1
1
  import React, { useMemo } from 'react'
2
2
  import Tooltip from '@cdc/core/components/ui/Tooltip'
3
3
  import Icon from '../ui/Icon'
4
- import { CheckBox, TextField } from './Inputs'
4
+ import { CheckBox, TextField, Select } from './Inputs'
5
5
  import MultiSelect from '../MultiSelect'
6
6
  import { UpdateFieldFunc } from '../../types/UpdateFieldFunc'
7
7
  import { Visualization } from '../../types/Visualization'
@@ -26,15 +26,13 @@ const DataTableEditor: React.FC<DataTableProps> = ({ config, updateField, isDash
26
26
  .map(([key]) => key)
27
27
  }, [config.columns])
28
28
 
29
- const getGroupableColumns = () => {
29
+ const groupPivotColumns = useMemo(() => {
30
30
  const columns: string[] = config.data.flatMap(Object.keys)
31
- const configuredColumns = Object.values(config.columns).map(col => col.name)
32
31
  const cols = _.uniq(columns).filter(key => {
33
- if (configuredColumns.includes(key)) return false
34
32
  return true
35
33
  })
36
34
  return cols
37
- }
35
+ }, [config.data])
38
36
 
39
37
  const changeGroupBy = (value: string) => {
40
38
  if (value === PLACEHOLDER) value = undefined
@@ -123,6 +121,7 @@ const DataTableEditor: React.FC<DataTableProps> = ({ config, updateField, isDash
123
121
  }
124
122
  />
125
123
  )}
124
+
126
125
  {config.type !== 'table' && (
127
126
  <TextField
128
127
  value={config.table.indexLabel}
@@ -163,7 +162,7 @@ const DataTableEditor: React.FC<DataTableProps> = ({ config, updateField, isDash
163
162
  />
164
163
  <CheckBox value={config.table.limitHeight} section='table' fieldName='limitHeight' label=' Limit Table Height' updateField={updateField} />
165
164
  {config.table.limitHeight && <TextField value={config.table.height} section='table' fieldName='height' label='Data Table Height' type='number' min={0} max={500} placeholder='Height(px)' updateField={updateField} />}
166
- <MultiSelect key={excludedColumns.join('') + 'excluded'} options={dataColumns.map(c => ({ label: c, value: c }))} selected={excludedColumns} fieldName='dataTable' label='Exclude Columns' section='columns' updateField={excludeColumns} />
165
+ {config?.visualizationType !== 'Sankey' && <MultiSelect key={excludedColumns.join('') + 'excluded'} options={dataColumns.map(c => ({ label: c, value: c }))} selected={excludedColumns} fieldName='dataTable' label='Exclude Columns' section='columns' updateField={excludeColumns} />}
167
166
  <CheckBox value={config.table.collapsible} fieldName='collapsible' label=' Collapsible' section='table' updateField={updateField} />
168
167
  {config.table.collapsible !== false && <CheckBox value={config.table.expanded} fieldName='expanded' label=' Expanded by Default' section='table' updateField={updateField} />}
169
168
  {isDashboard && config.type !== 'table' && <CheckBox value={config.table.showDataTableLink} fieldName='showDataTableLink' label='Show Data Table Name & Link' section='table' updateField={updateField} />}
@@ -173,29 +172,74 @@ const DataTableEditor: React.FC<DataTableProps> = ({ config, updateField, isDash
173
172
  <span className='edit-label column-heading'>Table Cell Min Width</span>
174
173
  <input type='number' value={config.table.cellMinWidth ? config.table.cellMinWidth : 0} onChange={e => updateField('table', null, 'cellMinWidth', e.target.value)} />
175
174
  </label>
176
- <label>
177
- <span className='edit-label column-heading'>
178
- Group By{' '}
175
+ {config?.visualizationType !== 'Sankey' && (
176
+ <label>
177
+ <span className='edit-label column-heading'>
178
+ Group By{' '}
179
+ <Tooltip style={{ textTransform: 'none' }}>
180
+ <Tooltip.Target>
181
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
182
+ </Tooltip.Target>
183
+ <Tooltip.Content>
184
+ <p>Choose a column to use for grouping data rows. The selected column will not be shown in the data table. You will only be able to choose a column which does not have a column configuration.</p>
185
+ </Tooltip.Content>
186
+ </Tooltip>
187
+ </span>
188
+
189
+ <select
190
+ value={config.table.groupBy}
191
+ onChange={event => {
192
+ changeGroupBy(event.target.value)
193
+ }}
194
+ >
195
+ {[PLACEHOLDER, ...groupPivotColumns.filter(col => col !== config.table.pivot?.columnName && col !== config.table.pivot?.valueColumn)].map(option => (
196
+ <option key={option}>{option}</option>
197
+ ))}
198
+ </select>
199
+ </label>
200
+ )}
201
+ <Select
202
+ label='Pivot Column: '
203
+ tooltip={
179
204
  <Tooltip style={{ textTransform: 'none' }}>
180
205
  <Tooltip.Target>
181
206
  <Icon display='question' style={{ marginLeft: '0.5rem' }} />
182
207
  </Tooltip.Target>
183
208
  <Tooltip.Content>
184
- <p>Choose a column to use for grouping data rows. The selected column will not be shown in the data table. You will only be able to choose a column which does not have a column configuration.</p>
209
+ <p>Select a Column whos data values will be pivoted to Column Values.</p>
185
210
  </Tooltip.Content>
186
211
  </Tooltip>
187
- </span>
188
- <select
189
- value={config.table.groupBy}
190
- onChange={event => {
191
- changeGroupBy(event.target.value)
192
- }}
193
- >
194
- {[PLACEHOLDER, ...getGroupableColumns()].map(option => (
195
- <option key={option}>{option}</option>
196
- ))}
197
- </select>
198
- </label>
212
+ }
213
+ value={config.table.pivot?.columnName}
214
+ options={groupPivotColumns.filter(col => col !== config.table.groupBy && col !== config.table.pivot?.valueColumn)}
215
+ initial='-Select-'
216
+ section='table'
217
+ subsection='pivot'
218
+ fieldName='columnName'
219
+ updateField={updateField}
220
+ />
221
+ {config.table.pivot?.columnName && (
222
+ <Select
223
+ label='Pivot Value Column: '
224
+ tooltip={
225
+ <Tooltip style={{ textTransform: 'none' }}>
226
+ <Tooltip.Target>
227
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
228
+ </Tooltip.Target>
229
+ <Tooltip.Content>
230
+ <p>The column whos values will be pivoted under the column selected as the Filter.</p>
231
+ </Tooltip.Content>
232
+ </Tooltip>
233
+ }
234
+ value={config.table.pivot?.valueColumn}
235
+ initial='-Select-'
236
+ section='table'
237
+ options={groupPivotColumns.filter(col => col !== config.table.pivot?.columnName && col !== config.table.groupBy)}
238
+ subsection='pivot'
239
+ fieldName='valueColumn'
240
+ updateField={updateField}
241
+ />
242
+ )}
199
243
  </>
200
244
  )
201
245
  }
@@ -0,0 +1,51 @@
1
+ import Icon from '../ui/Icon'
2
+
3
+ type OpenControls = [Record<string, boolean>, Function] // useState type
4
+
5
+ type FieldSetProps = {
6
+ fieldName: string
7
+ fieldKey: string | number
8
+ fieldType: string
9
+ controls: OpenControls
10
+ deleteField: Function
11
+ children: React.ReactNode
12
+ }
13
+
14
+ const FieldSet: React.FC<FieldSetProps> = ({ fieldName, fieldKey, fieldType, controls, deleteField, children }) => {
15
+ const [openControls, setOpenControls] = controls
16
+ const show = openControls[fieldKey]
17
+ const setShow = (key, value) => {
18
+ setOpenControls({ ...openControls, [key]: value })
19
+ }
20
+
21
+ if (!show)
22
+ return (
23
+ <div className='mb-1'>
24
+ <button onClick={() => setShow(fieldKey, true)}>
25
+ <Icon display='caretDown' />
26
+ </button>
27
+ <span> {fieldName ? `${fieldName}` : 'New ' + fieldType}</span>
28
+ </div>
29
+ )
30
+ return (
31
+ <fieldset className='edit-block mb-1' key={fieldKey}>
32
+ <div className='d-flex justify-content-between'>
33
+ <button onClick={() => setShow(fieldKey, false)}>
34
+ <Icon display='caretUp' />
35
+ </button>
36
+ <button
37
+ className='btn btn-danger btn-sm'
38
+ onClick={event => {
39
+ event.preventDefault()
40
+ deleteField()
41
+ }}
42
+ >
43
+ Remove
44
+ </button>
45
+ </div>
46
+ {children}
47
+ </fieldset>
48
+ )
49
+ }
50
+
51
+ export default FieldSet
@@ -0,0 +1,77 @@
1
+ import { UpdateFieldFunc } from '../../types/UpdateFieldFunc'
2
+ import _ from 'lodash'
3
+ import Footnotes, { Footnote } from '../../types/Footnotes'
4
+ import { footnotesSymbols } from '../../helpers/footnoteSymbols'
5
+ import InputSelect from '../inputs/InputSelect'
6
+ import { TextField } from './Inputs'
7
+ interface FootnotesEditorProps {
8
+ config: Footnotes
9
+ updateField: UpdateFieldFunc<Footnote[]>
10
+ }
11
+
12
+ const FootnotesEditor: React.FC<FootnotesEditorProps> = ({ config, updateField }) => {
13
+ const addStaticFootnote = () => {
14
+ const newStaticNotes = [...(config.staticFootnotes || []), { text: 'Add Footnote Text' }]
15
+ updateField(null, null, 'staticFootnotes', newStaticNotes)
16
+ }
17
+
18
+ const updateStaticFootnote = (footnoteIndex, footnoteUpdate: Footnote) => {
19
+ const footnoteCopy = _.cloneDeep(config.staticFootnotes)
20
+ footnoteCopy[footnoteIndex] = footnoteUpdate
21
+ updateField(null, null, 'staticFootnotes', footnoteCopy)
22
+ }
23
+
24
+ const deleteStaticFootnote = footnoteIndex => {
25
+ const footnoteCopy = _.cloneDeep(config.staticFootnotes)
26
+ footnoteCopy.splice(footnoteIndex, 1)
27
+ updateField(null, null, 'staticFootnotes', footnoteCopy)
28
+ }
29
+
30
+ const getOptions = (opts: string[]) => {
31
+ return [['', '--Select--']].concat(opts.map(key => [key, key]))
32
+ }
33
+
34
+ const datasets = config.datasets || {}
35
+
36
+ const dataColumns = config.dataKey ? getOptions(Object.keys(datasets[config.dataKey]?.data?.[0] || {})) : []
37
+ const dataSetOptions = getOptions(Object.keys(datasets))
38
+ return (
39
+ <>
40
+ <em>Dynamic Footnotes</em>
41
+ <div className='row border p-2'>
42
+ <InputSelect label='Select a Footnote Dataset' value={config.dataKey} options={dataSetOptions} fieldName='dataKey' updateField={updateField} />
43
+
44
+ {config.dataKey && (
45
+ <div className='p-3'>
46
+ <InputSelect label='Footnote Symbol Column' value={config.dynamicFootnotes?.symbolColumn} options={dataColumns} section='dynamicFootnotes' fieldName='symbolColumn' updateField={updateField} />
47
+ <InputSelect label='Footnote Text Column' value={config.dynamicFootnotes?.textColumn} options={dataColumns} section='dynamicFootnotes' fieldName='textColumn' updateField={updateField} />
48
+ <InputSelect label='Footnote Order Column' value={config.dynamicFootnotes?.orderColumn} options={dataColumns} section='dynamicFootnotes' fieldName='orderColumn' updateField={updateField} />
49
+ </div>
50
+ )}
51
+ </div>
52
+
53
+ <hr />
54
+
55
+ <em>Static Footnotes</em>
56
+
57
+ {config.staticFootnotes?.map((note, index) => (
58
+ <div key={index} className='row border p-2'>
59
+ <div className='col-8'>
60
+ <InputSelect label='Symbol' value={note.symbol} options={[['', '--Select--'], ...footnotesSymbols]} fieldName='symbol' updateField={(section, subsection, fieldName, value) => updateStaticFootnote(index, { ...note, symbol: value })} />{' '}
61
+ <TextField label='Text' value={note.text} fieldName='text' updateField={(section, subsection, fieldName, value) => updateStaticFootnote(index, { ...note, text: value })} />
62
+ </div>
63
+ <div className='col-2 ml-4'>
64
+ <button className='btn btn-danger p-1' onClick={() => deleteStaticFootnote(index)}>
65
+ Delete
66
+ </button>
67
+ </div>
68
+ </div>
69
+ ))}
70
+ <button className='btn btn-primary' onClick={addStaticFootnote}>
71
+ Add Static Footnote
72
+ </button>
73
+ </>
74
+ )
75
+ }
76
+
77
+ export default FootnotesEditor
@@ -9,6 +9,7 @@ export type Input = {
9
9
  subsection?: any
10
10
  updateField?: Function
11
11
  fieldName?: string
12
+ display?: boolean
12
13
  }
13
14
 
14
15
  export type TextFieldProps = {
@@ -39,7 +40,7 @@ export type SelectProps = {
39
40
  } & Input
40
41
 
41
42
  const TextField = memo((props: TextFieldProps) => {
42
- const { label, tooltip, section = null, subsection = null, fieldName, updateField, value: stateValue, type = 'text', i = null, min = null, ...attributes } = props
43
+ const { display = true, label, tooltip, section = null, subsection = null, fieldName, updateField, value: stateValue, type = 'text', i = null, min = null, ...attributes } = props
43
44
  const [value, setValue] = useState(stateValue)
44
45
  const [debouncedValue] = useDebounce(value, 500)
45
46
 
@@ -76,6 +77,9 @@ const TextField = memo((props: TextFieldProps) => {
76
77
  if ('date' === type) {
77
78
  formElement = <input type='date' name={name} onChange={onChange} {...attributes} value={value} />
78
79
  }
80
+ if (!display) {
81
+ return <></>
82
+ }
79
83
 
80
84
  return (
81
85
  <label>
@@ -89,8 +93,10 @@ const TextField = memo((props: TextFieldProps) => {
89
93
  })
90
94
 
91
95
  const CheckBox = memo((props: CheckboxProps) => {
92
- const { label, value, fieldName, section = null, subsection = null, tooltip, updateField, ...attributes } = props
93
-
96
+ const { display = true, label, value, fieldName, section = null, subsection = null, tooltip, updateField, ...attributes } = props
97
+ if (!display) {
98
+ return <></>
99
+ }
94
100
  return (
95
101
  <label className='checkbox column-heading'>
96
102
  <input
@@ -111,7 +117,7 @@ const CheckBox = memo((props: CheckboxProps) => {
111
117
  })
112
118
 
113
119
  const Select = memo((props: SelectProps) => {
114
- const { label, value, options, fieldName, section = null, subsection = null, required = false, tooltip, updateField, initial: initialValue, ...attributes } = props
120
+ const { display = true, label, value, options, fieldName, section = null, subsection = null, required = false, tooltip, updateField, initial: initialValue, ...attributes } = props
115
121
  let optionsJsx = options.map((optionName, index) => (
116
122
  <option value={optionName} key={index}>
117
123
  {optionName}
@@ -125,6 +131,9 @@ const Select = memo((props: SelectProps) => {
125
131
  </option>
126
132
  )
127
133
  }
134
+ if (!display) {
135
+ return <></>
136
+ }
128
137
 
129
138
  return (
130
139
  <label>