<NME> VirtualList.js
<BEF> import cn from 'classnames';
import React from 'react';
import Listbox from 'react-widgets/lib/Listbox';
import BaseVirtualList from 'react-list';
import ListOption from 'react-widgets/lib/ListOption';
  useMemo,
  useRef,
  useImperativeHandle,


export const virtualListPropTypes = {
  itemSizeEstimator: React.PropTypes.func,
  itemSizeGetter: React.PropTypes.func,
  pageSize: React.PropTypes.number,
  threshold: React.PropTypes.number,
  type: React.PropTypes.oneOf(['simple', 'variable', 'uniform']),
  useStaticSize: React.PropTypes.bool,
  useTranslate3d: React.PropTypes.bool,
}

class VirtualList extends React.Component {
  pageSize: PropTypes.number,
  static propTypes = {
    ...virtualListPropTypes,

    data: React.PropTypes.array,
    dataState: React.PropTypes.object,
    onSelect: React.PropTypes.func,
    onMove: React.PropTypes.func,

    activeId: React.PropTypes.string,
    optionComponent: CustomPropTypes.elementType,
    renderItem: React.PropTypes.func.isRequired,
    renderGroup: React.PropTypes.func,

    focusedItem: React.PropTypes.any,
    selectedItem: React.PropTypes.any,

    isDisabled: React.PropTypes.func.isRequired,
    textAccessor: React.PropTypes.func.isRequired,

    disabled: CustomPropTypes.disabled.acceptsArray,
    groupBy: CustomPropTypes.accessor,

    messages: React.PropTypes.shape({
      emptyList: CustomPropTypes.message
    })
  }
export function getVirtualListProps({
  type,
  itemSizeGetter,
  itemSizeEstimator,
  pageSize = 20,
  threshold = 300,
  useStaticSize,
  useTranslate3d,
  onRequestItems,
  hasNextPage,
  loadingComponent,
  ...props
}) {
  return {
    props,
    listProps: {
      onRequestItems,
      hasNextPage,
      loadingComponent,
      type,
      itemSizeGetter,
      itemSizeEstimator,
      pageSize,
      threshold,
      useStaticSize,
      useTranslate3d,
    },
  }
}

const VirtualList = React.forwardRef(
  (
    {
      data,
      activeId,
      focusedItem,
      selectedItem,
      onSelect,
      renderItem,
      textField,
      dataKey,

      disabled,
      pageSize,
      onRequestItems,
      searchTerm,
      renderGroup,
      className,
      messages,
      itemSizeGetter,
      itemSizeEstimator,
      threshold,
      useStaticSize,
      useTranslate3d = true,
      itemHeight,
      groupBy,
      type = 'variable',
      hasNextPage = false,
      loadingComponent: LoadingComponent,
      optionComponent: OptionComponent = ListOption,
    },
    ref,
  ) => {
    const innerRef = useRef()
    const accessors = useAccessors(textField, dataKey)
    const listCtx = useContext(OptionsContext)
    const flatData = useFlattenedData(data, groupBy)
    const disabledItems = toItemArray(disabled)

    function renderListbox(items, ref) {
      return (
        <div
          ref={ref}
          className={cn(className, 'rw-virtual-list')}
          emptyListMessage={messages.emptyList({})}
        >
          {items}
        </div>
      )
    }

    function renderOption(index, key) {
      let item = flatData[index]
      let len = flatData.length

      if (hasNextPage === true && index >= len) {
        if (onRequestItems)
          onRequestItems({
            pageSize,
            searchTerm,
            limit: len + pageSize,
            currentIndex: index,
          })

        return (
          <li key={key} className="rw-list-empty rw-list-option-loading">
            {LoadingComponent ? (
              <LoadingComponent key={key} index={index} pageSize={pageSize} />
            ) : (
              'Loading items…'
            )}
          </li>
        )
      }

      if (item && item.__isGroup) {
        return (
          <ListOptionGroup key={key}>
            {renderGroup({ group: item.group, searchTerm })}
          </ListOptionGroup>
        )
      }

      return (
        <OptionComponent
          key={key}
          activeId={activeId}
          dataItem={item}
          // disabled={isDisabled(item)}
          selected={selectedItem === item}
          onSelect={onSelect}
        >
          {renderItem
            ? renderItem({ item, index, searchTerm })
            : accessors.text(item)}
        </OptionComponent>
      )
    }

    let length = flatData.length

    if (hasNextPage === true) length += 1

    const scrollIntoView = useEventCallback(() => {
      if (!innerRef.current) return

      let idx = flatData.indexOf(listCtx?.focusedItem)

      if (idx !== -1) {
        innerRef.current.scrollAround(idx)
      }
    })

    useEffect(() => {
      scrollIntoView()
    }, [listCtx.focusedItem])

    useImperativeHandle(
      ref,
      () => ({
        scrollIntoView,
      }),
      [scrollIntoView],
    )

    return (
      <div
        className={cn(
          'rw-virtual-list-wrapper',
          type === 'uniform' && 'rw-virtual-list-fixed',
        )}
      >
        <BaseVirtualList
          ref={innerRef}
          type={type}
          length={length}
          pageSize={pageSize}
          threshold={threshold}
          useStaticSize={useStaticSize}
          useTranslate3d={useTranslate3d}
          itemRenderer={renderOption}
          itemsRenderer={renderListbox}
          itemSizeGetter={itemSizeGetter}
          itemSizeEstimator={itemSizeEstimator}
          // these are all to break the list's SCU
          focusedItem={focusedItem}
          selectedItem={selectedItem}
          searchTerm={searchTerm}
          onSelect={onSelect}
          disabled={disabled}
          itemHeight={itemHeight}
        />
      </div>
    )
  },
)

export default VirtualList

<MSG> fix deprecations

<DFF> @@ -1,5 +1,6 @@
 import cn from 'classnames';
 import React from 'react';
+import PropTypes from 'prop-types';
 import Listbox from 'react-widgets/lib/Listbox';
 import BaseVirtualList from 'react-list';
 import ListOption from 'react-widgets/lib/ListOption';
@@ -9,13 +10,13 @@ import * as CustomPropTypes from 'react-widgets/lib/util/PropTypes';
 
 
 export const virtualListPropTypes = {
-  itemSizeEstimator: React.PropTypes.func,
-  itemSizeGetter: React.PropTypes.func,
-  pageSize: React.PropTypes.number,
-  threshold: React.PropTypes.number,
-  type: React.PropTypes.oneOf(['simple', 'variable', 'uniform']),
-  useStaticSize: React.PropTypes.bool,
-  useTranslate3d: React.PropTypes.bool,
+  itemSizeEstimator: PropTypes.func,
+  itemSizeGetter: PropTypes.func,
+  pageSize: PropTypes.number,
+  threshold: PropTypes.number,
+  type: PropTypes.oneOf(['simple', 'variable', 'uniform']),
+  useStaticSize: PropTypes.bool,
+  useTranslate3d: PropTypes.bool,
 }
 
 class VirtualList extends React.Component {
@@ -23,26 +24,26 @@ class VirtualList extends React.Component {
   static propTypes = {
     ...virtualListPropTypes,
 
-    data: React.PropTypes.array,
-    dataState: React.PropTypes.object,
-    onSelect: React.PropTypes.func,
-    onMove: React.PropTypes.func,
+    data: PropTypes.array,
+    dataState: PropTypes.object,
+    onSelect: PropTypes.func,
+    onMove: PropTypes.func,
 
-    activeId: React.PropTypes.string,
+    activeId: PropTypes.string,
     optionComponent: CustomPropTypes.elementType,
-    renderItem: React.PropTypes.func.isRequired,
-    renderGroup: React.PropTypes.func,
+    renderItem: PropTypes.func.isRequired,
+    renderGroup: PropTypes.func,
 
-    focusedItem: React.PropTypes.any,
-    selectedItem: React.PropTypes.any,
+    focusedItem: PropTypes.any,
+    selectedItem: PropTypes.any,
 
-    isDisabled: React.PropTypes.func.isRequired,
-    textAccessor: React.PropTypes.func.isRequired,
+    isDisabled: PropTypes.func.isRequired,
+    textAccessor: PropTypes.func.isRequired,
 
     disabled: CustomPropTypes.disabled.acceptsArray,
     groupBy: CustomPropTypes.accessor,
 
-    messages: React.PropTypes.shape({
+    messages: PropTypes.shape({
       emptyList: CustomPropTypes.message
     })
   }

fix deprecations