From 05c400c391a252c7dc93f251eb79bbd62c922693 Mon Sep 17 00:00:00 2001 From: Gustav Hansen Date: Thu, 28 Jul 2022 15:20:33 +0200 Subject: [PATCH] ComponentIconPicker: Replace react-virtualized with react-window --- packages/core/admin/package.json | 2 +- packages/core/admin/webpack.alias.js | 2 +- .../components/ComponentIconPicker/index.js | 96 ++++++++----------- .../utils/getIndexFromColAndRow.js | 3 + .../utils/tests/getIndexFromColAndRow.test.js | 21 ++++ yarn.lock | 10 +- 6 files changed, 74 insertions(+), 60 deletions(-) create mode 100644 packages/core/content-type-builder/admin/src/components/ComponentIconPicker/utils/getIndexFromColAndRow.js create mode 100644 packages/core/content-type-builder/admin/src/components/ComponentIconPicker/utils/tests/getIndexFromColAndRow.test.js diff --git a/packages/core/admin/package.json b/packages/core/admin/package.json index 5557fc1868..c6ce0c42da 100644 --- a/packages/core/admin/package.json +++ b/packages/core/admin/package.json @@ -120,7 +120,7 @@ "react-router": "5.2.0", "react-router-dom": "5.2.0", "react-select": "^4.0.2", - "react-virtualized": "^9.22.3", + "react-window": "1.8.7", "redux": "^4.0.1", "redux-saga": "^0.16.0", "reselect": "^4.0.0", diff --git a/packages/core/admin/webpack.alias.js b/packages/core/admin/webpack.alias.js index 827483b2b5..737a914286 100644 --- a/packages/core/admin/webpack.alias.js +++ b/packages/core/admin/webpack.alias.js @@ -28,7 +28,7 @@ const aliasExactMatch = [ 'react-redux', 'react-router', 'react-router-dom', - 'react-virtualized', + 'react-window', 'react-select', 'redux', 'reselect', diff --git a/packages/core/content-type-builder/admin/src/components/ComponentIconPicker/index.js b/packages/core/content-type-builder/admin/src/components/ComponentIconPicker/index.js index ea0f0177b9..c4a0b925d3 100644 --- a/packages/core/content-type-builder/admin/src/components/ComponentIconPicker/index.js +++ b/packages/core/content-type-builder/admin/src/components/ComponentIconPicker/index.js @@ -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 ( +
+ {icon && ( + { + onChange({ target: { name, value: icon } }); + }} + isSelected={icon === value} + as="button" + type="button" + > + + + )} +
+ ); }; - const cellCount = icons.length; + const errorMessage = error ? formatMessage({ id: error, defaultMessage: error }) : ''; return ( @@ -105,44 +114,17 @@ const ComponentIconPicker = ({ error, intlLabel, name, onChange, value }) => { )} - - - - {({ width }) => { - return ( - { - const icon = icons[index]; - const isSelected = icon === value; - const handleClick = () => { - onChange({ target: { name, value: icon } }); - }; - - return ( -
- - - -
- ); - }} - cellSizeAndPositionGetter={cellSizeAndPositionGetter} - height={132} - width={width} - /> - ); - }} -
-
+ + + {IconRenderer} + {error && ( { + return columnIndex + rowIndex * numCols; +}; diff --git a/packages/core/content-type-builder/admin/src/components/ComponentIconPicker/utils/tests/getIndexFromColAndRow.test.js b/packages/core/content-type-builder/admin/src/components/ComponentIconPicker/utils/tests/getIndexFromColAndRow.test.js new file mode 100644 index 0000000000..cfee581b19 --- /dev/null +++ b/packages/core/content-type-builder/admin/src/components/ComponentIconPicker/utils/tests/getIndexFromColAndRow.test.js @@ -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); + }); + }); +}); diff --git a/yarn.lock b/yarn.lock index 1eb791746e..6681188cd0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -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"