Author SHA1 Message Date
Matt Aitken 6e41828512 ColumnItems are now virtualized 2022-05-02 17:41:20 +01:00
2 changed files with 61 additions and 21 deletions
+57 -6
View File
@@ -1,21 +1,36 @@
import { Title } from "./Primitives/Title";
import { colorForItemAtPath } from "~/utilities/colors";
import { IconComponent } from "~/useColumnView";
import { ColumnViewNode, IconComponent } from "~/useColumnView";
import { useJson } from "../hooks/useJson";
import { memo, useMemo } from "react";
import { memo, useCallback, useMemo, useRef } from "react";
import { ColumnItem } from "./ColumnItem";
import { useJsonColumnViewAPI } from "~/hooks/useJsonColumnView";
import { useVirtual } from "react-virtual";
export type ColumnProps = {
id: string;
title: string;
icon?: IconComponent;
hasHighlightedElement: boolean;
children: React.ReactNode;
items: ColumnViewNode[];
selectedPath: string[];
highlightedPath: string[];
};
function ColumnElement(column: ColumnProps) {
const { id, title, children } = column;
const { id, title, items, selectedPath, highlightedPath } = column;
const [json] = useJson();
const iconColor = useMemo(() => colorForItemAtPath(id, json), [id, json]);
const { goToNodeId } = useJsonColumnViewAPI();
const containerRef = useRef<HTMLDivElement>(null);
const rowVirtualizer = useVirtual({
size: items.length,
parentRef: containerRef,
estimateSize: useCallback(() => 36, []),
overscan: 5,
});
return (
<div
@@ -27,8 +42,44 @@ function ColumnElement(column: ColumnProps) {
{column.icon && <column.icon className="h-6 w-6 mr-1" />}
<Title className="">{title}</Title>
</div>
<div className="overflow-y-auto h-viewerHeight no-scrollbar">
{children}
<div
className="overflow-y-auto h-viewerHeight no-scrollbar"
ref={containerRef}
>
<div
style={{
height: `${rowVirtualizer.totalSize}px`,
width: "100%",
position: "relative",
}}
>
{rowVirtualizer.virtualItems.map((virtualRow) => {
const item = items[virtualRow.index];
return (
<div
key={virtualRow.index}
style={{
position: "absolute",
top: 0,
left: 0,
width: "100%",
height: `${virtualRow.size}px`,
transform: `translateY(${virtualRow.start}px)`,
}}
>
<ColumnItem
item={item}
json={json}
isSelected={selectedPath.includes(item.id)}
isHighlighted={
highlightedPath[highlightedPath.length - 1] === item.id
}
onClick={(id) => goToNodeId(id, "columnView")}
/>
</div>
);
})}
</div>
</div>
</div>
);
+4 -15
View File
@@ -14,7 +14,6 @@ function ColumnsElement({ columns }: { columns: ColumnDefinition[] }) {
const [json] = useJson();
const { selectedPath, highlightedPath, highlightedNodeId } =
useJsonColumnViewState();
const { goToNodeId } = useJsonColumnViewAPI();
const highlightedItemIsValue = useMemo<boolean>(() => {
if (highlightedNodeId == null) {
return false;
@@ -38,20 +37,10 @@ function ColumnsElement({ columns }: { columns: ColumnDefinition[] }) {
hasHighlightedElement={
highlightedPath[highlightedPath.length - 2] === column.id
}
>
{column.items.map((item) => (
<ColumnItem
key={item.id}
item={item}
json={json}
isSelected={selectedPath.includes(item.id)}
isHighlighted={
highlightedPath[highlightedPath.length - 1] === item.id
}
onClick={(id) => goToNodeId(id, "columnView")}
/>
))}
</Column>
selectedPath={selectedPath}
highlightedPath={highlightedPath}
items={column.items}
/>
);
})}
{highlightedItemIsValue ? <BlankColumn /> : null}