Skip to content

Commit

Permalink
fix: add GridTreeColumn header and footer renderers (#194)
Browse files Browse the repository at this point in the history
  • Loading branch information
web-padawan authored Dec 19, 2023
1 parent 0462893 commit 5d7cf31
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 23 deletions.
20 changes: 0 additions & 20 deletions src/GridTreeColumn.ts

This file was deleted.

44 changes: 44 additions & 0 deletions src/GridTreeColumn.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { type ComponentType, type ForwardedRef, forwardRef, type ReactElement, type RefAttributes } from 'react';
import type { GridDefaultItem } from './generated/Grid.js';
import {
GridTreeColumnElement,
GridTreeColumn as _GridTreeColumn,
type GridTreeColumnProps as _GridTreeColumnProps,
} from './generated/GridTreeColumn.js';
import type { GridEdgeReactRendererProps } from './renderers/grid.js';
import { useSimpleRenderer } from './renderers/useSimpleRenderer.js';
import type { OmittedGridColumnHTMLAttributes } from './GridColumn.js';

export * from './generated/GridTreeColumn.js';

export type GridTreeColumnProps<TItem> = Partial<
Omit<
_GridTreeColumnProps<TItem>,
'children' | 'footerRenderer' | 'headerRenderer' | 'renderer' | keyof OmittedGridColumnHTMLAttributes<TItem>
>
> &
Readonly<{
footerRenderer?: ComponentType<GridEdgeReactRendererProps<TItem>> | null;
headerRenderer?: ComponentType<GridEdgeReactRendererProps<TItem>> | null;
}>;

function GridTreeColumn<TItem = GridDefaultItem>(
props: GridTreeColumnProps<TItem>,
ref: ForwardedRef<GridTreeColumnElement<TItem>>,
): ReactElement | null {
const [headerPortals, headerRenderer] = useSimpleRenderer(props.headerRenderer);
const [footerPortals, footerRenderer] = useSimpleRenderer(props.footerRenderer);

return (
<_GridTreeColumn<TItem> {...props} headerRenderer={headerRenderer} footerRenderer={footerRenderer} ref={ref}>
{headerPortals}
{footerPortals}
</_GridTreeColumn>
);
}

const ForwardedGridTreeColumn = forwardRef(GridTreeColumn) as <TItem = GridDefaultItem>(
props: GridTreeColumnProps<TItem> & RefAttributes<GridTreeColumnElement<TItem>>,
) => ReactElement | null;

export { ForwardedGridTreeColumn as GridTreeColumn };
41 changes: 40 additions & 1 deletion test/Grid.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { expect, use as useChaiPlugin } from '@esm-bundle/chai';
import chaiDom from 'chai-dom';
import { cleanup, render } from '@testing-library/react/pure.js';
import { Grid } from '../src/Grid.js';
import { Grid, type GridDataProvider } from '../src/Grid.js';
import { GridColumn } from '../src/GridColumn.js';
import { GridFilterColumn } from '../src/GridFilterColumn.js';
import { GridProEditColumn } from '../src/GridProEditColumn.js';
import { GridSelectionColumn } from '../src/GridSelectionColumn.js';
import { GridSortColumn } from '../src/GridSortColumn.js';
import { GridTreeColumn } from '../src/GridTreeColumn.js';
import type { GridBodyReactRendererProps } from '../src/renderers/grid.js';
import catchRender from './utils/catchRender.js';
import { GridColumnGroup } from '../src/GridColumnGroup.js';
Expand All @@ -17,6 +18,8 @@ useChaiPlugin(chaiDom);
describe('Grid', () => {
type Item = Readonly<{ name: string; surname: string; role: string }>;

type TreeItem = { name: string; children: boolean };

const items = [
{ name: 'John', surname: 'Lennon', role: 'singer' },
{ name: 'Ringo', surname: 'Starr', role: 'drums' },
Expand Down Expand Up @@ -221,4 +224,40 @@ describe('Grid', () => {
expect(bodyCell2).to.have.text('Ringo');
});
});

describe('GridTreeColumn', () => {
const dataProvider: GridDataProvider<TreeItem> = ({ parentItem, page, pageSize }, cb) => {
const levelSize = 2;

const pageItems = [...Array(Math.min(levelSize, pageSize))].map((_, i) => {
const indexInLevel = page * pageSize + i;

return {
name: `${parentItem ? parentItem.name + '-' : ''}${indexInLevel}`,
children: true,
};
});

cb(pageItems, levelSize);
};

it('should render correctly', async () => {
render(
<Grid<TreeItem> dataProvider={dataProvider}>
<GridTreeColumn path="name" headerRenderer={DefaultHeaderRenderer} footerRenderer={DefaultFooterRenderer} />
<GridColumn path="name"></GridColumn>
</Grid>,
);

const [columns, cells] = await getGridMeaningfulParts('vaadin-grid-tree-column');
expect(columns).to.have.length(1);
expect(cells).to.have.length(7);

const [treeHeaderCell, nameHeaderCell, treeFooterCell] = cells;

expect(treeHeaderCell).to.have.text('Name');
expect(nameHeaderCell).to.have.text('Name');
expect(treeFooterCell).to.have.text('Name Footer');
});
});
});
2 changes: 0 additions & 2 deletions test/typings/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,6 @@ type GridTreeColumnProps = typeof gridTreeColumnProps;
assertType<string | null | undefined>(gridTreeColumnProps.path);

assertOmitted<GridColumnProps, GridTreeColumnProps>('renderer');
assertOmitted<GridColumnProps, GridTreeColumnProps>('headerRenderer');
assertOmitted<GridColumnProps, GridTreeColumnProps>('footerRenderer');
assertOmitted<GridColumnProps, GridTreeColumnProps>('children');

const gridSortColumnProps = React.createElement(GridSortColumn, {}).props;
Expand Down

0 comments on commit 5d7cf31

Please sign in to comment.