@wordpress/components
Version:
UI components for WordPress.
250 lines (237 loc) • 8.03 kB
JavaScript
import _extends from "@babel/runtime/helpers/esm/extends";
import { createElement } from "@wordpress/element";
/**
* External dependencies
*/
import { colord, extend } from 'colord';
import namesPlugin from 'colord/plugins/names';
import a11yPlugin from 'colord/plugins/a11y';
/**
* WordPress dependencies
*/
import { __, sprintf } from '@wordpress/i18n';
import { useCallback, useMemo, useState, forwardRef } from '@wordpress/element';
/**
* Internal dependencies
*/
import Dropdown from '../dropdown';
import { ColorPicker } from '../color-picker';
import CircularOptionPicker from '../circular-option-picker';
import { VStack } from '../v-stack';
import { Flex, FlexItem } from '../flex';
import { Truncate } from '../truncate';
import { ColorHeading } from './styles';
import DropdownContentWrapper from '../dropdown/dropdown-content-wrapper';
import { extractColorNameFromCurrentValue, isMultiplePaletteArray, normalizeColorValue, showTransparentBackground } from './utils';
extend([namesPlugin, a11yPlugin]);
function SinglePalette(_ref) {
let {
className,
clearColor,
colors,
onChange,
value,
actions
} = _ref;
const colorOptions = useMemo(() => {
return colors.map((_ref2, index) => {
let {
color,
name
} = _ref2;
const colordColor = colord(color);
const isSelected = value === color;
return createElement(CircularOptionPicker.Option, {
key: `${color}-${index}`,
isSelected: isSelected,
selectedIconProps: isSelected ? {
fill: colordColor.contrast() > colordColor.contrast('#000') ? '#fff' : '#000'
} : {},
tooltipText: name || // translators: %s: color hex code e.g: "#f00".
sprintf(__('Color code: %s'), color),
style: {
backgroundColor: color,
color
},
onClick: isSelected ? clearColor : () => onChange(color, index),
"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)
});
});
}, [colors, value, onChange, clearColor]);
return createElement(CircularOptionPicker, {
className: className,
options: colorOptions,
actions: actions
});
}
function MultiplePalettes(_ref3) {
let {
className,
clearColor,
colors,
onChange,
value,
actions,
headingLevel
} = _ref3;
if (colors.length === 0) {
return null;
}
return createElement(VStack, {
spacing: 3,
className: className
}, colors.map((_ref4, index) => {
let {
name,
colors: colorPalette
} = _ref4;
return createElement(VStack, {
spacing: 2,
key: index
}, createElement(ColorHeading, {
level: headingLevel
}, name), createElement(SinglePalette, {
clearColor: clearColor,
colors: colorPalette,
onChange: newColor => onChange(newColor, index),
value: value,
actions: colors.length === index + 1 ? actions : null
}));
}));
}
export function CustomColorPickerDropdown(_ref5) {
let {
isRenderedInSidebar,
popoverProps: receivedPopoverProps,
...props
} = _ref5;
const popoverProps = useMemo(() => ({
shift: true,
...(isRenderedInSidebar ? {
// When in the sidebar: open to the left (stacking),
// leaving the same gap as the parent popover.
placement: 'left-start',
offset: 34
} : {
// Default behavior: open below the anchor
placement: 'bottom',
offset: 8
}),
...receivedPopoverProps
}), [isRenderedInSidebar, receivedPopoverProps]);
return createElement(Dropdown, _extends({
contentClassName: "components-color-palette__custom-color-dropdown-content",
popoverProps: popoverProps
}, props));
}
function UnforwardedColorPalette(props, forwardedRef) {
const {
clearable = true,
colors = [],
disableCustomColors = false,
enableAlpha = false,
onChange,
value,
__experimentalIsRenderedInSidebar = false,
headingLevel = 2,
...otherProps
} = props;
const [normalizedColorValue, setNormalizedColorValue] = useState(value);
const clearColor = useCallback(() => onChange(undefined), [onChange]);
const customColorPaletteCallbackRef = useCallback(node => {
setNormalizedColorValue(normalizeColorValue(value, node));
}, [value]);
const hasMultipleColorOrigins = isMultiplePaletteArray(colors);
const buttonLabelName = useMemo(() => extractColorNameFromCurrentValue(value, colors, hasMultipleColorOrigins), [value, colors, hasMultipleColorOrigins]);
const renderCustomColorPicker = () => createElement(DropdownContentWrapper, {
paddingSize: "none"
}, createElement(ColorPicker, {
color: normalizedColorValue,
onChange: color => onChange(color),
enableAlpha: enableAlpha
}));
const colordColor = colord(normalizedColorValue !== null && normalizedColorValue !== void 0 ? normalizedColorValue : '');
const valueWithoutLeadingHash = value !== null && value !== void 0 && value.startsWith('#') ? value.substring(1) : value !== null && value !== void 0 ? value : '';
const customColorAccessibleLabel = !!valueWithoutLeadingHash ? sprintf( // translators: %1$s: The name of the color e.g: "vivid red". %2$s: The color's hex code e.g: "#f00".
__('Custom color picker. The currently selected color is called "%1$s" and has a value of "%2$s".'), buttonLabelName, valueWithoutLeadingHash) : __('Custom color picker.');
const paletteCommonProps = {
clearable,
clearColor,
onChange,
value,
actions: !!clearable && createElement(CircularOptionPicker.ButtonAction, {
onClick: clearColor
}, __('Clear')),
headingLevel
};
return createElement(VStack, _extends({
spacing: 3,
ref: forwardedRef
}, otherProps), !disableCustomColors && createElement(CustomColorPickerDropdown, {
isRenderedInSidebar: __experimentalIsRenderedInSidebar,
renderContent: renderCustomColorPicker,
renderToggle: _ref6 => {
let {
isOpen,
onToggle
} = _ref6;
return createElement(Flex, {
as: 'button',
ref: customColorPaletteCallbackRef,
justify: "space-between",
align: "flex-start",
className: "components-color-palette__custom-color",
"aria-expanded": isOpen,
"aria-haspopup": "true",
onClick: onToggle,
"aria-label": customColorAccessibleLabel,
style: showTransparentBackground(value) ? {
color: '#000'
} : {
background: value,
color: colordColor.contrast() > colordColor.contrast('#000') ? '#fff' : '#000'
}
}, createElement(FlexItem, {
isBlock: true,
as: Truncate,
className: "components-color-palette__custom-color-name"
}, buttonLabelName), createElement(FlexItem, {
as: "span",
className: "components-color-palette__custom-color-value"
}, valueWithoutLeadingHash));
}
}), hasMultipleColorOrigins ? createElement(MultiplePalettes, _extends({}, paletteCommonProps, {
colors: colors
})) : createElement(SinglePalette, _extends({}, paletteCommonProps, {
colors: colors
})));
}
/**
* Allows the user to pick a color from a list of pre-defined color entries.
*
* ```jsx
* import { ColorPalette } from '@wordpress/components';
* import { useState } from '@wordpress/element';
*
* const MyColorPalette = () => {
* const [ color, setColor ] = useState ( '#f00' )
* const colors = [
* { name: 'red', color: '#f00' },
* { name: 'white', color: '#fff' },
* { name: 'blue', color: '#00f' },
* ];
* return (
* <ColorPalette
* colors={ colors }
* value={ color }
* onChange={ ( color ) => setColor( color ) }
* />
* );
* } );
* ```
*/
export const ColorPalette = forwardRef(UnforwardedColorPalette);
export default ColorPalette;
//# sourceMappingURL=index.js.map