diff --git a/package.json b/package.json index 81cc639509e..c62c47897ed 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,6 @@ "@types/lodash": "^4.14.194", "@types/numeral": "^0.0.28", "@types/react-input-autosize": "^2.2.1", - "@types/react-virtualized-auto-sizer": "^1.0.1", "@types/react-window": "^1.8.5", "@types/refractor": "^3.0.0", "@types/resize-observer-browser": "^0.1.5", @@ -85,7 +84,7 @@ "react-input-autosize": "^3.0.0", "react-is": "^17.0.2", "react-remove-scroll-bar": "^2.3.4", - "react-virtualized-auto-sizer": "^1.0.6", + "react-virtualized-auto-sizer": "^1.0.20", "react-window": "^1.8.9", "refractor": "^3.5.0", "rehype-raw": "^5.0.0", diff --git a/src-docs/src/views/auto_sizer/auto_sizer.tsx b/src-docs/src/views/auto_sizer/auto_sizer.tsx index d0dc6f35cff..3c918ea48d5 100644 --- a/src-docs/src/views/auto_sizer/auto_sizer.tsx +++ b/src-docs/src/views/auto_sizer/auto_sizer.tsx @@ -3,6 +3,7 @@ import { css } from '@emotion/react'; import { EuiAutoSizer, + EuiAutoSize, EuiCode, EuiPanel, logicalSizeCSS, @@ -23,7 +24,7 @@ export default () => { return (
- {({ height, width }) => ( + {({ height, width }: EuiAutoSize) => ( height: {height}, width: {width} diff --git a/src/components/auto_sizer/auto_sizer.tsx b/src/components/auto_sizer/auto_sizer.tsx index b1ce97b3f51..2c1c960a689 100644 --- a/src/components/auto_sizer/auto_sizer.tsx +++ b/src/components/auto_sizer/auto_sizer.tsx @@ -6,8 +6,18 @@ * Side Public License, v 1. */ -import AutoSizer, { AutoSizerProps } from 'react-virtualized-auto-sizer'; +import type { ComponentProps } from 'react'; +import type { + Size, + HorizontalSize, + VerticalSize, +} from 'react-virtualized-auto-sizer'; -export interface EuiAutoSizerProps extends AutoSizerProps {} +export type EuiAutoSizerProps = ComponentProps; +export type EuiAutoSize = Size; +export type EuiAutoSizeHorizontal = HorizontalSize; +export type EuiAutoSizeVertical = VerticalSize; + +import AutoSizer from 'react-virtualized-auto-sizer'; export class EuiAutoSizer extends AutoSizer {} diff --git a/src/components/auto_sizer/index.ts b/src/components/auto_sizer/index.ts index 5bef4e49e35..73892f9c3c1 100644 --- a/src/components/auto_sizer/index.ts +++ b/src/components/auto_sizer/index.ts @@ -6,5 +6,4 @@ * Side Public License, v 1. */ -export type { EuiAutoSizerProps } from './auto_sizer'; -export { EuiAutoSizer } from './auto_sizer'; +export * from './auto_sizer'; diff --git a/src/components/code/code_block_virtualized.tsx b/src/components/code/code_block_virtualized.tsx index 6840f5aa9ab..22fd05b3aa8 100644 --- a/src/components/code/code_block_virtualized.tsx +++ b/src/components/code/code_block_virtualized.tsx @@ -10,7 +10,11 @@ import React, { HTMLAttributes, forwardRef, useMemo } from 'react'; import { FixedSizeList, ListChildComponentProps } from 'react-window'; import { RefractorNode } from 'refractor'; import { logicalStyles } from '../../global_styling'; -import { EuiAutoSizer } from '../auto_sizer'; +import { + EuiAutoSizer, + EuiAutoSize, + EuiAutoSizeHorizontal, +} from '../auto_sizer'; import { nodeToHtml } from './utils'; export const EuiCodeBlockVirtualized = ({ @@ -47,22 +51,34 @@ export const EuiCodeBlockVirtualized = ({ [codeProps] ); - return ( - - {({ height, width }) => ( + const virtualizationProps = { + itemData: data, + itemSize: rowHeight, + itemCount: data.length, + outerElementType: VirtualizedOuterElement, + innerElementType: VirtualizedInnerElement, + }; + + return typeof overflowHeight === 'number' ? ( + + {({ width }: EuiAutoSizeHorizontal) => ( {ListRow} )} + ) : ( + + {({ height, width }: EuiAutoSize) => ( + + {ListRow} + + )} + ); }; diff --git a/src/components/selectable/selectable_list/selectable_list.tsx b/src/components/selectable/selectable_list/selectable_list.tsx index d92c878b508..1f29762d580 100644 --- a/src/components/selectable/selectable_list/selectable_list.tsx +++ b/src/components/selectable/selectable_list/selectable_list.tsx @@ -21,7 +21,11 @@ import { areEqual, } from 'react-window'; import { CommonProps, ExclusiveUnion } from '../../common'; -import { EuiAutoSizer } from '../../auto_sizer'; +import { + EuiAutoSizer, + EuiAutoSize, + EuiAutoSizeHorizontal, +} from '../../auto_sizer'; import { EuiHighlight } from '../../highlight'; import { EuiSelectableOption } from '../selectable_option'; import { EuiSelectableOnChangeEvent } from '../selectable'; @@ -329,6 +333,67 @@ export class EuiSelectableList extends Component> { ); }, areEqual); + renderVirtualizedList = ( + heightIsFull: boolean, + optionArray: EuiSelectableOption[] + ) => { + if (!this.props.isVirtualized) return null; + + const { windowProps, height: forcedHeight, rowHeight } = this.props; + + const virtualizationProps = { + className: 'euiSelectableList__list', + ref: this.setListRef, + outerRef: this.removeScrollableTabStop, + innerRef: this.setListBoxRef, + innerElementType: 'ul', + itemCount: optionArray.length, + itemData: optionArray, + itemSize: rowHeight, + 'data-skip-axe': 'scrollable-region-focusable', + ...windowProps, + }; + + // Calculated height is only used if height is not full + let calculatedHeight = !heightIsFull ? forcedHeight || 0 : 0; + + // If calculatedHeight is still falsy, then calculate it + if (!heightIsFull && !calculatedHeight) { + const maxVisibleOptions = 7; + const numVisibleOptions = optionArray.length; + const numVisibleMoreThanMax = optionArray.length > maxVisibleOptions; + + if (numVisibleMoreThanMax) { + // Show only half of the last one to indicate there's more to scroll to + calculatedHeight = (maxVisibleOptions - 0.5) * rowHeight; + } else { + calculatedHeight = numVisibleOptions * rowHeight; + } + } + + return heightIsFull ? ( + + {({ width, height }: EuiAutoSize) => ( + + {this.ListRow} + + )} + + ) : ( + + {({ width }: EuiAutoSizeHorizontal) => ( + + {this.ListRow} + + )} + + ); + }; + render() { const { className, @@ -361,30 +426,10 @@ export class EuiSelectableList extends Component> { } = this.props; const optionArray = visibleOptions || options; - this.calculateAriaSetAttrs(optionArray); const heightIsFull = forcedHeight === 'full'; - let calculatedHeight = (heightIsFull ? false : forcedHeight) as - | false - | number - | undefined; - - // If calculatedHeight is still undefined, then calculate it - if (calculatedHeight === undefined) { - const maxVisibleOptions = 7; - const numVisibleOptions = optionArray.length; - const numVisibleMoreThanMax = optionArray.length > maxVisibleOptions; - - if (numVisibleMoreThanMax) { - // Show only half of the last one to indicate there's more to scroll to - calculatedHeight = (maxVisibleOptions - 0.5) * rowHeight!; - } else { - calculatedHeight = numVisibleOptions * rowHeight!; - } - } - const classes = classNames( 'euiSelectableList', { @@ -397,26 +442,7 @@ export class EuiSelectableList extends Component> { return (
{isVirtualized ? ( - - {({ width, height }) => ( - - {this.ListRow} - - )} - + this.renderVirtualizedList(heightIsFull, optionArray) ) : (