Skip to content

Commit

Permalink
feat: add Table HOC with group actions
Browse files Browse the repository at this point in the history
  • Loading branch information
krozhkov committed Nov 3, 2023
1 parent 6cb70a4 commit e8803b3
Show file tree
Hide file tree
Showing 6 changed files with 213 additions and 0 deletions.
56 changes: 56 additions & 0 deletions src/components/TableHOCs/__stories__/Table.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import React, {useCallback, useMemo, useState} from 'react';

import {Table} from '@gravity-ui/uikit';
import type {TableProps} from '@gravity-ui/uikit';
import type {Meta, StoryFn} from '@storybook/react';

import {TableWithGroupActions, columns, data} from './utils';
import type {DataItem} from './utils';

export default {
title: 'Components/TableHOCs',
component: Table,
args: {
columns,
data,
},
} as Meta<TableProps<DataItem>>;

// ---------------------------------
const WithTableSelectionTemplate: StoryFn<TableProps<DataItem>> = (args) => {
const [selectedIds, setSelectedIds] = useState<string[]>([]);

const handleClose = useCallback(() => setSelectedIds([]), []);

const showMessage = useCallback(
() => alert(`Are you sure you want to delete ${selectedIds.join(', ')}?`),
[selectedIds],
);

const groupActions = useMemo(
() => [
{
id: 'delete',
button: {
props: {children: 'Delete', onClick: showMessage},
},
dropdown: {
item: {text: 'Delete', action: showMessage},
},
},
],
[showMessage],
);

return (
<TableWithGroupActions
{...args}
selectedIds={selectedIds}
onSelectionChange={setSelectedIds}
formatTitle={(selected) => `${selected} Items`}
groupActions={groupActions}
onGroupActionsClose={handleClose}
/>
);
};
export const HOCWithTableGroupActions = WithTableSelectionTemplate.bind({});
77 changes: 77 additions & 0 deletions src/components/TableHOCs/__stories__/utils.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import {Table} from '@gravity-ui/uikit';
import type {TableColumnConfig} from '@gravity-ui/uikit';

import {withTableSelectionAndGroupActions} from '../';

export interface DataItem {
name: string;
city?: string;
phone: string;
count: number;
date: string;
disabled?: boolean;
}

export const data: DataItem[] = [
{
name: 'Nomlanga Compton',
city: 'Erli',
phone: '+7 (923) 737-89-72',
count: 82,
date: '2019-03-15',
},
{
name: 'Paul Hatfield',
city: 'Campitello di Fassa',
phone: '+7 (900) 333-82-02',
count: 51,
date: '2019-11-23',
},
{
name: 'Phelan Daniel',
city: 'Meugliano',
phone: '+7 (925) 549-50-23',
count: 10,
date: '2019-05-14',
},
{
name: 'Hiram Mayer',
city: '',
phone: '+7 (950) 372-56-84',
count: 54,
date: '2019-03-29',
},
{
name: 'Madeline Puckett',
phone: '+7 (908) 582-05-91',
count: 75,
date: '2019-02-01',
disabled: true,
},
];

export const columns: TableColumnConfig<DataItem>[] = [
{
id: 'name',
name: 'Name',
},
{
id: 'city',
name: 'City',
},
{
id: 'phone',
name: 'Phone',
},
{
id: 'count',
name: 'Count',
align: 'right',
},
{
id: 'date',
name: 'Date created',
},
];

export const TableWithGroupActions = withTableSelectionAndGroupActions<DataItem>(Table);
2 changes: 2 additions & 0 deletions src/components/TableHOCs/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export {withTableSelectionAndGroupActions} from './withTableSelectionAndGroupActions/withTableSelectionAndGroupActions';
export type {WithTableSelectionAndGroupActionsProps} from './withTableSelectionAndGroupActions/withTableSelectionAndGroupActions';
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
@use '../../variables';

$block: '.#{variables.$ns}with-table-group-actions';

#{$block} {
&__panel {
bottom: 0;
position: sticky;
z-index: 10;
margin-top: auto;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import React, {useMemo} from 'react';
import type {ComponentType, FC} from 'react';

import {withTableSelection} from '@gravity-ui/uikit';
import type {TableDataItem, TableProps, WithTableSelectionProps} from '@gravity-ui/uikit';

import {ActionsPanel, ActionsPanelProps} from '../../ActionsPanel';
import {block} from '../../utils/cn';

import './withTableSelectionAndGroupActions.scss';

const b = block('with-table-group-actions');

type ActionItem = ActionsPanelProps['actions'][number];

export interface WithTableSelectionAndGroupActionsProps {
groupActions: ActionItem[];
formatTitle: (selected: number) => string;
onGroupActionsClose?: () => void;
}

export function withTableSelectionAndGroupActions<I extends TableDataItem, E extends {} = {}>(
TableComponent: ComponentType<TableProps<I> & E>,
): ComponentType<
TableProps<I> & WithTableSelectionProps<I> & WithTableSelectionAndGroupActionsProps & E
> {
let componentName = TableComponent.displayName || TableComponent.name || 'Component';

if (componentName.includes('withTableSelection(')) {
throw new Error(
'You should use withTableSelectionAndGroupActions instead of withTableSelection HOC.',
);
}

const TableComponentWithSelection = withTableSelection(TableComponent);

componentName = TableComponentWithSelection.displayName || TableComponent.name || 'Component';

const TableWithGroupActions: FC<
TableProps<I> & WithTableSelectionProps<I> & WithTableSelectionAndGroupActionsProps & E
> = ({groupActions, formatTitle, onGroupActionsClose, ...props}) => {
const selected = props.selectedIds.length;
const renderTitle = useMemo(() => () => formatTitle(selected), [formatTitle, selected]);

return (
<>
<TableComponentWithSelection
{...(props as TableProps<I> & WithTableSelectionProps<I> & E)}
/>
{selected > 0 && (
<ActionsPanel
actions={groupActions}
onClose={onGroupActionsClose}
renderNote={renderTitle}
className={b('panel')}
/>
)}
</>
);
};

TableWithGroupActions.displayName = `withTableGroupActions(${componentName})`;

return TableWithGroupActions;
}
1 change: 1 addition & 0 deletions src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ export * from './SharePopover';
export * from './StoreBadge';
export * from './Stories';
export * from './StoriesGroup';
export * from './TableHOCs';

export {Lang, configure} from './utils/configure';

0 comments on commit e8803b3

Please sign in to comment.