diff --git a/packages/eui/changelogs/upcoming/7792.md b/packages/eui/changelogs/upcoming/7792.md new file mode 100644 index 00000000000..d55bf09b29d --- /dev/null +++ b/packages/eui/changelogs/upcoming/7792.md @@ -0,0 +1,3 @@ +**Bug fixes** + +- Fixed `EuiFlexGroup` and `EuiFlexItem` types to correctly accept global attribute props and simplify type resolution when used with `styled()`-like wrappers diff --git a/packages/eui/scripts/dtsgenerator.js b/packages/eui/scripts/dtsgenerator.js index b973005e67c..f8eacd8f665 100644 --- a/packages/eui/scripts/dtsgenerator.js +++ b/packages/eui/scripts/dtsgenerator.js @@ -106,6 +106,7 @@ const generator = dtsGenerator({ // 2. replace any import("src/...") declarations to import("@elastic/eui/src/...") // 3. replace any import("./...") declarations to import("@elastic/eui/src/...) // 4. generate & add EuiTokenObject +// 5. Fix React.ElementType being incorrectly expanded to React.ElementType generator.then(() => { const defsFilePath = path.resolve(baseDir, 'eui.d.ts'); @@ -155,6 +156,10 @@ generator.then(() => { } ) // end 3. .replace(/$/, `\n\n${buildEuiTokensObject()}`) // 4. + .replaceAll( + 'React.ElementType', + 'React.ElementType' + ) // 5. ); }); diff --git a/packages/eui/src/components/flex/flex_group.tsx b/packages/eui/src/components/flex/flex_group.tsx index c7bb866486b..9de2867907e 100644 --- a/packages/eui/src/components/flex/flex_group.tsx +++ b/packages/eui/src/components/flex/flex_group.tsx @@ -8,11 +8,12 @@ import React, { ComponentPropsWithoutRef, - ComponentType, ElementType, ForwardedRef, forwardRef, + FunctionComponent, PropsWithChildren, + ReactElement, Ref, } from 'react'; import classNames from 'classnames'; @@ -51,9 +52,7 @@ export const DIRECTIONS = [ ] as const; type FlexGroupDirection = (typeof DIRECTIONS)[number]; -type ComponentPropType = ElementType; - -export type EuiFlexGroupProps = +export type EuiFlexGroupProps = PropsWithChildren & CommonProps & ComponentPropsWithoutRef & { @@ -83,7 +82,7 @@ export type EuiFlexGroupProps = wrap?: boolean; }; -const EuiFlexGroupInternal = ( +const EuiFlexGroupInternal = ( { className, component = 'div' as TComponent, @@ -96,7 +95,7 @@ const EuiFlexGroupInternal = ( ...rest }: EuiFlexGroupProps, ref: ForwardedRef -) => { +): ReactElement, TComponent> => { const styles = useEuiMemoizedStyles(euiFlexGroupStyles); const cssStyles = [ styles.euiFlexGroup, @@ -110,10 +109,11 @@ const EuiFlexGroupInternal = ( const classes = classNames('euiFlexGroup', className); - // Cast the resolved component prop type to ComponentType to help TS - // process multiple infers and the overall type complexity. - // This might not be needed in TypeScript 5 - const Component = component as ComponentType; + // Cast `component` to FunctionComponent to simplify its type. + // Note that FunctionComponent type is used here for purely typing + // convenience since we specify the return type above, and function + // components don't support `ref`s, but that doesn't matter in this case. + const Component = component as FunctionComponent; return ; }; @@ -121,12 +121,12 @@ const EuiFlexGroupInternal = ( // Cast forwardRef return type to work with the generic TComponent type // and not fallback to implicit any typing export const EuiFlexGroup = forwardRef(EuiFlexGroupInternal) as (< - TComponent extends ComponentPropType = 'div', - TComponentRef = ReturnType + TComponent extends ElementType = 'div', + TComponentRef = ReactElement >( props: EuiFlexGroupProps & { ref?: Ref; } -) => ReturnType) & { displayName?: string }; +) => ReactElement) & { displayName?: string }; EuiFlexGroup.displayName = 'EuiFlexGroup'; diff --git a/packages/eui/src/components/flex/flex_item.tsx b/packages/eui/src/components/flex/flex_item.tsx index 2b29aeacf48..e32dc144375 100644 --- a/packages/eui/src/components/flex/flex_item.tsx +++ b/packages/eui/src/components/flex/flex_item.tsx @@ -11,10 +11,11 @@ import React, { useEffect, ComponentPropsWithoutRef, PropsWithChildren, - ComponentType, ForwardedRef, forwardRef, Ref, + ReactElement, + FunctionComponent, } from 'react'; import classNames from 'classnames'; import { CommonProps } from '../common'; @@ -39,9 +40,7 @@ const VALID_GROW_VALUES = [ 10, ] as const; -type ComponentPropType = ElementType; - -export type EuiFlexItemProps = +export type EuiFlexItemProps = PropsWithChildren & CommonProps & ComponentPropsWithoutRef & { @@ -53,20 +52,20 @@ export type EuiFlexItemProps = * such as `'div'` or `'span'`, a React component (a function, a class, * or an exotic component like `memo()`). * - * `` accepts and forwards all extra props to the custom + * `` accepts and forwards all extra props to the custom * component. * * @example * // Renders a