Back

100% Statements 12/12
100% Branches 17/17
100% Functions 5/5
100% Lines 12/12

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118                                                                                            100x   100x 78x         22x 1x                       21x 21x                   19x                   21x 8x   13x                         22x                          
import { __ } from '@wordpress/i18n';
import { Text } from '@wordpress/ui';
import { JetpackButton } from './feature-action';
import { FeatureItem } from './feature-item';
import { FeatureList } from './feature-list';
import styles from './styles.module.scss';
import type { FeatureState } from './feature-state';
import type { FeatureSelection } from './use-feature-selection';
import type { MoreFeaturesGroup } from './use-more-features';
import type { ReactNode } from 'react';
 
type MoreFeaturesProps = {
	groups: MoreFeaturesGroup[];
	selection: FeatureSelection;
	jetpack: MainFeaturePluginStatus;
	isList?: boolean;
	isNarrowed?: boolean;
	isSearching?: boolean;
};
 
/**
 * Jetpack's other modules, under headings, below the main features.
 *
 * The cards are the main features' own, minus the icon and the details modal, so the two
 * lists cannot drift apart. Shown only where Jetpack is installed; while it is off, the
 * modules cannot be read, so the section offers to activate it instead.
 *
 * @param {MoreFeaturesProps}   props             - The component props.
 * @param {MoreFeaturesGroup[]} props.groups      - The modules to show, grouped.
 * @param {FeatureSelection}    props.selection   - The selection shared with the bulk bar.
 * @param {string}              props.jetpack     - The Jetpack plugin's status.
 * @param {boolean}             props.isList      - Whether the tab is in its list view.
 * @param {boolean}             props.isNarrowed  - Whether a filter or a search is in play, which an offer to activate Jetpack cannot answer.
 * @param {boolean}             props.isSearching - Whether the rows are search results, which read as one list without headings.
 * @return The rendered component, or null when there is nothing to show.
 */
export function MoreFeatures( {
	groups,
	selection,
	jetpack,
	isList = false,
	isNarrowed = false,
	isSearching = false,
}: MoreFeaturesProps ) {
	// Without modules the only thing left to show is the offer to activate Jetpack, and that
	// answers neither a filter nor a search. Covers a status the page has not yet read.
	const offersActivate = jetpack === 'inactive' && ! isNarrowed;
 
	if ( ! groups.length && ! offersActivate ) {
		return null;
	}
 
	let body: ReactNode;
 
	if ( jetpack === 'inactive' ) {
		body = (
			<div className={ styles[ 'more-features__inactive' ] }>
				<Text variant="body-md">
					{ __(
						'Activate the Jetpack plugin to see and manage its other features.',
						'jetpack-my-jetpack'
					) }
				</Text>
				<JetpackButton installed />
			</div>
		);
	} else {
		const renderRows = ( states: FeatureState[] ) =>
			isList ? (
				<FeatureList
					states={ states }
					selection={ selection }
					showIcon={ false }
					origin="more_features"
				/>
			) : (
				<div className={ styles[ 'feature-grid' ] }>
					{ states.map( state => (
						<FeatureItem
							key={ state.feature.slug }
							state={ state }
							showIcon={ false }
							origin="more_features"
						/>
					) ) }
				</div>
			);
 
		body = isSearching
			? renderRows( groups.flatMap( group => group.states ) )
			: groups.map( group => (
					<div key={ group.label } className={ styles[ 'more-features__group' ] }>
						<Text
							variant="heading-lg"
							render={ <h3 /> }
							className={ styles[ 'feature-item__title' ] }
						>
							{ group.label }
						</Text>
						{ renderRows( group.states ) }
					</div>
				) );
	}
 
	return (
		<section className={ styles[ 'more-features' ] } aria-labelledby="more-features-heading">
			<Text
				variant="heading-xl"
				render={ <h2 id="more-features-heading" /> }
				className={ isSearching ? 'screen-reader-text' : undefined }
			>
				{ __( 'More Features', 'jetpack-my-jetpack' ) }
			</Text>
			{ body }
		</section>
	);
}