diff --git a/src/GridTreeColumn.ts b/src/GridTreeColumn.ts deleted file mode 100644 index f02487ed..00000000 --- a/src/GridTreeColumn.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './generated/GridTreeColumn.js'; diff --git a/src/GridTreeColumn.tsx b/src/GridTreeColumn.tsx new file mode 100644 index 00000000..e15c9f4f --- /dev/null +++ b/src/GridTreeColumn.tsx @@ -0,0 +1,40 @@ +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'; + +export * from './generated/GridTreeColumn.js'; + +export type GridTreeColumnProps = Partial< + Omit<_GridTreeColumnProps, 'children' | 'footerRenderer' | 'headerRenderer' | 'renderer'> +> & + Readonly<{ + footerRenderer?: ComponentType> | null; + headerRenderer?: ComponentType> | null; + }>; + +function GridTreeColumn( + props: GridTreeColumnProps, + ref: ForwardedRef>, +): ReactElement | null { + const [headerPortals, headerRenderer] = useSimpleRenderer(props.headerRenderer, { renderSync: true }); + const [footerPortals, footerRenderer] = useSimpleRenderer(props.footerRenderer, { renderSync: true }); + + return ( + <_GridTreeColumn {...props} headerRenderer={headerRenderer} footerRenderer={footerRenderer} ref={ref}> + {headerPortals} + {footerPortals} + + ); +} + +const ForwardedGridTreeColumn = forwardRef(GridTreeColumn) as ( + props: GridTreeColumnProps & RefAttributes>, +) => ReactElement | null; + +export { ForwardedGridTreeColumn as GridTreeColumn }; diff --git a/test/Grid.spec.tsx b/test/Grid.spec.tsx index 9206cb9f..ea0b127a 100644 --- a/test/Grid.spec.tsx +++ b/test/Grid.spec.tsx @@ -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'; @@ -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' }, @@ -221,4 +224,40 @@ describe('Grid', () => { expect(bodyCell2).to.have.text('Ringo'); }); }); + + describe('GridTreeColumn', () => { + const dataProvider: GridDataProvider = ({ 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( + dataProvider={dataProvider}> + + + , + ); + + 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'); + }); + }); });