From 1c4dbe5eaf3fe27b6fcb1e6adc55741b40e4ce59 Mon Sep 17 00:00:00 2001 From: Alexandr Isaev Date: Thu, 23 May 2024 14:53:01 +0300 Subject: [PATCH 1/2] fix(Flex,ListItemView): return ref drilling by React.forwardRef --- src/components/layout/Flex/Flex.tsx | 8 +- .../components/ListItemView/ListItemView.tsx | 229 +++++++++--------- 2 files changed, 123 insertions(+), 114 deletions(-) diff --git a/src/components/layout/Flex/Flex.tsx b/src/components/layout/Flex/Flex.tsx index 22ca7d3c2c..3a93a16493 100644 --- a/src/components/layout/Flex/Flex.tsx +++ b/src/components/layout/Flex/Flex.tsx @@ -128,7 +128,10 @@ type FlexPropsWithTypedAttrs = FlexProps & * --- * Storybook - https://preview.gravity-ui.com/uikit/?path=/docs/layout--playground#flex */ -export const Flex = function Flex(props: FlexProps) { +export const Flex = React.forwardRef(function Flex( + props: FlexProps, + ref: FlexRef, +) { const { as: propsAs, direction, @@ -187,6 +190,7 @@ export const Flex = function Flex(props: Fl }, className, )} + ref={ref} style={{ flexDirection: applyMediaProps(direction), flexGrow: grow === true ? 1 : grow, @@ -213,6 +217,6 @@ export const Flex = function Flex(props: Fl : children} ); -} as (( +}) as (( props: FlexPropsWithTypedAttrs & {ref?: FlexRef}, ) => React.ReactElement) & {displayName: string}; diff --git a/src/components/useList/components/ListItemView/ListItemView.tsx b/src/components/useList/components/ListItemView/ListItemView.tsx index aff283be05..e57cf6bc6c 100644 --- a/src/components/useList/components/ListItemView/ListItemView.tsx +++ b/src/components/useList/components/ListItemView/ListItemView.tsx @@ -15,11 +15,13 @@ import './ListItemView.scss'; const b = block('list-item-view'); -export interface ListItemViewProps extends QAProps, ListItemCommonProps { +export interface ListItemViewProps + extends QAProps, + ListItemCommonProps { /** * Ability to override default html tag */ - as?: keyof JSX.IntrinsicElements; + as?: T; /** * @default `m` */ @@ -43,7 +45,7 @@ export interface ListItemViewProps extends QAProps, ListItemCommonProps { /** * Note: if passed and `disabled` option is `true` click will not be appear */ - onClick?(): void; + onClick?: React.ComponentPropsWithoutRef['onClick']; style?: React.CSSProperties; className?: string; role?: React.AriaRole; @@ -59,6 +61,11 @@ export interface ListItemViewProps extends QAProps, ListItemCommonProps { id: ListItemId; } +type ListItemViewRef = React.ComponentPropsWithRef['ref']; + +type ListItemViewPropsWithTypedAttrs = ListItemViewProps & + Omit, keyof ListItemViewProps>; + interface SlotProps extends FlexProps { indentation?: number; } @@ -85,118 +92,116 @@ const renderSafeIndentation = (indentation?: number) => { return null; }; -export const ListItemView = React.forwardRef( - ( - { - id, - as = 'div', - size = 'm', - active, - selected, - disabled, - activeOnHover: propsActiveOnHover, - className, - hasSelectionIcon = true, - indentation, - startSlot, - subtitle, - endSlot, - title, - height, - expanded, - dragging, - style, - role = 'option', - onClick: _onClick, - ...rest - }: ListItemViewProps, - ref?: any, - ) => { - const isGroup = typeof expanded === 'boolean'; - const onClick = disabled ? undefined : _onClick; - const activeOnHover = - typeof propsActiveOnHover === 'boolean' ? propsActiveOnHover : Boolean(onClick); +export const ListItemView = React.forwardRef(function ListItemView< + T extends React.ElementType = 'div', +>( + { + id, + as: asProps, + size = 'm', + active, + selected, + disabled, + activeOnHover: propsActiveOnHover, + className, + hasSelectionIcon = true, + indentation, + startSlot, + subtitle, + endSlot, + title, + height, + expanded, + dragging, + style, + role = 'option', + onClick: _onClick, + ...rest + }: ListItemViewPropsWithTypedAttrs, + ref?: ListItemViewRef, +) { + const as: React.ElementType = asProps || 'div'; + const isGroup = typeof expanded === 'boolean'; + const onClick = disabled ? undefined : _onClick; + const activeOnHover = + typeof propsActiveOnHover === 'boolean' ? propsActiveOnHover : Boolean(onClick); - return ( - + + {hasSelectionIcon && ( + + {selected ? ( + + ) : null} + )} - style={{ - minHeight: height ?? modToHeight[size][Number(Boolean(subtitle))], - ...style, - }} - as={as} - ref={ref} - alignItems="center" - gap="4" - justifyContent="space-between" - {...rest} - > - - {hasSelectionIcon && ( - + ) : null} + + {startSlot} + +
+ {typeof title === 'string' ? ( + - {selected ? ( - - ) : null} - + {title} + + ) : ( + title )} - - {renderSafeIndentation(indentation)} - - {isGroup ? ( - - ) : null} - - {startSlot} - -
- {typeof title === 'string' ? ( - - {title} - - ) : ( - title - )} - {typeof subtitle === 'string' ? ( - - {subtitle} - - ) : ( - subtitle - )} -
- - - {endSlot} + {typeof subtitle === 'string' ? ( + + {subtitle} + + ) : ( + subtitle + )} +
- ); - }, -); -ListItemView.displayName = 'ListItemView'; + {endSlot} +
+ ); +}) as ({ + ref, + ...props +}: ListItemViewPropsWithTypedAttrs & {ref?: ListItemViewRef}) => React.ReactElement; From 285693267d2186949ecd364f360c79e6a5e8997e Mon Sep 17 00:00:00 2001 From: Alexandr Isaev Date: Thu, 23 May 2024 15:10:59 +0300 Subject: [PATCH 2/2] fix: typo --- src/components/useList/components/ListItemView/ListItemView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/useList/components/ListItemView/ListItemView.tsx b/src/components/useList/components/ListItemView/ListItemView.tsx index e57cf6bc6c..49d647a137 100644 --- a/src/components/useList/components/ListItemView/ListItemView.tsx +++ b/src/components/useList/components/ListItemView/ListItemView.tsx @@ -201,7 +201,7 @@ export const ListItemView = React.forwardRef(function ListItemView< {endSlot}
); -}) as ({ +}) as ({ ref, ...props }: ListItemViewPropsWithTypedAttrs & {ref?: ListItemViewRef}) => React.ReactElement;