@cdc/core 4.23.10-alpha → 4.23.11

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 (52) hide show
  1. package/assets/icon-deviation-bar.svg +1 -0
  2. package/components/DataTable/DataTable.tsx +205 -0
  3. package/components/DataTable/components/BoxplotHeader.tsx +16 -0
  4. package/components/DataTable/components/CellAnchor.tsx +44 -0
  5. package/components/DataTable/components/ChartHeader.tsx +91 -0
  6. package/components/DataTable/components/ExpandCollapse.tsx +21 -0
  7. package/components/DataTable/components/Icons.tsx +10 -0
  8. package/components/DataTable/components/MapHeader.tsx +56 -0
  9. package/components/DataTable/components/SkipNav.tsx +7 -0
  10. package/components/DataTable/helpers/boxplotCellMatrix.tsx +64 -0
  11. package/components/DataTable/helpers/chartCellMatrix.tsx +78 -0
  12. package/components/DataTable/helpers/customSort.ts +55 -0
  13. package/components/DataTable/helpers/getChartCellValue.ts +55 -0
  14. package/components/DataTable/helpers/getDataSeriesColumns.ts +28 -0
  15. package/components/DataTable/helpers/getSeriesName.ts +26 -0
  16. package/components/DataTable/helpers/mapCellMatrix.tsx +56 -0
  17. package/components/DataTable/helpers/regionCellMatrix.tsx +13 -0
  18. package/components/DataTable/helpers/standardizeState.js +76 -0
  19. package/components/DataTable/index.ts +1 -0
  20. package/components/DataTable/types/TableConfig.ts +57 -0
  21. package/components/DownloadButton.tsx +29 -0
  22. package/components/LegendCircle.jsx +2 -2
  23. package/components/Table/Table.tsx +49 -0
  24. package/components/Table/components/Cell.tsx +9 -0
  25. package/components/Table/components/GroupRow.tsx +16 -0
  26. package/components/Table/components/Row.tsx +19 -0
  27. package/components/Table/index.ts +1 -0
  28. package/components/Table/types/CellMatrix.ts +4 -0
  29. package/components/_stories/DataTable.stories.tsx +62 -0
  30. package/components/_stories/Table.stories.tsx +53 -0
  31. package/components/_stories/_mocks/dashboard_no_filter.json +121 -0
  32. package/components/_stories/_mocks/example-city-state.json +808 -0
  33. package/components/_stories/styles.scss +9 -0
  34. package/components/managers/{DataDesigner.jsx → DataDesigner.tsx} +96 -87
  35. package/components/ui/Title/Title.scss +95 -0
  36. package/components/ui/Title/index.tsx +34 -0
  37. package/components/ui/_stories/Title.stories.tsx +21 -0
  38. package/helpers/DataTransform.ts +41 -18
  39. package/helpers/cove/string.ts +11 -0
  40. package/package.json +2 -2
  41. package/styles/_data-table.scss +1 -0
  42. package/styles/heading-colors.scss +0 -3
  43. package/styles/v2/layout/_component.scss +0 -11
  44. package/types/Axis.ts +6 -0
  45. package/types/Color.ts +5 -0
  46. package/types/ComponentStyles.ts +7 -0
  47. package/types/ComponentThemes.ts +13 -0
  48. package/types/EditorColumnProperties.ts +8 -0
  49. package/types/Runtime.ts +9 -0
  50. package/types/Series.ts +1 -0
  51. package/types/Visualization.ts +21 -0
  52. package/components/DataTable.jsx +0 -759
@@ -0,0 +1,55 @@
1
+ import { parseDate, formatDate } from '@cdc/core/helpers/cove/date'
2
+ import { formatNumber } from '@cdc/core/helpers/cove/number'
3
+
4
+ // if its additional column, return formatting params
5
+ const isAdditionalColumn = (column, config) => {
6
+ let inthere = false
7
+ let formattingParams = {}
8
+ const { columns } = config
9
+ if (columns) {
10
+ Object.keys(columns).forEach(keycol => {
11
+ const col = columns[keycol]
12
+ if (col.name === column) {
13
+ inthere = true
14
+ formattingParams = {
15
+ addColPrefix: col.prefix,
16
+ addColSuffix: col.suffix,
17
+ addColRoundTo: col.roundToPlace ? col.roundToPlace : '',
18
+ addColCommas: col.commas
19
+ }
20
+ }
21
+ })
22
+ }
23
+ return formattingParams
24
+ }
25
+
26
+ export const getChartCellValue = (row, column, config, runtimeData) => {
27
+ const rowObj = runtimeData[row]
28
+ let cellValue // placeholder for formatting below
29
+ let labelValue = rowObj[column] // just raw X axis string
30
+ if (column === config.xAxis?.dataKey) {
31
+ // not the prettiest, but helper functions work nicely here.
32
+ cellValue = config.xAxis?.type === 'date' ? formatDate(config.xAxis?.dateDisplayFormat, parseDate(config.xAxis?.dateParseFormat, labelValue)) : labelValue
33
+ } else {
34
+ let resolvedAxis = 'left'
35
+ let leftAxisItems = config.series ? config.series.filter(item => item?.axis === 'Left') : []
36
+ let rightAxisItems = config.series ? config.series.filter(item => item?.axis === 'Right') : []
37
+
38
+ leftAxisItems.map(leftSeriesItem => {
39
+ if (leftSeriesItem.dataKey === column) resolvedAxis = 'left'
40
+ })
41
+
42
+ rightAxisItems.map(rightSeriesItem => {
43
+ if (rightSeriesItem.dataKey === column) resolvedAxis = 'right'
44
+ })
45
+
46
+ let addColParams = isAdditionalColumn(column, config)
47
+ if (addColParams) {
48
+ cellValue = config.dataFormat ? formatNumber(runtimeData[row][column], resolvedAxis, false, config, addColParams) : runtimeData[row][column]
49
+ } else {
50
+ cellValue = config.dataFormat ? formatNumber(runtimeData[row][column], resolvedAxis, false, config) : runtimeData[row][column]
51
+ }
52
+ }
53
+
54
+ return cellValue
55
+ }
@@ -0,0 +1,28 @@
1
+ export const getDataSeriesColumns = (config, isVertical, runtimeData): string[] => {
2
+ let tmpSeriesColumns
3
+ if (config.visualizationType !== 'Pie') {
4
+ tmpSeriesColumns = isVertical ? [config.xAxis?.dataKey] : [] //, ...config.runtime.seriesLabelsAll
5
+ if (config.series) {
6
+ config.series.forEach(element => {
7
+ tmpSeriesColumns.push(element.dataKey)
8
+ })
9
+ } else if (runtimeData && runtimeData.length > 0) {
10
+ tmpSeriesColumns = Object.keys(runtimeData[0])
11
+ }
12
+ } else {
13
+ tmpSeriesColumns = [config.xAxis?.dataKey, config.yAxis?.dataKey] //Object.keys(runtimeData[0])
14
+ }
15
+
16
+ // then add the additional Columns
17
+ if (config.columns && Object.keys(config.columns).length > 0) {
18
+ Object.keys(config.columns).forEach(function (key) {
19
+ var value = config.columns[key]
20
+ // add if not the index AND it is enabled to be added to data table
21
+ if (value.name !== config.xAxis?.dataKey && value.dataTable === true) {
22
+ tmpSeriesColumns.push(value.name)
23
+ }
24
+ })
25
+ }
26
+
27
+ return tmpSeriesColumns
28
+ }
@@ -0,0 +1,26 @@
1
+ const getLabel = (name, config) => {
2
+ let custLabel = ''
3
+ if (config.columns && Object.keys(config.columns).length > 0) {
4
+ Object.keys(config.columns).forEach(function (key) {
5
+ var tmpColumn = config.columns[key]
6
+ // add if not the index AND it is enabled to be added to data table
7
+ if (tmpColumn.name === name) {
8
+ custLabel = tmpColumn.label
9
+ }
10
+ })
11
+ return custLabel
12
+ }
13
+ }
14
+
15
+ export const getSeriesName = (column, config) => {
16
+ // If a user sets the name on a series use that.
17
+ let userUpdatedSeriesName = config.series ? config.series.filter(series => series.dataKey === column)?.[0]?.name : ''
18
+ if (userUpdatedSeriesName) return userUpdatedSeriesName
19
+
20
+ if (config.runtimeSeriesLabels && config.runtimeSeriesLabels[column]) return config.runtimeSeriesLabels[column]
21
+
22
+ let custLabel = getLabel(column, config) ? getLabel(column, config) : column
23
+ let text = column === config.xAxis?.dataKey ? config.table.indexLabel : custLabel
24
+
25
+ return text
26
+ }
@@ -0,0 +1,56 @@
1
+ import LegendCircle from '@cdc/core/components/LegendCircle'
2
+ import CellAnchor from '../components/CellAnchor'
3
+ import { DataTableProps } from '../DataTable'
4
+ import { ReactNode } from 'react'
5
+
6
+ type MapRowsProps = DataTableProps & {
7
+ rows: string[]
8
+ }
9
+
10
+ const mapCellArray = ({ rows, columns, runtimeData, config, applyLegendToRow, displayGeoName, formatLegendLocation, displayDataAsText, navigationHandler, setFilteredCountryCode }: MapRowsProps): ReactNode[][] => {
11
+ return rows.map(row =>
12
+ Object.keys(columns)
13
+ .filter(column => columns[column].dataTable === true && columns[column].name)
14
+ .map(column => {
15
+ let cellValue
16
+
17
+ if (column === 'geo') {
18
+ const rowObj = runtimeData[row]
19
+ const legendColor = applyLegendToRow(rowObj)
20
+
21
+ let labelValue
22
+ const mapZoomHandler = config.general.type === 'bubble' && config.general.allowMapZoom && config.general.geoType === 'world' ? () => setFilteredCountryCode(row) : undefined
23
+ if ((config.general.geoType !== 'single-state' && config.general.geoType !== 'us-county') || config.general.type === 'us-geocode') {
24
+ labelValue = displayGeoName(row)
25
+ } else {
26
+ labelValue = formatLegendLocation(row)
27
+ }
28
+ cellValue = (
29
+ <div className='col-12'>
30
+ <LegendCircle fill={legendColor[0]} />
31
+ <CellAnchor markup={labelValue} row={rowObj} columns={columns} navigationHandler={navigationHandler} mapZoomHandler={mapZoomHandler} />
32
+ </div>
33
+ )
34
+ } else {
35
+ // check for special classes
36
+ let specialValFound = ''
37
+ let columnName = config.columns[column].name
38
+ const { specialClasses } = config.legend
39
+ if (specialClasses && specialClasses.length && typeof specialClasses[0] === 'object') {
40
+ specialClasses.forEach(specialClass => {
41
+ if (specialClass.key === columnName) {
42
+ if (String(runtimeData[row][specialClass.key]) === specialClass.value) {
43
+ specialValFound = specialClass.label
44
+ }
45
+ }
46
+ })
47
+ }
48
+ cellValue = displayDataAsText(specialValFound || runtimeData[row][columnName], column)
49
+ }
50
+
51
+ return cellValue
52
+ })
53
+ )
54
+ }
55
+
56
+ export default mapCellArray
@@ -0,0 +1,13 @@
1
+ import { ReactNode } from 'react'
2
+
3
+ const regionCellMatrix = ({ config }): ReactNode[][] => {
4
+ return config.regions.map(region => {
5
+ if (config.visualizationType === 'Box Plot') return []
6
+ if (!Object.keys(region).includes('from') || !Object.keys(region).includes('to')) return []
7
+ // region.from and region.to had formatDate(parseDate()) on it
8
+ // but they returned undefined - removed both for now (TT)
9
+ return [region.label, region.from, region.to]
10
+ })
11
+ }
12
+
13
+ export default regionCellMatrix
@@ -0,0 +1,76 @@
1
+ const states = {
2
+ AL: 'Alabama',
3
+ AK: 'Alaska',
4
+ AS: 'American Samoa',
5
+ AZ: 'Arizona',
6
+ AR: 'Arkansas',
7
+ CA: 'California',
8
+ CO: 'Colorado',
9
+ CT: 'Connecticut',
10
+ DE: 'Delaware',
11
+ DC: 'District Of Columbia',
12
+ FM: 'Federated States Of Micronesia',
13
+ FL: 'Florida',
14
+ GA: 'Georgia',
15
+ GU: 'Guam',
16
+ HI: 'Hawaii',
17
+ ID: 'Idaho',
18
+ IL: 'Illinois',
19
+ IN: 'Indiana',
20
+ IA: 'Iowa',
21
+ KS: 'Kansas',
22
+ KY: 'Kentucky',
23
+ LA: 'Louisiana',
24
+ ME: 'Maine',
25
+ MH: 'Marshall Islands',
26
+ MD: 'Maryland',
27
+ MA: 'Massachusetts',
28
+ MI: 'Michigan',
29
+ MN: 'Minnesota',
30
+ MS: 'Mississippi',
31
+ MO: 'Missouri',
32
+ MT: 'Montana',
33
+ NE: 'Nebraska',
34
+ NV: 'Nevada',
35
+ NH: 'New Hampshire',
36
+ NJ: 'New Jersey',
37
+ NM: 'New Mexico',
38
+ NY: 'New York',
39
+ NC: 'North Carolina',
40
+ ND: 'North Dakota',
41
+ MP: 'Northern Mariana Islands',
42
+ OH: 'Ohio',
43
+ OK: 'Oklahoma',
44
+ OR: 'Oregon',
45
+ PW: 'Palau',
46
+ PA: 'Pennsylvania',
47
+ PR: 'Puerto Rico',
48
+ RI: 'Rhode Island',
49
+ SC: 'South Carolina',
50
+ SD: 'South Dakota',
51
+ TN: 'Tennessee',
52
+ TX: 'Texas',
53
+ UT: 'Utah',
54
+ VT: 'Vermont',
55
+ VI: 'Virgin Islands',
56
+ VA: 'Virginia',
57
+ WA: 'Washington',
58
+ WV: 'West Virginia',
59
+ WI: 'Wisconsin',
60
+ WY: 'Wyoming'
61
+ }
62
+ export const standardizeStateName = value => {
63
+ if (typeof value !== 'string' || !isNaN(Number(value))) {
64
+ return value
65
+ }
66
+
67
+ const upperValue = value.toUpperCase()
68
+
69
+ // Handle U.S. Virgin Islands variations
70
+ if (['U.S. VIRGIN ISLANDS', 'VI', 'US VIRGIN ISLANDS', 'VIRGIN ISLANDS'].includes(upperValue)) {
71
+ return 'U.S. VIRGIN ISLANDS'
72
+ }
73
+
74
+ // Return full name for state abbreviation or the original name
75
+ return states[upperValue] || value
76
+ }
@@ -0,0 +1 @@
1
+ export { default } from './DataTable'
@@ -0,0 +1,57 @@
1
+ import { Axis } from '@cdc/core/types/Axis'
2
+ import { Series } from '@cdc/core/types/Series'
3
+ import { Runtime } from '@cdc/core/types/Runtime'
4
+
5
+ export type TableConfig = {
6
+ type?: string
7
+ table: {
8
+ showVertical?: boolean
9
+ indexLabel: string
10
+ limitHeight: boolean
11
+ height: string | number
12
+ caption: string
13
+ download: boolean
14
+ }
15
+ xAxis?: Axis
16
+ yAxis?: Axis
17
+ boxplot?: {
18
+ tableData: Object[]
19
+ labels: {
20
+ mean: string
21
+ maximum: string
22
+ minimum: string
23
+ iqr: string
24
+ median: string
25
+ q1: string
26
+ q3: string
27
+ outliers: string
28
+ values: string
29
+ total: string
30
+ lowerBounds: string
31
+ upperBounds: string
32
+ }
33
+ plots: []
34
+ categories: string[]
35
+ }
36
+ visualizationType?: string
37
+ general?: {
38
+ geoType: string
39
+ type: string
40
+ showDownloadButton: boolean
41
+ allowMapZoom?: boolean
42
+ }
43
+ columns?: {
44
+ geo: {
45
+ name: string
46
+ }
47
+ }
48
+ legend?: {
49
+ specialClasses: { key: string; label: string; value: string }[]
50
+ }
51
+ series?: Series
52
+ regions?: { label: string; from: string; to: string }[]
53
+ runtimeSeriesLabels?: Object
54
+ dataFormat?: Object
55
+ runtime: Runtime
56
+ data: Object[]
57
+ }
@@ -0,0 +1,29 @@
1
+ import Papa from 'papaparse'
2
+
3
+ type DownloadButtonProps = {
4
+ rawData: Object
5
+ fileName: string
6
+ headerColor: string
7
+ skipId: string | number
8
+ }
9
+
10
+ const DownloadButton = ({ rawData, fileName, headerColor, skipId }: DownloadButtonProps) => {
11
+ const csvData = Papa.unparse(rawData)
12
+ const blob = new Blob([csvData], { type: 'text/csv;charset=utf-8;' })
13
+
14
+ const saveBlob = () => {
15
+ //@ts-ignore
16
+ if (typeof window.navigator.msSaveBlob === 'function') {
17
+ //@ts-ignore
18
+ navigator.msSaveBlob(blob, fileName)
19
+ }
20
+ }
21
+
22
+ return (
23
+ <a download={fileName} type='button' onClick={saveBlob} href={URL.createObjectURL(blob)} aria-label='Download this data in a CSV file format.' className={`${headerColor} no-border`} id={`${skipId}`} data-html2canvas-ignore role='button'>
24
+ Download Data (CSV)
25
+ </a>
26
+ )
27
+ }
28
+
29
+ export default DownloadButton
@@ -1,11 +1,11 @@
1
1
  import React from 'react'
2
2
 
3
- export default function LegendCircle({ fill, borderColor }) {
3
+ export default function LegendCircle({ fill, borderColor, display = 'inline-block' }) {
4
4
  const styles = {
5
5
  marginRight: '5px',
6
6
  borderRadius: '300px',
7
7
  verticalAlign: 'middle',
8
- display: 'inline-block',
8
+ display: display,
9
9
  height: '1em',
10
10
  width: '1em',
11
11
  border: borderColor ? `${borderColor} 1px solid` : 'rgba(0,0,0,.3) 1px solid',
@@ -0,0 +1,49 @@
1
+ import { ReactNode } from 'react'
2
+ import Row from './components/Row'
3
+ import GroupRow from './components/GroupRow'
4
+ import { CellMatrix, GroupCellMatrix } from './types/CellMatrix'
5
+
6
+ type TableProps = {
7
+ childrenMatrix: CellMatrix | GroupCellMatrix
8
+ tableName: string
9
+ caption: string
10
+ stickyHeader?: boolean
11
+ headContent: ReactNode
12
+ tableOptions: {
13
+ className: string
14
+ 'aria-live'?: 'off' | 'assertive' | 'polite'
15
+ hidden?: boolean
16
+ 'aria-rowcount'?: number
17
+ }
18
+ }
19
+
20
+ type Position = 'sticky'
21
+
22
+ const Table = ({ childrenMatrix, tableName, caption, stickyHeader, headContent, tableOptions }: TableProps) => {
23
+ const headStyle = stickyHeader ? { position: 'sticky' as Position, top: 0, zIndex: 999 } : {}
24
+ const isGroupedMatrix = !Array.isArray(childrenMatrix)
25
+ return (
26
+ <table {...tableOptions}>
27
+ <caption className='visually-hidden'>{caption}</caption>
28
+ <thead style={headStyle}>{headContent}</thead>
29
+ <tbody>
30
+ {isGroupedMatrix
31
+ ? Object.keys(childrenMatrix).flatMap(groupName => {
32
+ let colSpan = 0
33
+ const rows = childrenMatrix[groupName].map((row, i) => {
34
+ colSpan = row.length
35
+ const key = `${tableName}-${groupName}-row-${i}`
36
+ return <Row key={key} rowKey={key} childRow={row} />
37
+ })
38
+ return [<GroupRow label={groupName} colSpan={colSpan} key={`${tableName}-${groupName}`} />, ...rows]
39
+ })
40
+ : childrenMatrix.map((childRow, i) => {
41
+ const key = `${tableName}-row-${i}`
42
+ return <Row key={key} rowKey={key} childRow={childRow} />
43
+ })}
44
+ </tbody>
45
+ </table>
46
+ )
47
+ }
48
+
49
+ export default Table
@@ -0,0 +1,9 @@
1
+ const Cell = ({ children }) => {
2
+ return (
3
+ <td tabIndex={0} role='gridcell'>
4
+ {children}
5
+ </td>
6
+ )
7
+ }
8
+
9
+ export default Cell
@@ -0,0 +1,16 @@
1
+ type GroupRowProps = {
2
+ label: string
3
+ colSpan: number
4
+ }
5
+
6
+ const GroupRow = ({ label, colSpan }: GroupRowProps) => {
7
+ return (
8
+ <tr>
9
+ <th scope='colgroup' colSpan={colSpan}>
10
+ {label}
11
+ </th>
12
+ </tr>
13
+ )
14
+ }
15
+
16
+ export default GroupRow
@@ -0,0 +1,19 @@
1
+ import { ReactNode } from 'react'
2
+ import Cell from './Cell'
3
+
4
+ type RowProps = {
5
+ childRow: ReactNode[]
6
+ rowKey: string
7
+ }
8
+
9
+ const Row = ({ childRow, rowKey }: RowProps) => {
10
+ return (
11
+ <tr>
12
+ {childRow.map((child, i) => (
13
+ <Cell key={rowKey + '__' + i}>{child}</Cell>
14
+ ))}
15
+ </tr>
16
+ )
17
+ }
18
+
19
+ export default Row
@@ -0,0 +1 @@
1
+ export { default } from './Table'
@@ -0,0 +1,4 @@
1
+ import { ReactNode } from 'react'
2
+
3
+ export type CellMatrix = ReactNode[][]
4
+ export type GroupCellMatrix = Record<string, CellMatrix>
@@ -0,0 +1,62 @@
1
+ import { Meta, StoryObj } from '@storybook/react'
2
+
3
+ import DataTable from '../DataTable'
4
+ import './styles.scss'
5
+ import Example_1 from './_mocks/dashboard_no_filter.json'
6
+ import CityStateExample from './_mocks/example-city-state.json'
7
+ import { displayGeoName } from '@cdc/map/src/helpers/displayGeoName'
8
+
9
+ const meta: Meta<typeof DataTable> = {
10
+ title: 'Components/Organisms/DataTable',
11
+ component: DataTable
12
+ }
13
+
14
+ export default meta
15
+
16
+ type Story = StoryObj<typeof DataTable>
17
+
18
+ const datasetKey = 'dashboard_example_map.csv'
19
+
20
+ export const Primary: Story = {
21
+ args: {
22
+ config: Example_1,
23
+ dataConfig: Example_1.datasets[datasetKey],
24
+ rawData: Example_1.datasets[datasetKey].data,
25
+ runtimeData: Example_1.datasets[datasetKey].data,
26
+ expandDataTable: true,
27
+ tableTitle: 'COVE DataTable',
28
+ viewport: 'lg',
29
+ tabbingId: datasetKey
30
+ }
31
+ }
32
+
33
+ export const CityState: Story = {
34
+ args: {
35
+ config: CityStateExample,
36
+ dataConfig: CityStateExample,
37
+ rawData: CityStateExample.data,
38
+ runtimeData: CityStateExample.data,
39
+ expandDataTable: true,
40
+ tableTitle: 'CityStateExample DataTable',
41
+ viewport: 'lg',
42
+ tabbingId: '#asdf',
43
+ columns: CityStateExample.columns,
44
+ applyLegendToRow: () => ['#000'],
45
+ displayGeoName,
46
+ displayDataAsText: d => d
47
+ }
48
+ }
49
+
50
+ export const Grouped: Story = {
51
+ args: {
52
+ config: Example_1,
53
+ dataConfig: Example_1.datasets[datasetKey],
54
+ rawData: Example_1.datasets[datasetKey].data,
55
+ runtimeData: Example_1.datasets[datasetKey].data,
56
+ expandDataTable: true,
57
+ tableTitle: 'COVE DataTable',
58
+ groupBy: 'TimeZone',
59
+ viewport: 'lg',
60
+ tabbingId: datasetKey
61
+ }
62
+ }
@@ -0,0 +1,53 @@
1
+ import { Meta, StoryObj } from '@storybook/react'
2
+
3
+ import Table from '../Table'
4
+ import { ReactNode } from 'react'
5
+
6
+ const meta: Meta<typeof Table> = {
7
+ title: 'Components/Molecules/Table',
8
+ component: Table
9
+ }
10
+
11
+ export default meta
12
+
13
+ type Story = StoryObj<typeof Table>
14
+
15
+ function createMatrix(): ReactNode[][] {
16
+ const base = ['a', 'b', 'c'].map(el => <>{el}</>)
17
+ return [base, base]
18
+ }
19
+
20
+ export const Ungrouped: Story = {
21
+ args: {
22
+ childrenMatrix: createMatrix(),
23
+ tableName: 'COVE Table',
24
+ headContent: (
25
+ <tr>
26
+ <th>first</th>
27
+ <th>second</th>
28
+ <th>third</th>
29
+ </tr>
30
+ ),
31
+ tableOptions: { className: 'table table-bordered' }
32
+ }
33
+ }
34
+
35
+ function createGroupMatrix(): Record<string, ReactNode[][]> {
36
+ const base = ['a', 'b', 'c'].map(el => <>{el}</>)
37
+ return { group_1: [base, base], group_2: [base, base] }
38
+ }
39
+
40
+ export const Grouped: Story = {
41
+ args: {
42
+ childrenMatrix: createGroupMatrix(),
43
+ tableName: 'COVE Table',
44
+ headContent: (
45
+ <tr>
46
+ <th>first</th>
47
+ <th>second</th>
48
+ <th>third</th>
49
+ </tr>
50
+ ),
51
+ tableOptions: { className: 'table table-bordered' }
52
+ }
53
+ }