# thinkrank/1.0.0/src/admin/components/common/MediaPicker.js

ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console &amp; Local SEO, version 1.0.0. 196 lines.

- Page: https://pluginprobe.com/plugins/thinkrank/1.0.0/code/src/admin/components/common/MediaPicker.js
- Raw: https://pluginprobe.com/plugins/thinkrank/1.0.0/raw/src/admin/components/common/MediaPicker.js
- Modified: 2025-08-10T07:57:44+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/thinkrank/1.0.0/code/src/admin/components/common/MediaPicker.js#L10-L20`.

```javascript
/**
 * Media Picker Component
 * 
 * WordPress media library integration for selecting images
 * 
 * @package ThinkRank
 * @since 1.0.0
 */

import { useState } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import { 
    Button,
    Flex,
    FlexItem,
    __experimentalSpacer as Spacer
} from '@wordpress/components';

/**
 * Media Picker Component
 */
const MediaPicker = ({ 
    value, 
    onChange, 
    label, 
    help, 
    allowedTypes = ['image'], 
    multiple = false,
    disabled = false 
}) => {
    const [isOpen, setIsOpen] = useState(false);

    /**
     * Open WordPress media library
     */
    const openMediaLibrary = () => {
        if (disabled) return;

        // Check if wp.media is available
        if (typeof wp === 'undefined' || typeof wp.media === 'undefined') {
            console.error('WordPress media library not available');
            return;
        }

        // Create media frame
        const frame = wp.media({
            title: label || __('Select Media', 'thinkrank'),
            button: {
                text: __('Use this media', 'thinkrank')
            },
            multiple: multiple,
            library: {
                type: allowedTypes
            }
        });

        // Handle media selection
        frame.on('select', () => {
            const selection = frame.state().get('selection');
            
            if (multiple) {
                const attachments = selection.map(attachment => {
                    const data = attachment.toJSON();
                    return {
                        id: data.id,
                        url: data.url,
                        alt: data.alt || '',
                        title: data.title || '',
                        filename: data.filename || '',
                        mime: data.mime || '',
                        width: data.width || 0,
                        height: data.height || 0
                    };
                });
                onChange(attachments);
            } else {
                const attachment = selection.first().toJSON();
                const mediaData = {
                    id: attachment.id,
                    url: attachment.url,
                    alt: attachment.alt || '',
                    title: attachment.title || '',
                    filename: attachment.filename || '',
                    mime: attachment.mime || '',
                    width: attachment.width || 0,
                    height: attachment.height || 0
                };
                onChange(mediaData.url);
            }
        });

        // Open the frame
        frame.open();
    };

    /**
     * Remove selected media
     */
    const removeMedia = () => {
        onChange(multiple ? [] : '');
    };

    /**
     * Get media preview
     */
    const getMediaPreview = () => {
        if (!value) return null;

        if (multiple && Array.isArray(value)) {
            return value.map((item, index) => (
                <div key={index} className="media-preview-item">
                    <img 
                        src={item.url || item} 
                        alt={item.alt || ''} 
                        style={{ maxWidth: '100px', maxHeight: '100px', objectFit: 'cover' }}
                    />
                </div>
            ));
        }

        // Single media item
        const mediaUrl = typeof value === 'object' ? value.url : value;
        if (mediaUrl) {
            return (
                <div className="media-preview-item">
                    <img 
                        src={mediaUrl} 
                        alt="" 
                        style={{ maxWidth: '100px', maxHeight: '100px', objectFit: 'cover' }}
                    />
                </div>
            );
        }

        return null;
    };

    const hasMedia = multiple ? (Array.isArray(value) && value.length > 0) : !!value;

    return (
        <div className="thinkrank-media-picker">
            {label && (
                <label className="components-base-control__label">
                    {label}
                </label>
            )}
            
            <Spacer marginY={2} />
            
            <Flex direction="column" gap={3}>
                {hasMedia && (
                    <FlexItem>
                        <div className="media-preview">
                            {getMediaPreview()}
                        </div>
                    </FlexItem>
                )}
                
                <FlexItem>
                    <Flex gap={2}>
                        <Button
                            variant={hasMedia ? "secondary" : "primary"}
                            onClick={openMediaLibrary}
                            disabled={disabled}
                        >
                            {hasMedia 
                                ? __('Change Media', 'thinkrank')
                                : __('Select Media', 'thinkrank')
                            }
                        </Button>
                        
                        {hasMedia && (
                            <Button
                                variant="tertiary"
                                isDestructive
                                onClick={removeMedia}
                                disabled={disabled}
                            >
                                {__('Remove', 'thinkrank')}
                            </Button>
                        )}
                    </Flex>
                </FlexItem>
            </Flex>
            
            {help && (
                <p className="components-base-control__help">
                    {help}
                </p>
            )}
        </div>
    );
};

export default MediaPicker;

```
