Create New Item
Item Type
File
Folder
Item Name
Search file in folder and subfolders...
Are you sure want to rename?
optometrists
/
cache
/
cache
/
cache
/
.wp-cli
/
wp-content
/
plugins
/
woocommerce
/
packages
/
woocommerce-blocks
/
assets
/
js
/
base
/
components
/
read-more
:
index.js
Advanced Search
Upload
New Item
Settings
Back
Back Up
Advanced Editor
Save
/** * External dependencies */ import React, { createRef, Component } from 'react'; import PropTypes from 'prop-types'; import { __ } from '@wordpress/i18n'; /** * Internal dependencies */ import { clampLines } from './utils'; /** * Show text based content, limited to a number of lines, with a read more link. * * Based on https://github.com/zoltantothcom/react-clamp-lines. */ class ReadMore extends Component { constructor( props ) { super( ...arguments ); this.state = { /** * This is true when read more has been pressed and the full review is shown. */ isExpanded: false, /** * True if we are clamping content. False if the review is short. Null during init. */ clampEnabled: null, /** * Content is passed in via children. */ content: props.children, /** * Summary content generated from content HTML. */ summary: '.', }; this.reviewSummary = createRef(); this.reviewContent = createRef(); this.getButton = this.getButton.bind( this ); this.onClick = this.onClick.bind( this ); } componentDidMount() { if ( this.props.children ) { const { maxLines, ellipsis } = this.props; const lineHeight = this.reviewSummary.current.clientHeight + 1; const reviewHeight = this.reviewContent.current.clientHeight + 1; const maxHeight = lineHeight * maxLines + 1; const clampEnabled = reviewHeight > maxHeight; this.setState( { clampEnabled, } ); if ( clampEnabled ) { this.setState( { summary: clampLines( this.reviewContent.current.innerHTML, this.reviewSummary.current, maxHeight, ellipsis ), } ); } } } getButton() { const { isExpanded } = this.state; const { className, lessText, moreText } = this.props; const buttonText = isExpanded ? lessText : moreText; if ( ! buttonText ) { return; } return ( <a href="#more" className={ className + '__read_more' } onClick={ this.onClick } aria-expanded={ ! isExpanded } role="button" > { buttonText } </a> ); } /** * Handles the click event for the read more/less button. * * @param {Object} e event */ onClick( e ) { e.preventDefault(); const { isExpanded } = this.state; this.setState( { isExpanded: ! isExpanded, } ); } render() { const { className } = this.props; const { content, summary, clampEnabled, isExpanded } = this.state; if ( ! content ) { return null; } if ( clampEnabled === false ) { return ( <div className={ className }> <div ref={ this.reviewContent }>{ content }</div> </div> ); } return ( <div className={ className }> { ( ! isExpanded || clampEnabled === null ) && ( <div ref={ this.reviewSummary } aria-hidden={ isExpanded } dangerouslySetInnerHTML={ { __html: summary, } } /> ) } { ( isExpanded || clampEnabled === null ) && ( <div ref={ this.reviewContent } aria-hidden={ ! isExpanded } > { content } </div> ) } { this.getButton() } </div> ); } } ReadMore.propTypes = { children: PropTypes.node.isRequired, maxLines: PropTypes.number, ellipsis: PropTypes.string, moreText: PropTypes.string, lessText: PropTypes.string, className: PropTypes.string, }; ReadMore.defaultProps = { maxLines: 3, ellipsis: '…', moreText: __( 'Read more', 'woocommerce' ), lessText: __( 'Read less', 'woocommerce' ), className: 'read-more-content', }; export default ReadMore;