Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 16 additions & 17 deletions semcore/data-table/src/components/Body/Body.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,21 +92,22 @@ class BodyRoot<Data extends DataTableData, UniqKeyType> extends Component<DataTa
});
};

handleRef = (index: number, row: DTRow<UniqKeyType>) => (node: HTMLElement | null) => {
if (node) {
this.rowsHeightMap.set(index, [0, 0, node]);
this.setRowHeight(index, row);
}
};

handleComponentRef = (row: DTRow<UniqKeyType>) => (component: RowRoot<Data, UniqKeyType> | null) => {
requestAnimationFrame(() => {
if (component) {
this.rowsComponentsMap.set(row[UNIQ_ROW_KEY], component);
} else {
this.rowsComponentsMap.delete(row[UNIQ_ROW_KEY]);
handleComponentRef = (index: number, row: DTRow<UniqKeyType>, component: RowRoot<Data, UniqKeyType> | null) => {
const id = row[UNIQ_ROW_KEY];
if (component) {
if (this.asProps.virtualScroll) {
const node = component.rowElementRef.current;

if (node) {
this.rowsHeightMap.set(index, [0, 0, node]);
this.setRowHeight(index, row);
}
}
});

this.rowsComponentsMap.set(id, component);
} else {
this.rowsComponentsMap.delete(id);
}
};

getPropsToRow = (props: { row: DTRow<UniqKeyType>; mergedRow?: boolean }): DataTableRowProps<Data, UniqKeyType> => {
Expand Down Expand Up @@ -380,7 +381,6 @@ class BodyRoot<Data extends DataTableData, UniqKeyType> extends Component<DataTa
startIndex={this.startIndex}
rowIndex={index}
shadowVertical={shadowVertical}
handleRef={this.handleRef}
handleComponentRef={this.handleComponentRef}
getPropsToRow={this.getPropsToRow}
/>
Expand All @@ -391,8 +391,7 @@ class BodyRoot<Data extends DataTableData, UniqKeyType> extends Component<DataTa
<Row
key={row[UNIQ_ROW_KEY]?.toString()}
{...this.getPropsToRow({ row })}
ref={virtualScroll ? this.handleRef(this.startIndex + index, row) : undefined}
componentRef={this.handleComponentRef(row)}
componentRef={this.handleComponentRef}
/>
);
})}
Expand Down
9 changes: 5 additions & 4 deletions semcore/data-table/src/components/Body/Row.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class RowRoot<Data extends DataTableData, UniqKeyType> extends Component<
private openAccordionTimeout = 0;
private readonly cellStyle = new Map<string, React.CSSProperties>();

rowElementRef = React.createRef<HTMLDivElement>();
public rowElementRef = React.createRef<HTMLDivElement>();

state: State<UniqKeyType> = {
expandedForAnimation: false,
Expand All @@ -66,8 +66,8 @@ class RowRoot<Data extends DataTableData, UniqKeyType> extends Component<
}

componentDidMount() {
const { componentRef } = this.asProps;
componentRef?.(this);
const { rowIndex, componentRef, row } = this.asProps;
componentRef?.(rowIndex, row, this);

this.setAccordion();

Expand All @@ -83,7 +83,8 @@ class RowRoot<Data extends DataTableData, UniqKeyType> extends Component<
}

componentWillUnmount() {
this.asProps.componentRef?.(null);
const { rowIndex, componentRef, row } = this.asProps;
componentRef?.(rowIndex, row, null);

this.cellStyle.clear();
}
Expand Down
2 changes: 1 addition & 1 deletion semcore/data-table/src/components/Body/Row.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export type DataTableRowProps<Data extends DataTableData, UniqKeyType> = {
'accordionRowIndex'?: DataTableCellProps<Data, UniqKeyType>['accordionRowIndex'];
'isNonInteractive'?: boolean;

'componentRef'?: (component: RowRoot<Data, UniqKeyType> | null) => void;
'componentRef'?: (index: number, row: DTRow<UniqKeyType>, component: RowRoot<Data, UniqKeyType> | null) => void;

'accordionIndex'?: number;

Expand Down
6 changes: 2 additions & 4 deletions semcore/data-table/src/components/Body/RowGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ type RowGroupProps<Data extends DataTableData, UniqKeyType> = {
startIndex: number;
rowIndex: number;
shadowVertical?: '' | 'end' | 'start' | 'median';
handleRef: (index: number, row: DTRow<UniqKeyType>) => (node: HTMLElement | null) => void;
handleComponentRef: (row: DTRow<UniqKeyType>) => (component: RowRoot<Data, UniqKeyType> | null) => void;
handleComponentRef: (index: number, row: DTRow<UniqKeyType>, component: RowRoot<Data, UniqKeyType> | null) => void;
getPropsToRow: (props: { row: DTRow<UniqKeyType>; mergedRow?: boolean }) => DataTableRowProps<Data, UniqKeyType>;
};

Expand All @@ -44,13 +43,12 @@ export class RowGroup<Data extends DataTableData, UniqKeyType> extends React.Pur
<SRowGroup
role='rowgroup'
key={`gg_${groupUniqKey}`}
ref={this.props.handleRef(startIndex + rowIndex, rows[0])}
>
{rows.map((item, i) => {
return (
<Row
key={item[UNIQ_ROW_KEY]?.toString() ?? `gg_${groupUniqKey}_row_${i}`}
componentRef={this.props.handleComponentRef(item)}
componentRef={this.props.handleComponentRef}
{...getPropsToRow({ row: item, mergedRow: i > 0 ? true : false })}
shadowVertical={shadowVertical}
/>
Expand Down
2 changes: 1 addition & 1 deletion semcore/data-table/src/components/DataTable/DataTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -970,7 +970,7 @@ class DataTableRoot<
let gridTemplateRows: string | undefined = undefined;

if (virtualScroll && typeof virtualScroll !== 'boolean' && 'rowHeight' in virtualScroll) {
gridTemplateRows = `auto auto repeat(${this.totalRows}, minmax(${virtualScroll.rowHeight}px, auto))`;
gridTemplateRows = `${this.hasGroups ? 'auto auto' : 'auto'} repeat(${this.totalRows}, ${virtualScroll.rowHeight}px)`;
}

return sstyled(styles)(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import type { DemoProps as SelectableWithMergedRowsProps } from './examples/sele
import SideIndentsExample from './examples/side-indents';
import type { AccordionInTableProps } from './examples/table_perf/table_perf';
import TablePerfExample, { accordionInsideTableDefaultProps } from './examples/table_perf/table_perf';
import TablePerfVirtualizationExample from './examples/table_perf_virtualization';
import VirtualScrollWithH100Example from './examples/virtual-scroll-with-h100';

const meta: Meta<typeof DataTable> = {
Expand Down Expand Up @@ -217,3 +218,24 @@ export const TablePerf: StoryObj<AccordionInTableProps> = {
},
args: accordionInsideTableDefaultProps,
};

export const TablePerfVirtualization: StoryObj<AccordionInTableProps> = {
render: TablePerfVirtualizationExample,
argTypes: {
loading: { control: 'boolean' },
cropPosition: {
control: 'select',
options: ['end', 'middle'],
},
// UIK-4923: hintProps=false skips ellipsis JS calculation for cropPosition=end
hintProps: {
control: 'select',
options: ['default', 'false'],
mapping: {
default: undefined,
false: false,
},
},
},
args: accordionInsideTableDefaultProps,
};
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ export type AccordionInTableProps = {
cropPosition?: 'end' | 'middle';
};

const refsMap: Record<string | symbol, HTMLElement | null> = {};
export const refsMap: Record<string | symbol, HTMLElement | null> = {};

const COLUMNS_CONFIG = [
export const COLUMNS_CONFIG = [
{
id: 'actions',
defaultActive: true,
Expand Down Expand Up @@ -182,7 +182,7 @@ const COLUMNS_CONFIG = [
},
];

const cols = COLUMNS_CONFIG.map((c) => ({
export const cols = COLUMNS_CONFIG.map((c) => ({
name: c.id,
children: c.id,
gtcWidth: c.wMin ? `minmax(${c.wMin}px, 1fr)` : 'max-content',
Expand All @@ -198,12 +198,12 @@ const cols = COLUMNS_CONFIG.map((c) => ({
// );

// no memo
const componentsMap = Object.fromEntries(
export const componentsMap = Object.fromEntries(
COLUMNS_CONFIG.map((c) => [c.id, c.Component]),
);

const DEFAULT_LOCALE = 'en-US';
const DEFAULT_MESSAGES = {};
export const DEFAULT_LOCALE = 'en-US';
export const DEFAULT_MESSAGES = {};

const Demo = (demoProps: AccordionInTableProps) => {
const cropPos = demoProps.cropPosition ?? 'middle';
Expand Down Expand Up @@ -268,13 +268,13 @@ export const accordionInsideTableDefaultProps: AccordionInTableProps = {

Demo.defaultProps = accordionInsideTableDefaultProps;

const ChartExample = () => {
export const ChartExample = () => {
return (
<div style={{ width: '600px', height: '400px', background: '#fff' }} />
);
};

const data: DataTableData = [
export const data: DataTableData = [
{
payment_intent_id: '300749e8-77a6-4637-a36b-285e33af4c0a',
affected_payment_intent_id: '5f39d854-f1e3-4c20-a0f8-de290e23be5a',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { DataTable } from '@semcore/ui/data-table';
import { Text } from '@semcore/ui/typography';
import React from 'react';
import { IntlProvider } from 'react-intl';

import type { AccordionInTableProps } from './table_perf/table_perf';
import { accordionInsideTableDefaultProps, cols, componentsMap, DEFAULT_LOCALE, DEFAULT_MESSAGES, data, refsMap } from './table_perf/table_perf';

const data2 = Array.from({ length: 1000 }, (_, r) => {
const index = r % data.length;

// Object.entries skips symbol keys, so [ACCORDION] is dropped: accordion is not supported with fixed rowHeight
const d = Object.entries(data[index]).reduce<Record<string, any>>((acc, [key, value]) => {
if (key === 'payment_intent_id') {
acc[key] = `${r}__${value}`;
} else {
acc[key] = value;
}

return acc;
}, {});

return d;
});

const Demo = (demoProps: AccordionInTableProps) => {
const cropPos = demoProps.cropPosition ?? 'middle';

return (
<IntlProvider
locale={DEFAULT_LOCALE}
defaultLocale={DEFAULT_LOCALE}
messages={DEFAULT_MESSAGES}
>
<DataTable
loading={demoProps.loading}
data={data2}
aria-label='big-big table with virtualScroll'
defaultGridTemplateColumnWidth='1fr'
columns={cols}
w='calc(100vw - 50px)'
h={500}
headerProps={{ sticky: true }}
virtualScroll={{ rowHeight: 45 }}
renderCell={(props) => {
if (props.dataKey === 'description_ellipsis') {
return {
children: (
<Text
ellipsis:cropPosition={cropPos}
hint={demoProps.hintProps}
>
{String(props.row.payment_description)}
</Text>
),
};
}

// @ts-ignore
const Component = componentsMap[props.columnName];
if (Component) {
return {
children: <Component value={props.value} row={props.row} cellProps={props} headerRef={refsMap[props.columnName]} cropPosition={cropPos} hintProps={demoProps.hintProps} />,
};
}

return {
children: <Text>{props.value}</Text>,
};
}}
/>
</IntlProvider>
);
};

Demo.defaultProps = accordionInsideTableDefaultProps;

export default Demo;
Loading