From 33d7a621e5beccfacac57707b830b06c98d84e9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20L=C3=B3pez=20=C3=9Abeda?= Date: Thu, 19 Sep 2024 17:21:11 +0200 Subject: [PATCH] feat: added col, row & cell styles by its definitions --- packages/table/src/core/Cell/Cell.tsx | 12 ++- packages/table/src/core/Cell/StyledCell.ts | 4 +- packages/table/src/core/Row/Row.tsx | 30 ++++--- packages/table/src/core/Row/StyledTableRow.ts | 4 +- packages/table/src/core/Table/Table.tsx | 2 + .../table/src/core/TableBody/TableBody.tsx | 2 +- packages/table/src/core/utils/columns.ts | 4 +- packages/table/src/declarations.ts | 30 ++++--- .../afterRow/addAfterRowToRowDefs.test.ts | 33 +++++++ .../helpers/afterRow/addAfterRowToRowDefs.ts | 18 ++++ .../afterRow/addAfterRowsToRowDefs.test.ts | 87 +++++-------------- .../helpers/afterRow/addAfterRowsToRowDefs.ts | 60 +++++-------- packages/table/src/helpers/afterRow/index.ts | 1 + .../definitions/cell/getCellDef.test.ts | 56 ++++++++++++ .../helpers/definitions/cell/getCellDef.ts | 7 ++ .../src/helpers/definitions/cell/index.ts | 1 + .../table/src/helpers/definitions/index.ts | 2 + .../helpers/definitions/row/getRowDef.test.ts | 24 +++++ .../src/helpers/definitions/row/getRowDef.ts | 4 + .../src/helpers/definitions/row/index.ts | 2 + .../definitions/row/toggleHideRowDef.test.ts | 33 +++++++ .../definitions/row/toggleHideRowDef.ts | 6 ++ packages/table/src/helpers/index.ts | 1 + .../src/hooks/useAfterRow/useAfterRow.ts | 18 ++-- packages/table/stories/AfterRow.stories.tsx | 34 +++++--- 25 files changed, 324 insertions(+), 151 deletions(-) create mode 100644 packages/table/src/helpers/afterRow/addAfterRowToRowDefs.test.ts create mode 100644 packages/table/src/helpers/afterRow/addAfterRowToRowDefs.ts create mode 100644 packages/table/src/helpers/definitions/cell/getCellDef.test.ts create mode 100644 packages/table/src/helpers/definitions/cell/getCellDef.ts create mode 100644 packages/table/src/helpers/definitions/cell/index.ts create mode 100644 packages/table/src/helpers/definitions/index.ts create mode 100644 packages/table/src/helpers/definitions/row/getRowDef.test.ts create mode 100644 packages/table/src/helpers/definitions/row/getRowDef.ts create mode 100644 packages/table/src/helpers/definitions/row/index.ts create mode 100644 packages/table/src/helpers/definitions/row/toggleHideRowDef.test.ts create mode 100644 packages/table/src/helpers/definitions/row/toggleHideRowDef.ts diff --git a/packages/table/src/core/Cell/Cell.tsx b/packages/table/src/core/Cell/Cell.tsx index 81e68c2e..01fb663e 100644 --- a/packages/table/src/core/Cell/Cell.tsx +++ b/packages/table/src/core/Cell/Cell.tsx @@ -1,11 +1,12 @@ import * as React from 'react'; + import { GIPencilEditFilled } from '@devoinc/genesys-icons'; +import { mergeStyles } from '@devoinc/genesys-ui'; -import type { TColDef, TRow } from '../../declarations'; +import type { TCellDef, TColDef, TRow, TRowDef } from '../../declarations'; import { useRenderContent } from './useRenderContent'; import { useInitialState } from '../../editors/useInitialState'; import { TableContext, WrapperContext } from '../../context'; - import { StyledCellWrapper } from './StyledCellWrapper'; import { StyledCell } from './StyledCell'; import { StyledCellMarker } from './StyledCellMarker'; @@ -13,6 +14,7 @@ import { StyledCellMarker } from './StyledCellMarker'; interface CellProps { data: unknown; colDef: TColDef; + cellDef: TCellDef; width?: number; height?: number; offsetX?: number; @@ -24,6 +26,7 @@ interface CellProps { export const Cell: React.FC = ({ data, colDef, + cellDef, rowIndex, width, height, @@ -34,7 +37,9 @@ export const Cell: React.FC = ({ const { density, texts, highlightColumnsOnHover } = React.useContext(TableContext); const { height: wrapperHeight } = React.useContext(WrapperContext); - const { onReset } = colDef; + const onReset = colDef.onReset; + const colStyle = colDef?.style ?? ''; + const cellStyle = cellDef?.style ?? ''; useInitialState(data, onReset); @@ -53,6 +58,7 @@ export const Cell: React.FC = ({ aria-selected={isEditMode} onDoubleClick={onDoubleClick} ref={cellRef} + css={mergeStyles(colStyle, cellStyle)} > ; virtualRow: VirtualItem; state?: TStateRow; @@ -15,16 +15,14 @@ interface RowProps extends StyledTableRowProps { export const Row: React.FC = ({ columnVirtualizer, - data, + rowData, isAfterRow, isDragging, state = 'enabled', virtualRow, }) => { - const { striped, colDefs, rowDefs } = React.useContext(TableContext); - - const rowDef = getRowDef(rowDefs, data.id as string); - + const { striped, colDefs, rowDefs, cellDefs } = React.useContext(TableContext); + const rowDef = (getRowDef(rowDefs, rowData.id as string) ?? {}) as TRowDef; return ( = ({ isDragging={isDragging} $state={state} $striped={striped} + css={rowDef?.style} > {rowDef?.cellRenderer ? ( = ({ id: 'afterRow', cellRenderer: rowDef.cellRenderer, }} + cellDef={{ + colId: 'afterRow', + rowId: rowDef.id, + }} height={virtualRow.size} key={`cell-0`} offsetX={0} width={columnVirtualizer.getTotalSize()} rowIndex={virtualRow.index} - row={data} + row={rowData} data={null} colSpan={colDefs.length} /> @@ -56,16 +59,19 @@ export const Row: React.FC = ({ columnVirtualizer .getVirtualItems() .map((virtualColumn: VirtualItem) => { + const colDef = (colDefs[virtualColumn.index] ?? {}) as TColDef; + const cellDef = getCellDef(cellDefs, colDef.id, rowDef.id); return ( ); }) diff --git a/packages/table/src/core/Row/StyledTableRow.ts b/packages/table/src/core/Row/StyledTableRow.ts index ac2b022e..ad12ed81 100644 --- a/packages/table/src/core/Row/StyledTableRow.ts +++ b/packages/table/src/core/Row/StyledTableRow.ts @@ -1,5 +1,5 @@ import React from 'react'; -import styled, { css } from 'styled-components'; +import styled, { css, CSSProp } from 'styled-components'; import { pseudoElementMixin, pseudoElementOverlayMixin, @@ -18,6 +18,8 @@ export interface StyledTableRowProps { transform?: React.CSSProperties['transform']; $width?: React.CSSProperties['width']; $hide?: boolean; + // TODO: interface only for satisfy the type error with TS and inherit CSSProp + css?: CSSProp; } export const StyledTableRow = styled.tr.attrs( diff --git a/packages/table/src/core/Table/Table.tsx b/packages/table/src/core/Table/Table.tsx index 9281361d..0958bdab 100644 --- a/packages/table/src/core/Table/Table.tsx +++ b/packages/table/src/core/Table/Table.tsx @@ -12,6 +12,7 @@ export const Table: React.FC = ({ defaultColDef, colDefs = [], rowDefs = [], + cellDefs = [], columnPresets = [], density = 'default', striped = false, @@ -53,6 +54,7 @@ export const Table: React.FC = ({ onFilter, rowHeight, rowDefs, + cellDefs, }} > diff --git a/packages/table/src/core/TableBody/TableBody.tsx b/packages/table/src/core/TableBody/TableBody.tsx index 2a561401..125830b0 100644 --- a/packages/table/src/core/TableBody/TableBody.tsx +++ b/packages/table/src/core/TableBody/TableBody.tsx @@ -32,7 +32,7 @@ export const TableBody: React.FC = ({ ); diff --git a/packages/table/src/core/utils/columns.ts b/packages/table/src/core/utils/columns.ts index 7f577549..94e9b228 100644 --- a/packages/table/src/core/utils/columns.ts +++ b/packages/table/src/core/utils/columns.ts @@ -1,5 +1,5 @@ import { VirtualItem } from '@tanstack/react-virtual'; -import type { TColDef, TDefaultColDef, TPreset } from '../../declarations'; +import type { TColDef, TDefaultColDef, TColPreset } from '../../declarations'; export const getColDefByID = ( colDefs: TColDef[] = [], @@ -13,7 +13,7 @@ export const getColDefByID = ( export const getCollatedColumns = ( defaultColDef: TDefaultColDef, column: TColDef, - presets: TPreset[] = [], + presets: TColPreset[] = [], ): TColDef => { const preset = presets.find((element) => element.id === column.preset); return { ...defaultColDef, ...preset, ...column }; diff --git a/packages/table/src/declarations.ts b/packages/table/src/declarations.ts index dcc28726..76aa41a1 100644 --- a/packages/table/src/declarations.ts +++ b/packages/table/src/declarations.ts @@ -1,4 +1,5 @@ import * as React from 'react'; +import { CSSProp } from 'styled-components'; import { DateContext } from './valueFormatters/date'; @@ -26,6 +27,8 @@ export type TStateRow = | 'created' | 'deleted'; +// Definitions + export type TColDef = { id: string; headerName?: string; @@ -55,14 +58,13 @@ export type TColDef = { sort?: 'asc' | 'desc'; sortIndex?: React.ReactNode; - expandedRow?: boolean; isDragging?: boolean; onReset?: (initialValue: unknown) => void; tooltipField?: string; resizable?: boolean; + minWidth?: number; + width?: number; rowHeight?: number; - minWidth?: number | string; - width?: number | string; align?: TCellHorAlign; verticalAlign?: TCellVerAlign; textAlign?: React.CSSProperties['textAlign']; @@ -71,29 +73,34 @@ export type TColDef = { toEdge?: boolean; headerOnFilterPosition?: boolean; hide?: boolean; + style?: CSSProp; }; export type TRowDef = { hide?: boolean; id: string; - height?: React.CSSProperties['height']; + height?: number; + minHeight?: number; + isDragging?: boolean; cellRenderer?: | React.FC | (({ value, colDef, rowIndex, row }: TCellRenderer) => React.ReactNode); + style?: CSSProp; }; -export type TAfterRow = { +export type TCellDef = { + colId: string; + rowId: string; hide?: boolean; - id: string; + style?: CSSProp; }; -export type TCellDef = { - idColumn: string; - idRow: string; +export type TAfterRow = { hide?: boolean; + id: string; }; -export type TPreset = { +export type TColPreset = { id: string; } & Omit; @@ -159,9 +166,10 @@ export interface ITable { data: TData; colDefs?: TColDef[]; rowDefs?: TRowDef[]; + cellDefs?: TCellDef[]; afterRowDefs?: TAfterRow[]; defaultColDef?: TDefaultColDef; - columnPresets?: TPreset[]; + columnPresets?: TColPreset[]; context?: { [key: string]: unknown; }; diff --git a/packages/table/src/helpers/afterRow/addAfterRowToRowDefs.test.ts b/packages/table/src/helpers/afterRow/addAfterRowToRowDefs.test.ts new file mode 100644 index 00000000..7459ae68 --- /dev/null +++ b/packages/table/src/helpers/afterRow/addAfterRowToRowDefs.test.ts @@ -0,0 +1,33 @@ +import { describe, test, expect } from 'vitest'; + +import { TRowDef } from '../../declarations'; +import { addAfterRowToRowDefs } from './addAfterRowToRowDefs'; + +describe('Add afterrow to row defs', () => { + describe('addAfterRowToRowDefs', () => { + const cases: [string, TRowDef[], string, TRowDef[]][] = [ + [ + 'add element with rowdefs empty', + [], + '1', + [{ id: `afterRow-1`, hide: false }], + ], + [ + 'add element with rowdefs > 0', + [{ id: `afterRow-1`, hide: false }], + '2', + [ + { id: `afterRow-1`, hide: false }, + { id: `afterRow-2`, hide: false }, + ], + ], + ['add element with rowdefs empty', null, '1', undefined], + ]; + + test.each(cases)('%s', (_title, rowDefs, id, expected) => { + expect(addAfterRowToRowDefs(rowDefs, id, () => null, 13)).toMatchObject( + expected, + ); + }); + }); +}); diff --git a/packages/table/src/helpers/afterRow/addAfterRowToRowDefs.ts b/packages/table/src/helpers/afterRow/addAfterRowToRowDefs.ts new file mode 100644 index 00000000..c8441ac8 --- /dev/null +++ b/packages/table/src/helpers/afterRow/addAfterRowToRowDefs.ts @@ -0,0 +1,18 @@ +import * as React from 'react'; + +import type { TCellRenderer, TRowDef } from '../../declarations'; + +export const addAfterRowToRowDefs = ( + rowDefs: TRowDef[], + id: string, + afterRowRenderer: + | React.FC + | (({ value, colDef, rowIndex, row }: TCellRenderer) => React.ReactNode), + afterRowHeight: number, +) => + rowDefs?.concat({ + id: `afterRow-${id}`, + hide: false, + cellRenderer: afterRowRenderer, + height: afterRowHeight, + }); diff --git a/packages/table/src/helpers/afterRow/addAfterRowsToRowDefs.test.ts b/packages/table/src/helpers/afterRow/addAfterRowsToRowDefs.test.ts index 4010c2c7..d0bae6e4 100644 --- a/packages/table/src/helpers/afterRow/addAfterRowsToRowDefs.test.ts +++ b/packages/table/src/helpers/afterRow/addAfterRowsToRowDefs.test.ts @@ -1,83 +1,44 @@ import { describe, test, expect } from 'vitest'; import { TRowDef } from '../../declarations'; -import { - addAfterRowToRowDefs, - getRowDef, - setHideRowDef, -} from './addAfterRowsToRowDefs'; +import { addAfterRowsToRowDefs } from './addAfterRowsToRowDefs'; describe('Add afterrow to row defs', () => { - describe('getRowDef', () => { - const cases: [string, TRowDef[], string, TRowDef][] = [ - ['empty row defs return undefined', [], '1', undefined], - ['id null return undefined', [{ id: '1' }], null, undefined], - ['rowDef null return undefined', null, '1', undefined], - ['return element rowDef', [{ id: '1' }], '1', { id: '1' }], - ['id not find in rowDef', [{ id: '1' }], '2', undefined], - ]; - - test.each(cases)('%s', (_title, rowDefs, id, expected) => { - expect(getRowDef(rowDefs, id)).toEqual(expected); - }); - }); - - describe('addAfterRowToRowDefs', () => { - const cases: [string, TRowDef[], string, TRowDef[]][] = [ + describe('addAfterRowsToRowDefs', () => { + const cases: [string, TRowDef[], string[], TRowDef[]][] = [ [ 'add element with rowdefs empty', [], - '1', - [{ id: `afterRow-1`, hide: false }], - ], - [ - 'add element with rowdefs > 0', - [{ id: `afterRow-1`, hide: false }], - '2', + ['afterRow-1', 'afterRow-2'], [ - { id: `afterRow-1`, hide: false }, - { id: `afterRow-2`, hide: false }, + { id: 'afterRow-1', hide: true }, + { id: 'afterRow-2', hide: true }, ], ], - ['add element with rowdefs empty', null, '1', undefined], - ]; - - test.each(cases)('%s', (_title, rowDefs, id, expected) => { - expect(addAfterRowToRowDefs(rowDefs, id, () => null, 13)).toMatchObject( - expected, - ); - }); - }); - - describe('setHideRowDef', () => { - const cases: [string, TRowDef[], string, boolean, TRowDef[]][] = [ - ['empty rowdefs return empty rowdefs', [], '1', true, []], - ['rowdefs null return undefined', null, '1', true, undefined], - [ - 'changed visible to no visible', - [{ id: `afterRow-1`, hide: false }], - '1', - false, - [{ id: `afterRow-1`, hide: true }], - ], [ - 'changed no visible to visible', - [{ id: `afterRow-1`, hide: true }], - '1', - false, - [{ id: `afterRow-1`, hide: true }], + 'add two afterRows, one that already exists on rowDefs', + [{ id: 'afterRow-1', hide: false }], + ['afterRow-1', 'afterRow-2'], + [ + { id: 'afterRow-1', hide: false }, + { id: 'afterRow-2', hide: true }, + ], ], [ - 'id and isOpened null return same rowdefs', - [{ id: `afterRow-1`, hide: true }], - null, - null, - [{ id: `afterRow-1`, hide: true }], + 'add one afterRows, on a non empty rowDefs', + [{ id: '1', hide: false }], + ['afterRow-1'], + [ + { id: '1', hide: false }, + { id: 'afterRow-1', hide: true }, + ], ], ]; - test.each(cases)('%s', (_title, rowDefs, id, isOpened, expected) => { - expect(setHideRowDef(rowDefs, id, isOpened)).toEqual(expected); + test.each(cases)('%s', (_title, rowDefs, afterRowIds, expected) => { + expect( + addAfterRowsToRowDefs(rowDefs, afterRowIds, () => null, 13), + ).toMatchObject(expected); }); }); }); diff --git a/packages/table/src/helpers/afterRow/addAfterRowsToRowDefs.ts b/packages/table/src/helpers/afterRow/addAfterRowsToRowDefs.ts index 959697e6..8d01662d 100644 --- a/packages/table/src/helpers/afterRow/addAfterRowsToRowDefs.ts +++ b/packages/table/src/helpers/afterRow/addAfterRowsToRowDefs.ts @@ -1,53 +1,33 @@ import * as React from 'react'; -import { TCellRenderer, TRowDef } from '../../declarations'; + +import type { TCellRenderer, TRowDef } from '../../declarations'; +import { getRowDef } from '../definitions'; export const addAfterRowsToRowDefs = ( rowDefs: TRowDef[], - ids: string[], - afterRowRenderer: React.FC - | (({ value, colDef, rowIndex, row }: TCellRenderer) => React.ReactNode), + afterRowIds: string[], + afterRowRenderer: + | React.FC + | (({ value, colDef, rowIndex, row }: TCellRenderer) => React.ReactNode), afterRowHeight: number, ) => - ids.map((id) => { - const rowDef = getRowDef(rowDefs, id); - - const defaultRowDef = { - id, - hide: true, - cellRenderer: afterRowRenderer, - height: afterRowHeight, - }; + rowDefs + .reduce( + (prev, rowDef) => + afterRowIds.includes(rowDef.id) ? prev : prev.concat([rowDef]), + [], + ) + .concat( + afterRowIds.map((id) => { + const rowDef = getRowDef(rowDefs, id) ?? {}; - return rowDef - ? { ...defaultRowDef, ...rowDef } - : { + const defaultRowDef = { id, hide: true, cellRenderer: afterRowRenderer, height: afterRowHeight, }; - }) as TRowDef[]; - -export const getRowDef = (rowDefs: TRowDef[], id: string) => - rowDefs?.find((r) => r.id === id); - -export const addAfterRowToRowDefs = ( - rowDefs: TRowDef[], - id, - afterRowRenderer, - afterRowHeight, -) => - rowDefs?.concat({ - id: `afterRow-${id}`, - hide: false, - cellRenderer: afterRowRenderer, - height: afterRowHeight, - }); -export const setHideRowDef = (rowDefs: TRowDef[], id, isOpened) => - rowDefs?.map((rowDef: TRowDef) => { - if (rowDef.id === `afterRow-${id}`) { - rowDef.hide = !isOpened; - } - return rowDef; - }); + return { ...defaultRowDef, ...rowDef }; + }) as TRowDef[], + ); diff --git a/packages/table/src/helpers/afterRow/index.ts b/packages/table/src/helpers/afterRow/index.ts index c8e67a6c..fbd93736 100644 --- a/packages/table/src/helpers/afterRow/index.ts +++ b/packages/table/src/helpers/afterRow/index.ts @@ -1,2 +1,3 @@ export * from './addAfterRowsToData'; +export * from './addAfterRowToRowDefs'; export * from './addAfterRowsToRowDefs'; diff --git a/packages/table/src/helpers/definitions/cell/getCellDef.test.ts b/packages/table/src/helpers/definitions/cell/getCellDef.test.ts new file mode 100644 index 00000000..fc4ae6a4 --- /dev/null +++ b/packages/table/src/helpers/definitions/cell/getCellDef.test.ts @@ -0,0 +1,56 @@ +import { describe, test, expect } from 'vitest'; + +import { TCellDef } from '../../../declarations'; +import { getCellDef } from './getCellDef'; + +describe('helpers', () => { + describe('definitions', () => { + describe('cell', () => { + describe('getCellDef', () => { + const cases: [string, TCellDef[], string, string, TCellDef][] = [ + ['empty row defs return undefined', [], '1', '2', undefined], + [ + 'colId & rowId null return undefined', + [{ colId: '1', rowId: '2' }], + null, + null, + undefined, + ], + [ + 'colId null return undefined', + [{ colId: '1', rowId: '2' }], + null, + '2', + undefined, + ], + [ + 'rowId null return undefined', + [{ colId: '1', rowId: '2' }], + '1', + null, + undefined, + ], + ['rowDef null return undefined', null, '1', '2', undefined], + [ + 'return element cellDef', + [{ colId: '1', rowId: '2' }], + '1', + '2', + { colId: '1', rowId: '2' }, + ], + [ + 'id not find in rowDef', + [{ colId: '1', rowId: '2' }], + '1', + '3', + undefined, + ], + ]; + + test.each(cases)('%s', (_title, rowDefs, colId, rowId, expected) => { + expect(getCellDef(rowDefs, colId, rowId)).toEqual(expected); + }); + }); + }); + }); +}); diff --git a/packages/table/src/helpers/definitions/cell/getCellDef.ts b/packages/table/src/helpers/definitions/cell/getCellDef.ts new file mode 100644 index 00000000..32855dec --- /dev/null +++ b/packages/table/src/helpers/definitions/cell/getCellDef.ts @@ -0,0 +1,7 @@ +import type { TCellDef } from '../../declarations'; + +export const getCellDef = ( + cellDefs: TCellDef[], + colId: string, + rowId: string, +) => cellDefs?.find((cell) => cell.colId === colId && cell.rowId === rowId); diff --git a/packages/table/src/helpers/definitions/cell/index.ts b/packages/table/src/helpers/definitions/cell/index.ts new file mode 100644 index 00000000..1e370fea --- /dev/null +++ b/packages/table/src/helpers/definitions/cell/index.ts @@ -0,0 +1 @@ +export * from './getCellDef'; diff --git a/packages/table/src/helpers/definitions/index.ts b/packages/table/src/helpers/definitions/index.ts new file mode 100644 index 00000000..5dca1837 --- /dev/null +++ b/packages/table/src/helpers/definitions/index.ts @@ -0,0 +1,2 @@ +export * from './cell'; +export * from './row'; diff --git a/packages/table/src/helpers/definitions/row/getRowDef.test.ts b/packages/table/src/helpers/definitions/row/getRowDef.test.ts new file mode 100644 index 00000000..4e3d465d --- /dev/null +++ b/packages/table/src/helpers/definitions/row/getRowDef.test.ts @@ -0,0 +1,24 @@ +import { describe, test, expect } from 'vitest'; + +import { TRowDef } from '../../../declarations'; +import { getRowDef } from './getRowDef'; + +describe('helpers', () => { + describe('definitions', () => { + describe('row', () => { + describe('getRowDef', () => { + const cases: [string, TRowDef[], string, TRowDef][] = [ + ['empty row defs return undefined', [], '1', undefined], + ['id null return undefined', [{ id: '1' }], null, undefined], + ['rowDef null return undefined', null, '1', undefined], + ['return element rowDef', [{ id: '1' }], '1', { id: '1' }], + ['id not find in rowDef', [{ id: '1' }], '2', undefined], + ]; + + test.each(cases)('%s', (_title, rowDefs, id, expected) => { + expect(getRowDef(rowDefs, id)).toEqual(expected); + }); + }); + }); + }); +}); diff --git a/packages/table/src/helpers/definitions/row/getRowDef.ts b/packages/table/src/helpers/definitions/row/getRowDef.ts new file mode 100644 index 00000000..55654d51 --- /dev/null +++ b/packages/table/src/helpers/definitions/row/getRowDef.ts @@ -0,0 +1,4 @@ +import type { TRowDef } from '../../../declarations'; + +export const getRowDef = (rowDefs: TRowDef[], id: string) => + rowDefs?.find((row) => row.id === id); diff --git a/packages/table/src/helpers/definitions/row/index.ts b/packages/table/src/helpers/definitions/row/index.ts new file mode 100644 index 00000000..a5753460 --- /dev/null +++ b/packages/table/src/helpers/definitions/row/index.ts @@ -0,0 +1,2 @@ +export * from './getRowDef'; +export * from './toggleHideRowDef'; diff --git a/packages/table/src/helpers/definitions/row/toggleHideRowDef.test.ts b/packages/table/src/helpers/definitions/row/toggleHideRowDef.test.ts new file mode 100644 index 00000000..746a23eb --- /dev/null +++ b/packages/table/src/helpers/definitions/row/toggleHideRowDef.test.ts @@ -0,0 +1,33 @@ +import { describe, test, expect } from 'vitest'; + +import { TRowDef } from '../../../declarations'; +import { toggleHideRowDef } from './toggleHideRowDef'; + +describe('helpers', () => { + describe('definitions', () => { + describe('row', () => { + describe('toggleHideRowDef', () => { + const cases: [string, TRowDef[], string, TRowDef[]][] = [ + ['empty rowdefs return empty rowdefs', [], '1', []], + ['rowdefs null return undefined', null, '1', undefined], + [ + 'changed visible to no visible', + [{ id: '1', hide: false }], + '1', + [{ id: '1', hide: true }], + ], + [ + 'changed no visible to visible', + [{ id: '1', hide: true }], + '1', + [{ id: '1', hide: false }], + ], + ]; + + test.each(cases)('%s', (_title, rowDefs, id, expected) => { + expect(toggleHideRowDef(rowDefs, id)).toEqual(expected); + }); + }); + }); + }); +}); diff --git a/packages/table/src/helpers/definitions/row/toggleHideRowDef.ts b/packages/table/src/helpers/definitions/row/toggleHideRowDef.ts new file mode 100644 index 00000000..08e4e918 --- /dev/null +++ b/packages/table/src/helpers/definitions/row/toggleHideRowDef.ts @@ -0,0 +1,6 @@ +import type { TRowDef } from '../../../declarations'; + +export const toggleHideRowDef = (rowDefs: TRowDef[], id: string) => + rowDefs?.map((rowDef: TRowDef) => + rowDef.id === id ? { ...rowDef, hide: !rowDef.hide } : rowDef, + ); diff --git a/packages/table/src/helpers/index.ts b/packages/table/src/helpers/index.ts index 978f9b59..753a561a 100644 --- a/packages/table/src/helpers/index.ts +++ b/packages/table/src/helpers/index.ts @@ -1,5 +1,6 @@ export * from './afterRow'; export * from './addBulkColumnData'; +export * from './definitions'; export * from './getOptionsFromData'; export * from './orderDataByOrderStruct'; export * from './filterDataByFilterStruct'; diff --git a/packages/table/src/hooks/useAfterRow/useAfterRow.ts b/packages/table/src/hooks/useAfterRow/useAfterRow.ts index b4fbb605..e21207ef 100644 --- a/packages/table/src/hooks/useAfterRow/useAfterRow.ts +++ b/packages/table/src/hooks/useAfterRow/useAfterRow.ts @@ -9,9 +9,9 @@ import { deleteAfterRowToDataById, findDataById, getRowDef, - setHideRowDef, } from '../../helpers'; import type { TRowGroupingContext } from '../../facade/RowGrouping/RowGroupingContext'; +import { toggleHideRowDef } from '../../helpers'; export const useRenderAfterRow = ({ rowDefs, @@ -24,7 +24,9 @@ export const useRenderAfterRow = ({ onRowDefsChange: (rowDefs: TRowDef[]) => void; colDefs: TColDef[]; }) => { - const [selection, setSelection] = React.useState(initialSelection || []); + const [selection, setSelection] = React.useState( + initialSelection || [], + ); const colDefs = [ { id: 'rowGrouping', @@ -71,11 +73,14 @@ export const useOnDemandAfterRow = ({ initialSelection: string[]; data: TData; onDataChange: (data: TData) => void; - afterRowRenderer: React.FC - | (({ value, colDef, rowIndex, row }: TCellRenderer) => React.ReactNode); + afterRowRenderer: + | React.FC + | (({ value, colDef, rowIndex, row }: TCellRenderer) => React.ReactNode); afterRowHeight: React.CSSProperties['height']; }) => { - const [selection, setSelection] = React.useState(initialSelection || []); + const [selection, setSelection] = React.useState( + initialSelection || [], + ); const colDefs = [ { @@ -87,7 +92,6 @@ export const useOnDemandAfterRow = ({ onClick: (rowId) => { const nextSelection = updateSelection(selection)(rowId as string); setSelection(nextSelection); - const isOpened = nextSelection.includes(rowId); onRowDefsChange( !getRowDef(rowDefs, `afterRow-${rowId}`) @@ -97,7 +101,7 @@ export const useOnDemandAfterRow = ({ afterRowRenderer, afterRowHeight, ) - : setHideRowDef(rowDefs, rowId, isOpened), + : toggleHideRowDef(rowDefs, `afterRow-${rowId}`), ); onDataChange( findDataById(data, `afterRow-${rowId}`) diff --git a/packages/table/stories/AfterRow.stories.tsx b/packages/table/stories/AfterRow.stories.tsx index 7bc81b7b..eef47396 100644 --- a/packages/table/stories/AfterRow.stories.tsx +++ b/packages/table/stories/AfterRow.stories.tsx @@ -35,9 +35,8 @@ type Story = StoryObj; const initialData = Holo.of() .addType('index', (args = {}) => String(args.index + 1)) - .addType('rowGrouping', () => false) .schema({ - rowGrouping: 'rowGrouping', + rowGrouping: false, id: 'index', booleanValue: 'bool', name: 'name', @@ -71,6 +70,10 @@ const colDefsInitial = [ ]; const initalRowDefs = [ + { + id: '2', + style: 'background-color: rgb(255,200,200);', + }, { id: `afterRow-2`, hide: false, @@ -91,19 +94,23 @@ const BasicCmp = ({ const { orderStruct, onSort } = useOrderStruct([ { id: 'text', sort: 'desc' }, ]); - const dataOrdered = [...initialData].sort( - orderDataByOrderStruct(orderStruct), - ); - const [dataWithAfterRows, afterRowIds] = addAfterRowsToData(dataOrdered); - const [rowDefs, setRowDefs] = React.useState( - addAfterRowsToRowDefs( + const [rowDefs, setRowDefs] = React.useState(); + + const { dataWithAfterRows } = React.useMemo(() => { + const dataOrdered = [...initialData].sort( + orderDataByOrderStruct(orderStruct), + ); + const [dataWithAfterRows, afterRowIds] = addAfterRowsToData(dataOrdered); + const newRowDef = addAfterRowsToRowDefs( initalRowDefs, afterRowIds, afterRowRenderer, afterRowHeight, - ), - ); + ); + setRowDefs(newRowDef); + return { dataWithAfterRows }; + }, [initialData]); const { colDefs } = useRenderAfterRow({ rowDefs, @@ -124,6 +131,13 @@ const BasicCmp = ({ }} colDefs={colDefs} rowDefs={rowDefs} + cellDefs={[ + { + colId: 'name', + rowId: '2', + style: 'background-color: rgb(200,255,200);', + }, + ]} maxHeight={'80vh'} rowHeight={ROW_HEIGHT_MD} resizableColumns={true}