diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7cfebdaca1e..2875cb088c7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,7 @@
## [`master`](https://github.com/elastic/eui/tree/master)
-No public interface changes since `40.1.0`.
+- Added `EuiAutoSizer` component for setting dimensions on virtualized lists ([#5278](https://github.com/elastic/eui/pull/5278))
+- Added `testenv` mock for `EuiAutoSizer` ([#5278](https://github.com/elastic/eui/pull/5278))
## [`40.1.0`](https://github.com/elastic/eui/tree/v40.1.0)
diff --git a/scripts/babel/react-docgen-typescript.js b/scripts/babel/react-docgen-typescript.js
index e241e06035e..28998f8f684 100644
--- a/scripts/babel/react-docgen-typescript.js
+++ b/scripts/babel/react-docgen-typescript.js
@@ -63,6 +63,7 @@ module.exports = function ({ types }) {
// external modules whose props must be whitelisted
const whiteListedParent = [
+ 'AutoSizerProps',
'DragDropContextProps',
'DraggableProps',
'DroppableProps',
diff --git a/scripts/jest/setup/mocks.js b/scripts/jest/setup/mocks.js
index 8a19548f404..40ef676c97e 100644
--- a/scripts/jest/setup/mocks.js
+++ b/scripts/jest/setup/mocks.js
@@ -1,3 +1,8 @@
+jest.mock('./../../../src/components/auto_sizer', () => {
+ const { EuiAutoSizer } = require('./../../../src/components/auto_sizer/auto_sizer.testenv');
+ return { EuiAutoSizer };
+});
+
jest.mock('./../../../src/components/icon', () => {
const { EuiIcon } = require('./../../../src/components/icon/icon.testenv');
return { EuiIcon };
diff --git a/src-docs/src/routes.js b/src-docs/src/routes.js
index 8a53aa6ba3f..e536b900e17 100644
--- a/src-docs/src/routes.js
+++ b/src-docs/src/routes.js
@@ -38,6 +38,8 @@ import { AccordionExample } from './views/accordion/accordion_example';
import { AspectRatioExample } from './views/aspect_ratio/aspect_ratio_example';
+import { AutoSizerExample } from './views/auto_sizer/auto_sizer_example';
+
import { AvatarExample } from './views/avatar/avatar_example';
import { BadgeExample } from './views/badge/badge_example';
@@ -491,6 +493,7 @@ const navigation = [
name: 'Utilities',
items: [
AccessibilityExample,
+ AutoSizerExample,
BeaconExample,
ColorExample,
ColorPaletteExample,
diff --git a/src-docs/src/views/auto_sizer/auto_sizer.tsx b/src-docs/src/views/auto_sizer/auto_sizer.tsx
new file mode 100644
index 00000000000..87c053cfc13
--- /dev/null
+++ b/src-docs/src/views/auto_sizer/auto_sizer.tsx
@@ -0,0 +1,30 @@
+import React from 'react';
+import { css } from '@emotion/react';
+
+import { EuiAutoSizer, EuiCode, EuiPanel } from '../../../../src/components';
+
+export default () => {
+ const containerStyles = css`
+ height: 200px;
+ width: 100%;
+ `;
+
+ const panelStyles = css`
+ position: absolute;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ `;
+
+ return (
+
+
+ {({ height, width }) => (
+
+ {`height: ${height}, width: ${width}`}
+
+ )}
+
+
+ );
+};
diff --git a/src-docs/src/views/auto_sizer/auto_sizer_example.js b/src-docs/src/views/auto_sizer/auto_sizer_example.js
new file mode 100644
index 00000000000..d5402a70c6e
--- /dev/null
+++ b/src-docs/src/views/auto_sizer/auto_sizer_example.js
@@ -0,0 +1,42 @@
+import React from 'react';
+
+import { GuideSectionTypes } from '../../components';
+import { EuiLink, EuiAutoSizer } from '../../../../src/components';
+
+import AutoSizer from './auto_sizer';
+const autoSizerSource = require('!!raw-loader!./auto_sizer');
+
+const autoSizerSnippet = `
+ {({height, width}) =>
+ ()
+ }
+`;
+
+export const AutoSizerExample = {
+ title: 'Auto sizer',
+ sections: [
+ {
+ source: [
+ {
+ type: GuideSectionTypes.JS,
+ code: autoSizerSource,
+ },
+ ],
+ text: (
+
+ EuiAutoSizer helps components that use virtualized
+ rendering and/or require explicit dimensions to fill all available
+ space in the parent container. See the{' '}
+
+ react-virtualized-auto-sizer
+ {' '}
+ documentation as EuiAutoSizer is a passthrough
+ component for AutoSizer.
+
+ ),
+ props: { EuiAutoSizer },
+ demo: ,
+ snippet: autoSizerSnippet,
+ },
+ ],
+};
diff --git a/src/components/auto_sizer/auto_sizer.testenv.tsx b/src/components/auto_sizer/auto_sizer.testenv.tsx
new file mode 100644
index 00000000000..12d86eaa1f3
--- /dev/null
+++ b/src/components/auto_sizer/auto_sizer.testenv.tsx
@@ -0,0 +1,21 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import React from 'react';
+
+export const EuiAutoSizer = ({
+ children,
+ defaultHeight,
+ defaultWidth,
+}: any) => {
+ const childrenParams = {
+ height: defaultHeight ?? 600,
+ width: defaultWidth ?? 600,
+ };
+ return {children(childrenParams)}
;
+};
diff --git a/src/components/auto_sizer/auto_sizer.tsx b/src/components/auto_sizer/auto_sizer.tsx
new file mode 100644
index 00000000000..b1ce97b3f51
--- /dev/null
+++ b/src/components/auto_sizer/auto_sizer.tsx
@@ -0,0 +1,13 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import AutoSizer, { AutoSizerProps } from 'react-virtualized-auto-sizer';
+
+export interface EuiAutoSizerProps extends AutoSizerProps {}
+
+export class EuiAutoSizer extends AutoSizer {}
diff --git a/src/components/auto_sizer/index.ts b/src/components/auto_sizer/index.ts
new file mode 100644
index 00000000000..60d0bc66cac
--- /dev/null
+++ b/src/components/auto_sizer/index.ts
@@ -0,0 +1,9 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+export { EuiAutoSizer, EuiAutoSizerProps } from './auto_sizer';
diff --git a/src/components/code/__snapshots__/_code_block.test.tsx.snap b/src/components/code/__snapshots__/_code_block.test.tsx.snap
index d81ff99f035..87b636f6e33 100644
--- a/src/components/code/__snapshots__/_code_block.test.tsx.snap
+++ b/src/components/code/__snapshots__/_code_block.test.tsx.snap
@@ -79,8 +79,33 @@ exports[`EuiCodeBlockImpl block renders a virtualized code block 1`] = `
style="max-height:300px"
>
+ data-eui="EuiAutoSizer"
+ >
+
+
+
+ var some = 'code';
+
+
+
+ console.log(some);
+
+
+
+
diff --git a/src/components/code/__snapshots__/code_block.test.tsx.snap b/src/components/code/__snapshots__/code_block.test.tsx.snap
index 2d52ec41355..159dfe7daaf 100644
--- a/src/components/code/__snapshots__/code_block.test.tsx.snap
+++ b/src/components/code/__snapshots__/code_block.test.tsx.snap
@@ -6,8 +6,33 @@ exports[`EuiCodeBlock dynamic content renders a virtualized code block 1`] = `
style="height:50%"
>
+ data-eui="EuiAutoSizer"
+ >
+
+
+
+ var some = 'code';
+
+
+
+ console.log(some);
+
+
+
+
diff --git a/src/components/code/_code_block.tsx b/src/components/code/_code_block.tsx
index f4065d4e73e..672ab627062 100644
--- a/src/components/code/_code_block.tsx
+++ b/src/components/code/_code_block.tsx
@@ -22,8 +22,8 @@ import React, {
import classNames from 'classnames';
import { highlight, RefractorNode, listLanguages } from 'refractor';
import { FixedSizeList, ListChildComponentProps } from 'react-window';
-import AutoSizer from 'react-virtualized-auto-sizer';
import { keys, useCombinedRefs } from '../../services';
+import { EuiAutoSizer } from '../auto_sizer';
import { EuiButtonIcon } from '../button';
import { keysOf, CommonProps, ExclusiveUnion } from '../common';
import { EuiCopy } from '../copy';
@@ -394,7 +394,7 @@ export const EuiCodeBlockImpl: FunctionComponent
= ({
{isVirtualized ? (
-
+
{({ height, width }) => (
= ({
{ListRow}
)}
-
+
) : (
@@ -436,7 +436,7 @@ export const EuiCodeBlockImpl: FunctionComponent = ({
return (
{isVirtualized ? (
-
+
{({ height, width }) => (
= ({
{ListRow}
)}
-
+
) : (
+ data-eui="EuiAutoSizer"
+ >
+
+
+ -
+
+
+
+
+ Titan
+
+
+
+
+ -
+
+
+
+
+ Enceladus
+
+
+
+
+ -
+
+
+
+
+ Mimas
+
+
+
+
+ -
+
+
+
+
+ Pandora is one of Saturn's moons, named for a Titaness of Greek mythology
+
+
+
+
+ -
+
+
+
+
+ Tethys
+
+
+
+
+ -
+
+
+
+
+ Hyperion
+
+
+
+
+
+
+
`;
@@ -17,8 +184,194 @@ exports[`EuiSelectableListItem props activeOptionIndex 1`] = `
data-test-subj="test subject string"
>
+ data-eui="EuiAutoSizer"
+ >
+
+
+ -
+
+
+
+
+ Titan
+
+
+
+
+ -
+
+
+
+
+ Enceladus
+
+
+
+
+ -
+
+
+
+
+ Mimas
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+ Pandora is one of Saturn's moons, named for a Titaness of Greek mythology
+
+
+
+
+ -
+
+
+
+
+ Tethys
+
+
+
+
+ -
+
+
+
+
+ Hyperion
+
+
+
+
+
+
+
`;
@@ -28,8 +381,175 @@ exports[`EuiSelectableListItem props allowExclusions 1`] = `
data-test-subj="test subject string"
>
+ data-eui="EuiAutoSizer"
+ >
+
+
+ -
+
+
+
+
+ Titan
+
+
+
+
+ -
+
+
+
+
+ Enceladus
+
+
+
+
+ -
+
+
+
+
+ Mimas
+
+
+
+
+ -
+
+
+
+
+ Pandora is one of Saturn's moons, named for a Titaness of Greek mythology
+
+
+
+
+ -
+
+
+
+
+ Tethys
+
+
+
+
+ -
+
+
+
+
+ Hyperion
+
+
+
+
+
+
+
`;
@@ -39,8 +559,175 @@ exports[`EuiSelectableListItem props bordered 1`] = `
data-test-subj="test subject string"
>
+ data-eui="EuiAutoSizer"
+ >
+
+
+ -
+
+
+
+
+ Titan
+
+
+
+
+ -
+
+
+
+
+ Enceladus
+
+
+
+
+ -
+
+
+
+
+ Mimas
+
+
+
+
+ -
+
+
+
+
+ Pandora is one of Saturn's moons, named for a Titaness of Greek mythology
+
+
+
+
+ -
+
+
+
+
+ Tethys
+
+
+
+
+ -
+
+
+
+
+ Hyperion
+
+
+
+
+
+
+
`;
@@ -50,8 +737,175 @@ exports[`EuiSelectableListItem props height is forced 1`] = `
data-test-subj="test subject string"
>
+ data-eui="EuiAutoSizer"
+ >
+
+
+ -
+
+
+
+
+ Titan
+
+
+
+
+ -
+
+
+
+
+ Enceladus
+
+
+
+
+ -
+
+
+
+
+ Mimas
+
+
+
+
+ -
+
+
+
+
+ Pandora is one of Saturn's moons, named for a Titaness of Greek mythology
+
+
+
+
+ -
+
+
+
+
+ Tethys
+
+
+
+
+ -
+
+
+
+
+ Hyperion
+
+
+
+
+
+
+
`;
@@ -61,8 +915,175 @@ exports[`EuiSelectableListItem props height is full 1`] = `
data-test-subj="test subject string"
>
+ data-eui="EuiAutoSizer"
+ >
+
+
+ -
+
+
+
+
+ Titan
+
+
+
+
+ -
+
+
+
+
+ Enceladus
+
+
+
+
+ -
+
+
+
+
+ Mimas
+
+
+
+
+ -
+
+
+
+
+ Pandora is one of Saturn's moons, named for a Titaness of Greek mythology
+
+
+
+
+ -
+
+
+
+
+ Tethys
+
+
+
+
+ -
+
+
+
+
+ Hyperion
+
+
+
+
+
+
+
`;
@@ -72,8 +1093,175 @@ exports[`EuiSelectableListItem props renderOption 1`] = `
data-test-subj="test subject string"
>
+ data-eui="EuiAutoSizer"
+ >
+
+
+ -
+
+
+
+
+ => Titan
+
+
+
+
+ -
+
+
+
+
+ => Enceladus
+
+
+
+
+ -
+
+
+
+
+ => Mimas
+
+
+
+
+ -
+
+
+
+
+ => Pandora is one of Saturn's moons, named for a Titaness of Greek mythology
+
+
+
+
+ -
+
+
+
+
+ => Tethys
+
+
+
+
+ -
+
+
+
+
+ => Hyperion
+
+
+
+
+
+
+
`;
@@ -83,8 +1271,175 @@ exports[`EuiSelectableListItem props rowHeight 1`] = `
data-test-subj="test subject string"
>
+ data-eui="EuiAutoSizer"
+ >
+
+
+ -
+
+
+
+
+ Titan
+
+
+
+
+ -
+
+
+
+
+ Enceladus
+
+
+
+
+ -
+
+
+
+
+ Mimas
+
+
+
+
+ -
+
+
+
+
+ Pandora is one of Saturn's moons, named for a Titaness of Greek mythology
+
+
+
+
+ -
+
+
+
+
+ Tethys
+
+
+
+
+ -
+
+
+
+
+ Hyperion
+
+
+
+
+
+
+
`;
@@ -94,8 +1449,180 @@ exports[`EuiSelectableListItem props searchValue 1`] = `
data-test-subj="test subject string"
>
+ data-eui="EuiAutoSizer"
+ >
+
+
+ -
+
+
+
+
+ Titan
+
+
+
+
+ -
+
+
+
+
+ Enceladus
+
+
+
+
+ -
+
+
+
+
+
+ Mi
+
+ mas
+
+
+
+
+ -
+
+
+
+
+ Pandora is one of Saturn's moons, named for a Titaness of Greek mythology
+
+
+
+
+ -
+
+
+
+
+ Tethys
+
+
+
+
+ -
+
+
+
+
+ Hyperion
+
+
+
+
+
+
+
`;
@@ -105,8 +1632,180 @@ exports[`EuiSelectableListItem props searchValue 2`] = `
data-test-subj="test subject string"
>
+ data-eui="EuiAutoSizer"
+ >
+
+
+ -
+
+
+
+
+ Titan
+
+
+
+
+ -
+
+
+
+
+ Enceladus
+
+
+
+
+ -
+
+
+
+
+
+ Mi
+
+ mas
+
+
+
+
+ -
+
+
+
+
+ Pandora is one of Saturn's moons, named for a Titaness of Greek mythology
+
+
+
+
+ -
+
+
+
+
+ Tethys
+
+
+
+
+ -
+
+
+
+
+ Hyperion
+
+
+
+
+
+
+
`;
@@ -116,8 +1815,151 @@ exports[`EuiSelectableListItem props showIcons can be turned off 1`] = `
data-test-subj="test subject string"
>
+ data-eui="EuiAutoSizer"
+ >
+
+
+ -
+
+
+
+ Titan
+
+
+
+
+ -
+
+
+
+ Enceladus
+
+
+
+
+ -
+
+
+
+ Mimas
+
+
+
+
+ -
+
+
+
+ Pandora is one of Saturn's moons, named for a Titaness of Greek mythology
+
+
+
+
+ -
+
+
+
+ Tethys
+
+
+
+
+ -
+
+
+
+ Hyperion
+
+
+
+
+
+
+
`;
@@ -127,8 +1969,175 @@ exports[`EuiSelectableListItem props singleSelection can be forced so that at le
data-test-subj="test subject string"
>
+ data-eui="EuiAutoSizer"
+ >
+
+
+ -
+
+
+
+
+ Titan
+
+
+
+
+ -
+
+
+
+
+ Enceladus
+
+
+
+
+ -
+
+
+
+
+ Mimas
+
+
+
+
+ -
+
+
+
+
+ Pandora is one of Saturn's moons, named for a Titaness of Greek mythology
+
+
+
+
+ -
+
+
+
+
+ Tethys
+
+
+
+
+ -
+
+
+
+
+ Hyperion
+
+
+
+
+
+
+
`;
@@ -138,8 +2147,175 @@ exports[`EuiSelectableListItem props singleSelection can be turned on 1`] = `
data-test-subj="test subject string"
>
+ data-eui="EuiAutoSizer"
+ >
+
+
+ -
+
+
+
+
+ Titan
+
+
+
+
+ -
+
+
+
+
+ Enceladus
+
+
+
+
+ -
+
+
+
+
+ Mimas
+
+
+
+
+ -
+
+
+
+
+ Pandora is one of Saturn's moons, named for a Titaness of Greek mythology
+
+
+
+
+ -
+
+
+
+
+ Tethys
+
+
+
+
+ -
+
+
+
+
+ Hyperion
+
+
+
+
+
+
+
`;
@@ -149,7 +2325,121 @@ exports[`EuiSelectableListItem props visibleOptions 1`] = `
data-test-subj="test subject string"
>
+ data-eui="EuiAutoSizer"
+ >
+
+
+ -
+
+
+
+
+ Mimas
+
+
+
+
+ -
+
+
+
+
+ Pandora is one of Saturn's moons, named for a Titaness of Greek mythology
+
+
+
+
+ -
+
+
+
+
+ Tethys
+
+
+
+
+ -
+
+
+
+
+ Hyperion
+
+
+
+
+
+
+
`;
diff --git a/src/components/selectable/selectable_list/selectable_list.tsx b/src/components/selectable/selectable_list/selectable_list.tsx
index 6c6d41276d1..a4cd93b029c 100644
--- a/src/components/selectable/selectable_list/selectable_list.tsx
+++ b/src/components/selectable/selectable_list/selectable_list.tsx
@@ -8,20 +8,20 @@
import React, { Component, HTMLAttributes, ReactNode, memo } from 'react';
import classNames from 'classnames';
-import { CommonProps } from '../../common';
-import {
- EuiSelectableListItem,
- EuiSelectableListItemProps,
-} from './selectable_list_item';
-import { EuiHighlight } from '../../highlight';
-import { EuiSelectableOption } from '../selectable_option';
-import AutoSizer from 'react-virtualized-auto-sizer';
import {
FixedSizeList,
ListProps,
ListChildComponentProps as ReactWindowListChildComponentProps,
areEqual,
} from 'react-window';
+import { CommonProps } from '../../common';
+import { EuiAutoSizer } from '../../auto_sizer';
+import { EuiHighlight } from '../../highlight';
+import { EuiSelectableOption } from '../selectable_option';
+import {
+ EuiSelectableListItem,
+ EuiSelectableListItemProps,
+} from './selectable_list_item';
interface ListChildComponentProps
extends ReactWindowListChildComponentProps {
@@ -310,7 +310,7 @@ export class EuiSelectableList extends Component> {
return (
-
+
{({ width, height }) => (
extends Component> {
{this.ListRow}
)}
-
+
);
}