Skip to content

Commit aeb74d6

Browse files
committed
Merge branch 'main' into datagrid/perf
2 parents 30efd08 + 0396b26 commit aeb74d6

44 files changed

Lines changed: 768 additions & 193 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

changelogs/upcoming/7374.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
- Added new `EuiDataGrid` new prop: `cellContext`, an optional object of additional props passed to the cell render function.

changelogs/upcoming/7555.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
- `EuiBreadcrumbs`'s `popoverContent` API now accepts a render function that will be passed a `closePopover` callback, allowing consumers to close the breadcrumb popover from their popover content

src-docs/src/views/breadcrumbs/breadcrumbs_example.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,14 @@ export const BreadcrumbsExample = {
294294
accepted as they are controlled automatically by{' '}
295295
<strong>EuiBreadcrumbs</strong>.
296296
</p>
297+
<p>
298+
If you need the ability to close the breadcrumb popover from within
299+
your popover content, <EuiCode>popoverContent</EuiCode> accepts a
300+
render function that will be passed a{' '}
301+
<EuiCode>closePopover</EuiCode> callback, which you can invoke to
302+
close the popover. See the Deployment breadcrumb below for example
303+
usage.
304+
</p>
297305
<EuiCallOut
298306
color="warning"
299307
iconType="accessibility"

src-docs/src/views/breadcrumbs/popover_content.tsx

Lines changed: 28 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -41,37 +41,34 @@ export default () => {
4141
const breadcrumbs: EuiBreadcrumb[] = [
4242
{
4343
text: 'My deployment',
44-
popoverContent: (
45-
<>
46-
<EuiPopoverTitle paddingSize="s">Select a deployment</EuiPopoverTitle>
47-
<EuiContextMenuPanel
48-
size="s"
49-
items={[
50-
<EuiContextMenuItem
51-
key="A"
52-
href="#"
53-
onClick={(e) => e.preventDefault()}
54-
>
55-
Go to Deployment A
56-
</EuiContextMenuItem>,
57-
<EuiContextMenuItem
58-
key="B"
59-
href="#"
60-
onClick={(e) => e.preventDefault()}
61-
>
62-
Go to Deployment B
63-
</EuiContextMenuItem>,
64-
<EuiContextMenuItem
65-
key="C"
66-
href="#"
67-
onClick={(e) => e.preventDefault()}
68-
>
69-
Go to all deployments
70-
</EuiContextMenuItem>,
71-
]}
72-
/>
73-
</>
74-
),
44+
// Passing a render function allows closing the breadcrumb popover from within your content
45+
popoverContent: (closePopover) => {
46+
const onClick = (e: React.MouseEvent) => {
47+
e.preventDefault();
48+
closePopover();
49+
};
50+
return (
51+
<>
52+
<EuiPopoverTitle paddingSize="s">
53+
Select a deployment
54+
</EuiPopoverTitle>
55+
<EuiContextMenuPanel
56+
size="s"
57+
items={[
58+
<EuiContextMenuItem key="A" href="#" onClick={onClick}>
59+
Go to Deployment A
60+
</EuiContextMenuItem>,
61+
<EuiContextMenuItem key="B" href="#" onClick={onClick}>
62+
Go to Deployment B
63+
</EuiContextMenuItem>,
64+
<EuiContextMenuItem key="C" href="#" onClick={onClick}>
65+
Go to all deployments
66+
</EuiContextMenuItem>,
67+
]}
68+
/>
69+
</>
70+
);
71+
},
7572
popoverProps: { panelPaddingSize: 'none' },
7673
},
7774
{

src-docs/src/views/datagrid/_props_table.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,19 @@ export const DataGridPropsTable: FunctionComponent<{
2929
.filter((i) => !exclude?.includes(i))
3030
.sort();
3131

32+
// Manually move the cellContext prop after renderCellValue
33+
const cellContext = gridPropsKeys.splice(
34+
gridPropsKeys.findIndex((prop) => prop === 'cellContext'),
35+
1
36+
)[0];
37+
if (cellContext) {
38+
gridPropsKeys.splice(
39+
gridPropsKeys.findIndex((prop) => prop === 'renderCellValue') + 1,
40+
0,
41+
cellContext
42+
);
43+
}
44+
3245
const items: BasicItem[] = gridPropsKeys.map((prop) => {
3346
return {
3447
id: prop,

src-docs/src/views/datagrid/_snippets.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@ inMemory={{ level: 'sorting' }}`,
5353
},
5454
]}`,
5555
renderCellValue: 'renderCellValue={({ rowIndex, columnId }) => {}}',
56+
cellContext: `cellContext={{
57+
// Will be passed to your \`renderCellValue\` function/component as a prop
58+
yourData,
59+
}}
60+
renderCellValue={({ rowIndex, columnId, yourData }) => {}}`,
5661
renderCellPopover: `renderCellPopover={({ children, cellActions }) => (
5762
<>
5863
<EuiPopoverTitle>I'm a custom popover!</EuiPopoverTitle>

src-docs/src/views/datagrid/basics/_props.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ const gridLinks = {
2424
ref: '/tabular-content/data-grid-advanced#ref-methods',
2525
renderCustomGridBody:
2626
'/tabular-content/data-grid-advanced#custom-body-renderer',
27+
cellContext: '/tabular-content/data-grid-cells-popovers#cell-context',
2728
};
2829

2930
export const DataGridTopProps = () => {
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import React, { useState, useEffect, useCallback, ReactNode } from 'react';
2+
import { faker } from '@faker-js/faker';
3+
4+
import {
5+
EuiDataGrid,
6+
EuiDataGridColumn,
7+
type RenderCellValue,
8+
EuiButton,
9+
EuiSpacer,
10+
EuiSkeletonText,
11+
} from '../../../../../src';
12+
13+
type DataType = Array<{ [key: string]: ReactNode }>;
14+
15+
const columns: EuiDataGridColumn[] = [
16+
{ id: 'firstName' },
17+
{ id: 'lastName' },
18+
{ id: 'suffix' },
19+
{ id: 'boolean' },
20+
];
21+
22+
const CellValue: RenderCellValue = ({
23+
rowIndex,
24+
columnId,
25+
// Props from cellContext
26+
data,
27+
isLoading,
28+
}) => {
29+
if (isLoading) {
30+
return <EuiSkeletonText lines={1} />;
31+
}
32+
33+
const value = data[rowIndex][columnId];
34+
return value;
35+
};
36+
37+
export default () => {
38+
const [visibleColumns, setVisibleColumns] = useState(
39+
columns.map(({ id }) => id)
40+
);
41+
42+
const [data, setData] = useState<DataType>([]);
43+
const [cellContext, setCellContext] = useState({
44+
data,
45+
isLoading: false,
46+
});
47+
48+
// Mock fetching data from an async API
49+
const mockLoading = useCallback(() => {
50+
setCellContext((context) => ({
51+
...context,
52+
isLoading: true,
53+
}));
54+
55+
// End the loading state after 3 seconds
56+
const timeout = setTimeout(() => {
57+
setCellContext((context) => ({
58+
...context,
59+
isLoading: false,
60+
}));
61+
}, 3000);
62+
return () => clearTimeout(timeout);
63+
}, []);
64+
65+
const fetchData = useCallback(() => {
66+
mockLoading();
67+
68+
const data: DataType = [];
69+
for (let i = 1; i < 5; i++) {
70+
data.push({
71+
firstName: faker.person.firstName(),
72+
lastName: faker.person.lastName(),
73+
suffix: faker.person.suffix(),
74+
boolean: `${faker.datatype.boolean()}`,
75+
});
76+
}
77+
setData(data);
78+
setCellContext((context) => ({ ...context, data }));
79+
}, [mockLoading]);
80+
81+
// Fetch data on page load
82+
useEffect(() => {
83+
fetchData();
84+
}, [fetchData]);
85+
86+
return (
87+
<>
88+
<EuiButton size="s" onClick={fetchData}>
89+
Fetch grid data
90+
</EuiButton>
91+
<EuiSpacer size="s" />
92+
<EuiDataGrid
93+
aria-label="Data grid example of cellContext"
94+
columns={columns}
95+
columnVisibility={{ visibleColumns, setVisibleColumns }}
96+
rowCount={data.length}
97+
renderCellValue={CellValue}
98+
cellContext={cellContext}
99+
/>
100+
</>
101+
);
102+
};

src-docs/src/views/datagrid/cells_popovers/datagrid_cells_example.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ import { DataGridCellPopoverExample } from './datagrid_cell_popover_example';
2121
import DataGridFocus from './focus';
2222
const dataGridFocusSource = require('!!raw-loader!./focus');
2323

24+
import CellContext from './cell_context';
25+
const cellContextSource = require('!!raw-loader!./cell_context');
26+
2427
import {
2528
EuiDataGridColumn,
2629
EuiDataGridColumnCellAction,
@@ -218,5 +221,32 @@ export const DataGridCellsExample = {
218221
),
219222
demo: <DataGridFocus />,
220223
},
224+
{
225+
title: 'Cell context',
226+
source: [
227+
{
228+
type: GuideSectionTypes.TSX,
229+
code: cellContextSource,
230+
},
231+
],
232+
text: (
233+
<>
234+
<p>
235+
The <EuiCode>cellContext</EuiCode> prop is an easy way of passing
236+
your custom data or context from the top level of{' '}
237+
<strong>EuiDataGrid</strong> down to the cell content rendered by
238+
your <EuiCode>renderCellValue</EuiCode> function component.
239+
</p>
240+
<p>
241+
The primary use of the cell context API is performance: if your data
242+
relies on state from your app, it allows you to more easily define
243+
your <EuiCode>renderCellValue</EuiCode> function statically, instead
244+
of within your app, which in turn reduces the number of rerenders
245+
within your data grid.
246+
</p>
247+
</>
248+
),
249+
demo: <CellContext />,
250+
},
221251
],
222252
};

src-docs/src/views/theme/typography/_text_numbers.tsx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@ import {
77
EuiTextAlign,
88
EuiFlexGrid,
99
EuiFlexItem,
10-
useEuiNumberFormat,
10+
useEuiTheme,
11+
euiNumberFormat,
1112
} from '../../../../../src';
1213
import { css } from '@emotion/react';
1314
import { ThemeExample } from '../_components/_theme_example';
1415

1516
export default () => {
17+
const euiTheme = useEuiTheme();
1618
const themeContext = useContext(ThemeContext);
1719
const currentLanguage = themeContext.themeLanguage;
1820
const showSass = currentLanguage.includes('sass');
@@ -22,8 +24,8 @@ export default () => {
2224
{/* Mixin */}
2325
{!showSass ? (
2426
<ThemeExample
25-
title={<code>useEuiNumberFormat()</code>}
26-
type="hook"
27+
title={<code>euiNumberFormat(euiTheme)</code>}
28+
type="function"
2729
description={
2830
<p>
2931
Applies{' '}
@@ -49,7 +51,7 @@ export default () => {
4951
<EuiFlexItem>
5052
<p
5153
css={css`
52-
${useEuiNumberFormat()}
54+
${euiNumberFormat(euiTheme)}
5355
`}
5456
>
5557
<strong>With function</strong>
@@ -62,7 +64,7 @@ export default () => {
6264
</EuiFlexGrid>
6365
</EuiTextAlign>
6466
}
65-
snippet={'${useEuiNumberFormat()}'}
67+
snippet={'${euiNumberFormat(useEuiTheme())}'}
6668
snippetLanguage="emotion"
6769
/>
6870
) : (
@@ -84,7 +86,7 @@ export default () => {
8486
type="className"
8587
description={
8688
<p>
87-
Applies the <EuiCode>useEuiNumberFormat()</EuiCode> styles as an
89+
Applies the <EuiCode>euiNumberFormat()</EuiCode> styles as an
8890
overriding CSS utility class.
8991
</p>
9092
}

0 commit comments

Comments
 (0)