Merge pull request #13886 from strapi/feature/replace-virtualized-window

ComponentIconPicker: Replace react-virtualized with react-window
This commit is contained in:
Gustav Hansen 2022-07-29 14:34:48 +02:00 committed by GitHub
commit 21b95f9954
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 74 additions and 60 deletions

View File

@ -119,7 +119,7 @@
"react-refresh": "0.11.0",
"react-router": "5.2.0",
"react-router-dom": "5.2.0",
"react-virtualized": "^9.22.3",
"react-window": "1.8.7",
"redux": "^4.0.1",
"redux-saga": "^0.16.0",
"reselect": "^4.0.0",

View File

@ -28,7 +28,7 @@ const aliasExactMatch = [
'react-redux',
'react-router',
'react-router-dom',
'react-virtualized',
'react-window',
'react-select',
'redux',
'reselect',

View File

@ -1,7 +1,7 @@
import React, { useEffect, useState, useRef } from 'react';
import PropTypes from 'prop-types';
import { useIntl } from 'react-intl';
import { AutoSizer, Collection } from 'react-virtualized';
import { FixedSizeGrid } from 'react-window';
import { Searchbar } from '@strapi/design-system/Searchbar';
import { IconButton } from '@strapi/design-system/IconButton';
import Search from '@strapi/icons/Search';
@ -10,11 +10,14 @@ import { Box } from '@strapi/design-system/Box';
import { Flex } from '@strapi/design-system/Flex';
import { Stack } from '@strapi/design-system/Stack';
import { Typography } from '@strapi/design-system/Typography';
import { getIndexFromColAndRow } from './utils/getIndexFromColAndRow';
import useDataManager from '../../hooks/useDataManager';
import getTrad from '../../utils/getTrad';
import Cell from './Cell';
const CELL_WIDTH = 44;
const CELL_WIDTH = 42;
const COLUMN_COUNT = 18;
const ComponentIconPicker = ({ error, intlLabel, name, onChange, value }) => {
const { allIcons } = useDataManager();
@ -37,26 +40,32 @@ const ComponentIconPicker = ({ error, intlLabel, name, onChange, value }) => {
setIcons(() => allIcons.filter(icon => icon.includes(value)));
};
const errorMessage = error ? formatMessage({ id: error, defaultMessage: error }) : '';
// eslint-disable-next-line react/prop-types
const IconRenderer = ({ columnIndex, rowIndex, style }) => {
const icon = icons[getIndexFromColAndRow(columnIndex, rowIndex, COLUMN_COUNT)];
const cellSizeAndPositionGetter = ({ index }) => {
const columnCount = 16;
const columnPosition = index % (columnCount || 1);
const height = CELL_WIDTH;
const width = CELL_WIDTH;
const x = columnPosition * (width + 1);
const y = parseInt(index / 16, 10) * CELL_WIDTH;
return {
height,
width,
x,
y,
};
return (
<div style={style} key={`col-${columnIndex}`}>
{icon && (
<Cell
style={{ width: '100%', height: '100%' }}
alignItems="center"
justifyContent="center"
onClick={() => {
onChange({ target: { name, value: icon } });
}}
isSelected={icon === value}
as="button"
type="button"
>
<FontAwesomeIcon icon={icon} />
</Cell>
)}
</div>
);
};
const cellCount = icons.length;
const errorMessage = error ? formatMessage({ id: error, defaultMessage: error }) : '';
return (
<Box>
@ -105,44 +114,17 @@ const ComponentIconPicker = ({ error, intlLabel, name, onChange, value }) => {
)}
</Flex>
<Stack spacing={1}>
<Box background="neutral100" borderColor={error ? 'danger600' : ''} hasRadius>
<Box>
<AutoSizer disableHeight>
{({ width }) => {
return (
<Collection
cellCount={cellCount}
cellRenderer={({ index, key, style }) => {
const icon = icons[index];
const isSelected = icon === value;
const handleClick = () => {
onChange({ target: { name, value: icon } });
};
return (
<div style={{ ...style, width: CELL_WIDTH }} key={key}>
<Cell
style={{ width: '100%', height: CELL_WIDTH }}
alignItems="center"
justifyContent="center"
onClick={handleClick}
isSelected={isSelected}
as="button"
type="button"
>
<FontAwesomeIcon icon={icon} />
</Cell>
</div>
);
}}
cellSizeAndPositionGetter={cellSizeAndPositionGetter}
height={132}
width={width}
/>
);
}}
</AutoSizer>
</Box>
<Box padding={1} background="neutral100" borderColor={error ? 'danger600' : ''} hasRadius>
<FixedSizeGrid
columnCount={COLUMN_COUNT}
columnWidth={CELL_WIDTH}
height={132}
rowHeight={CELL_WIDTH}
rowCount={Math.ceil(icons.length / COLUMN_COUNT)}
width={CELL_WIDTH * COLUMN_COUNT}
>
{IconRenderer}
</FixedSizeGrid>
</Box>
{error && (
<Typography

View File

@ -0,0 +1,3 @@
export const getIndexFromColAndRow = (columnIndex, rowIndex, numCols) => {
return columnIndex + rowIndex * numCols;
};

View File

@ -0,0 +1,21 @@
import { getIndexFromColAndRow } from '../getIndexFromColAndRow';
const FIXTURE = [
[[0, 0, 2], 0],
[[1, 0, 2], 1],
[[0, 1, 2], 2],
[[0, 2, 2], 4],
[[1, 4, 2], 9],
];
describe('getIndexFromColAndRow', () => {
FIXTURE.forEach(([input, expected]) => {
test(`returns ${expected} for ${JSON.stringify(input)}`, () => {
expect(getIndexFromColAndRow(...input)).toBe(expected);
});
});
});

View File

@ -18034,7 +18034,7 @@ memfs@^3.1.2, memfs@^3.2.2, memfs@^3.4.1, memfs@^3.4.3:
dependencies:
fs-monkey "^1.0.3"
memoize-one@^5.0.0:
"memoize-one@>=3.1.1 <6", memoize-one@^5.0.0:
version "5.2.1"
resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e"
integrity sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==
@ -21671,6 +21671,14 @@ react-virtualized@^9.22.3:
prop-types "^15.7.2"
react-lifecycles-compat "^3.0.4"
react-window@1.8.7:
version "1.8.7"
resolved "https://registry.yarnpkg.com/react-window/-/react-window-1.8.7.tgz#5e9fd0d23f48f432d7022cdb327219353a15f0d4"
integrity sha512-JHEZbPXBpKMmoNO1bNhoXOOLg/ujhL/BU4IqVU9r8eQPcy5KQnGHIHDRkJ0ns9IM5+Aq5LNwt3j8t3tIrePQzA==
dependencies:
"@babel/runtime" "^7.0.0"
memoize-one ">=3.1.1 <6"
react@^17.0.2:
version "17.0.2"
resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"