Repository URL to install this package:
|
Version:
1.1.31 ▾
|
/* jshint esversion: 6 */
import PropTypes from 'prop-types';
import classnames from 'classnames';
import ResponsiveControl from '../common/responsive.js';
import ColorControl from '../common/color.js';
import Icons from '../common/icons.js';
import capitalizeFirstLetter from '../common/capitalize-first.js';
import KadenceWebfontLoader from '../common/font-loader.js';
import FontPairModal from './font-pair';
import map from 'lodash/map';
import { __ } from '@wordpress/i18n';
import { ButtonGroup, Popover, Dashicon, Toolbar, Tooltip, Button, TextControl, TabPanel, RangeControl, SelectControl } from '@wordpress/components';
import { Component, Fragment } from '@wordpress/element';
class TypographyComponent extends Component {
constructor() {
super( ...arguments );
this.updateValues = this.updateValues.bind( this );
this.getSizeUnitSelect = this.getSizeUnitSelect.bind( this );
this.getUnitSelect = this.getUnitSelect.bind( this );
this.setTypographyOptions = this.setTypographyOptions.bind( this );
this.maybesScroll = this.maybesScroll.bind( this );
this.onColorChange = this.onColorChange.bind( this );
this.remoteUpdate = this.remoteUpdate.bind( this );
this.linkRemoteUpdate = this.linkRemoteUpdate.bind( this );
let value = this.props.control.setting.get();
let baseDefault;
let familyBaseDefault = {
'family': '-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"',
'google': false,
'fallback': '',
};
let allBaseDefault = {
'size': {
'desktop': 18,
},
'sizeType': 'px',
'lineHeight': {
'desktop': 1.65,
},
'lineType': '-',
'letterSpacing': {
'desktop': '',
},
'spacingType': 'em',
'family': '-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"',
'google': false,
'style': 'normal',
'weight': 'regular',
'variant': 'regular',
'color': 'palette4',
'transform': '',
'fallback': '',
};
let noColorBaseDefault = {
'size': {
'desktop': 18,
},
'sizeType': 'px',
'lineHeight': {
'desktop': 1.65,
},
'lineType': '-',
'letterSpacing': {
'desktop': '',
},
'spacingType': 'em',
'family': '-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"',
'google': false,
'style': 'normal',
'weight': 'regular',
'variant': 'regular',
'transform': '',
'fallback': '',
};
let sizeBaseDefault = {
'size': {
'desktop': 18,
},
'sizeType': 'px',
'lineHeight': {
'desktop': 1.65,
},
'lineType': '-',
'letterSpacing': {
'desktop': '',
},
'spacingType': 'em',
'color': 'palette4',
'transform': '',
};
let defaultParams = {
min: {
px: '0',
em: '0',
rem: '0',
'-': '0',
},
max: {
px: '200',
em: '16',
rem: '16',
'-': '16',
},
step: {
px: '1',
em: '0.01',
rem: '0.01',
'-': '0.01',
},
sizeUnits: ['px', 'em', 'rem'],
lineUnits: ['-', 'px', 'em', 'rem'],
spacingUnits: [ 'px', 'em', 'rem'],
canInherit: true,
transform: [ 'none', 'capitalize', 'uppercase', 'lowercase'],
id: 'kadence-general-font',
options: 'all',
};
this.controlParams = this.props.control.params.input_attrs ? {
...defaultParams,
...this.props.control.params.input_attrs,
} : defaultParams;
if ( 'family' === this.controlParams.options ) {
baseDefault = familyBaseDefault;
} else if ( 'size' === this.controlParams.options ) {
baseDefault = sizeBaseDefault;
} else if ( 'no-color' === this.controlParams.options ) {
baseDefault = noColorBaseDefault;
} else {
baseDefault = allBaseDefault;
}
this.defaultValue = this.props.control.params.default ? {
...baseDefault,
...this.props.control.params.default
} : baseDefault;
value = value ? {
...JSON.parse( JSON.stringify( this.defaultValue ) ),
...value
} : JSON.parse( JSON.stringify( this.defaultValue ) );
this.state = {
currentDevice: 'desktop',
isVisible: false,
isPreviewVisible: false,
openTab: 'size',
typographyOptions: [],
typographyVariants: [],
activeFont: [],
value: value,
fontVars: ( kadenceCustomizerControlsData.gfontvars ? kadenceCustomizerControlsData.gfontvars : [] ),
customFontVars: ( kadenceCustomizerControlsData.cfontvars ? kadenceCustomizerControlsData.cfontvars : [] ),
};
this.linkRemoteUpdate();
}
componentDidMount() {
let base_font;
let heading_font;
const fontsarray = Object.keys( this.state.fontVars ).map( ( name ) => {
return { label: name, value: name, google: true, group: 'Google Font' };
} );
let customFonts = false;
if ( this.state.customFontVars ) {
customFonts = Object.keys( this.state.customFontVars ).map( ( name ) => {
return { label: name, value: name, google: false, group: 'Custom Font', variants:'custom' };
} );
}
const inheritFont = [
{ label: 'Inherit', value: 'inherit', google: false, },
];
let systemFonts = [
{ label: 'System Default', value: '-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"', google: false, variants:'systemstack' },
{ label: 'Arial, Helvetica, sans-serif', value: 'Arial, Helvetica, sans-serif', google: false, group: 'System Fonts'},
{ label: '"Arial Black", Gadget, sans-serif', value: '"Arial Black", Gadget, sans-serif', google: false, group: 'System Fonts' },
{ label: 'Helvetica, sans-serif', value: 'Helvetica, sans-serif', google: false, group: 'System Fonts'},
{ label: '"Comic Sans MS", cursive, sans-serif', value: '"Comic Sans MS", cursive, sans-serif', google: false, group: 'System Fonts' },
{ label: 'Impact, Charcoal, sans-serif', value: 'Impact, Charcoal, sans-serif', google: false, group: 'System Fonts' },
{ label: '"Lucida Sans Unicode", "Lucida Grande", sans-serif', value: '"Lucida Sans Unicode", "Lucida Grande", sans-serif', google: false, group: 'System Fonts' },
{ label: 'Tahoma, Geneva, sans-serif', value: 'Tahoma, Geneva, sans-serif', google: false, group: 'System Fonts' },
{ label: '"Trebuchet MS", Helvetica, sans-serif', value: '"Trebuchet MS", Helvetica, sans-serif', google: false, group: 'System Fonts' },
{ label: 'Verdana, Geneva, sans-serif', value: 'Verdana, Geneva, sans-serif', google: false, group: 'System Fonts' },
{ label: 'Georgia, serif', value: 'Georgia, serif', google: false, group: 'System Fonts' },
{ label: '"Palatino Linotype", "Book Antiqua", Palatino, serif', value: '"Palatino Linotype", "Book Antiqua", Palatino, serif', google: false, group: 'System Fonts' },
{ label: '"Times New Roman", Times, serif', value: '"Times New Roman", Times, serif', google: false, group: 'System Fonts' },
{ label: 'Courier, monospace', value: 'Courier, monospace', google: false, group: 'System Fonts' },
{ label: '"Lucida Console", Monaco, monospace', value: '"Lucida Console", Monaco, monospace', google: false, group: 'System Fonts' },
];
if ( customFonts ) {
systemFonts = customFonts.concat( systemFonts );
}
let typographyOptions = systemFonts.concat( fontsarray );
if ( this.controlParams.canInherit ) {
base_font = this.props.customizer.control( 'base_font' ).setting.get()
typographyOptions = inheritFont.concat( typographyOptions );
}
if ( this.controlParams.headingInherit ) {
heading_font = this.props.customizer.control( 'heading_font' ).setting.get()
}
this.setState( { typographyOptions: typographyOptions } );
const standardVariants = [
{ value: 'regular', label: 'Regular', weight: 'regular', style: 'normal' },
{ value: 'italic', label: 'Regular Italic', weight: 'regular', style: 'italic' },
{ value: '700', label: 'Bold 700', weight: '700', style: 'normal' },
{ value: '700italic', label: 'Bold 700 Italic', weight: '700', style: 'italic' },
];
const systemVariants = [
{ value: '100', label: 'Thin 100', weight: '100', style: 'normal' },
{ value: '100italic', label: 'Thin 100 Italic', weight: '100', style: 'italic' },
{ value: '200', label: 'Extra-Light 200', weight: '200', style: 'normal' },
{ value: '200italic', label: 'Extra-Light 200 Italic', weight: '200', style: 'italic' },
{ value: '300', label: 'Light 300', weight: '300', style: 'normal' },
{ value: '300italic', label: 'Light 300 Italic', weight: '300', style: 'italic' },
{ value: 'regular', label: 'Regular', weight: 'regular', style: 'normal' },
{ value: 'italic', label: 'Regular Italic', weight: 'regular', style: 'italic' },
{ value: '500', label: 'Medium 500', weight: '500', style: 'normal' },
{ value: '500italic', label: 'Medium 500 Italic', weight: '500', style: 'italic' },
{ value: '600', label: 'Semi-Bold 600', weight: '600', style: 'normal' },
{ value: '600italic', label: 'Semi-Bold 600 Italic', weight: '600', style: 'italic' },
{ value: '700', label: 'Bold 700', weight: '700', style: 'normal' },
{ value: '700italic', label: 'Bold 700 Italic', weight: '700', style: 'italic' },
{ value: '800', label: 'Extra-Bold 800', weight: '800', style: 'normal' },
{ value: '800italic', label: 'Extra-Bold 800 Italic', weight: '800', style: 'italic' },
{ value: '900', label: 'Ultra-Bold 900', weight: '900', style: 'normal' },
{ value: '900italic', label: 'Ultra-Bold 900 Italic', weight: '900', style: 'italic' },
];
let activeFont = ( typographyOptions ? typographyOptions.filter( ( { value } ) => value === this.state.value.family ) : [ { label: 'Inherit', value: 'inherit', google: false } ] );
if ( 'inherit' === this.state.value.family && this.controlParams.headingInherit && undefined !== heading_font.family ) {
activeFont = ( typographyOptions ? typographyOptions.filter( ( { value } ) => value === heading_font.family ) : activeFont );
} else if ( 'inherit' === this.state.value.family && undefined !== base_font.family ) {
activeFont = ( typographyOptions ? typographyOptions.filter( ( { value } ) => value === base_font.family ) : activeFont );
}
let fontStandardVariants = standardVariants;
if ( activeFont && activeFont[ 0 ] ) {
if ( undefined !== activeFont[ 0 ].variants && 'systemstack' === activeFont[ 0 ].variants ) {
fontStandardVariants = systemVariants;
}
if ( undefined !== activeFont[ 0 ].variants && 'custom' === activeFont[ 0 ].variants && this.state.customFontVars && undefined !== this.state.customFontVars[ activeFont[ 0 ].value ] ) {
fontStandardVariants = this.state.customFontVars[ activeFont[ 0 ].value ].v.map( opt => ( { label: capitalizeFirstLetter( opt ), value: opt } ) );
}
if ( activeFont[ 0 ].google && activeFont[ 0 ].value ) {
fontStandardVariants = this.state.fontVars[ activeFont[ 0 ].value ].v.map( opt => ( { label: capitalizeFirstLetter( opt ), value: opt } ) );
}
}
this.setState( { typographyVariants: fontStandardVariants } );
this.setState( { activeFont: activeFont } );
}
setTypographyOptions( typographyOptions ) {
let base_font;
let heading_font;
const standardVariants = [
{ value: 'regular', label: 'Regular', weight: 'regular', style: 'normal' },
{ value: 'italic', label: 'Regular Italic', weight: 'regular', style: 'italic' },
{ value: '700', label: 'Bold 700', weight: '700', style: 'normal' },
{ value: '700italic', label: 'Bold 700 Italic', weight: '700', style: 'italic' },
];
const systemVariants = [
{ value: '100', label: 'Thin 100', weight: '100', style: 'normal' },
{ value: '100italic', label: 'Thin 100 Italic', weight: '100', style: 'italic' },
{ value: '200', label: 'Extra-Light 200', weight: '200', style: 'normal' },
{ value: '200italic', label: 'Extra-Light 200 Italic', weight: '200', style: 'italic' },
{ value: '300', label: 'Light 300', weight: '300', style: 'normal' },
{ value: '300italic', label: 'Light 300 Italic', weight: '300', style: 'italic' },
{ value: 'regular', label: 'Regular', weight: 'regular', style: 'normal' },
{ value: 'italic', label: 'Regular Italic', weight: 'regular', style: 'italic' },
{ value: '500', label: 'Medium 500', weight: '500', style: 'normal' },
{ value: '500italic', label: 'Medium 500 Italic', weight: '500', style: 'italic' },
{ value: '600', label: 'Semi-Bold 600', weight: '600', style: 'normal' },
{ value: '600italic', label: 'Semi-Bold 600 Italic', weight: '600', style: 'italic' },
{ value: '700', label: 'Bold 700', weight: '700', style: 'normal' },
{ value: '700italic', label: 'Bold 700 Italic', weight: '700', style: 'italic' },
{ value: '800', label: 'Extra-Bold 800', weight: '800', style: 'normal' },
{ value: '800italic', label: 'Extra-Bold 800 Italic', weight: '800', style: 'italic' },
{ value: '900', label: 'Ultra-Bold 900', weight: '900', style: 'normal' },
{ value: '900italic', label: 'Ultra-Bold 900 Italic', weight: '900', style: 'italic' },
];
if ( this.controlParams.canInherit ) {
base_font = this.props.customizer.control( 'base_font' ).setting.get()
}
if ( this.controlParams.headingInherit ) {
heading_font = this.props.customizer.control( 'heading_font' ).setting.get()
}
let activeFont = ( typographyOptions ? typographyOptions.filter( ( { value } ) => value === this.state.value.family ) : [ { label: 'Inherit', value: 'inherit', google: false } ] );
if ( 'inherit' === this.state.value.family && this.controlParams.headingInherit && undefined !== heading_font.family && 'inherit' !== heading_font.family ) {
activeFont = ( typographyOptions ? typographyOptions.filter( ( { value } ) => value === heading_font.family ) : activeFont );
} else if ( 'inherit' === this.state.value.family && undefined !== base_font.family ) {
activeFont = ( typographyOptions ? typographyOptions.filter( ( { value } ) => value === base_font.family ) : activeFont )
}
let fontStandardVariants = standardVariants;
if ( activeFont && activeFont[ 0 ] ) {
if ( undefined !== activeFont[ 0 ].variants && 'systemstack' === activeFont[ 0 ].variants ) {
fontStandardVariants = systemVariants;
}
if ( undefined !== activeFont[ 0 ].variants && 'custom' === activeFont[ 0 ].variants && this.state.customFontVars && undefined !== this.state.customFontVars[ activeFont[ 0 ].value ] ) {
fontStandardVariants = this.state.customFontVars[ activeFont[ 0 ].value ].v.map( opt => ( { label: capitalizeFirstLetter( opt ), value: opt } ) );
}
if ( activeFont[ 0 ].google && activeFont[ 0 ].value ) {
fontStandardVariants = this.state.fontVars[ activeFont[ 0 ].value ].v.map( opt => ( { label: capitalizeFirstLetter( opt ), value: opt } ) );
}
}
this.setState( { typographyVariants: fontStandardVariants } );
this.setState( { activeFont: activeFont } );
}
maybesScroll( tab ) {
let self = this;
if ( 'font' === tab ) {
setTimeout(function(){
var myElement = document.getElementById( self.controlParams.id + '-active-font' );
if ( myElement ) {
var topPos = myElement.offsetTop - 50;
document.getElementById(self.controlParams.id ).scrollTop = topPos;
}
}, 100);
} else if ( 'style' === tab ) {
setTimeout(function(){
var myElement = document.getElementById( self.controlParams.id + '-active-style' );
if ( myElement ) {
var topPos = myElement.offsetTop - 50;
document.getElementById(self.controlParams.id + '-style').scrollTop = topPos;
}
}, 100);
}
}
onColorChange( color, isPalette ) {
let value = this.state.value;
if ( isPalette ) {
value.color = isPalette;
} else if ( undefined !== color.rgb && undefined !== color.rgb.a && 1 !== color.rgb.a ) {
value.color = 'rgba(' + color.rgb.r + ',' + color.rgb.g + ',' + color.rgb.b + ',' + color.rgb.a + ')';
} else {
value.color = color.hex;
}
this.updateValues( value );
}
render() {
const { typographyOptions } = this.state;
let deviceIndex = this.state.currentDevice;
let currentFamily;
let fontVar = ( this.controlParams.headingInherit ? 'var(--global-heading-font)' : 'var(--global-base-font)' );
let currentSize;
let currentLineHeight;
let currentLetterSpacing;
var placeholderLineHeight = this.controlParams.headingInherit ? 1.5 : 1.4;
var placeholderSize = this.controlParams.id === 'base_font' || ( this.controlParams.canInherit && ! this.controlParams.headingInherit ) ? 17 : '';
if ( 'all' === this.controlParams.options || 'no-color' === this.controlParams.options || 'family' === this.controlParams.options ) {
currentFamily = ( this.state.value.family && 'inherit' !== this.state.value.family ? this.state.value.family : fontVar );
}
if ( 'all' === this.controlParams.options || 'no-color' === this.controlParams.options || 'size' === this.controlParams.options ) {
// Size
if ( undefined === this.state.value.size[deviceIndex] ) {
let largerDevice = ( this.state.currentDevice === 'mobile' ? 'tablet' : 'desktop' );
if ( undefined !== this.state.value.size[largerDevice] && this.state.value.size[largerDevice] ) {
currentSize = this.state.value.size[largerDevice];
} else if ( 'tablet' === largerDevice && undefined !== this.state.value.size['desktop'] && this.state.value.size['desktop'] ) {
currentSize = this.state.value.size['desktop'];
}
} else if ( '' === this.state.value.size[deviceIndex] ) {
let largerDevice = ( this.state.currentDevice === 'mobile' ? 'tablet' : 'desktop' );
if ( undefined !== this.state.value.size[largerDevice] && this.state.value.size[largerDevice] ) {
currentSize = this.state.value.size[largerDevice];
} else if ( 'tablet' === largerDevice && undefined !== this.state.value.size['desktop'] && this.state.value.size['desktop'] ) {
currentSize = this.state.value.size['desktop'];
}
} else if ( '' !== this.state.value.size[deviceIndex] ) {
currentSize = this.state.value.size[deviceIndex]
}
// Height
if ( undefined === this.state.value.lineHeight[deviceIndex] ) {
let largerDevice = ( this.state.currentDevice === 'mobile' ? 'tablet' : 'desktop' );
if ( undefined !== this.state.value.lineHeight[largerDevice] && this.state.value.lineHeight[largerDevice] ) {
currentLineHeight = this.state.value.lineHeight[largerDevice];
} else if ( 'tablet' === largerDevice && undefined !== this.state.value.lineHeight['desktop'] && this.state.value.lineHeight['desktop'] ) {
currentLineHeight = this.state.value.lineHeight['desktop'];
}
} else if ( '' === this.state.value.lineHeight[deviceIndex] ) {
let largerDevice = ( this.state.currentDevice === 'mobile' ? 'tablet' : 'desktop' );
if ( undefined !== this.state.value.lineHeight[largerDevice] && this.state.value.lineHeight[largerDevice] ) {
currentLineHeight = this.state.value.lineHeight[largerDevice];
} else if ( 'tablet' === largerDevice && undefined !== this.state.value.lineHeight['desktop'] && this.state.value.lineHeight['desktop'] ) {
currentLineHeight = this.state.value.lineHeight['desktop'];
}
} else if ( '' !== this.state.value.lineHeight[deviceIndex] ) {
currentLineHeight = this.state.value.lineHeight[deviceIndex]
}
// Spacing
if ( undefined === this.state.value.letterSpacing[deviceIndex] ) {
let largerDevice = ( this.state.currentDevice === 'mobile' ? 'tablet' : 'desktop' );
if ( undefined !== this.state.value.letterSpacing[largerDevice] && this.state.value.letterSpacing[largerDevice] ) {
currentLetterSpacing = this.state.value.letterSpacing[largerDevice];
} else if ( 'tablet' === largerDevice && undefined !== this.state.value.letterSpacing['desktop'] && this.state.value.letterSpacing['desktop'] ) {
currentLetterSpacing = this.state.value.letterSpacing['desktop'];
}
} else if ( '' === this.state.value.letterSpacing[deviceIndex] ) {
let largerDevice = ( this.state.currentDevice === 'mobile' ? 'tablet' : 'desktop' );
if ( undefined !== this.state.value.letterSpacing[largerDevice] && this.state.value.letterSpacing[largerDevice] ) {
currentLetterSpacing = this.state.value.letterSpacing[largerDevice];
} else if ( 'tablet' === largerDevice && undefined !== this.state.value.letterSpacing['desktop'] && this.state.value.letterSpacing['desktop'] ) {
currentLetterSpacing = this.state.value.letterSpacing['desktop'];
}
} else if ( '' !== this.state.value.letterSpacing[deviceIndex] ) {
currentLetterSpacing = this.state.value.letterSpacing[deviceIndex]
}
}
const fontFamilyTab = (
<Fragment>
<div className="kadence-font-family-search">
<TextControl
type="text"
value={ this.state.search }
placeholder={ __( 'Search' ) }
autocomplete="off"
onChange={ value => this.setState( { search: value } ) }
/>
{ undefined !== this.state.search && '' !== this.state.search && (
<Button
className="kadence-clear-search"
onClick={ () => {
this.setState( { search: '' } )
} }
>
<Dashicon icon='no' />
</Button>
) }
</div>
<div className="kadence-font-family-list-wrapper">
<ButtonGroup id={ this.controlParams.id } className="kadence-font-family-list" aria-label={ __( 'Font Family List' ) }>
{ map( typographyOptions, ( { label, value, google, group }, index ) => {
if ( ( ! this.state.search || ( label && label.toLowerCase().includes( this.state.search.toLowerCase() ) ) ) ) {
return (
<Button
key={ index }
id={ ( value === this.state.value.family ?
this.controlParams.id + '-active-font' :
undefined ) }
className={ ( value === this.state.value.family ?
'active-radio ' :
'' ) + "kadence-font-family-choice" }
onClick={ () => onTypoFontChange( value, google ) }
>
{ label }
</Button>
);
}
} ) }
</ButtonGroup>
</div>
</Fragment>
);
const fontStyleTab = (
<Fragment>
<div className="kadence-font-variant-list-wrapper">
<ButtonGroup id={ this.controlParams.id + '-style' } className="kadence-font-variant-list" aria-label={ __( 'Font Style List' ) }>
{ map( this.state.typographyVariants, ( { label, value }, index ) => {
return (
<Button
key={ index }
id={ ( value === this.state.value.variant ?
this.controlParams.id + '-active-style' :
undefined ) }
className={ ( value === this.state.value.variant ?
'active-radio ' :
'' ) + "kadence-font-variant-choice" }
style={{
fontFamily: this.state.value.family,
fontWeight: ( value === 'italic' || value === 'regular' ? 'normal' : value.replace(/[^0-9]/g,'') ),
fontStyle: ( value.includes( 'italic' ) ? 'italic' : 'regular' ),
} }
onClick={ () => onVariantFontChange( value ) }
>
{ label }
</Button>
);
} ) }
</ButtonGroup>
</div>
</Fragment>
);
const fontSizeTab = (
<Fragment>
<div class="kadence-range-control">
<ResponsiveControl
onChange={ ( currentDevice) => this.setState( { currentDevice } ) }
controlLabel={ __( 'Font Size', 'kadence' ) }
tooltip={ false }
>
<RangeControl
allowReset={ true }
initialPosition={ ( currentSize ? currentSize : placeholderSize ) }
value={ currentSize }
onChange={ (val) => {
if ( val ) {
let value = this.state.value;
value.size[ this.state.currentDevice ] = val;
this.updateValues( value );
} else {
let value = this.state.value;
value.size[ this.state.currentDevice ] = '';
this.updateValues( value );
}
} }
min={this.controlParams.min[this.state.value.sizeType]}
max={this.controlParams.max[this.state.value.sizeType]}
step={this.controlParams.step[this.state.value.sizeType]}
/>
{ this.controlParams.sizeUnits && (
<div className="kadence-select-units">
{ this.getSizeUnitSelect() }
</div>
) }
</ResponsiveControl>
</div>
<div class="kadence-range-control">
<ResponsiveControl
onChange={ ( currentDevice) => this.setState( { currentDevice } ) }
controlLabel={ __( 'Line Height', 'kadence' ) }
tooltip={ false }
>
<RangeControl
allowReset={ true }
initialPosition={ ( currentLineHeight ? currentLineHeight : placeholderLineHeight ) }
value={ currentLineHeight }
onChange={ (val) => {
if ( val ) {
let value = this.state.value;
value.lineHeight[ this.state.currentDevice ] = val;
this.updateValues( value );
} else {
let value = this.state.value;
value.lineHeight[ this.state.currentDevice ] = '';
this.updateValues( value );
}
} }
min={this.controlParams.min[this.state.value.lineType]}
max={this.controlParams.max[this.state.value.lineType]}
step={this.controlParams.step[this.state.value.lineType]}
/>
{ this.controlParams.lineUnits && (
<div className="kadence-select-units">
{ this.getUnitSelect( 'lineUnits', 'lineType' ) }
</div>
) }
</ResponsiveControl>
</div>
<div class="kadence-range-control">
<ResponsiveControl
onChange={ ( currentDevice) => this.setState( { currentDevice } ) }
controlLabel={ __( 'Letter Spacing', 'kadence' ) }
tooltip={ false }
>
<RangeControl
allowReset={ true }
value={ currentLetterSpacing }
initialPosition={ ( currentLetterSpacing ? currentLetterSpacing : '' ) }
onChange={ (val) => {
if ( val ) {
let value = this.state.value;
value.letterSpacing[ this.state.currentDevice ] = val;
this.updateValues( value );
} else {
let value = this.state.value;
value.letterSpacing[ this.state.currentDevice ] = '';
this.updateValues( value );
}
} }
min={-4}
max={this.controlParams.max[this.state.value.spacingType]}
step={this.controlParams.step[this.state.value.spacingType]}
/>
{ this.controlParams.spacingUnits && (
<div className="kadence-select-units">
{ this.getUnitSelect( 'spacingUnits', 'spacingType' ) }
</div>
) }
</ResponsiveControl>
</div>
<div class="kadence-range-control kadence-transform-controls">
<span className="customize-control-title">{ __( 'Transform' ) }</span>
<ButtonGroup className="kadence-radio-container-control kadence-radio-icon-container-control">
{ this.controlParams.transform.map( ( item ) => {
return (
<Fragment>
<Button
isTertiary
className={ ( item === this.state.value.transform ?
'active-radio ' :
'' ) + item }
onClick={ () => {
let value = this.state.value;
if ( item === this.state.value.transform ) {
value.transform = '';
} else {
value.transform = item;
}
this.updateValues( value );
} }
>
{ Icons[ item ] }
</Button>
</Fragment>
);
} ) }
</ButtonGroup>
</div>
</Fragment>
);
const controlLabel = (
<Fragment>
{
this.props.control.params.label &&
<span className="customize-control-title">
<Tooltip text={ __( 'Reset Values', 'kadence' ) }>
<Button
className="reset kadence-reset"
onClick={ () => {
this.updateValues( this.defaultValue );
} }
>
<Dashicon icon='image-rotate' />
</Button>
</Tooltip>
{ this.props.control.params.label }
{ 'base_font' === this.controlParams.id && (
<FontPairModal control={ this.props.control } customizer={ this.props.customizer } />
) }
</span>
}
</Fragment>
);
const onTypoFontChange = ( selected, isGoogle ) => {
let value = this.state.value;
let variant;
let weight;
let style;
let fallback;
if ( isGoogle ) {
if ( 'family' === this.controlParams.options ) {
variant = this.state.fontVars[ selected ].v;
} else {
if ( this.state.fontVars[ selected ].v.includes( value.variant ) ) {
variant = value.variant;
} else if ( ! this.state.fontVars[ selected ].v.includes( 'regular' ) ) {
variant = this.state.fontVars[ selected ].v[ 0 ];
} else {
variant = 'regular';
}
if ( variant === 'regular' || variant === 'italic' ) {
weight = 'normal';
} else {
weight = variant.replace(/[^0-9]/g,'');
}
if ( variant.includes( 'italic' ) ) {
style = 'italic';
} else {
style = 'normal';
}
}
fallback = ( this.state.fontVars[ selected ].c && this.state.fontVars[ selected ].c[0] ? this.state.fontVars[ selected ].c[0] : '' );
} else {
variant = 'regular';
weight = '400';
style = 'normal';
fallback = '';
}
value.variant = variant;
value.family = selected;
value.google = ( isGoogle ? true : false );
value.fallback = fallback;
if ( 'family' !== this.controlParams.options ) {
value.weight = weight;
value.style = style;
}
this.updateValues( value );
}
const onVariantFontChange = ( variant ) => {
let value = this.state.value;
let weight;
let style;
if ( variant === 'regular' || variant === 'italic' ) {
weight = 'normal';
} else {
weight = variant.replace(/[^0-9]/g,'');
}
if ( variant.includes( 'italic' ) ) {
style = 'italic';
} else {
style = 'normal';
}
value.variant = variant;
value.weight = weight;
value.style = style;
this.updateValues( value );
}
const toggleVisible = ( tab ) => {
this.setTypographyOptions( this.state.typographyOptions );
this.setState( { openTab : tab } );
this.setState( { isVisible: true } );
this.maybesScroll( tab );
};
const toggleClose = () => {
if ( this.state.isVisible === true ) {
this.setState( { isVisible: false } );
}
};
const toggleVisiblePreview = () => {
this.setState( { isPreviewVisible: true } );
};
const toggleClosePreview = () => {
if ( this.state.isPreviewVisible === true ) {
this.setState( { isPreviewVisible: false } );
}
};
const configVariants = {
google: {
families: [ this.state.value.family + ':' + ( this.state.value.google && this.state.fontVars[ this.state.value.family ] && this.state.fontVars[ this.state.value.family ].v ? this.state.fontVars[ this.state.value.family ].v.toString() : '' ) ],
},
classes: false,
events: false,
};
return (
<div className="kadence-control-field kadence-typography-control-wrap">
<div className="kadence-typography-control">
{ controlLabel }
<div className="kadence-typography-controls">
{ this.state.isVisible && 'family' === this.controlParams.options && (
<Popover position="top right" className="kadence-popover-color kadence-popover-typography kadence-customizer-popover" onClose={ toggleClose }>
<div className="kadence-popover-typography-single-item">
{ fontFamilyTab }
</div>
</Popover>
) }
{ this.state.isVisible && ( 'all' === this.controlParams.options || 'no-color' === this.controlParams.options ) && (
<Popover position="top left" className="kadence-popover-color kadence-popover-typography kadence-customizer-popover" onClose={ toggleClose }>
<TabPanel className="kadence-popover-tabs kadence-typography-tabs kadence-background-tabs"
activeClass="active-tab"
initialTabName={ this.state.openTab }
onSelect={ ( value ) => this.maybesScroll( value ) }
tabs={ [
{
name: 'font',
title: __( 'Font', 'kadence' ),
className: 'kadence-font-typography',
},
{
name: 'style',
title: __( 'Style', 'kadence' ),
className: 'kadence-style-typography',
},
{
name: 'size',
title: __( 'Size', 'kadence' ),
className: 'kadence-size-typography',
},
] }>
{
( tab ) => {
let tabout;
if ( tab.name ) {
if ( 'style' === tab.name ) {
tabout = fontStyleTab;
} else if ( 'font' === tab.name ) {
tabout = fontFamilyTab;
} else {
tabout = fontSizeTab;
}
}
return <div>{ tabout }</div>;
}
}
</TabPanel>
</Popover>
) }
{ 'all' === this.controlParams.options && (
<ColorControl
presetColors={ this.state.colorPalette }
color={ ( undefined !== this.state.value.color && this.state.value.color ? this.state.value.color : '' ) }
usePalette={ true }
onChangeComplete={ ( color, isPalette ) => this.onColorChange( color, isPalette ) }
customizer={ this.props.customizer }
/>
) }
{ ( 'all' === this.controlParams.options || 'family' === this.controlParams.options || 'no-color' === this.controlParams.options ) && (
<Tooltip text={ this.controlParams.tooltip ? this.controlParams.tooltip : __( 'Select Font', 'kadence' ) }>
<div className="typography-button-wrap">
<Button className={ 'kadence-typography-family-indicate' } onClick={ () => { this.state.isVisible ? toggleClose() : toggleVisible('font') } }>
{ ( this.state.value.family === '-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"' ? 'System Default' : capitalizeFirstLetter( this.state.value.family ) ) }
</Button>
</div>
</Tooltip>
) }
{ ( 'all' === this.controlParams.options || 'no-color' === this.controlParams.options ) && (
<Tooltip text={ this.controlParams.tooltip ? this.controlParams.tooltip : __( 'Select Style', 'kadence' ) }>
<div className="typography-button-wrap">
<Button className={ 'kadence-typography-style-indicate' } onClick={ () => { this.state.isVisible ? toggleClose() : toggleVisible('style') } }>
{ this.state.value.variant ? this.state.value.variant : __( 'inherit', 'kadence' ) }
</Button>
</div>
</Tooltip>
) }
{ ( 'all' === this.controlParams.options || 'size' === this.controlParams.options || 'no-color' === this.controlParams.options ) && (
<Tooltip text={ this.controlParams.tooltip ? this.controlParams.tooltip : __( 'Select Size', 'kadence' ) }>
<div className="typography-button-wrap">
<Button className={ 'kadence-typography-size-indicate' } onClick={ () => { this.state.isVisible ? toggleClose() : toggleVisible('size') } }>
{ currentSize ? currentSize + this.state.value.sizeType : __( 'inherit', 'kadence' ) }
</Button>
</div>
</Tooltip>
) }
{ ( 'all' === this.controlParams.options || 'family' === this.controlParams.options || 'no-color' === this.controlParams.options ) && (
<Tooltip text={ __( 'Show Preview Text', 'kadence' ) }>
<div className="typography-button-wrap">
<Button className={ 'kadence-typography-preview-indicate' } onClick={ () => { this.state.isPreviewVisible ? toggleClosePreview() : toggleVisiblePreview() } }>
{ this.state.isPreviewVisible ? <Dashicon icon="arrow-up" /> : <Dashicon icon="arrow-down" /> }
</Button>
</div>
</Tooltip>
) }
</div>
</div>
{ this.state.value.google && (
<KadenceWebfontLoader config={ configVariants } >
</KadenceWebfontLoader>
) }
{ this.state.isPreviewVisible && (
<div className="kadence-preview-font" style={ {
fontFamily: currentFamily,
fontWeight: ( 'all' === this.controlParams.options || 'no-color' === this.controlParams.options ? this.state.value.weight : 'bold' ),
fontStyle: ( 'all' === this.controlParams.options || 'no-color' === this.controlParams.options ? this.state.value.style : undefined ),
fontSize: ( 'all' === this.controlParams.options || 'no-color' === this.controlParams.options ? currentSize + this.state.value.sizeType : undefined ),
lineHeight: ( 'all' === this.controlParams.options || 'no-color' === this.controlParams.options ? currentLineHeight + ( '-' === this.state.value.lineType ? '' : this.state.value.lineType ) : 1.3 ),
letterSpacing: ( ( 'all' === this.controlParams.options || 'no-color' === this.controlParams.options ) && currentLetterSpacing ? currentLetterSpacing + this.state.value.spacingType : undefined ),
textTransform: ( ( 'all' === this.controlParams.options || 'no-color' === this.controlParams.options ) && this.state.value.transform ? this.state.value.transform : undefined ),
color: ( this.state.value.color && this.state.value.color.includes( 'palette' ) ? 'var(--global-' + this.state.value.color + ')' : this.state.value.color ),
} }>
{ __( 'Design is not just what it looks like and feels like. Design is how it works.', 'kadence' ) }
</div>
) }
</div>
);
}
getUnitSelect( unitType, unitSetting ) {
const units = this.controlParams[ unitType ];
if ( this.state.currentDevice !== 'desktop' ) {
return ( <Button
className="is-single"
disabled
>{ this.state.value[ unitSetting ] }</Button> );
}
const unitOptions = units.map( unit => ( { label: unit, value: unit } ) );
return <SelectControl
value={ this.state.value[ unitSetting ] }
options={ unitOptions }
onChange={ ( val ) => {
let value = this.state.value;
value[ unitSetting ] = val;
this.updateValues( value );
} }
/>
}
getSizeUnitSelect() {
const { sizeUnits } = this.controlParams;
if ( this.state.currentDevice !== 'desktop' ) {
return ( <Button
className="is-single"
disabled
>{ this.state.value.sizeType }</Button> );
}
const unitOptions = sizeUnits.map( unit => ( { label: unit, value: unit } ) );
return <SelectControl
value={ this.state.value.sizeType }
options={ unitOptions }
onChange={ ( val ) => {
let value = this.state.value;
value['sizeType'] = val;
this.updateValues( value );
} }
/>
}
updateValues( value ) {
this.setTypographyOptions( this.state.typographyOptions );
if ( 'base_font' === this.controlParams.id ) {
document.documentElement.style.setProperty('--global-base-font' , value.family );
}
if ( 'heading_font' === this.controlParams.id ) {
document.documentElement.style.setProperty('--global-heading-font' , value.family );
}
this.setState( { value: value } );
this.props.control.setting.set( {
...this.props.control.setting.get(),
...value,
flag: ! this.props.control.setting.get().flag
} );
}
linkRemoteUpdate() {
if ( 'base_font' === this.controlParams.id || 'heading_font' === this.controlParams.id ) {
let self = this;
document.addEventListener( 'kadenceRemoteUpdateFonts', function( e ) {
if ( e.detail === 'typography' ) {
self.remoteUpdate();
}
} );
}
}
remoteUpdate() {
let allBaseDefault = {
'size': {
'desktop': 18,
},
'sizeType': 'px',
'lineHeight': {
'desktop': 1.65,
},
'lineType': '-',
'letterSpacing': {
'desktop': '',
},
'spacingType': 'em',
'family': '-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"',
'google': false,
'style': 'normal',
'weight': 'regular',
'variant': 'regular',
'color': 'palette4',
'transform': '',
'fallback': '',
};
let familyBaseDefault = {
'family': '-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"',
'google': false,
'fallback': '',
};
if ( 'heading_font' === this.controlParams.id ) {
allBaseDefault = familyBaseDefault;
}
let value = this.props.control.setting.get();
value = value ? {
...JSON.parse( JSON.stringify( allBaseDefault ) ),
...value
} : JSON.parse( JSON.stringify( allBaseDefault ) );
this.setState( { value: value } );
}
}
TypographyComponent.propTypes = {
control: PropTypes.object.isRequired,
customizer: PropTypes.object.isRequired
};
export default TypographyComponent;