@cdc/core 4.23.11 → 4.24.2
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/components/DataTable/DataTable.tsx +39 -10
- package/components/DataTable/components/ChartHeader.tsx +17 -5
- package/components/DataTable/components/ExpandCollapse.tsx +1 -1
- package/components/DataTable/helpers/chartCellMatrix.tsx +16 -2
- package/components/DataTable/helpers/customColumns.ts +25 -0
- package/components/DataTable/helpers/customSort.ts +9 -0
- package/components/DataTable/helpers/getChartCellValue.ts +2 -1
- package/components/DataTable/helpers/getDataSeriesColumns.ts +2 -1
- package/components/DataTable/helpers/getSeriesName.ts +15 -20
- package/components/DataTable/helpers/mapCellMatrix.tsx +4 -0
- package/components/DataTable/types/TableConfig.ts +11 -40
- package/components/EditorPanel/DataTableEditor.tsx +133 -0
- package/components/EditorPanel/Inputs.tsx +150 -0
- package/components/Filters.jsx +17 -15
- package/components/MediaControls.jsx +1 -1
- package/components/MultiSelect/MultiSelect.tsx +95 -0
- package/components/MultiSelect/index.ts +1 -0
- package/components/MultiSelect/multiselect.styles.css +50 -0
- package/components/Table/Table.tsx +23 -3
- package/components/Table/components/Cell.tsx +3 -3
- package/components/Table/components/GroupRow.tsx +6 -2
- package/components/Table/components/Row.tsx +9 -2
- package/components/Table/types/RowType.ts +5 -0
- package/components/_stories/DataTable.stories.tsx +41 -0
- package/components/_stories/EditorPanel.stories.tsx +53 -0
- package/components/_stories/Inputs.stories.tsx +37 -0
- package/components/_stories/MultiSelect.stories.tsx +24 -0
- package/components/_stories/_mocks/row_type.json +42 -0
- package/components/inputs/{InputSelect.jsx → InputSelect.tsx} +15 -5
- package/components/managers/DataDesigner.tsx +8 -8
- package/components/ui/{Icon.jsx → Icon.tsx} +3 -3
- package/components/ui/_stories/Colors.stories.tsx +92 -0
- package/components/ui/_stories/Icon.stories.tsx +17 -10
- package/helpers/DataTransform.ts +30 -2
- package/helpers/fetchRemoteData.js +5 -5
- package/helpers/getFileExtension.ts +28 -5
- package/helpers/getViewport.ts +23 -0
- package/helpers/isSolr.js +13 -0
- package/helpers/withDevTools.ts +50 -0
- package/package.json +2 -2
- package/styles/_data-table.scss +2 -5
- package/styles/_global-variables.scss +75 -0
- package/styles/base.scss +89 -69
- package/types/Action.ts +1 -0
- package/types/Axis.ts +39 -2
- package/types/BoxPlot.ts +21 -0
- package/types/Column.ts +16 -0
- package/types/FilterBehavior.ts +1 -0
- package/types/General.ts +9 -0
- package/types/Runtime.ts +21 -1
- package/types/Series.ts +1 -1
- package/types/Table.ts +21 -0
- package/types/UpdateFieldFunc.ts +1 -0
- package/types/ViewPort.ts +2 -0
- package/types/Visualization.ts +15 -9
- package/types/WCMSProps.ts +11 -0
- package/helpers/getViewport.js +0 -21
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"type": "row_group",
|
|
4
|
+
"overall": "",
|
|
5
|
+
"male": "",
|
|
6
|
+
"female": "",
|
|
7
|
+
"row_type": "row_group",
|
|
8
|
+
"nullColumn": null
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"type": "row_group_total",
|
|
12
|
+
"overall": "100",
|
|
13
|
+
"male": "50",
|
|
14
|
+
"female": "50",
|
|
15
|
+
"row_type": "row_group_total",
|
|
16
|
+
"nullColumn": null
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"type": "regular",
|
|
20
|
+
"overall": "50",
|
|
21
|
+
"male": "25",
|
|
22
|
+
"female": "25",
|
|
23
|
+
"row_type": null,
|
|
24
|
+
"nullColumn": null
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"type": "regular",
|
|
28
|
+
"overall": "50",
|
|
29
|
+
"male": "25",
|
|
30
|
+
"female": "25",
|
|
31
|
+
"row_type": null,
|
|
32
|
+
"nullColumn": null
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"type": "total",
|
|
36
|
+
"overall": "100",
|
|
37
|
+
"male": "50",
|
|
38
|
+
"female": "50",
|
|
39
|
+
"row_type": "total",
|
|
40
|
+
"nullColumn": null
|
|
41
|
+
}
|
|
42
|
+
]
|
|
@@ -1,9 +1,19 @@
|
|
|
1
|
-
import React, { memo } from 'react'
|
|
2
|
-
|
|
3
1
|
import '../../styles/v2/components/input/index.scss'
|
|
4
2
|
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
interface InputProps {
|
|
4
|
+
label?
|
|
5
|
+
value?
|
|
6
|
+
options: string[] | { [key: string]: string }
|
|
7
|
+
fieldName
|
|
8
|
+
section?
|
|
9
|
+
subsection?
|
|
10
|
+
required?
|
|
11
|
+
updateField
|
|
12
|
+
initial?
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const InputSelect = ({ label, value, options, fieldName, section = null, subsection = null, required = false, updateField, initial: initialValue, ...attributes }: InputProps) => {
|
|
16
|
+
let optionsJsx = []
|
|
7
17
|
|
|
8
18
|
if (Array.isArray(options)) {
|
|
9
19
|
//Handle basic array
|
|
@@ -48,6 +58,6 @@ const InputSelect = memo(({ label, value, options, fieldName, section = null, su
|
|
|
48
58
|
</select>
|
|
49
59
|
</label>
|
|
50
60
|
)
|
|
51
|
-
}
|
|
61
|
+
}
|
|
52
62
|
|
|
53
63
|
export default InputSelect
|
|
@@ -8,7 +8,7 @@ import '../../styles/v2/components/data-designer.scss'
|
|
|
8
8
|
|
|
9
9
|
type DataDesignerProps = {
|
|
10
10
|
configureData?: any // todo: add description here when understood better
|
|
11
|
-
updateDescriptionProp?: () => void // used to update data description fields
|
|
11
|
+
updateDescriptionProp?: (vizKey: string, dataKey: string, propName: string, value: any) => void // used to update data description fields
|
|
12
12
|
visualizationKey?: any // todo: add description here when understood better
|
|
13
13
|
dataKey?: string // appears to be the data file name, ie valid-data.csv
|
|
14
14
|
config?: any // can be one of many different types of chart configs that aren't fully established yet
|
|
@@ -198,16 +198,16 @@ const DataDesigner = (props: DataDesignerProps) => {
|
|
|
198
198
|
</div>
|
|
199
199
|
<div className='mb-2'>
|
|
200
200
|
<div className='mb-1'>Which properties in the dataset represent the numeric value? (all remaining properties will be treated as filters)</div>
|
|
201
|
-
{configureData.dataDescription.
|
|
201
|
+
{configureData.dataDescription.valueKeysTallSupport && configureData.dataDescription.valueKeysTallSupport.length > 0 && (
|
|
202
202
|
<ul className='value-list'>
|
|
203
|
-
{configureData.dataDescription.
|
|
203
|
+
{configureData.dataDescription.valueKeysTallSupport.map((valueKey, index) => (
|
|
204
204
|
<li key={`value-keys-list-${index}`}>
|
|
205
205
|
{valueKey}
|
|
206
206
|
<button
|
|
207
207
|
onClick={() => {
|
|
208
|
-
let newValueKeys = configureData.dataDescription.
|
|
208
|
+
let newValueKeys = configureData.dataDescription.valueKeysTallSupport
|
|
209
209
|
newValueKeys.splice(index, 1)
|
|
210
|
-
updateDescriptionProp(visualizationKey, dataKey, '
|
|
210
|
+
updateDescriptionProp(visualizationKey, dataKey, 'valueKeysTallSupport', newValueKeys)
|
|
211
211
|
}}
|
|
212
212
|
>
|
|
213
213
|
X
|
|
@@ -218,14 +218,14 @@ const DataDesigner = (props: DataDesignerProps) => {
|
|
|
218
218
|
)}
|
|
219
219
|
<select
|
|
220
220
|
onChange={e => {
|
|
221
|
-
if (e.target.value && (!configureData.dataDescription.
|
|
222
|
-
updateDescriptionProp(visualizationKey, dataKey, '
|
|
221
|
+
if (e.target.value && (!configureData.dataDescription.valueKeysTallSupport || configureData.dataDescription.valueKeysTallSupport.indexOf(e.target.value) === -1)) {
|
|
222
|
+
updateDescriptionProp(visualizationKey, dataKey, 'valueKeysTallSupport', [...(configureData.dataDescription.valueKeysTallSupport || []), e.target.value])
|
|
223
223
|
}
|
|
224
224
|
}}
|
|
225
225
|
>
|
|
226
226
|
<option value=''>Choose an option</option>
|
|
227
227
|
{Object.keys(configureData.data[0])
|
|
228
|
-
.filter(value => !configureData.dataDescription.
|
|
228
|
+
.filter(value => !configureData.dataDescription.valueKeysTallSupport || configureData.dataDescription.valueKeysTallSupport.indexOf(value) === -1)
|
|
229
229
|
.map((value, index) => (
|
|
230
230
|
<option value={value} key={`value-keys-option-${index}`}>
|
|
231
231
|
{value}
|
|
@@ -69,17 +69,17 @@ const iconHash = {
|
|
|
69
69
|
|
|
70
70
|
export const ICON_TYPES = Object.keys(iconHash)
|
|
71
71
|
|
|
72
|
-
const Icon = ({ display = '', base, alt = '', size, color, style, ...attributes }) => {
|
|
72
|
+
const Icon = ({ display = '', base = undefined, alt = '', size = undefined, color = undefined, style = undefined, ...attributes }) => {
|
|
73
73
|
const IconObj = iconHash[display] || null
|
|
74
74
|
|
|
75
75
|
const filteredAttrs = { ...attributes }
|
|
76
76
|
delete filteredAttrs.className
|
|
77
77
|
|
|
78
78
|
const styles = {
|
|
79
|
-
...style,
|
|
80
79
|
color: color ? color : null,
|
|
81
80
|
width: size ? size + 'px' : null,
|
|
82
|
-
cursor: display === 'move' ? 'move' : 'default'
|
|
81
|
+
cursor: display === 'move' ? 'move' : 'default',
|
|
82
|
+
...style
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
return (
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react'
|
|
2
|
+
|
|
3
|
+
const COLORS = [
|
|
4
|
+
['baseColor', '#333'],
|
|
5
|
+
['blue', '#005eaa'],
|
|
6
|
+
['lightestGray', '#f2f2f2'],
|
|
7
|
+
['lightGray', '#c7c7c7'],
|
|
8
|
+
['mediumGray', '#565656'],
|
|
9
|
+
['darkGray', '#333'],
|
|
10
|
+
['red', '#d8000c'],
|
|
11
|
+
['white', '#fff'],
|
|
12
|
+
|
|
13
|
+
['primary', '#005eaa'],
|
|
14
|
+
['secondary', '#88c3ea'],
|
|
15
|
+
['tertiary', '#c0e9ff'],
|
|
16
|
+
['quaternary', '#edf9ff'],
|
|
17
|
+
|
|
18
|
+
['purple-primary', '#712177'],
|
|
19
|
+
['purple-secondary', '#b890bb'],
|
|
20
|
+
['purple-tertiary', '#e3d3e4'],
|
|
21
|
+
['purple-quaternary', '#f7f2f7'],
|
|
22
|
+
|
|
23
|
+
['brown-primary', '#705043'],
|
|
24
|
+
['brown-secondary', '#ad907b'],
|
|
25
|
+
['brown-tertiary', '#d7ccc8'],
|
|
26
|
+
['brown-quaternary', '#f2ebe8'],
|
|
27
|
+
|
|
28
|
+
['teal-primary', '#00695c'],
|
|
29
|
+
['teal-secondary', '#4ebaaa'],
|
|
30
|
+
['teal-tertiary', '#ceece7'],
|
|
31
|
+
['teal-quaternary', '#ebf7f5'],
|
|
32
|
+
|
|
33
|
+
['pink-primary', '#af4448'],
|
|
34
|
+
['pink-secondary', '#e57373'],
|
|
35
|
+
['pink-tertiary', '#ffc2c2'],
|
|
36
|
+
['pink-quaternary', '#ffe7e7'],
|
|
37
|
+
|
|
38
|
+
['orange-primary', '#bb4d00'],
|
|
39
|
+
['orange-secondary', '#ffad42'],
|
|
40
|
+
['orange-tertiary', '#ffe97d'],
|
|
41
|
+
['orange-quaternary', '#fff4cf'],
|
|
42
|
+
|
|
43
|
+
['slate-primary', '#29434e'],
|
|
44
|
+
['slate-secondary', '#7e9ba5'],
|
|
45
|
+
['slate-tertiary', '#b6c6d2'],
|
|
46
|
+
['slate-quaternary', '#e2e8ed'],
|
|
47
|
+
|
|
48
|
+
['indigo-primary', '#26418f'],
|
|
49
|
+
['indigo-secondary', '#92a6dd'],
|
|
50
|
+
['indigo-tertiary', '#dee8ff'],
|
|
51
|
+
['indigo-quaternary', '#f2f6ff'],
|
|
52
|
+
|
|
53
|
+
['cyan-primary', '#006778'],
|
|
54
|
+
['cyan-secondary', '#65b0bd'],
|
|
55
|
+
['cyan-tertiary', '#cce5e9'],
|
|
56
|
+
['cyan-quaternary', '#ebf5f6'],
|
|
57
|
+
|
|
58
|
+
['green-primary', '#4b830d'],
|
|
59
|
+
['green-secondary', '#84bc49'],
|
|
60
|
+
['green-tertiary', '#dcedc8'],
|
|
61
|
+
['green-quaternary', '#f1f8e9'],
|
|
62
|
+
|
|
63
|
+
['amber-primary', '#fbab18'],
|
|
64
|
+
['amber-secondary', '#ffd54f'],
|
|
65
|
+
['amber-tertiary', '#ffecb3'],
|
|
66
|
+
['amber-quaternary', '#fff7e1']
|
|
67
|
+
]
|
|
68
|
+
|
|
69
|
+
const ColorArray = () => {
|
|
70
|
+
return (
|
|
71
|
+
<table className='table'>
|
|
72
|
+
{COLORS.map(([name, hex]) => (
|
|
73
|
+
<tr>
|
|
74
|
+
<td style={{ background: hex, width: '60px' }}></td>
|
|
75
|
+
<td>{name}</td>
|
|
76
|
+
<td>{hex}</td>
|
|
77
|
+
</tr>
|
|
78
|
+
))}
|
|
79
|
+
</table>
|
|
80
|
+
)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const meta: Meta<typeof ColorArray> = {
|
|
84
|
+
title: 'Components/Atoms/Colors',
|
|
85
|
+
component: ColorArray
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
type Story = StoryObj<typeof ColorArray>
|
|
89
|
+
|
|
90
|
+
export const Primary: Story = {}
|
|
91
|
+
|
|
92
|
+
export default meta
|
|
@@ -3,20 +3,27 @@ import type { Meta, StoryObj } from '@storybook/react'
|
|
|
3
3
|
|
|
4
4
|
import Icon, { ICON_TYPES } from '../Icon'
|
|
5
5
|
|
|
6
|
-
const
|
|
6
|
+
const IconArray = () => {
|
|
7
|
+
return (
|
|
8
|
+
<>
|
|
9
|
+
{ICON_TYPES.map(name => (
|
|
10
|
+
<div>
|
|
11
|
+
<span>
|
|
12
|
+
<Icon display={name} /> {name}{' '}
|
|
13
|
+
</span>
|
|
14
|
+
</div>
|
|
15
|
+
))}
|
|
16
|
+
</>
|
|
17
|
+
)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const meta: Meta<typeof IconArray> = {
|
|
7
21
|
title: 'Components/Atoms/Icon',
|
|
8
|
-
component:
|
|
9
|
-
parameters: {
|
|
10
|
-
display: ICON_TYPES
|
|
11
|
-
}
|
|
22
|
+
component: IconArray
|
|
12
23
|
}
|
|
13
24
|
|
|
14
25
|
type Story = StoryObj<typeof Icon>
|
|
15
26
|
|
|
16
|
-
export const Primary: Story = {
|
|
17
|
-
args: {
|
|
18
|
-
display: 'question'
|
|
19
|
-
}
|
|
20
|
-
}
|
|
27
|
+
export const Primary: Story = {}
|
|
21
28
|
|
|
22
29
|
export default meta
|
package/helpers/DataTransform.ts
CHANGED
|
@@ -128,8 +128,36 @@ export class DataTransform {
|
|
|
128
128
|
return standardized
|
|
129
129
|
}
|
|
130
130
|
} else if (description.series === true && description.singleRow === false) {
|
|
131
|
-
if (description.seriesKey !== undefined && description.xKey !== undefined && (description.valueKey !== undefined || (description.valueKeys !== undefined && description.valueKeys.length > 0))) {
|
|
132
|
-
if (description.
|
|
131
|
+
if (description.seriesKey !== undefined && description.xKey !== undefined && (description.valueKey !== undefined || (description.valueKeys !== undefined && description.valueKeys.length > 0) || (description.valueKeysTallSupport !== undefined && description.valueKeysTallSupport.length > 0))) {
|
|
132
|
+
if (description.valueKeysTallSupport !== undefined) {
|
|
133
|
+
let standardizedMapped = {}
|
|
134
|
+
let standardized: string[] = []
|
|
135
|
+
|
|
136
|
+
data.forEach(row => {
|
|
137
|
+
let uniqueKey = row[description.xKey];
|
|
138
|
+
Object.keys(row).forEach(key => {
|
|
139
|
+
if(key !== description.xKey && key !== description.seriesKey && description.valueKeysTallSupport.indexOf(key) === -1 && (!description.ignoredKeys || description.ignoredKeys.indexOf(key) === -1)){
|
|
140
|
+
uniqueKey += "|" + row[key];
|
|
141
|
+
}
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
if(!standardizedMapped[uniqueKey]){
|
|
145
|
+
standardizedMapped[uniqueKey] = {[description.xKey]: row[description.xKey]}
|
|
146
|
+
}
|
|
147
|
+
Object.keys(row).forEach(key => {
|
|
148
|
+
if(key !== description.xKey && key !== description.seriesKey && description.valueKeysTallSupport.indexOf(key) === -1 && (!description.ignoredKeys || description.ignoredKeys.indexOf(key) === -1)){
|
|
149
|
+
standardizedMapped[uniqueKey][key] = row[key];
|
|
150
|
+
}
|
|
151
|
+
})
|
|
152
|
+
description.valueKeysTallSupport.forEach(valueKey => {
|
|
153
|
+
standardizedMapped[uniqueKey][row[description.seriesKey] + '-' + valueKey] = row[valueKey];
|
|
154
|
+
})
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
standardized = Object.keys(standardizedMapped).map(key => standardizedMapped[key]);
|
|
158
|
+
|
|
159
|
+
return standardized
|
|
160
|
+
} else if (description.valueKeys !== undefined) {
|
|
133
161
|
let standardizedMapped = {}
|
|
134
162
|
let standardized: string[] = []
|
|
135
163
|
let valueKeys = description.valueKeys
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import Papa from 'papaparse'
|
|
2
|
+
import { isSolrCsv, isSolrJson } from '@cdc/core/helpers/isSolr'
|
|
2
3
|
|
|
3
|
-
export default async function (
|
|
4
|
+
export default async function (_url, visualizationType = '') {
|
|
5
|
+
let url = new URL(_url, window.location.origin)
|
|
4
6
|
try {
|
|
5
|
-
url = new URL(url, window.location.origin)
|
|
6
|
-
|
|
7
7
|
const path = url.pathname
|
|
8
8
|
const regex = /(?:\.([^.]+))?$/
|
|
9
9
|
const ext = regex.exec(path)[1]
|
|
10
10
|
|
|
11
|
-
if ('csv' === ext) {
|
|
11
|
+
if ('csv' === ext || isSolrCsv(_url)) {
|
|
12
12
|
return await fetch(url.href)
|
|
13
13
|
.then(response => response.text())
|
|
14
14
|
.then(responseText => {
|
|
@@ -30,7 +30,7 @@ export default async function (url, visualizationType = '') {
|
|
|
30
30
|
return parsedCsv.data
|
|
31
31
|
})
|
|
32
32
|
} else {
|
|
33
|
-
return await fetch(url.href).then(response => response.json())
|
|
33
|
+
return await fetch(isSolrCsv(_url) ? _url : url.href).then(response => response.json())
|
|
34
34
|
}
|
|
35
35
|
} catch {
|
|
36
36
|
// If we can't parse it, still attempt to fetch it
|
|
@@ -1,5 +1,28 @@
|
|
|
1
|
-
export const
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
}
|
|
1
|
+
// export const getFileExtensionx = (path: string): string => {
|
|
2
|
+
// const regex = /(?:\.([^.]+))?$/
|
|
3
|
+
// const outCome: RegExpExecArray | null = regex.exec(path)
|
|
4
|
+
// return outCome ? outCome[1] : ''
|
|
5
|
+
// }
|
|
6
|
+
|
|
7
|
+
export const getFileExtension = (url: string): string => {
|
|
8
|
+
const regexForExtension = /(?:\.([^.]+))$/
|
|
9
|
+
const regexForQueryParam = /[?&]wt=(csv|json)(?:&|$)/ // Regular expression for 'wt' query parameter
|
|
10
|
+
|
|
11
|
+
const urlObject = new URL(url, window.location.origin)
|
|
12
|
+
const pathname = urlObject.pathname
|
|
13
|
+
const searchParams = urlObject.search
|
|
14
|
+
|
|
15
|
+
// First, try to get the extension from the pathname
|
|
16
|
+
const pathnameMatch = regexForExtension.exec(pathname)
|
|
17
|
+
if (pathnameMatch && pathnameMatch[1]) {
|
|
18
|
+
return pathnameMatch[1]
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Then, try to get it from the query parameter 'wt'
|
|
22
|
+
const queryParamsMatch = regexForQueryParam.exec(searchParams)
|
|
23
|
+
if (queryParamsMatch && queryParamsMatch[1]) {
|
|
24
|
+
return queryParamsMatch[1]
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return ''
|
|
28
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ViewPort } from '../types/ViewPort'
|
|
2
|
+
|
|
3
|
+
export const viewports = {
|
|
4
|
+
lg: 1200,
|
|
5
|
+
md: 992,
|
|
6
|
+
sm: 768,
|
|
7
|
+
xs: 576,
|
|
8
|
+
xxs: 350
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export default function getViewport(size): ViewPort {
|
|
12
|
+
let result: ViewPort = 'lg'
|
|
13
|
+
|
|
14
|
+
if (size > 1200) return result
|
|
15
|
+
|
|
16
|
+
for (let viewport in viewports) {
|
|
17
|
+
if (size <= viewports[viewport]) {
|
|
18
|
+
result = viewport as ViewPort
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return result
|
|
23
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// This package hooks into the Redux Dev Tools extension
|
|
2
|
+
// It works as a wrapper for any reducer function
|
|
3
|
+
|
|
4
|
+
// Based on: https://github.com/MacKentoch/react-bootstrap-webpack-starter/blob/master/front/src/contexts/withDevTools/index.ts
|
|
5
|
+
|
|
6
|
+
// types
|
|
7
|
+
type DevToolsMessageType = 'DISPATCH' | string
|
|
8
|
+
|
|
9
|
+
type DevToolsMessagePayload = {
|
|
10
|
+
type?: string
|
|
11
|
+
state?: any
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
type DevToolsMessage = {
|
|
15
|
+
type?: DevToolsMessageType
|
|
16
|
+
payload?: DevToolsMessagePayload
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
type Action = {
|
|
20
|
+
type: string
|
|
21
|
+
payload?: any
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// the only method the devToolsWrapper hooks into is .send()
|
|
25
|
+
// all other type definitions are kept for reference.
|
|
26
|
+
// it's possible there's a DevTools type in the Redux library
|
|
27
|
+
// however this allows us to avoid another dependency as this project
|
|
28
|
+
// doesn't use Redux.
|
|
29
|
+
type DevTools = {
|
|
30
|
+
init: () => void
|
|
31
|
+
connect: () => any
|
|
32
|
+
subscribe: (message: DevToolsMessage) => any
|
|
33
|
+
send: (action: Action, newState: any) => any
|
|
34
|
+
unsubscribe: () => any
|
|
35
|
+
dispatch: (action: Action) => any
|
|
36
|
+
disconnect: () => any
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// constants
|
|
40
|
+
const withDevTools = typeof window !== 'undefined' && (window as any).__REDUX_DEVTOOLS_EXTENSION__
|
|
41
|
+
const devTools: DevTools = !withDevTools ? null : (window as any).__REDUX_DEVTOOLS_EXTENSION__.connect()
|
|
42
|
+
export const devToolsStore = !withDevTools ? null : devTools
|
|
43
|
+
|
|
44
|
+
export const devToolsWrapper =
|
|
45
|
+
<StateType, ActionTypes>(_reducer: (s: StateType, a: ActionTypes) => StateType) =>
|
|
46
|
+
(state: StateType, action: ActionTypes): StateType => {
|
|
47
|
+
const newState = _reducer(state, action)
|
|
48
|
+
devToolsStore?.send(action as Action, newState)
|
|
49
|
+
return newState
|
|
50
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cdc/core",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.24.2",
|
|
4
4
|
"description": "Core components, styles, hooks, and helpers, for the CDC Open Visualization project",
|
|
5
5
|
"moduleName": "CdcCore",
|
|
6
6
|
"main": "dist/cdccore",
|
|
@@ -30,5 +30,5 @@
|
|
|
30
30
|
"react": "^18.2.0",
|
|
31
31
|
"react-dom": "^18.2.0"
|
|
32
32
|
},
|
|
33
|
-
"gitHead": "
|
|
33
|
+
"gitHead": "edde49c96dee146de5e3a4537880b1bcf4dbee08"
|
|
34
34
|
}
|
package/styles/_data-table.scss
CHANGED
|
@@ -31,9 +31,6 @@ div.data-table-heading {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
table.horizontal {
|
|
34
|
-
tr {
|
|
35
|
-
display: flex;
|
|
36
|
-
}
|
|
37
34
|
|
|
38
35
|
th,
|
|
39
36
|
td {
|
|
@@ -42,7 +39,7 @@ table.horizontal {
|
|
|
42
39
|
}
|
|
43
40
|
|
|
44
41
|
table.data-table {
|
|
45
|
-
width: 100%;
|
|
42
|
+
min-width: 100%;
|
|
46
43
|
background: #fff;
|
|
47
44
|
position: relative;
|
|
48
45
|
border: none;
|
|
@@ -160,6 +157,7 @@ table.data-table {
|
|
|
160
157
|
|
|
161
158
|
th,
|
|
162
159
|
td {
|
|
160
|
+
width: 1% !important;
|
|
163
161
|
white-space: nowrap;
|
|
164
162
|
text-overflow: ellipsis;
|
|
165
163
|
overflow: hidden;
|
|
@@ -168,7 +166,6 @@ table.data-table {
|
|
|
168
166
|
}
|
|
169
167
|
}
|
|
170
168
|
tr {
|
|
171
|
-
display: flex;
|
|
172
169
|
& > * {
|
|
173
170
|
width: 100%;
|
|
174
171
|
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
$colors: (
|
|
2
|
+
'baseColor': #333,
|
|
3
|
+
'blue': #005eaa,
|
|
4
|
+
'lightestGray': #f2f2f2,
|
|
5
|
+
'lightGray': #c7c7c7,
|
|
6
|
+
'mediumGray': #565656,
|
|
7
|
+
'darkGray': #333,
|
|
8
|
+
'red': #d8000c,
|
|
9
|
+
'white': #fff,
|
|
10
|
+
|
|
11
|
+
'primary': #005eaa,
|
|
12
|
+
'secondary': #88c3ea,
|
|
13
|
+
'tertiary': #c0e9ff,
|
|
14
|
+
'quaternary': #edf9ff,
|
|
15
|
+
|
|
16
|
+
'purple-primary': #712177,
|
|
17
|
+
'purple-secondary': #b890bb,
|
|
18
|
+
'purple-tertiary': #e3d3e4,
|
|
19
|
+
'purple-quaternary': #f7f2f7,
|
|
20
|
+
|
|
21
|
+
'brown-primary': #705043,
|
|
22
|
+
'brown-secondary': #ad907b,
|
|
23
|
+
'brown-tertiary': #d7ccc8,
|
|
24
|
+
'brown-quaternary': #f2ebe8,
|
|
25
|
+
|
|
26
|
+
'teal-primary': #00695c,
|
|
27
|
+
'teal-secondary': #4ebaaa,
|
|
28
|
+
'teal-tertiary': #ceece7,
|
|
29
|
+
'teal-quaternary': #ebf7f5,
|
|
30
|
+
|
|
31
|
+
'pink-primary': #af4448,
|
|
32
|
+
'pink-secondary': #e57373,
|
|
33
|
+
'pink-tertiary': #ffc2c2,
|
|
34
|
+
'pink-quaternary': #ffe7e7,
|
|
35
|
+
|
|
36
|
+
'orange-primary': #bb4d00,
|
|
37
|
+
'orange-secondary': #ffad42,
|
|
38
|
+
'orange-tertiary': #ffe97d,
|
|
39
|
+
'orange-quaternary': #fff4cf,
|
|
40
|
+
|
|
41
|
+
'slate-primary': #29434e,
|
|
42
|
+
'slate-secondary': #7e9ba5,
|
|
43
|
+
'slate-tertiary': #b6c6d2,
|
|
44
|
+
'slate-quaternary': #e2e8ed,
|
|
45
|
+
|
|
46
|
+
'indigo-primary': #26418f,
|
|
47
|
+
'indigo-secondary': #92a6dd,
|
|
48
|
+
'indigo-tertiary': #dee8ff,
|
|
49
|
+
'indigo-quaternary': #f2f6ff,
|
|
50
|
+
|
|
51
|
+
'cyan-primary': #006778,
|
|
52
|
+
'cyan-secondary': #65b0bd,
|
|
53
|
+
'cyan-tertiary': #cce5e9,
|
|
54
|
+
'cyan-quaternary': #ebf5f6,
|
|
55
|
+
|
|
56
|
+
'green-primary': #4b830d,
|
|
57
|
+
'green-secondary': #84bc49,
|
|
58
|
+
'green-tertiary': #dcedc8,
|
|
59
|
+
'green-quaternary': #f1f8e9,
|
|
60
|
+
|
|
61
|
+
'amber-primary': #fbab18,
|
|
62
|
+
'amber-secondary': #ffd54f,
|
|
63
|
+
'amber-tertiary': #ffecb3,
|
|
64
|
+
'amber-quaternary': #fff7e1,
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
@mixin theme() {
|
|
68
|
+
:root {
|
|
69
|
+
@each $key, $value in $colors {
|
|
70
|
+
--#{$key}: #{$value};
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
@include theme();
|