Back

100% Statements 27/27
96.15% Branches 25/26
100% Functions 10/10
100% Lines 22/22

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 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147                                                            33x                   33x   32x 160x 151x 23x   128x 101x       33x   32x 160x 128x 119x 18x   101x         33x   90x                                     33x   17x                 26x                                 42x                                             33x                  
/**
 * MediaSourceMenu component
 * Displays a dropdown menu with grouped media source options
 */
 
import { Button, Dropdown, MenuGroup } from '@wordpress/components';
import { useCallback, useMemo } from '@wordpress/element';
import { __, _x } from '@wordpress/i18n';
import MediaSourceMenuItem from './media-source-menu-item';
import styles from './styles.module.scss';
import { MediaSourceMenuProps } from './types';
import { getMediaSourceOptions } from './utils/media-source-options';
 
/**
 * MediaSourceMenu component
 *
 * @param {MediaSourceMenuProps} props - Component props
 * @return {JSX.Element} MediaSourceMenu component
 */
export default function MediaSourceMenu( {
	currentSource,
	onSelect,
	onMediaLibraryClick,
	onAiImageClick,
	disabled = false,
	featuredImageId,
	includeDefaultOption = false,
	children,
}: MediaSourceMenuProps ) {
	// Get options from function to ensure translations are loaded
	const options = useMemo( () => getMediaSourceOptions(), [] );
 
	/*
	 * Group options for display:
	 * - Hide "Featured image" when no featured image exists.
	 * - Hide "Default" unless the caller opts in (per-network customization only).
	 * - In per-network mode, SIG and Featured image are always attached (no toggle to make
	 *   them link-preview-only), so they're surfaced under "Attachment". Default is the only
	 *   link-preview option.
	 */
	const linkPreviewOptions = useMemo(
		() =>
			options.filter( opt => {
				if ( opt.id === 'featured-image' && ! featuredImageId ) return false;
				if ( includeDefaultOption ) {
					return opt.id === null;
				}
				if ( opt.id === null ) return false;
				return opt.group === 'link-preview';
			} ),
		[ options, featuredImageId, includeDefaultOption ]
	);
	const attachmentOptions = useMemo(
		() =>
			options.filter( opt => {
				if ( opt.id === null ) return false;
				if ( opt.id === 'featured-image' && ! featuredImageId ) return false;
				if ( includeDefaultOption ) {
					return true;
				}
				return opt.group === 'attachment';
			} ),
		[ options, featuredImageId, includeDefaultOption ]
	);
 
	const renderToggle = useCallback(
		( { isOpen, onToggle }: { isOpen: boolean; onToggle: () => void } ) => (
			<>
				{ ! children && (
					<Button
						__next40pxDefaultSize
						className={ styles.selectButton }
						variant="secondary"
						onClick={ onToggle }
						aria-expanded={ isOpen }
						disabled={ disabled }
					>
						{ __( 'Select', 'jetpack-publicize-pkg' ) }
					</Button>
				) }
				{ children && children( { open: onToggle } ) }
			</>
		),
		[ children, disabled ]
	);
 
	const renderContent = useCallback(
		( { onClose }: { onClose: () => void } ) => (
			<>
				<MenuGroup
					label={ _x(
						'Link preview',
						'The image source to use for post link preview on social media.',
						'jetpack-publicize-pkg'
					) }
				>
					{ linkPreviewOptions.map( option => (
						<MediaSourceMenuItem
							key={ option.id ?? 'default' }
							option={ option }
							isSelected={ currentSource === option.id }
							onSelect={ onSelect }
							onClose={ onClose }
						/>
					) ) }
				</MenuGroup>
				<MenuGroup
					label={ _x(
						'Attachment',
						'The media source to use for post attachment on social media.',
						'jetpack-publicize-pkg'
					) }
				>
					{ attachmentOptions.map( option => (
						<MediaSourceMenuItem
							key={ option.id ?? 'default' }
							option={ option }
							isSelected={ currentSource === option.id }
							onSelect={ onSelect }
							onClose={ onClose }
							onMediaLibraryClick={ onMediaLibraryClick }
							onAiImageClick={ onAiImageClick }
						/>
					) ) }
				</MenuGroup>
			</>
		),
		[
			linkPreviewOptions,
			attachmentOptions,
			currentSource,
			onSelect,
			onMediaLibraryClick,
			onAiImageClick,
		]
	);
 
	return (
		<Dropdown
			className={ styles.dropdownMenu }
			popoverProps={ { placement: 'bottom-start' } }
			renderToggle={ renderToggle }
			renderContent={ renderContent }
		/>
	);
}