Skip to content

Commit

Permalink
first working virtualization for both rows and columns
Browse files Browse the repository at this point in the history
  • Loading branch information
radubrehar committed Sep 17, 2024
1 parent 6c6d0bb commit 186b124
Show file tree
Hide file tree
Showing 20 changed files with 200 additions and 297 deletions.
2 changes: 1 addition & 1 deletion examples/src/pages/demos/new-perf-approach.page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export default function App() {
</b>
);
};
const [brain] = React.useState(() => new MatrixBrain());
const [brain] = React.useState(() => new MatrixBrain('test'));

(globalThis as any).brain = brain;

Expand Down
2 changes: 1 addition & 1 deletion examples/src/pages/demos/new-perf-approach2.page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export default function App() {
</b>
);
};
const [brain] = React.useState(() => new MatrixBrain());
const [brain] = React.useState(() => new MatrixBrain('test'));

(globalThis as any).brain = brain;

Expand Down
3 changes: 2 additions & 1 deletion examples/src/pages/tests/horizontal-layout/default.page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ export function getRandomInt(min: number, max: number) {
return Math.floor(Math.random() * (max - min + 1) + min);
}

const domProps = { style: { height: '30vh', width: 900 } };
const domProps = { style: { height: '30vh', width: '90vw' } };
// const domProps = { style: { height: '30vh', width: 300 } };

// dataSource.length = 12;

Expand Down
6 changes: 3 additions & 3 deletions examples/src/pages/tests/horizontal-layout/test.page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const columns: InfiniteTablePropColumns<Developer> = {

const domProps = {
// style: { height: 420 /*30px header, 420 body*/, width: 230 },
style: { height: '50vh' /*30px header, 420 body*/, width: '50vw' },
style: { height: '50vh' /*30px header, 420 body*/, width: '30vw' },
};

const data = Array.from({ length: 10 }, (_, i) => ({
Expand Down Expand Up @@ -55,10 +55,10 @@ export default function App() {
wrapRowsHorizontally={wrapRowsHorizontally}
rowHeight={50}
domProps={domProps}
header={false}
header={true}
columnHeaderHeight={30}
columns={columns}
columnDefaultWidth={100}
columnDefaultWidth={200}
onCellClick={({ rowIndex, colIndex }) => {
console.log('clicked', rowIndex, colIndex);
}}
Expand Down
8 changes: 4 additions & 4 deletions examples/src/pages/tests/matrix-brain.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export default test.describe.parallel('MatrixBrain', () => {
const ROWS = 20;
const COLS = 7;

const brain = new MatrixBrain();
const brain = new MatrixBrain('test');

brain.update({
colWidth: COL_SIZE,
Expand Down Expand Up @@ -86,7 +86,7 @@ export default test.describe.parallel('MatrixBrain', () => {
const ROWS = 20;
const COLS = 7;

const brain = new MatrixBrain();
const brain = new MatrixBrain('test');

brain.update({
colWidth: COL_SIZE,
Expand Down Expand Up @@ -118,7 +118,7 @@ export default test.describe.parallel('MatrixBrain', () => {
const ROWS = 20;
const COLS = 7;

const brain = new MatrixBrain();
const brain = new MatrixBrain('test');

brain.update({
colWidth: COL_SIZE,
Expand Down Expand Up @@ -200,7 +200,7 @@ export default test.describe.parallel('MatrixBrain', () => {
const ROWS = 20;
const COLS = 7;

const brain = new MatrixBrain();
const brain = new MatrixBrain('test');

brain.update({
colWidth: COL_SIZE,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,52 +1,29 @@
import { TableRenderRange } from '../InfiniteTable';
import { Renderable } from '../types/Renderable';
import { HorizontalLayoutMatrixBrain } from '../VirtualBrain/HorizontalLayoutMatrixBrain';
import {
columnOffsetAtIndex,
columnOffsetAtIndexWhileReordering,
currentTransformY,
ReactHeadlessTableRenderer,
TableRenderCellFn,
TableRenderDetailRowFn,
} from './ReactHeadlessTableRenderer';

export class HorizontalLayoutTableRenderer extends ReactHeadlessTableRenderer {
protected brain: HorizontalLayoutMatrixBrain;
constructor(brain: HorizontalLayoutMatrixBrain) {
super(brain);
constructor(brain: HorizontalLayoutMatrixBrain, debugId?: string) {
super(brain, debugId);
this.brain = brain;
}

protected getCellRealCoordinates(rowIndex: number, colIndex: number) {
// return {
// rowIndex,
// colIndex,
// };
return this.brain.getHorizontalLayoutPositionFromMatrixCoordinates({
rowIndex,
colIndex,
});
}

renderRange(
range: TableRenderRange,

{
renderCell,
renderDetailRow,
force,
onRender,
}: {
force?: boolean;
renderCell: TableRenderCellFn;
renderDetailRow?: TableRenderDetailRowFn;
onRender: (items: Renderable[]) => void;
},
): Renderable[] {
return super.renderRange(range, {
renderCell,
renderDetailRow,
force,
onRender,
});
}

setTransform = (
element: HTMLElement,
rowIndex: number,
Expand All @@ -58,7 +35,7 @@ export class HorizontalLayoutTableRenderer extends ReactHeadlessTableRenderer {
scrollLeft?: boolean;
scrollTop?: boolean;
},
zIndex: number | 'auto' | undefined | null,
_zIndex: number | 'auto' | undefined | null,
) => {
const horizontalLayoutCoords = this.getCellRealCoordinates(
rowIndex,
Expand All @@ -69,7 +46,8 @@ export class HorizontalLayoutTableRenderer extends ReactHeadlessTableRenderer {
const pageIndex = Math.floor(
horizontalLayoutCoords.rowIndex / this.brain.rowsPerPage,
);
const pageOffset = pageIndex ? pageIndex * this.brain.pageWidth : 0;
const pageWidth = `${this.brain.pageWidth}px`;
const pageOffset = pageIndex ? `calc(${pageIndex} * ${pageWidth})` : '0px';

const columnOffsetX = `${columnOffsetAtIndex}-${horizontalLayoutCoords.colIndex}`;
const columnOffsetXWhileReordering = `${columnOffsetAtIndexWhileReordering}-${horizontalLayoutCoords.colIndex}`;
Expand All @@ -83,7 +61,7 @@ export class HorizontalLayoutTableRenderer extends ReactHeadlessTableRenderer {
element.style.setProperty(currentTransformY, currentTransformYValue);
}

const xOffset = `calc(var(${columnOffsetX}) + ${pageOffset}px)`;
const xOffset = `calc(var(${columnOffsetX}) + ${pageOffset})`;
const transformX = `var(${columnOffsetXWhileReordering}, ${xOffset})`;
const transformY = `var(${currentTransformY})`;

Expand Down
16 changes: 1 addition & 15 deletions source/src/components/HeadlessTable/RawTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { useEffect, useLayoutEffect, useMemo } from 'react';
import { AvoidReactDiff } from '../RawList/AvoidReactDiff';
import { Renderable } from '../types/Renderable';
import { SubscriptionCallback } from '../types/SubscriptionCallback';
import { buildSubscriptionCallback } from '../utils/buildSubscriptionCallback';
import { MatrixBrain } from '../VirtualBrain/MatrixBrain';
import { createRenderer } from './createRenderer';

import {
ReactHeadlessTableRenderer,
Expand All @@ -23,20 +23,6 @@ export type RawTableProps = {
onRenderUpdater?: SubscriptionCallback<Renderable>;
};

function createRenderer(brain: MatrixBrain) {
const renderer = new ReactHeadlessTableRenderer(brain);
const onRenderUpdater = buildSubscriptionCallback<Renderable>();

brain.onDestroy(() => {
renderer.destroy();
onRenderUpdater.destroy();
});

return {
renderer,
onRenderUpdater,
};
}
export function RawTableFn(props: RawTableProps) {
const { brain, renderCell, renderDetailRow } = props;

Expand Down
14 changes: 4 additions & 10 deletions source/src/components/HeadlessTable/ReactHeadlessTableRenderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -193,10 +193,11 @@ export class ReactHeadlessTableRenderer extends Logger {
}
};

constructor(brain: MatrixBrain) {
super('ReactHeadlessTableRenderer');
constructor(brain: MatrixBrain, debugId?: string) {
debugId = debugId || 'ReactHeadlessTableRenderer';
super(debugId);
this.brain = brain;
this.debugId = brain.name;
this.debugId = debugId;

this.mappedCells = new MappedCells();
this.mappedDetailRows = new MappedVirtualRows();
Expand Down Expand Up @@ -1306,13 +1307,6 @@ export class ReactHeadlessTableRenderer extends Logger {
renderedNode,
);

if (__DEV__) {
this.debug(
`Render cell ${rowIndex},${colIndex} at element ${elementIndex}`,
);
}

// console.log('update', rowIndex, colIndex, renderedNode);
itemUpdater(renderedNode);

this.updateElementPosition(elementIndex, { hidden, rowspan, colspan });
Expand Down
34 changes: 34 additions & 0 deletions source/src/components/HeadlessTable/createRenderer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { Renderable } from '../types/Renderable';
import { buildSubscriptionCallback } from '../utils/buildSubscriptionCallback';
import { HorizontalLayoutMatrixBrain } from '../VirtualBrain/HorizontalLayoutMatrixBrain';
import { MatrixBrain } from '../VirtualBrain/MatrixBrain';
import { HorizontalLayoutTableRenderer } from './HorizontalLayoutTableRenderer';
import { ReactHeadlessTableRenderer } from './ReactHeadlessTableRenderer';

export function createRenderer(brain: MatrixBrain) {
const renderer = !brain.isHorizontalLayoutBrain
? new ReactHeadlessTableRenderer(
brain,
`ReactHeadlessTableRenderer:${brain.name}`,
)
: new HorizontalLayoutTableRenderer(
brain as HorizontalLayoutMatrixBrain,
`HorizontalLayoutTableRenderer:${brain.name}`,
);

const onRenderUpdater = buildSubscriptionCallback<Renderable>();

brain.onDestroy(() => {
renderer.destroy();
onRenderUpdater.destroy();
});

if (__DEV__) {
(brain as any).renderer = renderer;
}

return {
renderer,
onRenderUpdater,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,17 @@ export function HScrollSyncContent(
const style = { ...domProps.style };

if (width === 'column') {
style.width = ThemeVars.runtime.totalVisibleColumnsWidth;
style.width = ThemeVars.runtime.totalVisibleColumnsWidthValue;
} else if (width === 'viewport') {
style.width = ThemeVars.runtime.bodyWidth;
}
if (minWidth === 'column') {
style.minWidth = ThemeVars.runtime.totalVisibleColumnsWidth;
style.minWidth = ThemeVars.runtime.totalVisibleColumnsWidthValue;
} else if (minWidth === 'viewport') {
style.minWidth = ThemeVars.runtime.bodyWidth;
}
if (maxWidth === 'column') {
style.maxWidth = ThemeVars.runtime.totalVisibleColumnsWidth;
style.maxWidth = ThemeVars.runtime.totalVisibleColumnsWidthValue;
} else if (maxWidth === 'viewport') {
style.maxWidth = ThemeVars.runtime.bodyWidth;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ function InfiniteTableHeaderFn<T>(
columnAndGroupTreeInfo,
columnGroupsMaxDepth,
showColumnFilters,
headerBrain,
],
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export type TableHeaderWrapperProps = {
headerBrain: MatrixBrain;
bodyBrain: MatrixBrain;
scrollbars: Scrollbars;
wrapRowsHorizontally: boolean;
};
export function TableHeaderWrapper<T>(props: TableHeaderWrapperProps) {
const { headerBrain, bodyBrain, scrollbars } = props;
Expand Down Expand Up @@ -175,7 +176,7 @@ export function TableHeaderWrapper<T>(props: TableHeaderWrapperProps) {
<div
className={HeaderWrapperCls}
style={{
height: height,
height,
}}
>
{header}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ export interface InfiniteTableColumnCellProps<T>
getData: () => InfiniteTableRowInfo<T>[];
toggleGroupRow: InfiniteTableToggleGroupRowFn;
rowIndexInPage: number | null;
pageIndex: number | null;
rowIndex: number;
rowHeight: number;
cellStyle?: InfiniteTablePropCellStyle<T>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,12 +236,17 @@ export function useCellRendering<T>(
? brain.getRowIndexInPage(rowIndex)
: null;

const pageIndex = wrapRowsHorizontally
? brain.getPageIndexForRow(rowIndex)
: null;

const cellProps: InfiniteTableColumnCellProps<T> = {
getData,
virtualized: true,
showZebraRows,
groupRenderStrategy,
rowIndexInPage,
pageIndex,
rowIndex,
rowInfo,
hidden,
Expand Down
19 changes: 16 additions & 3 deletions source/src/components/InfiniteTable/hooks/useDOMProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,12 @@ const publicRuntimeVars: Record<
}
> = {
bodyWidth: { name: stripVar(ThemeVars.runtime.bodyWidth), value: '' },
totalVisibleColumnsWidth: {
name: stripVar(ThemeVars.runtime.totalVisibleColumnsWidth),
totalVisibleColumnsWidthValue: {
name: stripVar(ThemeVars.runtime.totalVisibleColumnsWidthValue),
value: '',
},
totalVisibleColumnsWidthVar: {
name: stripVar(ThemeVars.runtime.totalVisibleColumnsWidthVar),
value: '',
},
visibleColumnsCount: {
Expand Down Expand Up @@ -170,12 +174,21 @@ export function useDOMProps<T>(
] = `calc(${InternalVars.bodyWidth} - ${InternalVars.scrollbarWidthVertical})`;

//@ts-ignore
cssVars[publicRuntimeVars.totalVisibleColumnsWidth.name] = `${
cssVars[publicRuntimeVars.totalVisibleColumnsWidthValue.name] = `${
computedPinnedStartColumnsWidth +
computedPinnedEndColumnsWidth +
computedUnpinnedColumnsWidth
}px`;

//@ts-ignore
cssVars[
publicRuntimeVars.totalVisibleColumnsWidthVar.name
] = `calc(${computedVisibleColumns
.map((_col, index) => {
return `var(${columnWidthAtIndex}-${index})`;
})
.join(' + ')})`;

//@ts-ignore
cssVars[publicRuntimeVars.visibleColumnsCount.name] =
computedVisibleColumns.length;
Expand Down
3 changes: 2 additions & 1 deletion source/src/components/InfiniteTable/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,12 @@ function InfiniteTableHeader<T>() {
const context = useInfiniteTable<T>();

const { state: componentState, getComputed } = context;
const { header, brain, headerBrain } = componentState;
const { header, brain, headerBrain, wrapRowsHorizontally } = componentState;
const { scrollbars } = getComputed();

return header ? (
<TableHeaderWrapper
wrapRowsHorizontally={!!wrapRowsHorizontally}
bodyBrain={brain}
headerBrain={headerBrain}
scrollbars={scrollbars}
Expand Down
Loading

0 comments on commit 186b124

Please sign in to comment.