@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.
- package/assets/icon-gear-multi.svg +23 -0
- package/components/AdvancedEditor/AdvancedEditor.tsx +93 -0
- package/components/AdvancedEditor/advanced-editor-styles.css +3 -0
- package/components/AdvancedEditor/index.ts +1 -0
- package/components/Alert/components/Alert.styles.css +15 -0
- package/components/Alert/components/Alert.tsx +39 -0
- package/components/Alert/index.tsx +3 -0
- package/components/DataTable/DataTable.tsx +127 -32
- package/components/DataTable/DataTableStandAlone.tsx +4 -25
- package/components/DataTable/components/DataTableEditorPanel.tsx +4 -4
- package/components/DataTable/components/ExpandCollapse.tsx +1 -1
- package/components/DataTable/helpers/chartCellMatrix.tsx +6 -12
- package/components/DataTable/helpers/getChartCellValue.ts +9 -5
- package/components/DataTable/helpers/getDataSeriesColumns.ts +10 -7
- package/components/DataTable/helpers/getRowType.ts +6 -0
- package/components/DataTable/helpers/mapCellMatrix.tsx +3 -3
- package/components/DataTable/types/TableConfig.ts +2 -1
- package/components/EditorPanel/ColumnsEditor.tsx +3 -30
- package/components/EditorPanel/DataTableEditor.tsx +66 -22
- package/components/EditorPanel/FieldSetWrapper.tsx +51 -0
- package/components/EditorPanel/FootnotesEditor.tsx +77 -0
- package/components/EditorPanel/Inputs.tsx +13 -4
- package/components/EditorPanel/VizFilterEditor/NestedDropdownEditor.tsx +268 -0
- package/components/EditorPanel/VizFilterEditor/VizFilterEditor.tsx +306 -0
- package/components/EditorPanel/VizFilterEditor/components/FilterOrder.tsx +40 -0
- package/components/EditorPanel/VizFilterEditor/index.ts +1 -0
- package/components/EditorWrapper/EditorWrapper.tsx +3 -4
- package/components/EditorWrapper/index.ts +1 -0
- package/components/Filters.tsx +520 -0
- package/components/Footnotes/Footnotes.tsx +25 -0
- package/components/Footnotes/FootnotesStandAlone.tsx +45 -0
- package/components/Footnotes/footnotes.css +5 -0
- package/components/Footnotes/index.ts +1 -0
- package/components/Layout/components/Responsive.tsx +14 -4
- package/components/Layout/components/Sidebar/components/Sidebar.tsx +14 -5
- package/components/Layout/components/Sidebar/components/sidebar.styles.scss +23 -20
- package/components/Layout/components/Visualization/index.tsx +19 -6
- package/components/Layout/components/Visualization/visualizations.scss +32 -26
- package/components/Layout/styles/editor.scss +0 -8
- package/components/Legend/Legend.Gradient.tsx +133 -0
- package/components/LegendShape.tsx +28 -0
- package/components/MultiSelect/MultiSelect.tsx +41 -11
- package/components/MultiSelect/multiselect.styles.css +0 -3
- package/components/NestedDropdown/NestedDropdown.tsx +47 -52
- package/components/NestedDropdown/nesteddropdown.styles.css +19 -25
- package/components/Table/Table.tsx +8 -5
- package/components/Table/components/Cell.tsx +2 -2
- package/components/Table/components/Row.tsx +25 -7
- package/components/_stories/Footnotes.stories.tsx +17 -0
- package/components/_stories/Layout.Debug.stories.tsx +91 -0
- package/components/_stories/_mocks/bar-chart-suppressed.json +474 -0
- package/components/_stories/styles.scss +14 -1
- package/components/createBarElement.jsx +4 -4
- package/components/inputs/InputSelect.tsx +17 -6
- package/components/ui/Icon.tsx +22 -16
- package/components/ui/Title/Title.scss +0 -8
- package/helpers/DataTransform.ts +2 -2
- package/helpers/addValuesToFilters.ts +135 -0
- package/helpers/cove/accessibility.ts +17 -4
- package/helpers/cove/fontSettings.ts +2 -0
- package/helpers/coveUpdateWorker.ts +30 -9
- package/helpers/filterVizData.ts +49 -0
- package/helpers/formatConfigBeforeSave.ts +95 -0
- package/helpers/gatherQueryParams.ts +14 -7
- package/helpers/getGradientLegendWidth.ts +15 -0
- package/helpers/getTextWidth.ts +18 -0
- package/helpers/lineChartHelpers.js +2 -1
- package/helpers/pivotData.ts +18 -0
- package/helpers/queryStringUtils.ts +29 -0
- package/helpers/scaling.ts +7 -0
- package/helpers/tests/addValuesToFilters.test.ts +55 -0
- package/helpers/tests/filterVizData.test.ts +31 -0
- package/helpers/tests/invertValue.test.ts +35 -0
- package/helpers/tests/updateFieldFactory.test.ts +1 -0
- package/helpers/updateFieldFactory.ts +1 -1
- package/helpers/updatePaletteNames.ts +19 -0
- package/helpers/{useDataVizClasses.js → useDataVizClasses.ts} +3 -2
- package/helpers/ver/4.24.5.ts +3 -3
- package/helpers/ver/4.24.7.ts +123 -0
- package/helpers/ver/4.24.9.ts +63 -0
- package/helpers/ver/tests/4.24.9.test.ts +22 -0
- package/helpers/ver/versionNeedsUpdate.ts +9 -0
- package/package.json +6 -4
- package/styles/_button-section.scss +7 -2
- package/styles/_data-table.scss +0 -1
- package/styles/_global.scss +6 -2
- package/styles/base.scss +4 -0
- package/styles/filters.scss +4 -0
- package/styles/v2/themes/_color-definitions.scss +1 -0
- package/types/Annotation.ts +46 -0
- package/types/Axis.ts +3 -2
- package/types/ConfigureData.ts +1 -1
- package/types/Dimensions.ts +1 -0
- package/types/Footnotes.ts +17 -0
- package/types/General.ts +5 -0
- package/types/Runtime.ts +2 -7
- package/types/Table.ts +6 -0
- package/types/Visualization.ts +31 -9
- package/types/VizFilter.ts +39 -7
- package/LICENSE +0 -201
- package/components/AdvancedEditor.jsx +0 -74
- package/components/EditorPanel/VizFilterEditor.tsx +0 -234
- package/components/Filters.jsx +0 -461
- package/components/LegendCircle.jsx +0 -17
- package/helpers/queryStringUtils.js +0 -26
- package/helpers/updatePaletteNames.js +0 -16
- package/types/BaseVisualizationType.ts +0 -1
- /package/components/{Waiting.jsx → Waiting.tsx} +0 -0
- /package/helpers/ver/{4.23.4.ts → 4.24.4.ts} +0 -0
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { useState, useEffect, useRef, useMemo } from 'react'
|
|
2
2
|
import './nesteddropdown.styles.css'
|
|
3
3
|
import Icon from '@cdc/core/components/ui/Icon'
|
|
4
|
+
import { VizFilter } from '../../types/VizFilter'
|
|
4
5
|
|
|
5
6
|
const Options: React.FC<{
|
|
6
7
|
currentOptions: (string | number)[]
|
|
7
8
|
label: string
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
handleSubGroupSelect: Function
|
|
10
|
+
userSelectedLabel: string
|
|
10
11
|
userSearchTerm: string
|
|
11
|
-
}> = ({ currentOptions, label,
|
|
12
|
+
}> = ({ currentOptions = [], label, handleSubGroupSelect, userSelectedLabel, userSearchTerm }) => {
|
|
12
13
|
const [isTierOneExpanded, setIsTierOneExpanded] = useState(true)
|
|
13
|
-
|
|
14
14
|
const checkMark = <>✔</>
|
|
15
15
|
|
|
16
16
|
useEffect(() => {
|
|
@@ -29,23 +29,24 @@ const Options: React.FC<{
|
|
|
29
29
|
if (currentItem.className === 'selectable-item') currentItem.parentNode.parentNode.focus()
|
|
30
30
|
setIsTierOneExpanded(false)
|
|
31
31
|
} else if (e.key === 'Enter') {
|
|
32
|
-
currentItem.className === 'selectable-item' ?
|
|
32
|
+
currentItem.className === 'selectable-item' ? handleSubGroupSelect(currentItem.dataset.value) : setIsTierOneExpanded(!isTierOneExpanded)
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
return (
|
|
37
37
|
<>
|
|
38
38
|
<li role='treeitem' key={label} tabIndex={0} aria-label={label} onClick={handleGroupClick} onKeyUp={handleKeyUp} className='nested-dropdown-group'>
|
|
39
|
-
<span
|
|
39
|
+
<span className={'font-weight-bold'}>{label} </span>
|
|
40
40
|
{
|
|
41
41
|
<span className='list-arrow' aria-hidden='true'>
|
|
42
42
|
{isTierOneExpanded ? <Icon display='caretFilledUp' /> : <Icon display='caretFilledDown' />}
|
|
43
43
|
</span>
|
|
44
44
|
}
|
|
45
45
|
<ul aria-expanded={isTierOneExpanded} role='group' tabIndex={-1} aria-labelledby={label} className={isTierOneExpanded ? '' : 'hide'}>
|
|
46
|
-
{currentOptions.map(tierTwo => {
|
|
46
|
+
{currentOptions.map((tierTwo, tierTwoIndex) => {
|
|
47
47
|
const regionID = label + tierTwo
|
|
48
|
-
|
|
48
|
+
const isSelected = regionID === userSelectedLabel
|
|
49
|
+
|
|
49
50
|
return (
|
|
50
51
|
<li
|
|
51
52
|
key={regionID}
|
|
@@ -56,10 +57,16 @@ const Options: React.FC<{
|
|
|
56
57
|
aria-selected={isSelected}
|
|
57
58
|
data-value={tierTwo}
|
|
58
59
|
onClick={e => {
|
|
59
|
-
|
|
60
|
+
handleSubGroupSelect(tierTwo)
|
|
60
61
|
}}
|
|
61
62
|
>
|
|
62
|
-
{isSelected ?
|
|
63
|
+
{isSelected ? (
|
|
64
|
+
<span className='check-mark' aria-hidden='true'>
|
|
65
|
+
{checkMark}
|
|
66
|
+
</span>
|
|
67
|
+
) : (
|
|
68
|
+
''
|
|
69
|
+
)}
|
|
63
70
|
|
|
64
71
|
{tierTwo}
|
|
65
72
|
</li>
|
|
@@ -72,42 +79,43 @@ const Options: React.FC<{
|
|
|
72
79
|
}
|
|
73
80
|
|
|
74
81
|
interface NestedDropdownProps {
|
|
75
|
-
|
|
76
|
-
|
|
82
|
+
isEditor?: boolean
|
|
83
|
+
currentFilter: VizFilter
|
|
77
84
|
listLabel: string
|
|
78
85
|
handleSelectedItems: Function
|
|
79
86
|
}
|
|
80
87
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
88
|
+
type OptionsMemo = [string, (string | number)[]][]
|
|
89
|
+
|
|
90
|
+
const NestedDropdown: React.FC<NestedDropdownProps> = ({ currentFilter, listLabel, handleSelectedItems }) => {
|
|
91
|
+
const optsMemo: OptionsMemo = useMemo(() => {
|
|
92
|
+
// keep custom ordered value order
|
|
93
|
+
const values = currentFilter.orderedValues?.filter(value => currentFilter.values.includes(value)) || currentFilter.values
|
|
94
|
+
return values.map(value => {
|
|
95
|
+
if (!currentFilter.subGrouping) return [value, []]
|
|
96
|
+
const { orderedValues, values } = currentFilter.subGrouping.valuesLookup[value]
|
|
97
|
+
const subFilterValues = orderedValues?.filter(value => values.includes(value)) || values
|
|
98
|
+
return [value, subFilterValues]
|
|
99
|
+
})
|
|
100
|
+
}, [currentFilter, currentFilter.subGrouping])
|
|
101
|
+
const groupFilterActive = currentFilter.active
|
|
102
|
+
const subGroupFilterActive = currentFilter.subGrouping?.active ?? ''
|
|
93
103
|
|
|
94
|
-
const [userSelectedTierTwoLabel, setUserSelectedTierTwoLabel] = useState(null)
|
|
95
104
|
const [userSearchTerm, setUserSearchTerm] = useState('')
|
|
96
|
-
const [inputValue, setInputValue] = useState('')
|
|
105
|
+
const [inputValue, setInputValue] = useState(subGroupFilterActive !== '' ? `${groupFilterActive} - ${subGroupFilterActive}` : 'Select an Option')
|
|
97
106
|
const [inputHasFocus, setInputHasFocus] = useState(false)
|
|
98
107
|
const [isListOpened, setIsListOpened] = useState(false)
|
|
99
108
|
|
|
100
109
|
const searchInput = useRef(null)
|
|
101
110
|
const searchDropdown = useRef(null)
|
|
102
111
|
|
|
103
|
-
const
|
|
112
|
+
const chooseSelectedSubGroup = (tierOne: string, tierTwo: string) => {
|
|
104
113
|
searchInput.current.focus()
|
|
105
|
-
const selectedItemValue = tierTwo
|
|
106
|
-
setUserSelectedTierTwoLabel(tierOne + tierTwo)
|
|
114
|
+
const selectedItemValue = `${tierOne} - ${tierTwo}`
|
|
107
115
|
setUserSearchTerm('')
|
|
108
116
|
setIsListOpened(false)
|
|
109
117
|
setInputValue(selectedItemValue)
|
|
110
|
-
handleSelectedItems(tierOne, tierTwo)
|
|
118
|
+
handleSelectedItems([tierOne, tierTwo])
|
|
111
119
|
}
|
|
112
120
|
|
|
113
121
|
const handleKeyUp = e => {
|
|
@@ -182,25 +190,12 @@ const NestedDropdown: React.FC<NestedDropdownProps> = ({ data, tiers: [firstTier
|
|
|
182
190
|
}
|
|
183
191
|
}
|
|
184
192
|
|
|
185
|
-
const filterOptions:
|
|
193
|
+
const filterOptions: OptionsMemo = useMemo(() => {
|
|
186
194
|
if (!userSearchTerm) return optsMemo
|
|
187
|
-
const newOptions: Record<string, (string | number)[]> = {}
|
|
188
195
|
const newRegex = new RegExp(`^${userSearchTerm}`, 'i')
|
|
189
|
-
|
|
190
|
-
if (tierOne.match(newRegex)) {
|
|
191
|
-
newOptions[tierOne] = [...optsMemo[tierOne]]
|
|
192
|
-
} else {
|
|
193
|
-
const newSecondTierOptions = optsMemo[tierOne].filter(tierTwo => String(tierTwo).match(newRegex))
|
|
194
|
-
if (newSecondTierOptions.length > 0) {
|
|
195
|
-
newOptions[tierOne] = newSecondTierOptions
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
return newOptions
|
|
196
|
+
return optsMemo.filter(([tierOne, tierTwo]) => tierOne.match(newRegex) || tierTwo.some(value => String(value).match(newRegex)))
|
|
200
197
|
}, [userSearchTerm])
|
|
201
198
|
|
|
202
|
-
const filterOptionsKeys = Object.keys(filterOptions)
|
|
203
|
-
|
|
204
199
|
const handleSearchTermChange = e => {
|
|
205
200
|
const newSearchTerm = e.target.value
|
|
206
201
|
setIsListOpened(true)
|
|
@@ -233,16 +228,16 @@ const NestedDropdown: React.FC<NestedDropdownProps> = ({ data, tiers: [firstTier
|
|
|
233
228
|
</span>
|
|
234
229
|
</div>
|
|
235
230
|
<ul role='tree' key={listLabel} tabIndex={-1} aria-labelledby='main-nested-dropdown' aria-expanded={isListOpened} ref={searchDropdown} className={`main-nested-dropdown-container ${isListOpened ? '' : 'hide'}`}>
|
|
236
|
-
{filterOptions
|
|
237
|
-
?
|
|
231
|
+
{filterOptions?.length
|
|
232
|
+
? filterOptions.map(([groupName, options]) => {
|
|
238
233
|
return (
|
|
239
234
|
<Options
|
|
240
|
-
currentOptions={
|
|
241
|
-
label={
|
|
242
|
-
|
|
243
|
-
|
|
235
|
+
currentOptions={options}
|
|
236
|
+
label={groupName}
|
|
237
|
+
handleSubGroupSelect={(subGroupValue: string) => {
|
|
238
|
+
chooseSelectedSubGroup(groupName, subGroupValue)
|
|
244
239
|
}}
|
|
245
|
-
|
|
240
|
+
userSelectedLabel={groupFilterActive + subGroupFilterActive}
|
|
246
241
|
userSearchTerm={userSearchTerm}
|
|
247
242
|
/>
|
|
248
243
|
)
|
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
.nested-dropdown {
|
|
2
|
-
|
|
2
|
+
.nested-dropdown-group {
|
|
3
3
|
list-style: none;
|
|
4
|
-
cursor: pointer;
|
|
5
|
-
|
|
6
|
-
&:focus {
|
|
7
|
-
border: 2px solid var(--orange);
|
|
8
|
-
}
|
|
9
4
|
}
|
|
10
5
|
|
|
11
6
|
.search-input {
|
|
@@ -25,11 +20,24 @@
|
|
|
25
20
|
cursor: pointer;
|
|
26
21
|
}
|
|
27
22
|
|
|
28
|
-
.selectable-item
|
|
29
|
-
|
|
23
|
+
.selectable-item {
|
|
24
|
+
list-style: none;
|
|
25
|
+
padding-left: 20px;
|
|
26
|
+
position: relative;
|
|
27
|
+
font-weight: normal;
|
|
28
|
+
white-space: nowrap;
|
|
29
|
+
|
|
30
|
+
& .check-mark {
|
|
31
|
+
position: absolute;
|
|
32
|
+
left: 0px;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
&:hover {
|
|
36
|
+
background-color: var(--lightGray);
|
|
37
|
+
}
|
|
30
38
|
}
|
|
31
39
|
|
|
32
|
-
|
|
40
|
+
.nested-dropdown-input-container {
|
|
33
41
|
position: relative;
|
|
34
42
|
& > span.list-arrow {
|
|
35
43
|
position: absolute;
|
|
@@ -42,26 +50,12 @@
|
|
|
42
50
|
}
|
|
43
51
|
}
|
|
44
52
|
|
|
45
|
-
&
|
|
53
|
+
& .main-nested-dropdown-container {
|
|
46
54
|
max-height: 375px;
|
|
47
55
|
overflow-y: scroll;
|
|
48
56
|
position: absolute;
|
|
49
57
|
z-index: 3;
|
|
50
|
-
width:
|
|
51
|
-
|
|
52
|
-
& > li {
|
|
53
|
-
font-weight: bold;
|
|
54
|
-
|
|
55
|
-
& > ul > li {
|
|
56
|
-
position: relative;
|
|
57
|
-
font-weight: normal;
|
|
58
|
-
white-space: nowrap;
|
|
59
|
-
& > span {
|
|
60
|
-
position: absolute;
|
|
61
|
-
left: -20px;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
58
|
+
width: 325px;
|
|
65
59
|
}
|
|
66
60
|
|
|
67
61
|
.hide {
|
|
@@ -3,6 +3,7 @@ import Row from './components/Row'
|
|
|
3
3
|
import GroupRow from './components/GroupRow'
|
|
4
4
|
import { CellMatrix, GroupCellMatrix } from './types/CellMatrix'
|
|
5
5
|
import { RowType } from './types/RowType'
|
|
6
|
+
import { PreliminaryDataItem } from '@cdc/chart/src/types/ChartConfig'
|
|
6
7
|
|
|
7
8
|
type TableProps = {
|
|
8
9
|
childrenMatrix: CellMatrix | GroupCellMatrix
|
|
@@ -21,13 +22,15 @@ type TableProps = {
|
|
|
21
22
|
hasRowType?: boolean // if it has row type then the first column is the row type which will explain how to render the row
|
|
22
23
|
fontSize: 'small' | 'medium' | 'large'
|
|
23
24
|
viewport: 'lg' | 'md' | 'sm' | 'xs' | 'xxs'
|
|
25
|
+
preliminaryData?: PreliminaryDataItem[]
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
type Position = 'sticky'
|
|
27
29
|
|
|
28
|
-
const Table = ({ childrenMatrix, tableName, caption, stickyHeader, headContent, tableOptions, wrapColumns, hasRowType, fontSize, viewport }: TableProps) => {
|
|
30
|
+
const Table = ({ childrenMatrix, tableName, caption, stickyHeader, headContent, tableOptions, wrapColumns, hasRowType, fontSize, viewport, preliminaryData }: TableProps) => {
|
|
29
31
|
const headStyle = stickyHeader ? { position: 'sticky' as Position, top: 0, zIndex: 2 } : {}
|
|
30
32
|
const isGroupedMatrix = !Array.isArray(childrenMatrix)
|
|
33
|
+
|
|
31
34
|
return (
|
|
32
35
|
<table {...tableOptions}>
|
|
33
36
|
<caption className='visually-hidden'>{caption}</caption>
|
|
@@ -39,7 +42,7 @@ const Table = ({ childrenMatrix, tableName, caption, stickyHeader, headContent,
|
|
|
39
42
|
const rows = childrenMatrix[groupName].map((row, i) => {
|
|
40
43
|
colSpan = row.length
|
|
41
44
|
const key = `${tableName}-${groupName}-row-${i}`
|
|
42
|
-
return <Row key={key} rowKey={key} childRow={row} wrapColumns={wrapColumns} cellMinWidth={tableOptions.cellMinWidth} fontSize={fontSize} viewport={viewport} />
|
|
45
|
+
return <Row preliminaryData={preliminaryData} key={key} rowKey={key} childRow={row} wrapColumns={wrapColumns} cellMinWidth={tableOptions.cellMinWidth} fontSize={fontSize} viewport={viewport} />
|
|
43
46
|
})
|
|
44
47
|
return [<GroupRow label={groupName} colSpan={colSpan} key={`${tableName}-${groupName}`} />, ...rows]
|
|
45
48
|
})
|
|
@@ -49,17 +52,17 @@ const Table = ({ childrenMatrix, tableName, caption, stickyHeader, headContent,
|
|
|
49
52
|
if (hasRowType) rowType = childRowCopy.shift()
|
|
50
53
|
const key = `${tableName}-row-${i}`
|
|
51
54
|
if (rowType === undefined) {
|
|
52
|
-
return <Row key={key} rowKey={key} childRow={childRow} wrapColumns={wrapColumns} cellMinWidth={tableOptions.cellMinWidth} fontSize={fontSize} viewport={viewport} />
|
|
55
|
+
return <Row preliminaryData={preliminaryData} key={key} rowKey={key} childRow={childRow} wrapColumns={wrapColumns} cellMinWidth={tableOptions.cellMinWidth} fontSize={fontSize} viewport={viewport} />
|
|
53
56
|
} else {
|
|
54
57
|
switch (rowType) {
|
|
55
58
|
case RowType.row_group:
|
|
56
59
|
return <GroupRow label={childRowCopy[0]} colSpan={childRowCopy.length} key={key} />
|
|
57
60
|
case RowType.total:
|
|
58
|
-
return <Row key={key} rowKey={key} childRow={childRowCopy} isTotal={true} wrapColumns={wrapColumns} cellMinWidth={tableOptions.cellMinWidth} fontSize={fontSize} viewport={viewport} />
|
|
61
|
+
return <Row preliminaryData={preliminaryData} key={key} rowKey={key} childRow={childRowCopy} isTotal={true} wrapColumns={wrapColumns} cellMinWidth={tableOptions.cellMinWidth} fontSize={fontSize} viewport={viewport} />
|
|
59
62
|
case RowType.row_group_total:
|
|
60
63
|
return <GroupRow label={childRowCopy[0]} colSpan={1} key={key} data={childRowCopy.slice(1)} />
|
|
61
64
|
default:
|
|
62
|
-
return <Row key={key} rowKey={key} childRow={childRowCopy} wrapColumns={wrapColumns} cellMinWidth={tableOptions.cellMinWidth} fontSize={fontSize} viewport={viewport} />
|
|
65
|
+
return <Row preliminaryData={preliminaryData} key={key} rowKey={key} childRow={childRowCopy} wrapColumns={wrapColumns} cellMinWidth={tableOptions.cellMinWidth} fontSize={fontSize} viewport={viewport} />
|
|
63
66
|
}
|
|
64
67
|
}
|
|
65
68
|
})}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
const Cell = ({ children, style, isBold = false }) => {
|
|
1
|
+
const Cell = ({ children, style, isBold = false, ariaLabel }) => {
|
|
2
2
|
return (
|
|
3
|
-
<td tabIndex={0} role='gridcell' style={style}>
|
|
3
|
+
<td aria-label={ariaLabel} tabIndex={0} role='gridcell' style={style}>
|
|
4
4
|
{isBold ? <strong>{children}</strong> : children}
|
|
5
5
|
</td>
|
|
6
6
|
)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { ReactNode } from 'react'
|
|
1
|
+
import { ReactNode, FC } from 'react'
|
|
2
2
|
import Cell from './Cell'
|
|
3
|
+
import { PreliminaryDataItem } from '@cdc/chart/src/types/ChartConfig'
|
|
3
4
|
|
|
4
5
|
type RowProps = {
|
|
5
6
|
childRow: ReactNode[]
|
|
@@ -9,20 +10,37 @@ type RowProps = {
|
|
|
9
10
|
cellMinWidth?: number
|
|
10
11
|
fontSize: 'small' | 'medium' | 'large'
|
|
11
12
|
viewport: 'lg' | 'md' | 'sm' | 'xs' | 'xxs'
|
|
13
|
+
style?: object
|
|
14
|
+
preliminaryData?: PreliminaryDataItem[]
|
|
12
15
|
}
|
|
13
16
|
|
|
14
|
-
const Row
|
|
17
|
+
const Row: FC<RowProps> = props => {
|
|
18
|
+
const { childRow, rowKey, wrapColumns, cellMinWidth = 0, isTotal, fontSize, viewport, preliminaryData } = props
|
|
15
19
|
const whiteSpace = wrapColumns ? 'unset' : 'nowrap'
|
|
16
20
|
const minWidth = cellMinWidth + 'px'
|
|
17
21
|
const fontSizes = { small: 16, medium: 18, large: 20 }
|
|
18
22
|
const cellFontSize = ['sm', 'xs', 'xxs'].includes(viewport) ? '11px' : `${fontSizes[fontSize]}px`
|
|
23
|
+
|
|
19
24
|
return (
|
|
20
25
|
<tr>
|
|
21
|
-
{childRow.map((child, i) =>
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
+
{childRow.map((child, i) => {
|
|
27
|
+
const style =
|
|
28
|
+
(preliminaryData?.some(
|
|
29
|
+
pd => pd.type === 'suppression' && child === pd.iconCode && pd.displayGray && pd.displayTable
|
|
30
|
+
) && { color: '#777772' }) ||
|
|
31
|
+
{}
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<Cell
|
|
35
|
+
ariaLabel={style?.color ? 'suppressed data' : ''}
|
|
36
|
+
key={rowKey + '__' + i}
|
|
37
|
+
style={{ whiteSpace, minWidth, fontSize: cellFontSize, ...style }}
|
|
38
|
+
isBold={isTotal}
|
|
39
|
+
>
|
|
40
|
+
{child}
|
|
41
|
+
</Cell>
|
|
42
|
+
)
|
|
43
|
+
})}
|
|
26
44
|
</tr>
|
|
27
45
|
)
|
|
28
46
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Meta, StoryObj } from '@storybook/react'
|
|
2
|
+
import Footnotes from '../Footnotes'
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof Footnotes> = {
|
|
5
|
+
title: 'Components/Organisms/Footnotes',
|
|
6
|
+
component: Footnotes
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export default meta
|
|
10
|
+
|
|
11
|
+
type Story = StoryObj<typeof Footnotes>
|
|
12
|
+
|
|
13
|
+
export const Primary: Story = {
|
|
14
|
+
args: {
|
|
15
|
+
footnotes: [{ symbol: '*', text: 'This is a footnote' }, { symbol: '†', text: 'This is another footnote' }, { text: 'This is a third footnote' }]
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { Meta, StoryObj } from '@storybook/react'
|
|
3
|
+
import './styles.scss'
|
|
4
|
+
import CdcChart from '@cdc/chart'
|
|
5
|
+
import CdcMap from '@cdc/map'
|
|
6
|
+
import CdcMarkupInclude from '@cdc/markup-include'
|
|
7
|
+
import CdcFilteredText from '@cdc/filtered-text'
|
|
8
|
+
import CdcDashboard from '@cdc/dashboard'
|
|
9
|
+
import CdcWaffleChart from '@cdc/waffle-chart'
|
|
10
|
+
import config from './../../../chart/src/_stories/_mock/bar-chart-suppressed.json'
|
|
11
|
+
import mapConfig from './../../../map/examples/default-usa.json'
|
|
12
|
+
import markupConfig from './../../../markup-include/src/data/initial-state.js'
|
|
13
|
+
import filteredTextConfig from './_mocks/filtered-text-config.json'
|
|
14
|
+
import waffleChartConfig from './../../../waffle-chart/examples/gallery/count.json'
|
|
15
|
+
import dashboardConfig from './../../../dashboard/examples/full-dashboard.json'
|
|
16
|
+
|
|
17
|
+
// Determine the component based on config.type
|
|
18
|
+
const getComponent = config => {
|
|
19
|
+
switch (config.type) {
|
|
20
|
+
case 'map':
|
|
21
|
+
return CdcMap
|
|
22
|
+
case 'chart':
|
|
23
|
+
return CdcChart
|
|
24
|
+
case 'markup-include':
|
|
25
|
+
return CdcMarkupInclude
|
|
26
|
+
case 'waffle-chart':
|
|
27
|
+
return CdcWaffleChart
|
|
28
|
+
case 'dashboard':
|
|
29
|
+
return CdcDashboard
|
|
30
|
+
default:
|
|
31
|
+
return () => <div>Unknown component type</div>
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const meta = {
|
|
36
|
+
title: 'Components/Templates/Layout/Debug',
|
|
37
|
+
component: args => {
|
|
38
|
+
const Component = getComponent(args.config)
|
|
39
|
+
return (
|
|
40
|
+
<div className=''>
|
|
41
|
+
<Component {...args} />
|
|
42
|
+
</div>
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
} as Meta
|
|
46
|
+
|
|
47
|
+
export default meta
|
|
48
|
+
|
|
49
|
+
type Story = StoryObj
|
|
50
|
+
|
|
51
|
+
export const Chart: Story = {
|
|
52
|
+
args: {
|
|
53
|
+
config,
|
|
54
|
+
isEditor: true
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export const Map: Story = {
|
|
59
|
+
args: {
|
|
60
|
+
config: mapConfig,
|
|
61
|
+
isEditor: true
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export const MarkupInclude: StoryObj<typeof CdcMarkupInclude> = {
|
|
66
|
+
args: {
|
|
67
|
+
config: markupConfig,
|
|
68
|
+
isEditor: true
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export const WaffleChart: StoryObj<typeof CdcWaffleChart> = {
|
|
73
|
+
args: {
|
|
74
|
+
config: waffleChartConfig,
|
|
75
|
+
isEditor: true
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export const Dashboard: StoryObj<typeof CdcDashboard> = {
|
|
80
|
+
args: {
|
|
81
|
+
config: dashboardConfig,
|
|
82
|
+
isEditor: true
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// export const WaffleChart: StoryObj<typeof CdcWaffleChart> = {
|
|
87
|
+
// args: {
|
|
88
|
+
// config: waffleChartConfig,
|
|
89
|
+
// isEditor: true
|
|
90
|
+
// }
|
|
91
|
+
// }
|