|
|
|
@ -33,17 +33,20 @@ import {
|
|
|
|
|
|
|
|
|
|
|
|
import { useAsyncList } from 'react-stately';
|
|
|
|
import { useAsyncList } from 'react-stately';
|
|
|
|
|
|
|
|
|
|
|
|
import { useBreakpoints } from '@/hooks';
|
|
|
|
import { useBreakpoints, useStringGetter } from '@/hooks';
|
|
|
|
import { MediaQueryKeys } from '@/hooks/useBreakpoints';
|
|
|
|
import { MediaQueryKeys } from '@/hooks/useBreakpoints';
|
|
|
|
|
|
|
|
|
|
|
|
import { Checkbox } from '@/components/Checkbox';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import { breakpoints } from '@/styles';
|
|
|
|
import { breakpoints } from '@/styles';
|
|
|
|
import { layoutMixins } from '@/styles/layoutMixins';
|
|
|
|
import { layoutMixins } from '@/styles/layoutMixins';
|
|
|
|
|
|
|
|
import { CaretIcon } from '@/icons';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import { STRING_KEYS } from '@/constants/localization';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import { MustBigNumber } from '@/lib/numbers';
|
|
|
|
|
|
|
|
|
|
|
|
import { Icon, IconName } from './Icon';
|
|
|
|
import { Icon, IconName } from './Icon';
|
|
|
|
import { Tag } from './Tag';
|
|
|
|
import { Tag } from './Tag';
|
|
|
|
import { MustBigNumber } from '@/lib/numbers';
|
|
|
|
import { Button } from './Button';
|
|
|
|
|
|
|
|
|
|
|
|
export { TableCell } from './Table/TableCell';
|
|
|
|
export { TableCell } from './Table/TableCell';
|
|
|
|
export { TableColumnHeader } from './Table/TableColumnHeader';
|
|
|
|
export { TableColumnHeader } from './Table/TableColumnHeader';
|
|
|
|
@ -65,7 +68,7 @@ export type TableItem<TableRowData> = {
|
|
|
|
onSelect?: (key: TableRowData) => void;
|
|
|
|
onSelect?: (key: TableRowData) => void;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
export type ColumnDef<TableRowData extends object> = {
|
|
|
|
type ColumnDef<TableRowData extends object> = {
|
|
|
|
columnKey: string;
|
|
|
|
columnKey: string;
|
|
|
|
label: React.ReactNode;
|
|
|
|
label: React.ReactNode;
|
|
|
|
tag?: React.ReactNode;
|
|
|
|
tag?: React.ReactNode;
|
|
|
|
@ -80,7 +83,7 @@ export type ColumnDef<TableRowData extends object> = {
|
|
|
|
width?: ColumnSize;
|
|
|
|
width?: ColumnSize;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
type ElementProps<TableRowData extends object | CustomRowConfig, TableRowKey extends Key> = {
|
|
|
|
export type ElementProps<TableRowData extends object | CustomRowConfig, TableRowKey extends Key> = {
|
|
|
|
label?: string;
|
|
|
|
label?: string;
|
|
|
|
columns: ColumnDef<TableRowData>[];
|
|
|
|
columns: ColumnDef<TableRowData>[];
|
|
|
|
data: TableRowData[];
|
|
|
|
data: TableRowData[];
|
|
|
|
@ -92,6 +95,7 @@ type ElementProps<TableRowData extends object | CustomRowConfig, TableRowKey ext
|
|
|
|
selectionBehavior?: 'replace' | 'toggle';
|
|
|
|
selectionBehavior?: 'replace' | 'toggle';
|
|
|
|
onRowAction?: (key: TableRowKey, row: TableRowData) => void;
|
|
|
|
onRowAction?: (key: TableRowKey, row: TableRowData) => void;
|
|
|
|
slotEmpty?: React.ReactNode;
|
|
|
|
slotEmpty?: React.ReactNode;
|
|
|
|
|
|
|
|
initialNumRowsToShow?: number;
|
|
|
|
// collection: TableCollection<string>;
|
|
|
|
// collection: TableCollection<string>;
|
|
|
|
// children: React.ReactNode;
|
|
|
|
// children: React.ReactNode;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
@ -121,6 +125,7 @@ export const Table = <TableRowData extends object, TableRowKey extends Key>({
|
|
|
|
selectionMode = 'single',
|
|
|
|
selectionMode = 'single',
|
|
|
|
selectionBehavior = 'toggle',
|
|
|
|
selectionBehavior = 'toggle',
|
|
|
|
slotEmpty,
|
|
|
|
slotEmpty,
|
|
|
|
|
|
|
|
initialNumRowsToShow = data.length,
|
|
|
|
// shouldRowRender,
|
|
|
|
// shouldRowRender,
|
|
|
|
|
|
|
|
|
|
|
|
// collection,
|
|
|
|
// collection,
|
|
|
|
@ -136,6 +141,7 @@ export const Table = <TableRowData extends object, TableRowKey extends Key>({
|
|
|
|
style,
|
|
|
|
style,
|
|
|
|
}: ElementProps<TableRowData, TableRowKey> & StyleProps) => {
|
|
|
|
}: ElementProps<TableRowData, TableRowKey> & StyleProps) => {
|
|
|
|
const [selectedKeys, setSelectedKeys] = useState(new Set<TableRowKey>());
|
|
|
|
const [selectedKeys, setSelectedKeys] = useState(new Set<TableRowKey>());
|
|
|
|
|
|
|
|
const [numRowsToShow, setNumRowsToShow] = useState(initialNumRowsToShow);
|
|
|
|
|
|
|
|
|
|
|
|
const currentBreakpoints = useBreakpoints();
|
|
|
|
const currentBreakpoints = useBreakpoints();
|
|
|
|
const shownColumns = columns.filter(
|
|
|
|
const shownColumns = columns.filter(
|
|
|
|
@ -209,6 +215,12 @@ export const Table = <TableRowData extends object, TableRowKey extends Key>({
|
|
|
|
onRowAction &&
|
|
|
|
onRowAction &&
|
|
|
|
((key: TableRowKey) => onRowAction(key, data.find((row) => getRowKey(row) === key)!))
|
|
|
|
((key: TableRowKey) => onRowAction(key, data.find((row) => getRowKey(row) === key)!))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
numColumns={shownColumns.length}
|
|
|
|
|
|
|
|
onViewMoreClick={
|
|
|
|
|
|
|
|
numRowsToShow !== undefined && numRowsToShow < data.length
|
|
|
|
|
|
|
|
? () => setNumRowsToShow(data.length)
|
|
|
|
|
|
|
|
: undefined
|
|
|
|
|
|
|
|
}
|
|
|
|
// shouldRowRender={shouldRowRender}
|
|
|
|
// shouldRowRender={shouldRowRender}
|
|
|
|
hideHeader={hideHeader}
|
|
|
|
hideHeader={hideHeader}
|
|
|
|
withGradientCardRows={withGradientCardRows}
|
|
|
|
withGradientCardRows={withGradientCardRows}
|
|
|
|
@ -233,7 +245,7 @@ export const Table = <TableRowData extends object, TableRowKey extends Key>({
|
|
|
|
)}
|
|
|
|
)}
|
|
|
|
</TableHeader>
|
|
|
|
</TableHeader>
|
|
|
|
|
|
|
|
|
|
|
|
<TableBody items={list.items}>
|
|
|
|
<TableBody items={list.items.slice(0, numRowsToShow)}>
|
|
|
|
{(item) => (
|
|
|
|
{(item) => (
|
|
|
|
<Row key={getRowKey(item)}>
|
|
|
|
<Row key={getRowKey(item)}>
|
|
|
|
{(columnKey) => (
|
|
|
|
{(columnKey) => (
|
|
|
|
@ -267,6 +279,8 @@ const TableRoot = <TableRowData extends object | CustomRowConfig, TableRowKey ex
|
|
|
|
onRowAction?: (key: TableRowKey) => void;
|
|
|
|
onRowAction?: (key: TableRowKey) => void;
|
|
|
|
// shouldRowRender?: (prevRowData: object, currentRowData: object) => boolean;
|
|
|
|
// shouldRowRender?: (prevRowData: object, currentRowData: object) => boolean;
|
|
|
|
children: CollectionChildren<TableRowData>;
|
|
|
|
children: CollectionChildren<TableRowData>;
|
|
|
|
|
|
|
|
numColumns: number;
|
|
|
|
|
|
|
|
onViewMoreClick?: () => void;
|
|
|
|
|
|
|
|
|
|
|
|
hideHeader?: boolean;
|
|
|
|
hideHeader?: boolean;
|
|
|
|
withGradientCardRows?: boolean;
|
|
|
|
withGradientCardRows?: boolean;
|
|
|
|
@ -276,7 +290,7 @@ const TableRoot = <TableRowData extends object | CustomRowConfig, TableRowKey ex
|
|
|
|
withScrollSnapColumns?: boolean;
|
|
|
|
withScrollSnapColumns?: boolean;
|
|
|
|
withScrollSnapRows?: boolean;
|
|
|
|
withScrollSnapRows?: boolean;
|
|
|
|
}) => {
|
|
|
|
}) => {
|
|
|
|
const { selectionMode, selectionBehavior } = props;
|
|
|
|
const { selectionMode, selectionBehavior, numColumns, onViewMoreClick } = props;
|
|
|
|
|
|
|
|
|
|
|
|
const state = useTableState<TableRowData>({
|
|
|
|
const state = useTableState<TableRowData>({
|
|
|
|
...props,
|
|
|
|
...props,
|
|
|
|
@ -337,6 +351,7 @@ const TableRoot = <TableRowData extends object | CustomRowConfig, TableRowKey ex
|
|
|
|
<TableBodyRowGroup
|
|
|
|
<TableBodyRowGroup
|
|
|
|
withGradientCardRows={props.withGradientCardRows}
|
|
|
|
withGradientCardRows={props.withGradientCardRows}
|
|
|
|
withInnerBorders={props.withInnerBorders}
|
|
|
|
withInnerBorders={props.withInnerBorders}
|
|
|
|
|
|
|
|
withOuterBorder={props.withOuterBorder}
|
|
|
|
>
|
|
|
|
>
|
|
|
|
{/* {Array.from(collection.getChildren!(collection.body.key), (row) => */}
|
|
|
|
{/* {Array.from(collection.getChildren!(collection.body.key), (row) => */}
|
|
|
|
{[...collection.body.childNodes].map((row) =>
|
|
|
|
{[...collection.body.childNodes].map((row) =>
|
|
|
|
@ -382,6 +397,9 @@ const TableRoot = <TableRowData extends object | CustomRowConfig, TableRowKey ex
|
|
|
|
</TableRow>
|
|
|
|
</TableRow>
|
|
|
|
)
|
|
|
|
)
|
|
|
|
)}
|
|
|
|
)}
|
|
|
|
|
|
|
|
{onViewMoreClick ? (
|
|
|
|
|
|
|
|
<ViewMoreRow colSpan={numColumns} onClick={onViewMoreClick} />
|
|
|
|
|
|
|
|
) : undefined}
|
|
|
|
</TableBodyRowGroup>
|
|
|
|
</TableBodyRowGroup>
|
|
|
|
</Styled.Table>
|
|
|
|
</Styled.Table>
|
|
|
|
);
|
|
|
|
);
|
|
|
|
@ -415,6 +433,7 @@ const TableBodyRowGroup = ({
|
|
|
|
children,
|
|
|
|
children,
|
|
|
|
withGradientCardRows,
|
|
|
|
withGradientCardRows,
|
|
|
|
withInnerBorders,
|
|
|
|
withInnerBorders,
|
|
|
|
|
|
|
|
withOuterBorder,
|
|
|
|
}: { children: React.ReactNode } & StyleProps) => {
|
|
|
|
}: { children: React.ReactNode } & StyleProps) => {
|
|
|
|
const { rowGroupProps } = useTableRowGroup();
|
|
|
|
const { rowGroupProps } = useTableRowGroup();
|
|
|
|
|
|
|
|
|
|
|
|
@ -423,6 +442,7 @@ const TableBodyRowGroup = ({
|
|
|
|
{...rowGroupProps}
|
|
|
|
{...rowGroupProps}
|
|
|
|
withGradientCardRows={withGradientCardRows}
|
|
|
|
withGradientCardRows={withGradientCardRows}
|
|
|
|
withInnerBorders={withInnerBorders}
|
|
|
|
withInnerBorders={withInnerBorders}
|
|
|
|
|
|
|
|
withOuterBorder={withOuterBorder}
|
|
|
|
>
|
|
|
|
>
|
|
|
|
{children}
|
|
|
|
{children}
|
|
|
|
</Styled.Tbody>
|
|
|
|
</Styled.Tbody>
|
|
|
|
@ -489,6 +509,23 @@ const TableColumnHeader = <TableRowData extends object>({
|
|
|
|
);
|
|
|
|
);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export const ViewMoreRow = ({ colSpan, onClick }: { colSpan: number; onClick: () => void }) => {
|
|
|
|
|
|
|
|
const stringGetter = useStringGetter();
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
|
|
|
<Styled.Tr key="viewmore">
|
|
|
|
|
|
|
|
<Styled.Td
|
|
|
|
|
|
|
|
colSpan={colSpan}
|
|
|
|
|
|
|
|
onMouseDown={(e: MouseEvent) => e.preventDefault()}
|
|
|
|
|
|
|
|
onPointerDown={(e: MouseEvent) => e.preventDefault()}
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
<Styled.ViewMoreButton slotRight={<CaretIcon />} onClick={onClick}>
|
|
|
|
|
|
|
|
{stringGetter({ key: STRING_KEYS.VIEW_MORE })}
|
|
|
|
|
|
|
|
</Styled.ViewMoreButton>
|
|
|
|
|
|
|
|
</Styled.Td>
|
|
|
|
|
|
|
|
</Styled.Tr>
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
export const TableRow = <TableRowData extends object>({
|
|
|
|
export const TableRow = <TableRowData extends object>({
|
|
|
|
item,
|
|
|
|
item,
|
|
|
|
children,
|
|
|
|
children,
|
|
|
|
@ -660,7 +697,7 @@ Styled.Empty = styled.div<{ withOuterBorder: boolean }>`
|
|
|
|
|
|
|
|
|
|
|
|
justify-items: center;
|
|
|
|
justify-items: center;
|
|
|
|
align-content: center;
|
|
|
|
align-content: center;
|
|
|
|
padding: 2rem;
|
|
|
|
padding: 4rem;
|
|
|
|
gap: 0.75em;
|
|
|
|
gap: 0.75em;
|
|
|
|
|
|
|
|
|
|
|
|
color: var(--color-text-0);
|
|
|
|
color: var(--color-text-0);
|
|
|
|
@ -868,6 +905,18 @@ Styled.Tbody = styled.tbody<StyleProps>`
|
|
|
|
--stickyArea2-paddingLeft: var(--border-width);
|
|
|
|
--stickyArea2-paddingLeft: var(--border-width);
|
|
|
|
--stickyArea2-paddingRight: var(--border-width);
|
|
|
|
--stickyArea2-paddingRight: var(--border-width);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tr:first-of-type {
|
|
|
|
|
|
|
|
box-shadow: 0 calc(var(--border-width)) 0 0 var(--border-color);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
`}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
${({ withOuterBorder }) =>
|
|
|
|
|
|
|
|
withOuterBorder &&
|
|
|
|
|
|
|
|
css`
|
|
|
|
|
|
|
|
tr:last-of-type:not(:only-of-type) {
|
|
|
|
|
|
|
|
box-shadow: 0 calc(-1 * var(--border-width)) 0 0 var(--border-color);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
tr:first-of-type {
|
|
|
|
tr:first-of-type {
|
|
|
|
box-shadow: none;
|
|
|
|
box-shadow: none;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -922,3 +971,15 @@ Styled.Row = styled.div`
|
|
|
|
${layoutMixins.inlineRow}
|
|
|
|
${layoutMixins.inlineRow}
|
|
|
|
padding: var(--tableCell-padding);
|
|
|
|
padding: var(--tableCell-padding);
|
|
|
|
`;
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Styled.ViewMoreButton = styled(Button)`
|
|
|
|
|
|
|
|
--button-backgroundColor: var(--color-layer-2);
|
|
|
|
|
|
|
|
--button-textColor: var(--color-text-1);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
svg {
|
|
|
|
|
|
|
|
width: 0.675rem;
|
|
|
|
|
|
|
|
margin-left: 0.5ch;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
`;
|
|
|
|
|