Skip to content

Commit

Permalink
feat(Table): add options for WithTableSettings HOC (#1029)
Browse files Browse the repository at this point in the history
  • Loading branch information
amje authored Sep 29, 2023
1 parent 770ef85 commit b338bf9
Show file tree
Hide file tree
Showing 5 changed files with 135 additions and 70 deletions.
22 changes: 19 additions & 3 deletions src/components/Table/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,23 @@ function SelectionTable() {

## Usage with HOC `withTableSettings`

Enables functionality for table column settings.
Enables functionality for table column settings. You can use ut in two forms:

```jsx
import {Table, withTableSettings} from './withTableSettings';

// No options passed
const MyTable1 = withTableSettings(Table);
// or with options
const MyTable1 = withTableSettings({sortable: false})(Table);
```

### Options

| Name | Description | Type | Default |
| :------- | :------------------------------------------------ | :---------------: | :-----: |
| width | Settings' popup width | `number` `string` | |
| sortable | Whether or not add ability to sort settings items | `boolean` | `true` |

### ColumnMeta

Expand All @@ -214,7 +230,7 @@ Enables functionality for table column settings.

| Name | Description | Type |
| :----------------- | :---------------------------- | :------------------------------------------: |
| settingsPopupWidth | TableColumnSetup pop-up width | `string` |
| settingsPopupWidth | TableColumnSetup pop-up width | `number` `string` |
| settings | Current settings | `TableSettingsData` |
| updateSettings | Settings update handl | `(data: TableSettingsData) => Promise<void>` |

Expand All @@ -232,7 +248,7 @@ type TableSettingsData = Array<{
```jsx
import {Table, withTableSettings} from '@gravity-ui/uikit';

const MyTable = withTableSettings(Table);
const MyTable = withTableSettings({width: 100, sortable: false})(Table);
const data = [
{id: 1, text: 'Hello'},
{id: 2, text: 'World'},
Expand Down
19 changes: 17 additions & 2 deletions src/components/Table/__stories__/Table.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
TableWithCopy,
TableWithSelection,
TableWithSettings,
TableWithSettingsFactory,
TableWithSorting,
columns,
data,
Expand Down Expand Up @@ -144,7 +145,7 @@ const WithTableSelectionTemplate: StoryFn<TableProps<DataItem>> = (args) => {
export const HOCWithTableSelection = WithTableSelectionTemplate.bind({});

// ---------------------------------
const WithTableSettingsTemplate: StoryFn<TableProps<DataItem>> = (args) => {
const WithTableSettingsTemplate: StoryFn<TableProps<DataItem>> = (args, context) => {
const [settings, setSettings] = React.useState<TableSettingsData>(() =>
columns.map((x) => ({id: x.id, isSelected: true})),
);
Expand All @@ -154,9 +155,23 @@ const WithTableSettingsTemplate: StoryFn<TableProps<DataItem>> = (args) => {
[],
);

return <TableWithSettings {...args} settings={settings} updateSettings={updateSettings} />;
if (context.parameters.isFactory) {
return (
<TableWithSettingsFactory
{...args}
settings={settings}
updateSettings={updateSettings}
/>
);
} else {
return <TableWithSettings {...args} settings={settings} updateSettings={updateSettings} />;
}
};
export const HOCWithTableSettings = WithTableSettingsTemplate.bind({});
export const HOCWithTableSettingsFactory = WithTableSettingsTemplate.bind({});
HOCWithTableSettingsFactory.parameters = {
isFactory: true,
};

// ---------------------------------
const columnsWithSorting = _cloneDeep(columns);
Expand Down
1 change: 1 addition & 0 deletions src/components/Table/__stories__/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,5 @@ export const TableWithAction = withTableActions<DataItem>(Table);
export const TableWithCopy = withTableCopy<DataItem>(Table);
export const TableWithSelection = withTableSelection<DataItem>(Table);
export const TableWithSettings = withTableSettings<DataItem>(Table);
export const TableWithSettingsFactory = withTableSettings<DataItem>({sortable: false})(Table);
export const TableWithSorting = withTableSorting<DataItem>(Table);
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export interface TableColumnSetupProps {
filterable?: boolean;

onUpdate: (updated: Item[]) => void;
popupWidth?: string;
popupWidth?: number | string;
popupPlacement?: PopperPlacement;
getItemTitle?: (item: Item) => TableColumnSetupItem['title'];
showStatus?: boolean;
Expand Down
161 changes: 97 additions & 64 deletions src/components/Table/hoc/withTableSettings/withTableSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,76 +114,109 @@ function prepareUpdateSettings(items: TableColumnSetupItem[]): TableSettingsData
}));
}

export interface WithTableSettingsOptions {
width?: number | string;
sortable?: boolean;
}

export interface WithTableSettingsProps {
settingsPopupWidth?: string;
/**
* @deprecated Use factory notation: "withTableSettings({width: <value>})(Table)"
*/
settingsPopupWidth?: number | string;
settings: TableSettingsData;
updateSettings: (data: TableSettingsData) => void;
}

const b = block('table');

export function withTableSettings<I extends TableDataItem, E extends {} = {}>(
TableComponent: React.ComponentType<TableProps<I> & E>,
): React.ComponentType<TableProps<I> & WithTableSettingsProps & E> {
const componentName = getComponentName(TableComponent);

const TableWithSettings = ({
updateSettings,
settings,
columns,
settingsPopupWidth,
...restTableProps
}: TableProps<I> & WithTableSettingsProps & E) => {
const actualItems = React.useMemo(
() => getActualItems(columns, settings || []),
[columns, settings],
);

const onUpdateColumns = React.useCallback(
(newItems: TableColumnSetupItem[]) => {
updateSettings(prepareUpdateSettings(newItems));
},
[updateSettings],
);

const columnSetupItems = React.useMemo(
() => prepareColumnSetupItems(actualItems),
[actualItems],
);

const enhancedColumns = React.useMemo(
() =>
enhanceSystemColumn(filterColumns(columns, actualItems), (systemColumn) => {
// eslint-disable-next-line react/display-name
systemColumn.name = () => (
<div className={b('settings')}>
<TableColumnSetup
popupWidth={settingsPopupWidth}
popupPlacement={['bottom-end', 'bottom', 'top-end', 'top']}
onUpdate={onUpdateColumns}
items={columnSetupItems}
switcher={
<Button view="flat" className={b('settings-button')}>
<Icon data={Gear} />
</Button>
}
/>
</div>
);
}),
[actualItems, columnSetupItems, columns, onUpdateColumns, settingsPopupWidth],
);

return (
<React.Fragment>
<TableComponent
{...(restTableProps as Omit<TableProps<I>, 'columns'> & E)}
columns={enhancedColumns}
/>
</React.Fragment>
);
};
TableWithSettings.displayName = `withTableSettings(${componentName})`;

return TableWithSettings;
Component: React.ComponentType<TableProps<I> & E>,
): React.ComponentType<TableProps<I> & WithTableSettingsProps & E>;
export function withTableSettings<I extends TableDataItem, E extends {} = {}>(
options?: WithTableSettingsOptions,
): (
Component: React.ComponentType<TableProps<I> & E>,
) => React.ComponentType<TableProps<I> & WithTableSettingsProps & E>;
export function withTableSettings<I extends TableDataItem, E extends {} = {}>(
ComponentOrOptions?: WithTableSettingsOptions | React.ComponentType<TableProps<I> & E>,
):
| React.ComponentType<TableProps<I> & WithTableSettingsProps & E>
| ((
Component: React.ComponentType<TableProps<I> & E>,
) => React.ComponentType<TableProps<I> & WithTableSettingsProps & E>) {
function tableWithSettingsFactory(
TableComponent: React.ComponentType<TableProps<I> & E>,
{width, sortable}: WithTableSettingsOptions = {},
) {
const componentName = getComponentName(TableComponent);

function TableWithSettings({
updateSettings,
settings,
columns,
settingsPopupWidth,
...restTableProps
}: TableProps<I> & WithTableSettingsProps & E) {
const actualItems = React.useMemo(
() => getActualItems(columns, settings || []),
[columns, settings],
);

const onUpdateColumns = React.useCallback(
(newItems: TableColumnSetupItem[]) => {
updateSettings(prepareUpdateSettings(newItems));
},
[updateSettings],
);

const columnSetupItems = React.useMemo(
() => prepareColumnSetupItems(actualItems),
[actualItems],
);

const enhancedColumns = React.useMemo(
() =>
enhanceSystemColumn(filterColumns(columns, actualItems), (systemColumn) => {
// eslint-disable-next-line react/display-name
systemColumn.name = () => (
<div className={b('settings')}>
<TableColumnSetup
popupWidth={settingsPopupWidth || width}
popupPlacement={['bottom-end', 'bottom', 'top-end', 'top']}
sortable={sortable}
onUpdate={onUpdateColumns}
items={columnSetupItems}
switcher={
<Button view="flat" className={b('settings-button')}>
<Icon data={Gear} />
</Button>
}
/>
</div>
);
}),
[actualItems, columnSetupItems, columns, onUpdateColumns, settingsPopupWidth],
);

return (
<React.Fragment>
<TableComponent
{...(restTableProps as Omit<TableProps<I>, 'columns'> & E)}
columns={enhancedColumns}
/>
</React.Fragment>
);
}
TableWithSettings.displayName = `withTableSettings(${componentName})`;

return TableWithSettings;
}

if (typeof ComponentOrOptions === 'function') {
return tableWithSettingsFactory(ComponentOrOptions);
} else {
return (TableComponent: React.ComponentType<TableProps<I> & E>) =>
tableWithSettingsFactory(TableComponent, ComponentOrOptions);
}
}

0 comments on commit b338bf9

Please sign in to comment.