@gechiui/components
Version:
UI components for GeChiUI.
206 lines (193 loc) • 4.71 kB
JavaScript
/**
* External dependencies
*/
import { map } from 'lodash';
import { colord, extend } from 'colord';
import namesPlugin from 'colord/plugins/names';
import a11yPlugin from 'colord/plugins/a11y';
import classnames from 'classnames';
/**
* GeChiUI dependencies
*/
import { __, sprintf } from '@gechiui/i18n';
import { useCallback, useMemo } from '@gechiui/element';
/**
* Internal dependencies
*/
import Dropdown from '../dropdown';
import { ColorPicker } from '../color-picker';
import CircularOptionPicker from '../circular-option-picker';
import { VStack } from '../v-stack';
import { ColorHeading } from './styles';
extend( [ namesPlugin, a11yPlugin ] );
function SinglePalette( {
className,
clearColor,
colors,
onChange,
value,
actions,
} ) {
const colorOptions = useMemo( () => {
return map( colors, ( { color, name } ) => {
const colordColor = colord( color );
return (
<CircularOptionPicker.Option
key={ color }
isSelected={ value === color }
selectedIconProps={
value === color
? {
fill:
colordColor.contrast() >
colordColor.contrast( '#000' )
? '#fff'
: '#000',
}
: {}
}
tooltipText={
name ||
// translators: %s: color hex code e.g: "#f00".
sprintf( __( '颜色代码:%s' ), color )
}
style={ { backgroundColor: color, color } }
onClick={
value === color ? clearColor : () => onChange( color )
}
aria-label={
name
? // translators: %s: The name of the color e.g: "vivid red".
sprintf( __( '颜色:%s' ), name )
: // translators: %s: color hex code e.g: "#f00".
sprintf( __( '颜色代码:%s' ), color )
}
/>
);
} );
}, [ colors, value, onChange, clearColor ] );
return (
<CircularOptionPicker
className={ className }
options={ colorOptions }
actions={ actions }
/>
);
}
function MultiplePalettes( {
className,
clearColor,
colors,
onChange,
value,
actions,
} ) {
return (
<VStack spacing={ 3 } className={ className }>
{ colors.map( ( { name, colors: colorPalette }, index ) => {
return (
<VStack spacing={ 2 } key={ index }>
<ColorHeading>{ name }</ColorHeading>
<SinglePalette
clearColor={ clearColor }
colors={ colorPalette }
onChange={ onChange }
value={ value }
actions={
colors.length === index + 1 ? actions : null
}
/>
</VStack>
);
} ) }
</VStack>
);
}
export function CustomColorPickerDropdown( { isRenderedInSidebar, ...props } ) {
return (
<Dropdown
contentClassName={ classnames(
'components-color-palette__custom-color-dropdown-content',
{
'is-rendered-in-sidebar': isRenderedInSidebar,
}
) }
{ ...props }
/>
);
}
export default function ColorPalette( {
clearable = true,
className,
colors,
disableCustomColors = false,
enableAlpha,
onChange,
value,
__experimentalHasMultipleOrigins = false,
__experimentalIsRenderedInSidebar = false,
} ) {
const clearColor = useCallback( () => onChange( undefined ), [ onChange ] );
const Component =
__experimentalHasMultipleOrigins && colors?.length
? MultiplePalettes
: SinglePalette;
const renderCustomColorPicker = () => (
<ColorPicker
color={ value }
onChange={ ( color ) => onChange( color ) }
enableAlpha={ enableAlpha }
/>
);
let dropdownPosition;
if ( __experimentalIsRenderedInSidebar ) {
dropdownPosition = 'bottom left';
}
const colordColor = colord( value );
return (
<VStack spacing={ 3 } className={ className }>
{ ! disableCustomColors && (
<CustomColorPickerDropdown
position={ dropdownPosition }
isRenderedInSidebar={ __experimentalIsRenderedInSidebar }
renderContent={ renderCustomColorPicker }
renderToggle={ ( { isOpen, onToggle } ) => (
<button
className="components-color-palette__custom-color"
aria-expanded={ isOpen }
aria-haspopup="true"
onClick={ onToggle }
aria-label={ __( '自定义颜色选择器' ) }
style={ {
background: value,
color:
colordColor.contrast() >
colordColor.contrast( '#000' )
? '#fff'
: '#000',
} }
>
{ value }
</button>
) }
/>
) }
<Component
clearable={ clearable }
clearColor={ clearColor }
colors={ colors }
onChange={ onChange }
value={ value }
actions={
!! clearable && (
<CircularOptionPicker.ButtonAction
onClick={ clearColor }
>
{ __( '清除' ) }
</CircularOptionPicker.ButtonAction>
)
}
/>
</VStack>
);
}