Skip to content

Commit

Permalink
Showing 14 changed files with 267 additions and 113 deletions.
3 changes: 3 additions & 0 deletions changelogs/upcoming/7529.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
**CSS-in-JS conversions**

- Added a new memoization/performance optimization utility for CSS-in-JS styles
5 changes: 2 additions & 3 deletions src/components/beacon/beacon.tsx
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@ import { CommonProps } from '../common';
import classNames from 'classnames';

import { logicalStyles } from '../../global_styling';
import { useEuiTheme } from '../../services';
import { useEuiMemoizedStyles } from '../../services';

import { euiBeaconStyles } from './beacon.styles';

@@ -48,9 +48,8 @@ export const EuiBeacon: FunctionComponent<EuiBeaconProps> = ({
style,
...rest
}) => {
const euiTheme = useEuiTheme();
const styles = useEuiMemoizedStyles(euiBeaconStyles);
const classes = classNames('euiBeacon', className);
const styles = euiBeaconStyles(euiTheme);
const cssStyles = [styles.euiBeacon, styles[color]];

const beaconStyle = useMemo(
14 changes: 6 additions & 8 deletions src/components/code/code.styles.ts
Original file line number Diff line number Diff line change
@@ -9,12 +9,10 @@
import { css } from '@emotion/react';
import { logicalShorthandCSS } from '../../global_styling';
import { UseEuiTheme } from '../../services';
import { UseEuiCodeSyntaxVariables } from './code_syntax.styles';
import { euiCodeSyntaxVariables } from './code_syntax.styles';

export const euiCodeStyles = (
euiThemeContext: UseEuiTheme,
euiCodeSyntaxVariables: UseEuiCodeSyntaxVariables
) => {
export const euiCodeStyles = (euiThemeContext: UseEuiTheme) => {
const codeSyntaxVariables = euiCodeSyntaxVariables(euiThemeContext);
const { euiTheme } = euiThemeContext;

return {
@@ -25,12 +23,12 @@ export const euiCodeStyles = (
font-family: ${euiTheme.font.familyCode};
font-size: 0.9em; /* 1 */
${logicalShorthandCSS('padding', '0.2em 0.5em')} /* 1 */
background: ${euiCodeSyntaxVariables.backgroundColor};
background: ${codeSyntaxVariables.backgroundColor};
border-radius: ${euiTheme.border.radius.small};
font-weight: ${euiTheme.font.weight.bold};
color: ${euiCodeSyntaxVariables.inlineCodeColor};
color: ${codeSyntaxVariables.inlineCodeColor};
${euiCodeSyntaxVariables.tokensCss}
${codeSyntaxVariables.tokensCss}
`,
transparentBackground: css`
background: transparent;
5 changes: 2 additions & 3 deletions src/components/code/code.tsx
Original file line number Diff line number Diff line change
@@ -15,8 +15,7 @@ import {
checkSupportedLanguage,
getHtmlContent,
} from './utils';
import { useEuiTheme } from '../../services';
import { useEuiCodeSyntaxVariables } from './code_syntax.styles';
import { useEuiMemoizedStyles } from '../../services';
import { euiCodeStyles } from './code.styles';

export type EuiCodeProps = EuiCodeSharedProps;
@@ -47,7 +46,7 @@ export const EuiCode: FunctionComponent<EuiCodeProps> = ({

const classes = classNames('euiCode', className);

const styles = euiCodeStyles(useEuiTheme(), useEuiCodeSyntaxVariables());
const styles = useEuiMemoizedStyles(euiCodeStyles);
const cssStyles = [
styles.euiCode,
transparentBackground && styles.transparentBackground,
19 changes: 7 additions & 12 deletions src/components/code/code_block.styles.ts
Original file line number Diff line number Diff line change
@@ -22,22 +22,20 @@ import {
} from '../../global_styling';
import { UseEuiTheme } from '../../services';

import { UseEuiCodeSyntaxVariables } from './code_syntax.styles';
import { euiCodeSyntaxVariables } from './code_syntax.styles';

export const euiCodeBlockStyles = (
euiThemeContext: UseEuiTheme,
euiCodeSyntaxVariables: UseEuiCodeSyntaxVariables
) => {
export const euiCodeBlockStyles = (euiThemeContext: UseEuiTheme) => {
const codeSyntaxVariables = euiCodeSyntaxVariables(euiThemeContext);
const { euiTheme } = euiThemeContext;

return {
euiCodeBlock: css`
max-inline-size: 100%;
display: block;
position: relative;
background: ${euiCodeSyntaxVariables.backgroundColor};
background: ${codeSyntaxVariables.backgroundColor};
${euiCodeSyntaxVariables.tokensCss}
${codeSyntaxVariables.tokensCss}
`,
// Font size
s: css`
@@ -134,17 +132,14 @@ export const euiCodeBlockPreStyles = (euiThemeContext: UseEuiTheme) => {
};
};

export const euiCodeBlockCodeStyles = (
euiThemeContext: UseEuiTheme,
euiCodeSyntaxVariables: UseEuiCodeSyntaxVariables
) => {
export const euiCodeBlockCodeStyles = (euiThemeContext: UseEuiTheme) => {
const { euiTheme } = euiThemeContext;

return {
euiCodeBlock__code: css`
font-family: ${euiTheme.font.familyCode};
font-size: inherit;
color: ${euiCodeSyntaxVariables.color};
color: ${euiTheme.colors.text};
display: block;
`,
isVirtualized: css`
41 changes: 22 additions & 19 deletions src/components/code/code_block.tsx
Original file line number Diff line number Diff line change
@@ -9,7 +9,12 @@
import React, { FunctionComponent, useMemo } from 'react';
import { RefractorNode } from 'refractor';
import classNames from 'classnames';
import { useCombinedRefs, useEuiTheme } from '../../services';

import {
useCombinedRefs,
useEuiTheme,
useEuiMemoizedStyles,
} from '../../services';
import { ExclusiveUnion } from '../common';
import {
EuiCodeSharedProps,
@@ -32,7 +37,6 @@ import {
euiCodeBlockPreStyles,
euiCodeBlockCodeStyles,
} from './code_block.styles';
import { useEuiCodeSyntaxVariables } from './code_syntax.styles';

// Based on observed line height for non-virtualized code blocks
const fontSizeToRowHeightMap = {
@@ -123,7 +127,6 @@ export const EuiCodeBlock: FunctionComponent<EuiCodeBlockProps> = ({
...rest
}) => {
const euiTheme = useEuiTheme();
const euiCodeSyntaxVariables = useEuiCodeSyntaxVariables();
const language = useMemo(
() => checkSupportedLanguage(_language),
[_language]
@@ -177,7 +180,7 @@ export const EuiCodeBlock: FunctionComponent<EuiCodeBlockProps> = ({
const hasControls = !!(copyButton || fullScreenButton);
const hasBothControls = !!(copyButton && fullScreenButton);

const styles = euiCodeBlockStyles(euiTheme, euiCodeSyntaxVariables);
const styles = useEuiMemoizedStyles(euiCodeBlockStyles);
const cssStyles = [
styles.euiCodeBlock,
styles[fontSize],
@@ -188,26 +191,26 @@ export const EuiCodeBlock: FunctionComponent<EuiCodeBlockProps> = ({
: styles.hasControls[paddingSize]),
];

const preStyles = useEuiMemoizedStyles(euiCodeBlockPreStyles);
const [preProps, preFullscreenProps] = useMemo(() => {
const isWhiteSpacePre = whiteSpace === 'pre' || isVirtualized;

const styles = euiCodeBlockPreStyles(euiTheme);
const cssStyles = [
styles.euiCodeBlock__pre,
preStyles.euiCodeBlock__pre,
isWhiteSpacePre
? styles.whiteSpace.pre.pre
: styles.whiteSpace.preWrap.preWrap,
? preStyles.whiteSpace.pre.pre
: preStyles.whiteSpace.preWrap.preWrap,
];

const preProps = {
className: 'euiCodeBlock__pre',
css: [
...cssStyles,
styles.padding[paddingSize],
preStyles.padding[paddingSize],
hasControls &&
(isWhiteSpacePre
? styles.whiteSpace.pre.controlsOffset[paddingSize]
: styles.whiteSpace.preWrap.controlsOffset[paddingSize]),
? preStyles.whiteSpace.pre.controlsOffset[paddingSize]
: preStyles.whiteSpace.preWrap.controlsOffset[paddingSize]),
],
tabIndex: isVirtualized ? 0 : tabIndex,
};
@@ -216,19 +219,19 @@ export const EuiCodeBlock: FunctionComponent<EuiCodeBlockProps> = ({
css: [
...cssStyles,
// Force fullscreen to use xl padding
styles.padding.xl,
preStyles.padding.xl,
hasControls &&
(isWhiteSpacePre
? styles.whiteSpace.pre.controlsOffset.xl
: styles.whiteSpace.preWrap.controlsOffset.xl),
? preStyles.whiteSpace.pre.controlsOffset.xl
: preStyles.whiteSpace.preWrap.controlsOffset.xl),
],
tabIndex: 0,
onKeyDown,
};

return [preProps, preFullscreenProps];
}, [
euiTheme,
preStyles,
whiteSpace,
isVirtualized,
hasControls,
@@ -237,11 +240,11 @@ export const EuiCodeBlock: FunctionComponent<EuiCodeBlockProps> = ({
tabIndex,
]);

const codeStyles = useEuiMemoizedStyles(euiCodeBlockCodeStyles);
const codeProps = useMemo(() => {
const styles = euiCodeBlockCodeStyles(euiTheme, euiCodeSyntaxVariables);
const cssStyles = [
styles.euiCodeBlock__code,
isVirtualized && styles.isVirtualized,
codeStyles.euiCodeBlock__code,
isVirtualized && codeStyles.isVirtualized,
];

return {
@@ -250,7 +253,7 @@ export const EuiCodeBlock: FunctionComponent<EuiCodeBlockProps> = ({
'data-code-language': language,
...rest,
};
}, [language, euiTheme, euiCodeSyntaxVariables, isVirtualized, rest]);
}, [codeStyles, language, isVirtualized, rest]);

return (
<div
10 changes: 4 additions & 6 deletions src/components/code/code_block_controls.styles.ts
Original file line number Diff line number Diff line change
@@ -16,21 +16,19 @@
import { css } from '@emotion/react';
import { euiPaddingSize } from '../../global_styling';
import { UseEuiTheme } from '../../services';
import { UseEuiCodeSyntaxVariables } from './code_syntax.styles';
import { euiCodeSyntaxVariables } from './code_syntax.styles';

export const euiCodeBlockControlsStyles = (
euiThemeContext: UseEuiTheme,
euiCodeSyntaxVariables: UseEuiCodeSyntaxVariables
) => {
export const euiCodeBlockControlsStyles = (euiThemeContext: UseEuiTheme) => {
const { euiTheme } = euiThemeContext;
const codeSyntaxVariables = euiCodeSyntaxVariables(euiThemeContext);

return {
euiCodeBlock__controls: css`
position: absolute;
display: flex;
flex-direction: column;
gap: ${euiTheme.size.xs};
background: ${euiCodeSyntaxVariables.backgroundColor};
background: ${codeSyntaxVariables.backgroundColor};
`,
offset: {
none: css`
8 changes: 2 additions & 6 deletions src/components/code/code_block_controls.tsx
Original file line number Diff line number Diff line change
@@ -7,19 +7,15 @@
*/

import React, { FC, Fragment, ReactNode } from 'react';
import { useEuiTheme } from '../../services';
import { useEuiMemoizedStyles } from '../../services';
import type { EuiCodeBlockPaddingSize } from './code_block';
import { useEuiCodeSyntaxVariables } from './code_syntax.styles';
import { euiCodeBlockControlsStyles } from './code_block_controls.styles';

export const EuiCodeBlockControls: FC<{
controls: ReactNode[];
paddingSize: EuiCodeBlockPaddingSize;
}> = ({ paddingSize, controls }) => {
const styles = euiCodeBlockControlsStyles(
useEuiTheme(),
useEuiCodeSyntaxVariables()
);
const styles = useEuiMemoizedStyles(euiCodeBlockControlsStyles);
const cssStyles = [styles.euiCodeBlock__controls, styles.offset[paddingSize]];

const hasControls = controls.some((control) => !!control);
5 changes: 2 additions & 3 deletions src/components/code/code_block_full_screen.tsx
Original file line number Diff line number Diff line change
@@ -14,12 +14,11 @@ import React, {
useMemo,
PropsWithChildren,
} from 'react';
import { keys, useEuiTheme } from '../../services';
import { keys, useEuiMemoizedStyles } from '../../services';
import { useEuiI18n } from '../i18n';
import { EuiButtonIcon } from '../button';
import { EuiFocusTrap } from '../focus_trap';
import { EuiOverlayMask } from '../overlay_mask';
import { useEuiCodeSyntaxVariables } from './code_syntax.styles';
import { euiCodeBlockStyles } from './code_block.styles';

/**
@@ -92,7 +91,7 @@ export const useFullScreen = ({
export const EuiCodeBlockFullScreenWrapper: FunctionComponent<
PropsWithChildren
> = ({ children }) => {
const styles = euiCodeBlockStyles(useEuiTheme(), useEuiCodeSyntaxVariables());
const styles = useEuiMemoizedStyles(euiCodeBlockStyles);
const cssStyles = [
styles.euiCodeBlock,
styles.l, // Force fullscreen to use large font
90 changes: 40 additions & 50 deletions src/components/code/code_syntax.styles.ts
Original file line number Diff line number Diff line change
@@ -6,56 +6,51 @@
* Side Public License, v 1.
*/

import { useMemo } from 'react';
import {
useEuiTheme,
UseEuiTheme,
makeHighContrastColor,
euiPaletteColorBlind,
} from '../../services';

const visColors = euiPaletteColorBlind();

// These variables are computationally expensive, so it needs
// to be a hook in order to memoize it per theme
export const useEuiCodeSyntaxVariables = () => {
const { euiTheme } = useEuiTheme();

return useMemo(() => {
const backgroundColor = euiTheme.colors.lightestShade;

return {
backgroundColor: backgroundColor,
color: makeHighContrastColor(euiTheme.colors.text)(backgroundColor),
inlineCodeColor: makeHighContrastColor(visColors[3])(backgroundColor),
selectedBackgroundColor: 'inherit',
commentColor: makeHighContrastColor(euiTheme.colors.subduedText)(
backgroundColor
),
selectorTagColor: 'inherit',
stringColor: makeHighContrastColor(visColors[2])(backgroundColor),
tagColor: makeHighContrastColor(visColors[1])(backgroundColor),
nameColor: makeHighContrastColor(visColors[1])(backgroundColor),
numberColor: makeHighContrastColor(visColors[0])(backgroundColor),
keywordColor: makeHighContrastColor(visColors[3])(backgroundColor),
functionTitleColor: 'inherit',
typeColor: makeHighContrastColor(visColors[1])(backgroundColor),
attributeColor: 'inherit',
symbolColor: makeHighContrastColor(visColors[9])(backgroundColor),
paramsColor: 'inherit',
metaColor: makeHighContrastColor(euiTheme.colors.subduedText)(
backgroundColor
),
titleColor: makeHighContrastColor(visColors[7])(backgroundColor),
sectionColor: makeHighContrastColor(visColors[9])(backgroundColor),
additionColor: makeHighContrastColor(visColors[0])(backgroundColor),
deletionColor: makeHighContrastColor(euiTheme.colors.danger)(
backgroundColor
),
selectorClassColor: 'inherit',
selectorIdColor: 'inherit',

get tokensCss() {
return `
// These variables are computationally expensive - do not call them outside `useEuiMemoizedStyles`
export const euiCodeSyntaxVariables = ({ euiTheme }: UseEuiTheme) => {
const backgroundColor = euiTheme.colors.lightestShade;

return {
backgroundColor: backgroundColor,
color: makeHighContrastColor(euiTheme.colors.text)(backgroundColor),
inlineCodeColor: makeHighContrastColor(visColors[3])(backgroundColor),
selectedBackgroundColor: 'inherit',
commentColor: makeHighContrastColor(euiTheme.colors.subduedText)(
backgroundColor
),
selectorTagColor: 'inherit',
stringColor: makeHighContrastColor(visColors[2])(backgroundColor),
tagColor: makeHighContrastColor(visColors[1])(backgroundColor),
nameColor: makeHighContrastColor(visColors[1])(backgroundColor),
numberColor: makeHighContrastColor(visColors[0])(backgroundColor),
keywordColor: makeHighContrastColor(visColors[3])(backgroundColor),
functionTitleColor: 'inherit',
typeColor: makeHighContrastColor(visColors[1])(backgroundColor),
attributeColor: 'inherit',
symbolColor: makeHighContrastColor(visColors[9])(backgroundColor),
paramsColor: 'inherit',
metaColor: makeHighContrastColor(euiTheme.colors.subduedText)(
backgroundColor
),
titleColor: makeHighContrastColor(visColors[7])(backgroundColor),
sectionColor: makeHighContrastColor(visColors[9])(backgroundColor),
additionColor: makeHighContrastColor(visColors[0])(backgroundColor),
deletionColor: makeHighContrastColor(euiTheme.colors.danger)(
backgroundColor
),
selectorClassColor: 'inherit',
selectorIdColor: 'inherit',

get tokensCss() {
return `
.token.punctuation:not(.interpolation-punctuation):not([class*='attr-']) {
opacity: .7;
}
@@ -181,11 +176,6 @@ export const useEuiCodeSyntaxVariables = () => {
.token.entity {
cursor: help;
}`;
},
};
}, [euiTheme]);
},
};
};

export type UseEuiCodeSyntaxVariables = ReturnType<
typeof useEuiCodeSyntaxVariables
>;
1 change: 1 addition & 0 deletions src/services/theme/index.ts
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@ export {
} from './hooks';
export type { EuiThemeProviderProps } from './provider';
export { EuiThemeProvider } from './provider';
export { useEuiMemoizedStyles } from './style_memoization';
export { getEuiDevProviderWarning, setEuiDevProviderWarning } from './warning';
export {
buildTheme,
9 changes: 6 additions & 3 deletions src/services/theme/provider.tsx
Original file line number Diff line number Diff line change
@@ -31,6 +31,7 @@ import {
EuiColorModeContext,
} from './context';
import { EuiEmotionThemeProvider } from './emotion';
import { EuiThemeMemoizedStylesProvider } from './style_memoization';
import { buildTheme, getColorMode, getComputed, mergeDeep } from './utils';
import {
EuiThemeColorMode,
@@ -229,9 +230,11 @@ export const EuiThemeProvider = <T extends {} = {}>({
<EuiModificationsContext.Provider value={modifications}>
<EuiThemeContext.Provider value={theme}>
<EuiNestedThemeContext.Provider value={nestedThemeContext}>
<EuiEmotionThemeProvider>
{renderedChildren}
</EuiEmotionThemeProvider>
<EuiThemeMemoizedStylesProvider>
<EuiEmotionThemeProvider>
{renderedChildren}
</EuiEmotionThemeProvider>
</EuiThemeMemoizedStylesProvider>
</EuiNestedThemeContext.Provider>
</EuiThemeContext.Provider>
</EuiModificationsContext.Provider>
85 changes: 85 additions & 0 deletions src/services/theme/style_memoization.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* 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, { useState } from 'react';
import { css } from '@emotion/react';
import { fireEvent } from '@testing-library/react';
import { render, renderHook } from '../../test/rtl';
import { testOnReactVersion } from '../../test/internal';

import type { UseEuiTheme } from './hooks';
import { EuiThemeProvider } from './provider';

import { useEuiMemoizedStyles } from './style_memoization';

describe('useEuiMemoizedStyles', () => {
beforeEach(jest.clearAllMocks);

const componentStyles = jest.fn(({ euiTheme }: UseEuiTheme) => ({
someComponent: css`
color: ${euiTheme.colors.primaryText};
`,
}));
const Component = () => {
const [rerender, setRerender] = useState(false);
const styles = useEuiMemoizedStyles(componentStyles);
return (
<button
css={styles.someComponent}
onClick={() => setRerender(!rerender)}
/>
);
};

it('memoizes the passed fn, only computing the styles once regardless of other rerenders', () => {
const { getByRole } = render(<Component />);

expect(componentStyles).toHaveBeenCalledTimes(1);
expect(getByRole('button')).toHaveStyleRule('color', '#006bb8');

fireEvent.click(getByRole('button'));
expect(componentStyles).toHaveBeenCalledTimes(1);
});

it('recomputes styles if the upstream theme changes', () => {
const { rerender, getByRole } = render(
<EuiThemeProvider colorMode="light">
<Component />
</EuiThemeProvider>
);
expect(componentStyles).toHaveBeenCalledTimes(1);
expect(getByRole('button')).toHaveStyleRule('color', '#006bb8');

rerender(
<EuiThemeProvider colorMode="dark">
<Component />
</EuiThemeProvider>
);
expect(componentStyles).toHaveBeenCalledTimes(2);
expect(getByRole('button')).toHaveStyleRule('color', '#36a2ef');

// Should not recompute styles if no theme changes
rerender(
<EuiThemeProvider colorMode="dark">
<Component />
</EuiThemeProvider>
);
expect(componentStyles).toHaveBeenCalledTimes(2);
});

testOnReactVersion(['18'])(
'throws an error if passed anonymous functions',
() => {
expect(() =>
renderHook(() => useEuiMemoizedStyles(() => ({})))
).toThrowError(
'Styles are memoized per function. Your style functions must be statically defined in order to not create a new map entry every rerender.'
);
}
);
});
85 changes: 85 additions & 0 deletions src/services/theme/style_memoization.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* 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, {
FunctionComponent,
PropsWithChildren,
createContext,
useContext,
useState,
useMemo,
} from 'react';
import type { SerializedStyles, CSSObject } from '@emotion/react';

import { useUpdateEffect } from '../hooks';
import { useEuiTheme, UseEuiTheme } from './hooks';

type Styles = SerializedStyles | CSSObject | string | null;
type StylesMaps = Record<string, Styles | Record<string, Styles>>;
// NOTE: We're specifically using a WeakMap instead of a Map in order to allow
// unmounted components to have their styles garbage-collected by the browser
// @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap
type MemoizedStylesMap = WeakMap<Function, StylesMaps>;

export const EuiThemeMemoizedStylesContext = createContext<MemoizedStylesMap>(
new WeakMap()
);

export const EuiThemeMemoizedStylesProvider: FunctionComponent<
PropsWithChildren
> = ({ children }) => {
// Note: we *should not* use `useMemo` instead of `useState` here, as useMemo is not guaranteed
// and its cache can get thrown away by React (https://react.dev/reference/react/useMemo#caveats)
const [componentStyles, rerenderStyles] = useState<MemoizedStylesMap>(
new WeakMap()
);

// On theme update, wipe the map, which causes the below hook to recompute all styles
const { euiTheme } = useEuiTheme();
useUpdateEffect(() => {
rerenderStyles(new WeakMap());
}, [euiTheme]);

return (
<EuiThemeMemoizedStylesContext.Provider value={componentStyles}>
{children}
</EuiThemeMemoizedStylesContext.Provider>
);
};

/**
* Hook that memoizes the returned values of components style fns/generators
* per-theme
*/
export const useEuiMemoizedStyles = <
T extends (theme: UseEuiTheme) => StylesMaps
>(
styleGenerator: T
): ReturnType<T> => {
const memoizedStyles = useContext(EuiThemeMemoizedStylesContext);
const euiThemeContext = useEuiTheme();

const memoizedComponentStyles = useMemo(() => {
if (!styleGenerator.name) {
throw new Error(
'Styles are memoized per function. Your style functions must be statically defined in order to not create a new map entry every rerender.'
);
}
const existingStyles = memoizedStyles.get(styleGenerator);
if (existingStyles) {
return existingStyles;
} else {
const generatedStyles = styleGenerator(euiThemeContext);
memoizedStyles.set(styleGenerator, generatedStyles);

return generatedStyles;
}
}, [styleGenerator, memoizedStyles, euiThemeContext]);

return memoizedComponentStyles as ReturnType<T>;
};

0 comments on commit 47ab766

Please sign in to comment.