@ndlib/component-library 1.0.48 → 1.0.50
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/dist/components/elements/TableV2/TableV2.stories.d.ts +10 -0
- package/dist/components/elements/TableV2/TableV2.stories.js +98 -0
- package/dist/components/elements/TableV2/index.d.ts +29 -0
- package/dist/components/elements/TableV2/index.js +105 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { TableV2 } from '.';
|
|
3
|
+
declare const meta: Meta<typeof TableV2>;
|
|
4
|
+
export default meta;
|
|
5
|
+
type Story = StoryObj<typeof TableV2>;
|
|
6
|
+
export declare const Default: Story;
|
|
7
|
+
export declare const OmitColumn: Story;
|
|
8
|
+
export declare const ResponsiveColumn: Story;
|
|
9
|
+
export declare const ColumnGroup: Story;
|
|
10
|
+
export declare const Sortable: Story;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { TableV2, TableColumnV2 } from '.';
|
|
3
|
+
import { SORT_DIRECTION, sortByKey } from '../../../utils/sortByKey';
|
|
4
|
+
import { useState } from 'react';
|
|
5
|
+
import { UIVersion2 } from '../../../utils/decorators/UIVersion2';
|
|
6
|
+
const meta = {
|
|
7
|
+
title: 'Elements/TableV2',
|
|
8
|
+
component: TableV2,
|
|
9
|
+
tags: ['autodocs'],
|
|
10
|
+
decorators: [UIVersion2],
|
|
11
|
+
};
|
|
12
|
+
export default meta;
|
|
13
|
+
const data = [
|
|
14
|
+
{
|
|
15
|
+
name: 'Steve Rogers',
|
|
16
|
+
age: 100,
|
|
17
|
+
position: 'Ethics Officer',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
name: 'Natasha Romanoff',
|
|
21
|
+
age: 35,
|
|
22
|
+
position: 'Opposition Researcher',
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
name: 'Thor',
|
|
26
|
+
age: 1500,
|
|
27
|
+
position: 'VP of Thunder',
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
name: 'Peter Parker',
|
|
31
|
+
age: 18,
|
|
32
|
+
position: 'Web Crawling Expert',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
name: 'Kate Bishop',
|
|
36
|
+
age: 22,
|
|
37
|
+
position: 'Trust Fund Recipient',
|
|
38
|
+
},
|
|
39
|
+
];
|
|
40
|
+
export const Default = {
|
|
41
|
+
render: () => (_jsxs(TableV2, { data: data, alternateRowColor: true, children: [_jsx(TableColumnV2, { header: "Name", dataKey: "name", sx: {
|
|
42
|
+
width: '160px',
|
|
43
|
+
} }), _jsx(TableColumnV2, { header: "Age", sx: {
|
|
44
|
+
width: '100px',
|
|
45
|
+
}, children: (row) => row.age }), _jsx(TableColumnV2, { header: "Occupation", children: (row) => row.position })] })),
|
|
46
|
+
};
|
|
47
|
+
export const OmitColumn = {
|
|
48
|
+
render: () => {
|
|
49
|
+
const someCondition = false;
|
|
50
|
+
return (_jsxs(TableV2, { data: data, alternateRowColor: true, children: [_jsx(TableColumnV2, { header: "Name", dataKey: "name", sx: {
|
|
51
|
+
width: '160px',
|
|
52
|
+
} }), someCondition ? (_jsx(TableColumnV2, { header: "Age", sx: {
|
|
53
|
+
width: '100px',
|
|
54
|
+
}, children: (row) => row.age })) : null, _jsx(TableColumnV2, { header: "Occupation", children: (row) => row.position })] }));
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
export const ResponsiveColumn = {
|
|
58
|
+
render: () => {
|
|
59
|
+
return (_jsxs(TableV2, { data: data, alternateRowColor: true, children: [_jsx(TableColumnV2, { header: "Name", dataKey: "name", sx: {
|
|
60
|
+
width: '160px',
|
|
61
|
+
} }), _jsx(TableColumnV2, { breakpoint: 2, header: "Age", sx: {
|
|
62
|
+
width: '100px',
|
|
63
|
+
}, children: (row) => row.age }), _jsx(TableColumnV2, { header: "Occupation", children: (row) => row.position })] }));
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
export const ColumnGroup = {
|
|
67
|
+
render: () => {
|
|
68
|
+
return (_jsxs(TableV2, { data: data, alternateRowColor: true, children: [_jsx(TableColumnV2, { header: "Name", dataKey: "name", sx: {
|
|
69
|
+
width: '160px',
|
|
70
|
+
} }), [
|
|
71
|
+
_jsx(TableColumnV2, { header: "Age", sx: {
|
|
72
|
+
width: '100px',
|
|
73
|
+
}, children: (row) => row.age }),
|
|
74
|
+
_jsx(TableColumnV2, { header: "Occupation", children: (row) => row.position }),
|
|
75
|
+
]] }));
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
const SortableStory = () => {
|
|
79
|
+
const [sortConfig, setSortConfig] = useState({
|
|
80
|
+
key: 'name',
|
|
81
|
+
direction: SORT_DIRECTION.ASC,
|
|
82
|
+
});
|
|
83
|
+
const sorted = sortByKey({
|
|
84
|
+
items: data,
|
|
85
|
+
config: sortConfig,
|
|
86
|
+
});
|
|
87
|
+
return (_jsxs(TableV2, { data: sorted, alternateRowColor: true, sortConfig: sortConfig, updateSort: setSortConfig, children: [_jsx(TableColumnV2, { header: "Name", dataKey: "name", sortable: true, sx: {
|
|
88
|
+
width: '160px',
|
|
89
|
+
} }), [
|
|
90
|
+
_jsx(TableColumnV2, { header: "Age", sortKey: "age", sortable: true, sx: {
|
|
91
|
+
width: '100px',
|
|
92
|
+
}, children: (row) => row.age }),
|
|
93
|
+
_jsx(TableColumnV2, { header: "Occupation", sortable: true, dataKey: "position" }),
|
|
94
|
+
]] }));
|
|
95
|
+
};
|
|
96
|
+
export const Sortable = {
|
|
97
|
+
render: SortableStory,
|
|
98
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { StyledElementPropsV2, StylesPropV2 } from '../../../theme';
|
|
2
|
+
import { SortConfig } from '../../../utils/sortByKey';
|
|
3
|
+
type ColumnRenderFn<RowData> = (data: RowData) => React.ReactNode;
|
|
4
|
+
type ColumnProps<RowData extends object> = {
|
|
5
|
+
header: string;
|
|
6
|
+
sortable?: boolean;
|
|
7
|
+
sortKey?: keyof RowData;
|
|
8
|
+
dataKey?: keyof RowData;
|
|
9
|
+
headerStyles?: StylesPropV2;
|
|
10
|
+
align?: 'left' | 'center' | 'right';
|
|
11
|
+
alignHeader?: 'left' | 'center' | 'right';
|
|
12
|
+
children?: ColumnRenderFn<RowData>;
|
|
13
|
+
breakpoint?: number;
|
|
14
|
+
sx?: StylesPropV2;
|
|
15
|
+
};
|
|
16
|
+
type ChildList = ChildList[] | JSX.Element | null | undefined;
|
|
17
|
+
type TableProps<RowData> = StyledElementPropsV2<HTMLTableElement, {
|
|
18
|
+
data: RowData[];
|
|
19
|
+
sortConfig?: SortConfig<RowData>;
|
|
20
|
+
updateSort?: (sortConfig: SortConfig<RowData>) => void;
|
|
21
|
+
children: ChildList[];
|
|
22
|
+
cellStyles?: StylesPropV2;
|
|
23
|
+
alternateRowColor?: boolean;
|
|
24
|
+
showRowDividers?: boolean;
|
|
25
|
+
showColumnDividers?: boolean;
|
|
26
|
+
}>;
|
|
27
|
+
export declare function TableColumnV2<RowData extends object>(props: ColumnProps<RowData>): null;
|
|
28
|
+
export declare function TableV2<RowData extends object>(props: TableProps<RowData>): import("react/jsx-runtime").JSX.Element;
|
|
29
|
+
export {};
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo } from 'react';
|
|
3
|
+
import { COLOR } from '../../../theme/colors';
|
|
4
|
+
import { useEnvironment } from '../../providers/env';
|
|
5
|
+
import { FONT_SIZE, TYPOGRAPHY_TYPE, typographyStyleMap, } from '../../../theme/typography';
|
|
6
|
+
import { useMediaQueryV2 } from '../../providers/mediaV2';
|
|
7
|
+
import { RowV2 } from '../RowV2';
|
|
8
|
+
import _ArrowDropDown from '@mui/icons-material/ArrowDropDown';
|
|
9
|
+
import _ArrowDropUp from '@mui/icons-material/ArrowDropUp';
|
|
10
|
+
import { importedDefaultComponentShim } from '../../../utils/misc';
|
|
11
|
+
import { Icon } from '../Icon';
|
|
12
|
+
import { SORT_DIRECTION } from '../../../utils/sortByKey';
|
|
13
|
+
import { processSx } from '../../../utils/processSx';
|
|
14
|
+
const ArrowDropDown = importedDefaultComponentShim(_ArrowDropDown);
|
|
15
|
+
const ArrowDropUp = importedDefaultComponentShim(_ArrowDropUp);
|
|
16
|
+
const useColumnSpec = (children) => {
|
|
17
|
+
const headerList = [];
|
|
18
|
+
const parseHeaders = (children) => {
|
|
19
|
+
children.forEach((child) => {
|
|
20
|
+
if (Array.isArray(child)) {
|
|
21
|
+
parseHeaders(child);
|
|
22
|
+
}
|
|
23
|
+
else if (child) {
|
|
24
|
+
headerList.push(child.props.header);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
parseHeaders(children);
|
|
29
|
+
const columnList = JSON.stringify(headerList);
|
|
30
|
+
return useMemo(() => {
|
|
31
|
+
const columnProps = [];
|
|
32
|
+
const parseColumnProps = (children) => {
|
|
33
|
+
children.forEach((child) => {
|
|
34
|
+
if (Array.isArray(child)) {
|
|
35
|
+
parseColumnProps(child);
|
|
36
|
+
}
|
|
37
|
+
else if (child) {
|
|
38
|
+
columnProps.push(child.props);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
};
|
|
42
|
+
parseColumnProps(children);
|
|
43
|
+
return columnProps;
|
|
44
|
+
}, [columnList]);
|
|
45
|
+
};
|
|
46
|
+
export function TableColumnV2(props) {
|
|
47
|
+
const { flagInDevelopment } = useEnvironment();
|
|
48
|
+
flagInDevelopment('TableColumnV2 should not be used outside of Table component');
|
|
49
|
+
console.log('We offer this log to you in reverence, oh compiler gods', props);
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
export function TableV2(props) {
|
|
53
|
+
const { role, data, alternateRowColor = true, cellStyles, sx, children, showRowDividers = true, showColumnDividers = false, sortConfig, updateSort, } = props;
|
|
54
|
+
const cellTypographyStyles = typographyStyleMap[TYPOGRAPHY_TYPE.CONDENSED_TEXT_MEDIUM];
|
|
55
|
+
const headerTypographyStyles = typographyStyleMap[TYPOGRAPHY_TYPE.CONTROL_MEDIUM];
|
|
56
|
+
const { breakpoint } = useMediaQueryV2();
|
|
57
|
+
const columnSpec = useColumnSpec(children);
|
|
58
|
+
const getCellStyles = (params) => {
|
|
59
|
+
const { columnProps, rowIndex, columnIndex } = params;
|
|
60
|
+
const isLastColumn = columnIndex === columnSpec.length - 1;
|
|
61
|
+
const isLastRow = rowIndex === data.length - 1;
|
|
62
|
+
const cellAlign = columnProps.align || 'left';
|
|
63
|
+
const styles = Object.assign({ bg: alternateRowColor && rowIndex % 2 === 1
|
|
64
|
+
? COLOR.EXTRA_EXTRA_LIGHT_GRAY
|
|
65
|
+
: COLOR.WHITE, p: 3, borderBottom: showRowDividers && !isLastRow ? '1px solid' : 'none', borderRight: showColumnDividers && !isLastColumn ? '1px solid' : 'none', borderColor: COLOR.LIGHT_GRAY, textAlign: cellAlign }, cellTypographyStyles);
|
|
66
|
+
return Object.assign(Object.assign(Object.assign({}, styles), cellStyles), columnProps.sx);
|
|
67
|
+
};
|
|
68
|
+
const processedStyles = processSx(sx);
|
|
69
|
+
return (_jsxs("table", { role: role, style: processedStyles, children: [_jsx("thead", { role: "rowgroup", children: _jsx("tr", { children: columnSpec.map((column, i) => {
|
|
70
|
+
const isLastColumn = i === columnSpec.length - 1;
|
|
71
|
+
if (column.breakpoint && breakpoint < column.breakpoint) {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
const canSort = sortConfig && column.sortable;
|
|
75
|
+
const sortKey = column.sortKey || column.dataKey;
|
|
76
|
+
const onSort = () => {
|
|
77
|
+
if (canSort) {
|
|
78
|
+
const direction = sortConfig.direction === SORT_DIRECTION.ASC
|
|
79
|
+
? SORT_DIRECTION.DESC
|
|
80
|
+
: SORT_DIRECTION.ASC;
|
|
81
|
+
updateSort &&
|
|
82
|
+
updateSort({ key: sortKey, direction });
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
const headerStyles = Object.assign(Object.assign({ textAlign: (column.alignHeader || column.align || 'left'), borderBottom: '1px solid', borderRight: showColumnDividers && !isLastColumn ? '1px solid' : 'none', borderColor: COLOR.LIGHT_GRAY, px: 3, pb: 1 }, headerTypographyStyles), column.headerStyles);
|
|
86
|
+
const processedHeaderStyles = processSx(headerStyles);
|
|
87
|
+
return (_jsx("th", { role: "columnheader", style: processedHeaderStyles, children: _jsxs(RowV2, { onClick: onSort, tabIndex: canSort ? 0 : undefined, sx: { cursor: canSort ? 'pointer' : 'default' }, children: [column.header, canSort &&
|
|
88
|
+
sortConfig.key === sortKey &&
|
|
89
|
+
(sortConfig.direction === SORT_DIRECTION.ASC ? (_jsx(Icon, { icon: ArrowDropUp, sx: { ml: 1 }, size: FONT_SIZE.MD })) : (_jsx(Icon, { icon: ArrowDropDown, sx: { ml: 1 }, size: FONT_SIZE.MD })))] }) }, i));
|
|
90
|
+
}) }) }), _jsx("tbody", { role: "rowgroup", children: data.map((rowData, rowIndex) => {
|
|
91
|
+
return (_jsx("tr", { role: "row", children: columnSpec.map((column, columnIndex) => {
|
|
92
|
+
if (column.breakpoint && breakpoint < column.breakpoint) {
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
const { children, dataKey } = column;
|
|
96
|
+
const cellStyles = getCellStyles({
|
|
97
|
+
columnProps: column,
|
|
98
|
+
rowIndex,
|
|
99
|
+
columnIndex,
|
|
100
|
+
});
|
|
101
|
+
const processedCellStyles = processSx(cellStyles);
|
|
102
|
+
return (_jsx("td", { style: processedCellStyles, children: _jsxs(_Fragment, { children: [dataKey ? rowData[dataKey] : null, !dataKey && children && children(rowData)] }) }, columnIndex));
|
|
103
|
+
}) }, rowIndex));
|
|
104
|
+
}) })] }));
|
|
105
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -59,6 +59,7 @@ export { SpinnerV2, SPINNERV2_SIZE } from './components/elements/SpinnerV2';
|
|
|
59
59
|
export { Pill, PILL_SIZE, PILL_TYPE } from './components/elements/Pill';
|
|
60
60
|
export { PillV2, PILLV2_SIZE, PILLV2_TYPE } from './components/elements/PillV2';
|
|
61
61
|
export { Table, TableColumn } from './components/elements/Table';
|
|
62
|
+
export { TableV2, TableColumnV2 } from './components/elements/TableV2';
|
|
62
63
|
export { TabList, Tab } from './components/elements/TabList';
|
|
63
64
|
export { TabListV2, TabV2 } from './components/elements/TabListV2';
|
|
64
65
|
export { RawHtml } from './components/elements/RawHtml';
|
package/dist/index.js
CHANGED
|
@@ -58,6 +58,7 @@ export { SpinnerV2, SPINNERV2_SIZE } from './components/elements/SpinnerV2';
|
|
|
58
58
|
export { Pill, PILL_SIZE, PILL_TYPE } from './components/elements/Pill';
|
|
59
59
|
export { PillV2, PILLV2_SIZE, PILLV2_TYPE } from './components/elements/PillV2';
|
|
60
60
|
export { Table, TableColumn } from './components/elements/Table';
|
|
61
|
+
export { TableV2, TableColumnV2 } from './components/elements/TableV2';
|
|
61
62
|
export { TabList, Tab } from './components/elements/TabList';
|
|
62
63
|
export { TabListV2, TabV2 } from './components/elements/TabListV2';
|
|
63
64
|
export { RawHtml } from './components/elements/RawHtml';
|