Path : /home/vishqocm/vjmedia.in/wp-content/plugins/coblocks/src/blocks/icon/components/
File Upload :
Current File : /home/vishqocm/vjmedia.in/wp-content/plugins/coblocks/src/blocks/icon/components/inspector.js

/**
 * External dependencies
 */
import classnames from 'classnames';
import map from 'lodash/map';

/**
 * Internal dependencies
 */
import applyWithColors from './colors';
import svg from './svgs';
import { DEFAULT_ICON_SIZE } from '.././';
import { MIN_ICON_SIZE, MAX_ICON_SIZE } from './edit';

/**
 * WordPress dependencies
 */
const { __, _x, sprintf } = wp.i18n;
const { Component, Fragment } = wp.element;
const { compose } = wp.compose;
const { InspectorControls, ContrastChecker, PanelColorSettings } = wp.blockEditor;
const { PanelBody, withFallbackStyles, RangeControl, TextControl, Button, BaseControl, NavigableMenu, Dropdown, Dashicon, Tooltip, ToggleControl } = wp.components;

/**
 * Module constants
 */
const NEW_TAB_REL = 'noreferrer noopener';

/**
 * Fallback styles
 */
const { getComputedStyle } = window;
const applyFallbackStyles = withFallbackStyles( ( node, ownProps ) => {
	const { backgroundColor, iconColor } = ownProps.attributes;
	const editableNode = node.querySelector( '[contenteditable="true"]' );
	const computedStyles = editableNode ? getComputedStyle( editableNode ) : null;
	return {
		fallbackBackgroundColor: backgroundColor || ! computedStyles ? undefined : computedStyles.backgroundColor,
		fallbackIconColor: iconColor || ! computedStyles ? undefined : computedStyles.color,
	};
} );

/**
 * Inspector controls
 */
class Inspector extends Component {
	constructor() {
		super( ...arguments );

		this.state = { filteredIcons: svg, searchValue: '', isSearching: false };

		this.onChangeSize = this.onChangeSize.bind( this );
		this.generateMaxPadding = this.generateMaxPadding.bind( this );
		this.onSetNewTab = this.onSetNewTab.bind( this );
	}

	onChangeSize( value, size ) {
		this.props.setAttributes( { iconSize: value } );
		if ( size ) {
			if ( size < 0 ) {
				size = '';
			}
			this.props.setAttributes( { height: size, width: size } );
		}
	}

	// Dynamically set the padding based on icon width.
	// Prevents disapearing icons when the combined padding is more than than width of the icon.
	generateMaxPadding( width ) {
		if ( width <= 60 ) {
			return 10;
		}
		return Math.round( width / 4 );
	}

	onSetNewTab( value ) {
		const { rel } = this.props.attributes;
		const linkTarget = value ? '_blank' : undefined;

		let updatedRel = rel;
		if ( linkTarget && ! rel ) {
			updatedRel = NEW_TAB_REL;
		} else if ( ! linkTarget && rel === NEW_TAB_REL ) {
			updatedRel = undefined;
		}

		this.props.setAttributes( {
			linkTarget,
			rel: updatedRel,
		} );
	}

	render() {
		const {
			clientId,
			attributes,
			setAttributes,
			backgroundColor,
			iconColor,
			fallbackBackgroundColor,
			fallbackIconColor,
			setBackgroundColor,
			setIconColor,
			className,
			label = __( 'Size' ),
			help,
		} = this.props;

		const {
			icon,
			borderRadius,
			padding,
			iconSize,
			width,
			href,
			linkTarget,
			rel,
		} = attributes;

		let iconStyle = 'outlined';

		if ( className.includes( 'is-style-filled' ) ) {
			iconStyle = 'filled';
		}

		const filterList = ( event ) => {
			const filtered = {};

			this.setState( { searchValue: event, isSearching: true } );

			if ( event === '' ) {
				this.setState( { isSearching: false } );
			}

			const updatedList = Object.entries( svg[ iconStyle ] ).filter( function( item ) {
				const text = item[ 0 ] + ' ' + item[ 1 ].keywords;
				return text.toLowerCase().search(
					event.toLowerCase() ) !== -1;
			} );

			filtered.outlined = {};
			filtered.filled = {};
			updatedList.forEach( ( [ key ] ) => {
				filtered.outlined[ key ] = svg.outlined[ key ];
				filtered.filled[ key ] = svg.filled[ key ];
			} );

			this.setState( { filteredIcons: filtered } );
		};

		const utilitySizes = [
			{
				name: __( 'Small' ),
				size: 40,
				slug: 'small',
			},
			{
				name: __( 'Medium' ),
				size: padding ? DEFAULT_ICON_SIZE + 28 : DEFAULT_ICON_SIZE,
				slug: 'medium',
			},
			{
				name: __( 'Large' ),
				size: 120,
				slug: 'large',
			}, {
				name: __( 'Huge' ),
				size: 200,
				slug: 'huge',
			},
		];

		const currentSize = utilitySizes.find( ( utility ) => utility.slug === iconSize );

		return (
			<Fragment>
				<InspectorControls>
					<PanelBody title={ __( 'Icon Settings' ) }>
						{ iconSize === 'advanced' ?
							<Fragment>
								<div className="components-base-control components-coblocks-icon-block--advanced-size">
									<Button
										className="components-color-palette__clear"
										type="button"
										onClick={ () => {
											document.getElementById( 'block-' + clientId ).getElementsByClassName( 'wp-block-coblocks-icon__inner' )[ 0 ].style.height = 'auto';
											this.onChangeSize( 'medium', DEFAULT_ICON_SIZE );
										} }
										isSmall
										isDefault
										aria-label={ sprintf( __( 'Turn off advanced %s settings' ), label.toLowerCase() ) }
									>
										{ __( 'Reset' ) }
									</Button>
									<RangeControl
										label={ __( 'Size' ) }
										value={ width }
										onChange={ ( nextWidth ) => {
											document.getElementById( 'block-' + clientId ).getElementsByClassName( 'wp-block-coblocks-icon__inner' )[ 0 ].style.height = 'auto';
											setAttributes( { width: nextWidth, height: nextWidth } );
										} }
										min={ padding ? MIN_ICON_SIZE + 28 : MIN_ICON_SIZE }
										max={ MAX_ICON_SIZE }
										step={ 1 }
									/>
								</div>
							</Fragment> :
							<BaseControl id="textarea-1" label={ label } help={ help }>
								<div className="components-font-size-picker__buttons">
									<Dropdown
										className="components-font-size-picker__dropdown"
										contentClassName="components-font-size-picker__dropdown-content components-coblocks-dimensions-control__dropdown-content"
										position="bottom"
										renderToggle={ ( { isOpen, onToggle } ) => (
											<Button
												className="components-font-size-picker__selector"
												isLarge
												onClick={ onToggle }
												aria-expanded={ isOpen }
												aria-label={ sprintf( __( 'Custom %s size' ), label.toLowerCase() ) }
											>
												{ ( currentSize && currentSize.name ) || ( ! iconSize && _x( 'Normal', 'size name' ) ) || _x( 'Custom', 'size name' ) }
											</Button>
										) }
										renderContent={ () => (
											<NavigableMenu>
												{ map( utilitySizes, ( { name, size, slug } ) => (
													<Button
														key={ slug }
														onClick={ () => this.onChangeSize( slug, size ) }
														className={ `is-${ slug }-size` }
														role="menuitem"
													>
														{ ( iconSize === slug || ( ! iconSize && slug === 'normal' ) ) && <Dashicon icon="saved" /> }
														<span className="components-font-size-picker__dropdown-text-size">
															{ name }
														</span>
													</Button>
												) ) }
											</NavigableMenu>
										) }
									/>
									<Button
										className="components-color-palette__clear"
										type="button"
										onClick={ () => this.onChangeSize( 'advanced', '' ) }
										isDefault
										aria-label={ sprintf( __( 'Advanced %s settings' ), label.toLowerCase() ) }
										isPrimary={ iconSize === 'advanced' }
									>
										{ __( 'Advanced' ) }
									</Button>
								</div>
							</BaseControl>
						}
						{ backgroundColor.color &&
							<Fragment>
								<RangeControl
									label={ __( 'Radius' ) }
									value={ borderRadius }
									onChange={ ( nextBorderRadius ) => setAttributes( { borderRadius: nextBorderRadius } ) }
									min={ 0 }
									max={ 200 }
									step={ 1 }
								/>
								<RangeControl
									label={ __( 'Padding' ) }
									value={ padding }
									onChange={ ( nextPadding ) => setAttributes( { padding: nextPadding } ) }
									min={ 5 }
									max={ this.generateMaxPadding( width ) }
									step={ 1 }
								/>
							</Fragment>
						}
						<TextControl
							type="text"
							autoComplete="off"
							label={ __( 'Icon Search' ) }
							value={ this.state.searchValue }
							className="coblocks-icon-types-list__search"
							onChange={ ( evt ) => {
								filterList( evt );
							} }
						/>
						<div className="coblocks-icon-types-list-wrapper">
							<ul className="editor-block-types-list coblocks-icon-types-list">
								{ ! this.state.isSearching ?
									<li className="editor-block-types-list__list-item selected-svg">
										<Button
											isLarge
											className="editor-block-list-item-button"
											onClick={ () => {
												return false;
											} }
										>
											<span className="editor-block-types-list__item-icon">
												{ svg[ iconStyle ][ icon ].icon }
											</span>
										</Button>
									</li> :
									null
								}
								{ Object.keys( this.state.filteredIcons[ iconStyle ] ).length > 0 ?
									Object.keys( this.state.filteredIcons[ iconStyle ] ).map( ( keyName, i ) => {
										return (
											<li key={ `editor-pblock-types-list-item-${ i }` } className={ classnames(
												'editor-block-types-list__list-item', {
													'is-selected': icon && ( icon === keyName ),
												},
											) }>
												<Tooltip text={ ( svg[ iconStyle ][ keyName ].label ) ? svg[ iconStyle ][ keyName ].label : keyName }>
													<Button
														isLarge
														className="editor-block-list-item-button"
														onClick={ () => {
															setAttributes( { icon: keyName } );
														} }
													>
														<span className="editor-block-types-list__item-icon">
															{ svg[ iconStyle ][ keyName ].icon }
														</span>
													</Button>
												</Tooltip>
											</li>
										);
									} ) :
									<li className="no-results"> { __( 'No results found.' ) } </li>
								}
							</ul>
						</div>
					</PanelBody>
					<PanelBody
						title={ __( 'Link Settings' ) }
						initialOpen={ false } >
						<TextControl
							label={ __( 'Link URL' ) }
							value={ href || '' }
							onChange={ value => setAttributes( { href: value } ) }
							placeholder="https://" />
						<TextControl
							label={ __( 'Link Rel' ) }
							value={ rel || '' }
							onChange={ value => setAttributes( { rel: value } ) }
						/>
						<ToggleControl
							label={ !! linkTarget ? __( 'Opening in New Tab' ) : __( 'Open in New Tab' ) }
							onChange={ this.onSetNewTab }
							checked={ linkTarget === '_blank' } />
					</PanelBody>
					<PanelColorSettings
						title={ __( 'Color Settings' ) }
						initialOpen={ false }
						colorSettings={ [
							{
								isLargeText: true,
								value: iconColor.color,
								onChange: setIconColor,
								label: __( 'Icon Color' ),
							},
							{
								value: backgroundColor.color,
								onChange: ( newBackground ) => {
									// Auto assign padding.
									if ( padding === 0 ) {
										setAttributes( { padding: 10 } );
									}

									// Reset padding when colors are cleared.
									if ( ! newBackground ) {
										setAttributes( { padding: 0, borderRadius: 0 } );
									}

									setBackgroundColor( newBackground );
								},
								label: __( 'Background Color' ),
							},

						] }
					>
						<ContrastChecker
							{ ...{
								iconColor: iconColor.color,
								backgroundColor: backgroundColor.color,
								fallbackIconColor,
								fallbackBackgroundColor,
							} }
						/>
					</PanelColorSettings>
				</InspectorControls>
			</Fragment>
		);
	}
}

export default compose( [
	applyWithColors,
	applyFallbackStyles,
] )( Inspector );