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 }
/>
);
}
|