IconGrid: experiment with various list virtualization libraries
This commit is contained in:
@@ -5,9 +5,13 @@
|
||||
|
||||
.grid-item {
|
||||
margin: 4px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: aquamarine;
|
||||
filter: grayscale(100%);
|
||||
transition: 0.5s ease;
|
||||
transition: filter 0.5s ease;
|
||||
}
|
||||
|
||||
.grid-item:hover {
|
||||
|
||||
@@ -1,27 +1,101 @@
|
||||
import React from "react";
|
||||
import React, { useRef, useCallback, useMemo } from "react";
|
||||
import { useRecoilValue } from "recoil";
|
||||
import { useVirtual } from "react-virtual";
|
||||
|
||||
import { filteredQueryResultsSelector } from "../../state/selectors";
|
||||
import { iconColorAtom, iconSizeAtom } from "../../state/atoms";
|
||||
import "./IconGrid.css";
|
||||
|
||||
type IconGridProps = {};
|
||||
|
||||
const COLUMN_COUNT = 5;
|
||||
|
||||
const IconGrid: React.FC<IconGridProps> = () => {
|
||||
const parentRef = useRef<HTMLDivElement>(null);
|
||||
const color = useRecoilValue(iconColorAtom);
|
||||
const size = useRecoilValue(iconSizeAtom);
|
||||
const filteredQueryResults = useRecoilValue(filteredQueryResultsSelector);
|
||||
// const categorizedQueryResults = useRecoilValue(categorizedQueryResultsSelector);
|
||||
// console.log(categorizedQueryResults);
|
||||
|
||||
// const rowVirtualizer = useVirtual({
|
||||
// size: useMemo(() => Math.ceil(filteredQueryResults.length / COLUMN_COUNT), [
|
||||
// filteredQueryResults,
|
||||
// ]),
|
||||
// parentRef,
|
||||
// estimateSize: useCallback(() => 220 * COLUMN_COUNT, []),
|
||||
// });
|
||||
|
||||
const rowVirtualizer = useVirtual({
|
||||
size: useMemo(() => Math.ceil(filteredQueryResults.length / COLUMN_COUNT), [
|
||||
filteredQueryResults,
|
||||
]),
|
||||
parentRef,
|
||||
estimateSize: useCallback(() => 240, []),
|
||||
overscan: 5,
|
||||
});
|
||||
|
||||
const columnVirtualizer = useVirtual({
|
||||
horizontal: true,
|
||||
size: COLUMN_COUNT,
|
||||
parentRef,
|
||||
estimateSize: useCallback(() => 160, []),
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="grid">
|
||||
{filteredQueryResults.map((icon) => (
|
||||
<div key={`ph-${icon.name}-${icon.style}`} className="grid-item">
|
||||
<img
|
||||
src={icon.asset}
|
||||
alt={`${icon.name} icon`}
|
||||
width="100%"
|
||||
/>
|
||||
<div style={{ padding: 16 }}>{icon.name}</div>
|
||||
<>
|
||||
<div ref={parentRef} style={{ height: "90vh", width: "100%", overflowY: "auto" }}>
|
||||
<div
|
||||
style={{
|
||||
height: `${rowVirtualizer.totalSize}px`,
|
||||
// width: `${columnVirtualizer.totalSize}px`,
|
||||
// height: `${rowVirtualizer.totalSize}px`,
|
||||
width: "100%",
|
||||
position: "relative",
|
||||
}}
|
||||
className="grid"
|
||||
>
|
||||
{rowVirtualizer.virtualItems.map((virtualRow) => (
|
||||
<React.Fragment key={virtualRow.index}>
|
||||
{columnVirtualizer.virtualItems.map((virtualColumn) => (
|
||||
<div
|
||||
key={virtualColumn.index}
|
||||
style={{
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: `${virtualColumn.size}px`,
|
||||
height: `${virtualRow.size}px`,
|
||||
transform: `translateX(${virtualColumn.start}px) translateY(${virtualRow.start}px)`,
|
||||
}}
|
||||
className="grid-item"
|
||||
>
|
||||
{(function () {
|
||||
const icon =
|
||||
filteredQueryResults[
|
||||
virtualRow.index * COLUMN_COUNT + virtualColumn.index
|
||||
];
|
||||
if (!icon) return null;
|
||||
return (
|
||||
<>
|
||||
<img
|
||||
color={color}
|
||||
style={{ height: size, width: size }}
|
||||
src={icon.asset}
|
||||
alt={`${icon.name} icon`}
|
||||
width="100%"
|
||||
/>
|
||||
<p style={{ padding: 16 }}>{icon.name}</p>
|
||||
</>
|
||||
);
|
||||
})()}
|
||||
</div>
|
||||
))}
|
||||
</React.Fragment>
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
34
src/components/IconGrid/IconGridRL.tsx
Normal file
34
src/components/IconGrid/IconGridRL.tsx
Normal file
@@ -0,0 +1,34 @@
|
||||
import React from "react";
|
||||
import { useRecoilValue } from "recoil";
|
||||
import ReactList from "react-list";
|
||||
|
||||
import { filteredQueryResultsSelector } from "../../state/selectors";
|
||||
import "./IconGrid.css";
|
||||
|
||||
type IconGridProps = {};
|
||||
|
||||
const IconGridRL: React.FC<IconGridProps> = () => {
|
||||
const filteredQueryResults = useRecoilValue(filteredQueryResultsSelector);
|
||||
|
||||
const renderItem = (index: number, key: number | string) => {
|
||||
const icon = filteredQueryResults[index];
|
||||
return (
|
||||
<div key={key} className="grid-item" style={{ width: 120}}>
|
||||
<img src={icon.asset} alt={`${icon.name} icon`} width="100%" />
|
||||
<div style={{ padding: 16 }}>{icon.name}</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={{ overflow: "auto", maxHeight: 400 }}>
|
||||
<ReactList
|
||||
itemRenderer={renderItem}
|
||||
length={filteredQueryResults.length}
|
||||
type="uniform"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default IconGridRL;
|
||||
34
src/components/IconGrid/IconGridVirtualized.tsx
Normal file
34
src/components/IconGrid/IconGridVirtualized.tsx
Normal file
@@ -0,0 +1,34 @@
|
||||
import React from "react";
|
||||
import { useRecoilValue } from "recoil";
|
||||
import { Grid } from "react-virtualized";
|
||||
|
||||
import { filteredQueryResultsSelector } from "../../state/selectors";
|
||||
import "./IconGrid.css";
|
||||
|
||||
type IconGridProps = {};
|
||||
|
||||
const COLUMN_COUNT = 5;
|
||||
|
||||
export default class IconGridVirtualized extends React.PureComponent {
|
||||
constructor(props: IconGridProps) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
render() {
|
||||
const filteredQueryResults = useRecoilValue(filteredQueryResultsSelector);
|
||||
|
||||
const cellRenderer = () => <div></div>
|
||||
|
||||
return (
|
||||
<Grid
|
||||
columnCount={COLUMN_COUNT}
|
||||
columnWidth={100}
|
||||
height={300}
|
||||
rowCount={Math.ceil(filteredQueryResults.length / COLUMN_COUNT)}
|
||||
rowHeight={220}
|
||||
width={300}
|
||||
cellRenderer={cellRenderer}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user