@@ -4,6 +4,8 @@ import { css } from '@patternfly/react-styles';
44import lineClamp from '@patternfly/react-tokens/dist/esm/c_expandable_section_m_truncate__content_LineClamp' ;
55import AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-icon' ;
66import { PickOptional } from '../../helpers/typeUtils' ;
7+ import { debounce } from '../../helpers/util' ;
8+ import { getResizeObserver } from '../../helpers/resizeObserver' ;
79
810export enum ExpandableSectionVariant {
911 default = 'default' ,
@@ -61,6 +63,8 @@ export interface ExpandableSectionProps extends React.HTMLProps<HTMLDivElement>
6163
6264interface ExpandableSectionState {
6365 isExpanded : boolean ;
66+ hasToggle : boolean ;
67+ previousWidth : number ;
6468}
6569
6670const setLineClamp = ( lines : number , element : HTMLDivElement ) => {
@@ -77,11 +81,15 @@ export class ExpandableSection extends React.Component<ExpandableSectionProps, E
7781 super ( props ) ;
7882
7983 this . state = {
80- isExpanded : props . isExpanded
84+ isExpanded : props . isExpanded ,
85+ hasToggle : true ,
86+ previousWidth : undefined
8187 } ;
8288 }
8389
8490 expandableContentRef = React . createRef < HTMLDivElement > ( ) ;
91+ observer : any = ( ) => { } ;
92+
8593 static defaultProps : PickOptional < ExpandableSectionProps > = {
8694 className : '' ,
8795 toggleText : '' ,
@@ -114,9 +122,16 @@ export class ExpandableSection extends React.Component<ExpandableSectionProps, E
114122 }
115123
116124 componentDidMount ( ) {
117- if ( this . props . variant === ExpandableSectionVariant . truncate && this . props . truncateMaxLines ) {
125+ if ( this . props . variant === ExpandableSectionVariant . truncate ) {
118126 const expandableContent = this . expandableContentRef . current ;
119- setLineClamp ( this . props . truncateMaxLines , expandableContent ) ;
127+ this . setState ( { previousWidth : expandableContent . offsetWidth } ) ;
128+ this . observer = getResizeObserver ( expandableContent , this . handleResize , false ) ;
129+
130+ if ( this . props . truncateMaxLines ) {
131+ setLineClamp ( this . props . truncateMaxLines , expandableContent ) ;
132+ }
133+
134+ this . checkToggleVisibility ( ) ;
120135 }
121136 }
122137
@@ -127,9 +142,38 @@ export class ExpandableSection extends React.Component<ExpandableSectionProps, E
127142 ) {
128143 const expandableContent = this . expandableContentRef . current ;
129144 setLineClamp ( this . props . truncateMaxLines , expandableContent ) ;
145+ this . checkToggleVisibility ( ) ;
146+ }
147+ }
148+
149+ componentWillUnmount ( ) {
150+ if ( this . props . variant === ExpandableSectionVariant . truncate ) {
151+ this . observer ( ) ;
130152 }
131153 }
132154
155+ checkToggleVisibility = ( ) => {
156+ if ( this . expandableContentRef ?. current ) {
157+ const maxLines = this . props . truncateMaxLines || parseInt ( lineClamp . value ) ;
158+ const totalLines =
159+ this . expandableContentRef . current . scrollHeight /
160+ parseInt ( getComputedStyle ( this . expandableContentRef . current ) . lineHeight ) ;
161+
162+ this . setState ( {
163+ hasToggle : totalLines > maxLines
164+ } ) ;
165+ }
166+ } ;
167+
168+ resize = ( ) => {
169+ const { offsetWidth } = this . expandableContentRef . current ;
170+ if ( this . state . previousWidth !== offsetWidth ) {
171+ this . setState ( { previousWidth : offsetWidth } ) ;
172+ this . checkToggleVisibility ( ) ;
173+ }
174+ } ;
175+ handleResize = debounce ( this . resize , 250 ) ;
176+
133177 render ( ) {
134178 const {
135179 onToggle : onToggleProp ,
@@ -210,7 +254,7 @@ export class ExpandableSection extends React.Component<ExpandableSectionProps, E
210254 >
211255 { children }
212256 </ div >
213- { variant === ExpandableSectionVariant . truncate && expandableToggle }
257+ { variant === ExpandableSectionVariant . truncate && this . state . hasToggle && expandableToggle }
214258 </ div >
215259 ) ;
216260 }
0 commit comments