UNPKG

@wordpress/components

Version:
328 lines (319 loc) 7.81 kB
/** * External dependencies */ import classnames from 'classnames'; import { isEmpty, kebabCase } from 'lodash'; /** * WordPress dependencies */ import { __, sprintf } from '@wordpress/i18n'; import { useEffect, useState } from '@wordpress/element'; import { edit, close, chevronDown, chevronUp, plus } from '@wordpress/icons'; /** * Internal dependencies */ import Dropdown from '../dropdown'; import CircularOptionPicker from '../circular-option-picker'; import ColorPicker from '../color-picker'; import Button from '../button'; import TextControl from '../text-control'; import BaseControl from '../base-control'; function DropdownOpenOnMount( { shouldOpen, isOpen, onToggle } ) { useEffect( () => { if ( shouldOpen && ! isOpen ) { onToggle(); } }, [] ); return null; } function ColorOption( { color, name, slug, onChange, onRemove, onConfirm, confirmLabel = __( 'OK' ), isEditingNameOnMount = false, isEditingColorOnMount = false, onCancel, immutableColorSlugs = [], } ) { const [ isHover, setIsHover ] = useState( false ); const [ isFocused, setIsFocused ] = useState( false ); const [ isEditingName, setIsEditingName ] = useState( isEditingNameOnMount ); const [ isShowingAdvancedPanel, setIsShowingAdvancedPanel ] = useState( false ); const isShowingControls = ( isHover || isFocused || isEditingName || isShowingAdvancedPanel ) && ! immutableColorSlugs.includes( slug ); return ( <div tabIndex={ 0 } className={ classnames( 'components-color-edit__color-option', { 'is-hover': isHover && ! isEditingName && ! isShowingAdvancedPanel, } ) } onMouseEnter={ () => setIsHover( true ) } onMouseLeave={ () => setIsHover( false ) } onFocus={ () => setIsFocused( true ) } onBlur={ () => setIsFocused( false ) } aria-label={ name ? // translators: %s: The name of the color e.g: "vivid red". sprintf( __( 'Color: %s' ), name ) : // translators: %s: color hex code e.g: "#f00". sprintf( __( 'Color code: %s' ), color ) } > <div className="components-color-edit__color-option-main-area"> <Dropdown renderToggle={ ( { isOpen, onToggle } ) => ( <> <DropdownOpenOnMount shouldOpen={ isEditingColorOnMount } isOpen={ isOpen } onToggle={ onToggle } /> <CircularOptionPicker.Option style={ { backgroundColor: color, color } } aria-expanded={ isOpen } aria-haspopup="true" onClick={ onToggle } aria-label={ __( 'Edit color value' ) } /> </> ) } renderContent={ () => ( <ColorPicker color={ color } onChangeComplete={ ( newColor ) => onChange( { color: newColor.hex, slug, name, } ) } disableAlpha /> ) } /> { ! isEditingName && ( <div className="components-color-edit__color-option-color-name"> { name } </div> ) } { isEditingName && ( <> <TextControl className="components-color-edit__color-option-color-name-input" hideLabelFromVision onChange={ ( newColorName ) => onChange( { color, slug: kebabCase( newColorName ), name: newColorName, } ) } label={ __( 'Color name' ) } placeholder={ __( 'Name' ) } value={ name } /> <Button onClick={ () => { setIsEditingName( false ); setIsFocused( false ); if ( onConfirm ) { onConfirm(); } } } isPrimary > { confirmLabel } </Button> </> ) } { ! isEditingName && ( <> <Button className={ classnames( { 'components-color-edit__hidden-control': ! isShowingControls, } ) } icon={ edit } label={ __( 'Edit color name' ) } onClick={ () => setIsEditingName( true ) } /> <Button className={ classnames( { 'components-color-edit__hidden-control': ! isShowingControls, } ) } icon={ close } label={ __( 'Remove color' ) } onClick={ onRemove } /> </> ) } <Button className={ classnames( { 'components-color-edit__hidden-control': ! isShowingControls, } ) } icon={ isShowingAdvancedPanel ? chevronUp : chevronDown } label={ __( 'Additional color settings' ) } onClick={ () => { if ( isShowingAdvancedPanel ) { setIsFocused( false ); } setIsShowingAdvancedPanel( ! isShowingAdvancedPanel ); } } aria-expanded={ isShowingAdvancedPanel } /> </div> { onCancel && ( <Button className="components-color-edit__cancel-button" onClick={ onCancel } > { __( 'Cancel' ) } </Button> ) } { isShowingAdvancedPanel && ( <TextControl className="components-color-edit__slug-input" onChange={ ( newSlug ) => onChange( { color, slug: newSlug, name, } ) } label={ __( 'Slug' ) } value={ slug } /> ) } </div> ); } function ColorInserter( { onInsert, onCancel } ) { const [ color, setColor ] = useState( { color: '#fff', name: '', slug: '', } ); return ( <ColorOption color={ color.color } name={ color.name } slug={ color.slug } onChange={ setColor } confirmLabel={ __( 'Save' ) } onConfirm={ () => onInsert( color ) } isEditingNameOnMount isEditingColorOnMount onCancel={ onCancel } /> ); } export default function ColorEdit( { colors, onChange, emptyUI, immutableColorSlugs, canReset = true, } ) { const [ isInsertingColor, setIsInsertingColor ] = useState( false ); return ( <BaseControl> <fieldset> <div className="components-color-edit__label-and-insert-container"> <legend> <div> <BaseControl.VisualLabel> { __( 'Color palette' ) } </BaseControl.VisualLabel> </div> </legend> { ! isInsertingColor && ( <Button onClick={ () => { setIsInsertingColor( true ); } } className="components-color-edit__insert-button" icon={ plus } /> ) } </div> <div> { ! isEmpty( colors ) && colors.map( ( color, index ) => { return ( <ColorOption key={ index } color={ color.color } name={ color.name } slug={ color.slug } immutableColorSlugs={ immutableColorSlugs } onChange={ ( newColor ) => { onChange( colors.map( ( currentColor, currentIndex ) => { if ( currentIndex === index ) { return newColor; } return currentColor; } ) ); } } onRemove={ () => { onChange( colors.filter( ( _currentColor, currentIndex ) => { if ( currentIndex === index ) { return false; } return true; } ) ); } } /> ); } ) } { isInsertingColor && ( <ColorInserter onInsert={ ( newColor ) => { setIsInsertingColor( false ); onChange( [ ...( colors || [] ), newColor ] ); } } onCancel={ () => setIsInsertingColor( false ) } /> ) } { ! isInsertingColor && isEmpty( colors ) && emptyUI } </div> { !! canReset && ( <Button isSmall isSecondary className="components-color-edit__reset-button" onClick={ () => onChange() } > { __( 'Reset' ) } </Button> ) } </fieldset> </BaseControl> ); }