@gechiui/block-editor
Version:
220 lines (199 loc) • 5.17 kB
JavaScript
/**
* GeChiUI dependencies
*/
import { CustomSelectControl } from '@gechiui/components';
import { useMemo } from '@gechiui/element';
import { __, _x, sprintf } from '@gechiui/i18n';
const FONT_STYLES = [
{
name: _x( 'Regular', 'font style' ),
value: 'normal',
},
{
name: _x( 'Italic', 'font style' ),
value: 'italic',
},
];
const FONT_WEIGHTS = [
{
name: _x( 'Thin', 'font weight' ),
value: '100',
},
{
name: _x( 'Extra Light', 'font weight' ),
value: '200',
},
{
name: _x( 'Light', 'font weight' ),
value: '300',
},
{
name: _x( 'Regular', 'font weight' ),
value: '400',
},
{
name: _x( 'Medium', 'font weight' ),
value: '500',
},
{
name: _x( 'Semi Bold', 'font weight' ),
value: '600',
},
{
name: _x( 'Bold', 'font weight' ),
value: '700',
},
{
name: _x( 'Extra Bold', 'font weight' ),
value: '800',
},
{
name: _x( 'Black', 'font weight' ),
value: '900',
},
];
/**
* Adjusts font appearance field label in case either font styles or weights
* are disabled.
*
* @param {boolean} hasFontStyles Whether font styles are enabled and present.
* @param {boolean} hasFontWeights Whether font weights are enabled and present.
* @return {string} A label representing what font appearance is being edited.
*/
export const getFontAppearanceLabel = ( hasFontStyles, hasFontWeights ) => {
if ( ! hasFontStyles ) {
return __( '字体粗细' );
}
if ( ! hasFontWeights ) {
return __( '字体样式' );
}
return __( '外观' );
};
/**
* Control to display unified font style and weight options.
*
* @param {Object} props Component props.
*
* @return {GCElement} Font appearance control.
*/
export default function FontAppearanceControl( props ) {
const {
onChange,
hasFontStyles = true,
hasFontWeights = true,
value: { fontStyle, fontWeight },
} = props;
const hasStylesOrWeights = hasFontStyles || hasFontWeights;
const label = getFontAppearanceLabel( hasFontStyles, hasFontWeights );
const defaultOption = {
key: 'default',
name: __( '默认' ),
style: { fontStyle: undefined, fontWeight: undefined },
};
// Combines both font style and weight options into a single dropdown.
const combineOptions = () => {
const combinedOptions = [ defaultOption ];
FONT_STYLES.forEach( ( { name: styleName, value: styleValue } ) => {
FONT_WEIGHTS.forEach(
( { name: weightName, value: weightValue } ) => {
const optionName =
styleValue === 'normal'
? weightName
: sprintf(
/* translators: 1: Font weight name. 2: Font style name. */
__( '%2$s, %1$s' ),
weightName,
styleName
);
combinedOptions.push( {
key: `${ styleValue }-${ weightValue }`,
name: optionName,
style: {
fontStyle: styleValue,
fontWeight: weightValue,
},
} );
}
);
} );
return combinedOptions;
};
// Generates select options for font styles only.
const styleOptions = () => {
const combinedOptions = [ defaultOption ];
FONT_STYLES.forEach( ( { name, value } ) => {
combinedOptions.push( {
key: value,
name,
style: { fontStyle: value, fontWeight: undefined },
} );
} );
return combinedOptions;
};
// Generates select options for font weights only.
const weightOptions = () => {
const combinedOptions = [ defaultOption ];
FONT_WEIGHTS.forEach( ( { name, value } ) => {
combinedOptions.push( {
key: value,
name,
style: { fontStyle: undefined, fontWeight: value },
} );
} );
return combinedOptions;
};
// Map font styles and weights to select options.
const selectOptions = useMemo( () => {
if ( hasFontStyles && hasFontWeights ) {
return combineOptions();
}
return hasFontStyles ? styleOptions() : weightOptions();
}, [ props.options ] );
// Find current selection by comparing font style & weight against options,
// and fall back to the Default option if there is no matching option.
const currentSelection =
selectOptions.find(
( option ) =>
option.style.fontStyle === fontStyle &&
option.style.fontWeight === fontWeight
) || selectOptions[ 0 ];
// Adjusts screen reader description based on styles or weights.
const getDescribedBy = () => {
if ( ! currentSelection ) {
return __( '没有选定的字体外观' );
}
if ( ! hasFontStyles ) {
return sprintf(
// translators: %s: Currently selected font weight.
__( '当前选择的字体粗细:%s' ),
currentSelection.name
);
}
if ( ! hasFontWeights ) {
return sprintf(
// translators: %s: Currently selected font style.
__( '当前选择的字体样式:%s' ),
currentSelection.name
);
}
return sprintf(
// translators: %s: Currently selected font appearance.
__( '当前选择的字体外观:%s' ),
currentSelection.name
);
};
return (
hasStylesOrWeights && (
<CustomSelectControl
className="components-font-appearance-control"
label={ label }
describedBy={ getDescribedBy() }
options={ selectOptions }
value={ currentSelection }
onChange={ ( { selectedItem } ) =>
onChange( selectedItem.style )
}
/>
)
);
}