feat: initial ACRIB WordPress deployment
- WordPress 6.9.4 (es_ES) with Kadence theme - Homepage: Hero, La Asociación, Pilares, Beneficios, Eventos, Miembros, Hazte Miembro, Contacto - Brand identity: #13294b navy, #a12932 burgundy, #c69c48 gold - Fonts: Raleway (headings) + Source Sans 3 (body) + Lato (UI) - Plugins: Kadence Blocks, Polylang, Contact Form 7 - Custom CSS with full brand styling and responsive layout - HTTPS enforced via wp-config.php proxy detection
This commit is contained in:
@@ -0,0 +1,146 @@
|
||||
/* jshint esversion: 6 */
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
import ResponsiveControl from '../common/responsive.js';
|
||||
import Icons from '../common/icons.js';
|
||||
import { ReactSortable } from "react-sortablejs";
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
const { ButtonGroup, Dashicon, Tooltip, Button } = wp.components;
|
||||
|
||||
const { Component, Fragment } = wp.element;
|
||||
class AvailableComponent extends Component {
|
||||
constructor() {
|
||||
super( ...arguments );
|
||||
this.linkRemovingItem = this.linkRemovingItem.bind( this );
|
||||
this.onDragEnd = this.onDragEnd.bind( this );
|
||||
this.onDragStart = this.onDragStart.bind( this );
|
||||
this.onUpdate = this.onUpdate.bind( this );
|
||||
this.onDragStop = this.onDragStop.bind( this );
|
||||
this.focusPanel = this.focusPanel.bind( this );
|
||||
let settings = {};
|
||||
let defaultParams = {};
|
||||
this.controlParams = this.props.control.params.input_attrs ? {
|
||||
...defaultParams,
|
||||
...this.props.control.params.input_attrs,
|
||||
} : defaultParams;
|
||||
if ( kadenceCustomizerControlsData.source && undefined !== this.props.customizer.control( kadenceCustomizerControlsData.source + '[' + this.controlParams.group + ']' ) ) {
|
||||
settings = this.props.customizer.control( kadenceCustomizerControlsData.source + '[' + this.controlParams.group + ']' ).setting.get();
|
||||
} else if ( undefined !== this.props.customizer.control( this.controlParams.group ) ) {
|
||||
settings = this.props.customizer.control( this.controlParams.group ).setting.get();
|
||||
}
|
||||
this.choices = ( kadenceCustomizerControlsData && kadenceCustomizerControlsData.choices && kadenceCustomizerControlsData.choices[ this.controlParams.group ] ? kadenceCustomizerControlsData.choices[ this.controlParams.group ] : [] );
|
||||
this.state = {
|
||||
settings: settings,
|
||||
};
|
||||
this.linkRemovingItem();
|
||||
}
|
||||
onUpdate() {
|
||||
if ( kadenceCustomizerControlsData.source && undefined !== this.props.customizer.control( kadenceCustomizerControlsData.source + '[' + this.controlParams.group + ']' ) ) {
|
||||
const settings = this.props.customizer.control( kadenceCustomizerControlsData.source + '[' + this.controlParams.group + ']' ).setting.get();
|
||||
this.setState( { settings: settings } );
|
||||
} else if ( undefined !== this.props.customizer.control( this.controlParams.group ) ) {
|
||||
const settings = this.props.customizer.control( this.controlParams.group ).setting.get();
|
||||
this.setState( { settings: settings } );
|
||||
}
|
||||
}
|
||||
onDragStart() {
|
||||
var dropzones = document.querySelectorAll( '.kadence-builder-area' );
|
||||
var i;
|
||||
for (i = 0; i < dropzones.length; ++i) {
|
||||
dropzones[i].classList.add( 'kadence-dragging-dropzones' );
|
||||
}
|
||||
}
|
||||
onDragStop() {
|
||||
var dropzones = document.querySelectorAll( '.kadence-builder-area' );
|
||||
var i;
|
||||
for (i = 0; i < dropzones.length; ++i) {
|
||||
dropzones[i].classList.remove( 'kadence-dragging-dropzones' );
|
||||
}
|
||||
}
|
||||
focusPanel( item ) {
|
||||
if ( undefined !== this.props.customizer.section( this.choices[ item ].section ) ) {
|
||||
this.props.customizer.section( this.choices[ item ].section ).focus();
|
||||
}
|
||||
}
|
||||
onDragEnd( items ) {
|
||||
if ( items.length != null && items.length === 0 ) {
|
||||
this.onUpdate();
|
||||
}
|
||||
}
|
||||
render() {
|
||||
const renderItem = ( item, row ) => {
|
||||
let available = true;
|
||||
this.controlParams.zones.map( ( zone ) => {
|
||||
Object.keys( this.state.settings[zone] ).map( ( area ) => {
|
||||
if ( this.state.settings[zone][area].includes( item ) ) {
|
||||
available = false;
|
||||
}
|
||||
} );
|
||||
} );
|
||||
let theitem = [ {
|
||||
id: item,
|
||||
} ];
|
||||
return (
|
||||
<Fragment>
|
||||
{ available && row === 'available' && (
|
||||
<ReactSortable animation={100} onStart={ () => this.onDragStart() } onEnd={ () => this.onDragStop() } group={ { name: this.controlParams.group, put: false } } className={ 'kadence-builder-item-start kadence-move-item' } list={ theitem } setList={ newState => this.onDragEnd( newState ) } >
|
||||
<div className="kadence-builder-item" data-id={ item } data-section={ undefined !== this.choices[ item ] && undefined !== this.choices[ item ].section ? this.choices[ item ].section : '' } key={ item }>
|
||||
<span
|
||||
className="kadence-builder-item-icon kadence-move-icon"
|
||||
>
|
||||
{ Icons['drag'] }
|
||||
</span>
|
||||
{ ( undefined !== this.choices[ item ] && undefined !== this.choices[ item ].name ? this.choices[ item ].name : '' ) }
|
||||
</div>
|
||||
</ReactSortable>
|
||||
) }
|
||||
{ ! available && row === 'links' && (
|
||||
<div className={ 'kadence-builder-item-start' }>
|
||||
<Button className="kadence-builder-item" data-id={ item } onClick={ () => this.focusPanel( item ) } data-section={ undefined !== this.choices[ item ] && undefined !== this.choices[ item ].section ? this.choices[ item ].section : '' } key={ item }>
|
||||
{ ( undefined !== this.choices[ item ] && undefined !== this.choices[ item ].name ? this.choices[ item ].name : '' ) }
|
||||
<span
|
||||
className="kadence-builder-item-icon"
|
||||
>
|
||||
<Dashicon icon="arrow-right-alt2"/>
|
||||
</span>
|
||||
</Button>
|
||||
</div>
|
||||
) }
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
return (
|
||||
<div className="kadence-control-field kadence-available-items">
|
||||
{ Object.keys( this.choices ).map( ( item ) => {
|
||||
return renderItem( item, 'links' );
|
||||
} ) }
|
||||
<div className="kadence-available-items-title">
|
||||
<span className="customize-control-title">{ __( 'Available Items', 'kadence' ) }</span>
|
||||
</div>
|
||||
<div className="kadence-available-items-pool">
|
||||
{ Object.keys( this.choices ).map( ( item ) => {
|
||||
return renderItem( item, 'available' );
|
||||
} ) }
|
||||
</div>
|
||||
{ this.props.control.renderNotice() }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
linkRemovingItem() {
|
||||
let self = this;
|
||||
document.addEventListener( 'kadenceRemovedBuilderItem', function( e ) {
|
||||
if ( e.detail === self.controlParams.group ) {
|
||||
self.onUpdate();
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
AvailableComponent.propTypes = {
|
||||
control: PropTypes.object.isRequired,
|
||||
customizer: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
export default AvailableComponent;
|
||||
@@ -0,0 +1,11 @@
|
||||
import { createRoot } from '@wordpress/element';
|
||||
import AvailableComponent from './available-component.js';
|
||||
|
||||
export const AvailableControl = wp.customize.KadenceControl.extend( {
|
||||
renderContent: function renderContent() {
|
||||
let control = this;
|
||||
let root = createRoot( control.container[0] );
|
||||
root.render( <AvailableComponent control={ control } customizer={ wp.customize } /> );
|
||||
// ReactDOM.render( <AvailableComponent control={ control } customizer={ wp.customize } />, control.container[0] );
|
||||
}
|
||||
} );
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,122 @@
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import classnames from 'classnames';
|
||||
|
||||
/**
|
||||
* WordPress dependencies
|
||||
*/
|
||||
import { Icon, check } from '@wordpress/icons';
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
const {
|
||||
Button,
|
||||
Dropdown,
|
||||
Tooltip,
|
||||
} = wp.components;
|
||||
|
||||
function Option( {
|
||||
className,
|
||||
isSelected,
|
||||
selectedIconProps,
|
||||
tooltipText,
|
||||
...additionalProps
|
||||
} ) {
|
||||
const optionButton = (
|
||||
<Button
|
||||
isPressed={ isSelected }
|
||||
className={ classnames(
|
||||
className,
|
||||
'components-circular-option-picker__option'
|
||||
) }
|
||||
{ ...additionalProps }
|
||||
/>
|
||||
);
|
||||
return (
|
||||
<div className="components-circular-option-picker__option-wrapper">
|
||||
{ tooltipText ? (
|
||||
<Tooltip text={ tooltipText }>{ optionButton }</Tooltip>
|
||||
) : (
|
||||
optionButton
|
||||
) }
|
||||
{ isSelected && (
|
||||
<Icon
|
||||
icon={ check }
|
||||
{ ...( selectedIconProps ? selectedIconProps : {} ) }
|
||||
/>
|
||||
) }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function DropdownLinkAction( {
|
||||
buttonProps,
|
||||
className,
|
||||
dropdownProps,
|
||||
linkText,
|
||||
} ) {
|
||||
return (
|
||||
<Dropdown
|
||||
className={ classnames(
|
||||
'components-circular-option-picker__dropdown-link-action',
|
||||
className
|
||||
) }
|
||||
renderToggle={ ( { isOpen, onToggle } ) => (
|
||||
<Button
|
||||
aria-expanded={ isOpen }
|
||||
onClick={ onToggle }
|
||||
isLink
|
||||
{ ...buttonProps }
|
||||
>
|
||||
{ linkText }
|
||||
</Button>
|
||||
) }
|
||||
{ ...dropdownProps }
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function ButtonAction( { className, children, ...additionalProps } ) {
|
||||
return (
|
||||
<Button
|
||||
className={ classnames(
|
||||
'components-circular-option-picker__clear',
|
||||
className
|
||||
) }
|
||||
isSmall
|
||||
isSecondary
|
||||
{ ...additionalProps }
|
||||
>
|
||||
{ children }
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
export default function CircularOptionPicker( {
|
||||
actions,
|
||||
className,
|
||||
options,
|
||||
children,
|
||||
} ) {
|
||||
return (
|
||||
<div
|
||||
className={ classnames(
|
||||
'components-circular-option-picker',
|
||||
className
|
||||
) }
|
||||
>
|
||||
{ options }
|
||||
{ children }
|
||||
{ actions && (
|
||||
<div className="components-circular-option-picker__custom-clear-wrapper">
|
||||
{ actions }
|
||||
</div>
|
||||
) }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
CircularOptionPicker.Option = Option;
|
||||
CircularOptionPicker.ButtonAction = ButtonAction;
|
||||
CircularOptionPicker.DropdownLinkAction = DropdownLinkAction;
|
||||
@@ -0,0 +1,229 @@
|
||||
import { createRoot } from '@wordpress/element';
|
||||
|
||||
import BackgroundComponent from './background-component.js';
|
||||
|
||||
export const BackgroundControl = wp.customize.MediaControl.extend( {
|
||||
renderContent: function renderContent() {
|
||||
let control = this;
|
||||
let root = createRoot( control.container[0] );
|
||||
root.render( <BackgroundComponent control={control} customizer={ wp.customize }/> );
|
||||
},
|
||||
initialize: function( id, options ) {
|
||||
var control = this,
|
||||
args = options || {};
|
||||
|
||||
args.params = args.params || {};
|
||||
if ( ! args.params.type ) {
|
||||
args.params.type = 'kadence-basic';
|
||||
}
|
||||
if ( ! args.params.content ) {
|
||||
args.params.content = jQuery( '<li></li>' );
|
||||
args.params.content.attr( 'id', 'customize-control-' + id.replace( /]/g, '' ).replace( /\[/g, '-' ) );
|
||||
args.params.content.attr( 'class', 'customize-control customize-control-' + args.params.type );
|
||||
}
|
||||
control.propertyElements = [];
|
||||
wp.customize.Control.prototype.initialize.call( control, id, args );
|
||||
},
|
||||
|
||||
/**
|
||||
* Add bidirectional data binding links between inputs and the setting(s).
|
||||
*
|
||||
* This is copied from wp.customize.Control.prototype.initialize(). It
|
||||
* should be changed in Core to be applied once the control is embedded.
|
||||
*
|
||||
* @private
|
||||
* @returns {null}
|
||||
*/
|
||||
_setUpSettingRootLinks: function() {
|
||||
var control = this,
|
||||
nodes = control.container.find( '[data-customize-setting-link]' );
|
||||
|
||||
nodes.each( function() {
|
||||
var node = jQuery( this );
|
||||
|
||||
wp.customize( node.data( 'customizeSettingLink' ), function( setting ) {
|
||||
var element = new wp.customize.Element( node );
|
||||
control.elements.push( element );
|
||||
element.sync( setting );
|
||||
element.set( setting() );
|
||||
} );
|
||||
} );
|
||||
},
|
||||
|
||||
/**
|
||||
* Add bidirectional data binding links between inputs and the setting properties.
|
||||
*
|
||||
* @private
|
||||
* @returns {null}
|
||||
*/
|
||||
_setUpSettingPropertyLinks: function() {
|
||||
var control = this,
|
||||
nodes;
|
||||
|
||||
if ( ! control.setting ) {
|
||||
return;
|
||||
}
|
||||
|
||||
nodes = control.container.find( '[data-customize-setting-property-link]' );
|
||||
|
||||
nodes.each( function() {
|
||||
var node = jQuery( this ),
|
||||
element,
|
||||
propertyName = node.data( 'customizeSettingPropertyLink' );
|
||||
|
||||
element = new wp.customize.Element( node );
|
||||
control.propertyElements.push( element );
|
||||
element.set( control.setting()[ propertyName ] );
|
||||
|
||||
element.bind( function( newPropertyValue ) {
|
||||
var newSetting = control.setting();
|
||||
if ( newPropertyValue === newSetting[ propertyName ] ) {
|
||||
return;
|
||||
}
|
||||
newSetting = _.clone( newSetting );
|
||||
newSetting[ propertyName ] = newPropertyValue;
|
||||
control.setting.set( newSetting );
|
||||
} );
|
||||
control.setting.bind( function( newValue ) {
|
||||
if ( newValue[ propertyName ] !== element.get() ) {
|
||||
element.set( newValue[ propertyName ] );
|
||||
}
|
||||
} );
|
||||
} );
|
||||
},
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
ready: function() {
|
||||
var control = this;
|
||||
// Shortcut so that we don't have to use _.bind every time we add a callback.
|
||||
_.bindAll( control, 'openFrame', 'select' );
|
||||
// Bind events, with delegation to facilitate re-rendering.
|
||||
control.container.on( 'click keydown', '.upload-button', function( e ) {
|
||||
let event = new CustomEvent( 'kadenceOpenMediaModal', {
|
||||
'detail': false,
|
||||
} );
|
||||
document.dispatchEvent( event );
|
||||
control.openFrame( e );
|
||||
} );
|
||||
|
||||
control._setUpSettingRootLinks();
|
||||
control._setUpSettingPropertyLinks();
|
||||
|
||||
wp.customize.Control.prototype.ready.call( control );
|
||||
|
||||
control.setting.bind( control.renderContent() );
|
||||
|
||||
control.deferred.embedded.done( function() {
|
||||
} );
|
||||
},
|
||||
|
||||
/**
|
||||
* Embed the control in the document.
|
||||
*
|
||||
* Override the embed() method to do nothing,
|
||||
* so that the control isn't embedded on load,
|
||||
* unless the containing section is already expanded.
|
||||
*
|
||||
* @returns {null}
|
||||
*/
|
||||
embed: function() {
|
||||
var control = this,
|
||||
sectionId = control.section();
|
||||
|
||||
if ( ! sectionId ) {
|
||||
return;
|
||||
}
|
||||
|
||||
wp.customize.section( sectionId, function( section ) {
|
||||
if ( section.expanded() || wp.customize.settings.autofocus.control === control.id ) {
|
||||
control.actuallyEmbed();
|
||||
} else {
|
||||
section.expanded.bind( function( expanded ) {
|
||||
if ( expanded ) {
|
||||
control.actuallyEmbed();
|
||||
}
|
||||
} );
|
||||
}
|
||||
} );
|
||||
},
|
||||
|
||||
/**
|
||||
* Deferred embedding of control when actually
|
||||
*
|
||||
* This function is called in Section.onChangeExpanded() so the control
|
||||
* will only get embedded when the Section is first expanded.
|
||||
*
|
||||
* @returns {null}
|
||||
*/
|
||||
actuallyEmbed: function() {
|
||||
var control = this;
|
||||
if ( 'resolved' === control.deferred.embedded.state() ) {
|
||||
return;
|
||||
}
|
||||
control.renderContent();
|
||||
control.deferred.embedded.resolve(); // This triggers control.ready().
|
||||
// Fire event after control is initialized.
|
||||
control.container.trigger( 'init' );
|
||||
},
|
||||
|
||||
/**
|
||||
* This is not working with autofocus.
|
||||
*
|
||||
* @param {object} [args] Args.
|
||||
* @returns {null}
|
||||
*/
|
||||
focus: function( args ) {
|
||||
var control = this;
|
||||
control.actuallyEmbed();
|
||||
wp.customize.Control.prototype.focus.call( control, args );
|
||||
},
|
||||
/**
|
||||
* Callback handler for when an attachment is selected in the media modal.
|
||||
* Gets the selected image information, and sets it within the control.
|
||||
*/
|
||||
select: function() {
|
||||
// Get the attachment from the modal frame.
|
||||
var node,
|
||||
attachment = this.frame.state().get( 'selection' ).first().toJSON(),
|
||||
device = wp.customize.previewedDevice.get(),
|
||||
settings = this.setting();
|
||||
// This is a hack to make the popup background work, I don't like this and need to find a better solution.
|
||||
if ( this.id && this.id === 'header_popup_background' ) {
|
||||
if ( device === 'tablet' || device === 'mobile' ) {
|
||||
if ( undefined !== settings['desktop'] && undefined !== settings['desktop'].type && settings['desktop'].type === 'image' ) {
|
||||
if ( undefined !== settings[device] && undefined !== settings[device].type && settings[device].type === 'image' ) {
|
||||
// Leave this alone
|
||||
} else {
|
||||
device = 'desktop';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( undefined === this.params.attachment ) {
|
||||
this.params.attachment = {};
|
||||
}
|
||||
if ( undefined === this.params.input_attrs.attachments ) {
|
||||
this.params.input_attrs.attachments = {};
|
||||
}
|
||||
this.params.input_attrs.attachments[ device ] = attachment;
|
||||
if ( undefined === settings[ device ] ) {
|
||||
settings[ device ] = {};
|
||||
}
|
||||
if ( undefined === settings[ device ].image ) {
|
||||
settings[ device ].image = {};
|
||||
}
|
||||
settings[ device ].image.url = attachment.url;
|
||||
// Set the Customizer setting; the callback takes care of rendering.
|
||||
let event = new CustomEvent( 'kadenceOpenMediaModal', {
|
||||
'detail': true,
|
||||
} );
|
||||
document.dispatchEvent( event );
|
||||
this.setting.set( {
|
||||
...this.setting.get(),
|
||||
...settings,
|
||||
flag: ! this.setting.get().flag
|
||||
} );
|
||||
},
|
||||
} );
|
||||
@@ -0,0 +1,112 @@
|
||||
/* jshint esversion: 6 */
|
||||
|
||||
const { Component, Fragment } = wp.element;
|
||||
import { isString } from "lodash";
|
||||
import KadenceColorPicker from "../../common/color-picker";
|
||||
import SwatchesControl from "../../common/swatches";
|
||||
|
||||
import {
|
||||
getGradientWithColorAtPositionChanged,
|
||||
getGradientWithColorStopAdded,
|
||||
} from "./utils";
|
||||
|
||||
class KadenceGradientColorPicker extends Component {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.state = {
|
||||
color: this.props.color ? this.props.color : "",
|
||||
alreadyInsertedPoint: false,
|
||||
};
|
||||
}
|
||||
render() {
|
||||
const getColorValue = () => {
|
||||
let color;
|
||||
const paletteIndex = this.state.color?.match(/\d+$/)?.[0] - 1;
|
||||
if (
|
||||
undefined !== this.state.color &&
|
||||
"" !== this.state.color &&
|
||||
null !== this.state.color &&
|
||||
isString(this.state.color) &&
|
||||
this.state.color.includes("palette")
|
||||
) {
|
||||
color = this.props.activePalette[paletteIndex]?.color;
|
||||
} else {
|
||||
color = this.state.color;
|
||||
}
|
||||
return color;
|
||||
};
|
||||
return (
|
||||
<div className="kadence-background-color-wrap">
|
||||
<KadenceColorPicker
|
||||
color={getColorValue()}
|
||||
onChangeComplete={(color) => {
|
||||
let rgb = {
|
||||
type: "rgba",
|
||||
value: "",
|
||||
};
|
||||
if (undefined !== color.rgb) {
|
||||
this.setState({ color: color.rgb });
|
||||
rgb.value = color.rgb;
|
||||
} else {
|
||||
this.setState({ color: color.hex });
|
||||
rgb.type = "literal";
|
||||
rgb.value = color.hex;
|
||||
}
|
||||
//console.log( rgb );
|
||||
let newGradient;
|
||||
if (this.state.alreadyInsertedPoint) {
|
||||
newGradient = getGradientWithColorAtPositionChanged(
|
||||
this.props.gradientAST,
|
||||
this.props.insertPosition,
|
||||
rgb
|
||||
);
|
||||
} else {
|
||||
newGradient = getGradientWithColorStopAdded(
|
||||
this.props.gradientAST,
|
||||
this.props.insertPosition,
|
||||
rgb
|
||||
);
|
||||
this.setState({ alreadyInsertedPoint: true });
|
||||
}
|
||||
this.props.onChange(newGradient);
|
||||
}}
|
||||
/>
|
||||
<SwatchesControl
|
||||
colors={this.props.activePalette}
|
||||
isPalette={
|
||||
undefined !== this.state.color &&
|
||||
"" !== this.state.color &&
|
||||
isString(this.state.color) &&
|
||||
this.state.color.includes("palette")
|
||||
? this.state.color
|
||||
: ""
|
||||
}
|
||||
onClick={(color, palette) => {
|
||||
this.setState({ color: palette });
|
||||
let rgb = {
|
||||
type: "literal",
|
||||
value: "var(--global-" + palette + ")",
|
||||
};
|
||||
let newGradient;
|
||||
if (this.state.alreadyInsertedPoint) {
|
||||
newGradient = getGradientWithColorAtPositionChanged(
|
||||
this.props.gradientAST,
|
||||
this.props.insertPosition,
|
||||
rgb
|
||||
);
|
||||
} else {
|
||||
newGradient = getGradientWithColorStopAdded(
|
||||
this.props.gradientAST,
|
||||
this.props.insertPosition,
|
||||
rgb
|
||||
);
|
||||
this.setState({ alreadyInsertedPoint: true });
|
||||
}
|
||||
this.props.onChange(newGradient);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
export default KadenceGradientColorPicker;
|
||||
@@ -0,0 +1,20 @@
|
||||
export const INSERT_POINT_WIDTH = 23;
|
||||
export const GRADIENT_MARKERS_WIDTH = 18;
|
||||
export const MINIMUM_DISTANCE_BETWEEN_INSERTER_AND_MARKER =
|
||||
( INSERT_POINT_WIDTH + GRADIENT_MARKERS_WIDTH ) / 2;
|
||||
export const MINIMUM_ABSOLUTE_LEFT_POSITION = 5;
|
||||
export const MINIMUM_DISTANCE_BETWEEN_POINTS = 0;
|
||||
export const MINIMUM_DISTANCE_BETWEEN_INSERTER_AND_POINT = 10;
|
||||
export const KEYBOARD_CONTROL_POINT_VARIATION = MINIMUM_DISTANCE_BETWEEN_INSERTER_AND_POINT;
|
||||
export const MINIMUM_SIGNIFICANT_MOVE = 5;
|
||||
export const DEFAULT_GRADIENT =
|
||||
'linear-gradient(135deg, rgba(6, 147, 227, 1) 0%, rgb(155, 81, 224) 100%)';
|
||||
export const COLOR_POPOVER_PROPS = {
|
||||
className: 'components-custom-gradient-picker__color-picker-popover kadence-popover-color',
|
||||
position: 'top',
|
||||
};
|
||||
export const DEFAULT_LINEAR_GRADIENT_ANGLE = 180;
|
||||
export const HORIZONTAL_GRADIENT_ORIENTATION = {
|
||||
type: 'angular',
|
||||
value: 90,
|
||||
};
|
||||
@@ -0,0 +1,298 @@
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import classnames from 'classnames';
|
||||
|
||||
/**
|
||||
* WordPress dependencies
|
||||
*/
|
||||
const {
|
||||
useRef,
|
||||
Component,
|
||||
useEffect,
|
||||
} = wp.element;
|
||||
import { __, sprintf } from '@wordpress/i18n';
|
||||
const {
|
||||
useInstanceId,
|
||||
} = wp.compose;
|
||||
|
||||
import KadenceGradientColorPicker from './edit-color-picker';
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
const {
|
||||
Button,
|
||||
ColorPicker,
|
||||
Dropdown,
|
||||
VisuallyHidden,
|
||||
KeyboardShortcuts,
|
||||
} = wp.components;
|
||||
import {
|
||||
getGradientWithColorAtIndexChanged,
|
||||
getGradientWithControlPointRemoved,
|
||||
getGradientWithPositionAtIndexChanged,
|
||||
getGradientWithPositionAtIndexDecreased,
|
||||
getGradientWithPositionAtIndexIncreased,
|
||||
getHorizontalRelativeGradientPosition,
|
||||
isControlPointOverlapping,
|
||||
} from './utils';
|
||||
import {
|
||||
COLOR_POPOVER_PROPS,
|
||||
GRADIENT_MARKERS_WIDTH,
|
||||
MINIMUM_SIGNIFICANT_MOVE,
|
||||
} from './constants';
|
||||
|
||||
class ControlPointKeyboardMove extends Component {
|
||||
constructor() {
|
||||
super( ...arguments );
|
||||
this.increase = this.increase.bind( this );
|
||||
this.decrease = this.decrease.bind( this );
|
||||
this.shortcuts = {
|
||||
right: this.increase,
|
||||
left: this.decrease,
|
||||
};
|
||||
}
|
||||
increase( event ) {
|
||||
// Stop propagation of the key press event to avoid focus moving
|
||||
// to another editor area.
|
||||
event.stopPropagation();
|
||||
const { gradientIndex, onChange, gradientAST } = this.props;
|
||||
onChange(
|
||||
getGradientWithPositionAtIndexIncreased(
|
||||
gradientAST,
|
||||
gradientIndex
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
decrease( event ) {
|
||||
// Stop propagation of the key press event to avoid focus moving
|
||||
// to another editor area.
|
||||
event.stopPropagation();
|
||||
const { gradientIndex, onChange, gradientAST } = this.props;
|
||||
onChange(
|
||||
getGradientWithPositionAtIndexDecreased(
|
||||
gradientAST,
|
||||
gradientIndex
|
||||
)
|
||||
);
|
||||
}
|
||||
render() {
|
||||
const { children } = this.props;
|
||||
return (
|
||||
<KeyboardShortcuts shortcuts={ this.shortcuts }>
|
||||
{ children }
|
||||
</KeyboardShortcuts>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function ControlPointButton( {
|
||||
isOpen,
|
||||
position,
|
||||
color,
|
||||
onChange,
|
||||
gradientIndex,
|
||||
gradientAST,
|
||||
...additionalProps
|
||||
} ) {
|
||||
const instanceId = useInstanceId( ControlPointButton );
|
||||
const descriptionId = `components-custom-gradient-picker__control-point-button-description-${ instanceId }`;
|
||||
return (
|
||||
<ControlPointKeyboardMove
|
||||
onChange={ onChange }
|
||||
gradientIndex={ gradientIndex }
|
||||
gradientAST={ gradientAST }
|
||||
>
|
||||
<Button
|
||||
aria-label={ sprintf(
|
||||
// translators: %1$s: gradient position e.g: 70%, %2$s: gradient color code e.g: rgb(52,121,151).
|
||||
__(
|
||||
'Gradient control point at position %1$s with color code %2$s.'
|
||||
),
|
||||
position,
|
||||
color
|
||||
) }
|
||||
aria-describedby={ descriptionId }
|
||||
aria-haspopup="true"
|
||||
aria-expanded={ isOpen }
|
||||
className={ classnames(
|
||||
'components-custom-gradient-picker__control-point-button',
|
||||
{
|
||||
'is-active': isOpen,
|
||||
}
|
||||
) }
|
||||
style={ {
|
||||
left: position,
|
||||
} }
|
||||
{ ...additionalProps }
|
||||
/>
|
||||
<VisuallyHidden id={ descriptionId }>
|
||||
{ __(
|
||||
'Use your left or right arrow keys or drag and drop with the mouse to change the gradient position. Press the button to change the color or remove the control point.'
|
||||
) }
|
||||
</VisuallyHidden>
|
||||
</ControlPointKeyboardMove>
|
||||
);
|
||||
}
|
||||
|
||||
export default function ControlPoints( {
|
||||
gradientPickerDomRef,
|
||||
ignoreMarkerPosition,
|
||||
markerPoints,
|
||||
onChange,
|
||||
gradientAST,
|
||||
activePalette,
|
||||
onStartControlPointChange,
|
||||
onStopControlPointChange,
|
||||
} ) {
|
||||
const controlPointMoveState = useRef();
|
||||
|
||||
const onMouseMove = ( event ) => {
|
||||
const relativePosition = getHorizontalRelativeGradientPosition(
|
||||
event.clientX,
|
||||
gradientPickerDomRef.current,
|
||||
GRADIENT_MARKERS_WIDTH
|
||||
);
|
||||
const {
|
||||
gradientAST: referenceGradientAST,
|
||||
position,
|
||||
significantMoveHappened,
|
||||
} = controlPointMoveState.current;
|
||||
if ( ! significantMoveHappened ) {
|
||||
const initialPosition =
|
||||
referenceGradientAST.colorStops[ position ].length.value;
|
||||
if (
|
||||
Math.abs( initialPosition - relativePosition ) >=
|
||||
MINIMUM_SIGNIFICANT_MOVE
|
||||
) {
|
||||
controlPointMoveState.current.significantMoveHappened = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
! isControlPointOverlapping(
|
||||
referenceGradientAST,
|
||||
relativePosition,
|
||||
position
|
||||
)
|
||||
) {
|
||||
onChange(
|
||||
getGradientWithPositionAtIndexChanged(
|
||||
referenceGradientAST,
|
||||
position,
|
||||
relativePosition
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const cleanEventListeners = () => {
|
||||
if (
|
||||
window &&
|
||||
window.removeEventListener &&
|
||||
controlPointMoveState.current &&
|
||||
controlPointMoveState.current.listenersActivated
|
||||
) {
|
||||
window.removeEventListener( 'mousemove', onMouseMove );
|
||||
window.removeEventListener( 'mouseup', cleanEventListeners );
|
||||
onStopControlPointChange();
|
||||
controlPointMoveState.current.listenersActivated = false;
|
||||
}
|
||||
};
|
||||
|
||||
useEffect( () => {
|
||||
return () => {
|
||||
cleanEventListeners();
|
||||
};
|
||||
}, [] );
|
||||
|
||||
return markerPoints.map(
|
||||
( point, index ) =>
|
||||
point &&
|
||||
ignoreMarkerPosition !== point.positionValue && (
|
||||
<Dropdown
|
||||
key={ index }
|
||||
onClose={ onStopControlPointChange }
|
||||
renderToggle={ ( { isOpen, onToggle } ) => (
|
||||
<ControlPointButton
|
||||
key={ index }
|
||||
onClick={ () => {
|
||||
if (
|
||||
controlPointMoveState.current &&
|
||||
controlPointMoveState.current
|
||||
.significantMoveHappened
|
||||
) {
|
||||
return;
|
||||
}
|
||||
if ( isOpen ) {
|
||||
onStopControlPointChange();
|
||||
} else {
|
||||
onStartControlPointChange();
|
||||
}
|
||||
onToggle();
|
||||
} }
|
||||
onMouseDown={ () => {
|
||||
if ( window && window.addEventListener ) {
|
||||
controlPointMoveState.current = {
|
||||
gradientAST,
|
||||
position: index,
|
||||
significantMoveHappened: false,
|
||||
listenersActivated: true,
|
||||
};
|
||||
onStartControlPointChange();
|
||||
window.addEventListener(
|
||||
'mousemove',
|
||||
onMouseMove
|
||||
);
|
||||
window.addEventListener(
|
||||
'mouseup',
|
||||
cleanEventListeners
|
||||
);
|
||||
}
|
||||
} }
|
||||
isOpen={ isOpen }
|
||||
position={ point.position }
|
||||
color={ point.color }
|
||||
onChange={ onChange }
|
||||
gradientAST={ gradientAST }
|
||||
gradientIndex={ index }
|
||||
/>
|
||||
) }
|
||||
renderContent={ ( { onClose } ) => (
|
||||
<>
|
||||
<KadenceGradientColorPicker
|
||||
color={ point.color }
|
||||
activePalette={ activePalette }
|
||||
onChange={ ( value ) => {
|
||||
onChange(
|
||||
getGradientWithColorAtIndexChanged(
|
||||
gradientAST,
|
||||
index,
|
||||
value
|
||||
)
|
||||
);
|
||||
} }
|
||||
/>
|
||||
<Button
|
||||
className="components-custom-gradient-picker__remove-control-point"
|
||||
onClick={ () => {
|
||||
onChange(
|
||||
getGradientWithControlPointRemoved(
|
||||
gradientAST,
|
||||
index
|
||||
)
|
||||
);
|
||||
onClose();
|
||||
} }
|
||||
isLink
|
||||
>
|
||||
{ __( 'Remove Control Point' ) }
|
||||
</Button>
|
||||
</>
|
||||
) }
|
||||
popoverProps={ COLOR_POPOVER_PROPS }
|
||||
/>
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,260 @@
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
|
||||
import { some } from 'lodash';
|
||||
import classnames from 'classnames';
|
||||
|
||||
/**
|
||||
* WordPress dependencies
|
||||
*/
|
||||
const {
|
||||
useRef,
|
||||
useReducer,
|
||||
useState
|
||||
} = wp.element;
|
||||
import { plusCircle } from '@wordpress/icons';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import {
|
||||
Button,
|
||||
Dropdown,
|
||||
ColorPicker,
|
||||
} from '@wordpress/components';
|
||||
import KadenceGradientColorPicker from './color-picker';
|
||||
|
||||
import ControlPoints from './control-points';
|
||||
import {
|
||||
INSERT_POINT_WIDTH,
|
||||
COLOR_POPOVER_PROPS,
|
||||
MINIMUM_DISTANCE_BETWEEN_INSERTER_AND_POINT,
|
||||
} from './constants';
|
||||
import { serializeGradient } from './serializer';
|
||||
import {
|
||||
getGradientWithColorAtPositionChanged,
|
||||
getGradientWithColorStopAdded,
|
||||
getHorizontalRelativeGradientPosition,
|
||||
getMarkerPoints,
|
||||
getGradientParsed,
|
||||
getLinearGradientRepresentationOfARadial,
|
||||
} from './utils';
|
||||
|
||||
function InsertPoint( {
|
||||
onChange,
|
||||
gradientAST,
|
||||
onOpenInserter,
|
||||
onCloseInserter,
|
||||
insertPosition,
|
||||
activePalette,
|
||||
} ) {
|
||||
const [ alreadyInsertedPoint, setAlreadyInsertedPoint ] = useState( false );
|
||||
return (
|
||||
<Dropdown
|
||||
className="components-custom-gradient-picker__inserter"
|
||||
onClose={ () => {
|
||||
onCloseInserter();
|
||||
} }
|
||||
renderToggle={ ( { isOpen, onToggle } ) => (
|
||||
<Button
|
||||
aria-expanded={ isOpen }
|
||||
onClick={ () => {
|
||||
if ( isOpen ) {
|
||||
onCloseInserter();
|
||||
} else {
|
||||
setAlreadyInsertedPoint( false );
|
||||
onOpenInserter();
|
||||
}
|
||||
onToggle();
|
||||
} }
|
||||
className="components-custom-gradient-picker__insert-point"
|
||||
icon={ plusCircle }
|
||||
style={ {
|
||||
left:
|
||||
insertPosition !== null
|
||||
? `${ insertPosition }%`
|
||||
: undefined,
|
||||
} }
|
||||
/>
|
||||
) }
|
||||
renderContent={ () => (
|
||||
<KadenceGradientColorPicker
|
||||
color={''}
|
||||
onChange={ ( value ) => onChange( value ) }
|
||||
activePalette={ activePalette }
|
||||
gradientAST={ gradientAST }
|
||||
insertPosition={ insertPosition }
|
||||
/>
|
||||
) }
|
||||
popoverProps={ COLOR_POPOVER_PROPS }
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function customGradientBarReducer( state, action ) {
|
||||
switch ( action.type ) {
|
||||
case 'MOVE_INSERTER':
|
||||
if ( state.id === 'IDLE' || state.id === 'MOVING_INSERTER' ) {
|
||||
return {
|
||||
id: 'MOVING_INSERTER',
|
||||
insertPosition: action.insertPosition,
|
||||
};
|
||||
}
|
||||
break;
|
||||
case 'STOP_INSERTER_MOVE':
|
||||
if ( state.id === 'MOVING_INSERTER' ) {
|
||||
return {
|
||||
id: 'IDLE',
|
||||
};
|
||||
}
|
||||
break;
|
||||
case 'OPEN_INSERTER':
|
||||
if ( state.id === 'MOVING_INSERTER' ) {
|
||||
return {
|
||||
id: 'INSERTING_CONTROL_POINT',
|
||||
insertPosition: state.insertPosition,
|
||||
};
|
||||
}
|
||||
break;
|
||||
case 'CLOSE_INSERTER':
|
||||
if ( state.id === 'INSERTING_CONTROL_POINT' ) {
|
||||
return {
|
||||
id: 'IDLE',
|
||||
};
|
||||
}
|
||||
break;
|
||||
case 'START_CONTROL_CHANGE':
|
||||
if ( state.id === 'IDLE' ) {
|
||||
return {
|
||||
id: 'MOVING_CONTROL_POINT',
|
||||
};
|
||||
}
|
||||
break;
|
||||
case 'STOP_CONTROL_CHANGE':
|
||||
if ( state.id === 'MOVING_CONTROL_POINT' ) {
|
||||
return {
|
||||
id: 'IDLE',
|
||||
};
|
||||
}
|
||||
break;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
const customGradientBarReducerInitialState = { id: 'IDLE' };
|
||||
|
||||
export default function CustomGradientBar( { value, onChange, activePalette } ) {
|
||||
const { gradientAST, gradientValue, hasGradient } = getGradientParsed(
|
||||
value
|
||||
);
|
||||
|
||||
const onGradientStructureChange = ( newGradientStructure ) => {
|
||||
onChange( serializeGradient( newGradientStructure ) );
|
||||
};
|
||||
|
||||
const gradientPickerDomRef = useRef();
|
||||
const markerPoints = getMarkerPoints( gradientAST );
|
||||
|
||||
const [ gradientBarState, gradientBarStateDispatch ] = useReducer(
|
||||
customGradientBarReducer,
|
||||
customGradientBarReducerInitialState
|
||||
);
|
||||
const onMouseEnterAndMove = ( event ) => {
|
||||
const insertPosition = getHorizontalRelativeGradientPosition(
|
||||
event.clientX,
|
||||
gradientPickerDomRef.current,
|
||||
INSERT_POINT_WIDTH
|
||||
);
|
||||
|
||||
// If the insert point is close to an existing control point don't show it.
|
||||
if (
|
||||
some( markerPoints, ( { positionValue } ) => {
|
||||
return (
|
||||
Math.abs( insertPosition - positionValue ) <
|
||||
MINIMUM_DISTANCE_BETWEEN_INSERTER_AND_POINT
|
||||
);
|
||||
} )
|
||||
) {
|
||||
if ( gradientBarState.id === 'MOVING_INSERTER' ) {
|
||||
gradientBarStateDispatch( { type: 'STOP_INSERTER_MOVE' } );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
gradientBarStateDispatch( { type: 'MOVE_INSERTER', insertPosition } );
|
||||
};
|
||||
|
||||
const onMouseLeave = () => {
|
||||
gradientBarStateDispatch( { type: 'STOP_INSERTER_MOVE' } );
|
||||
};
|
||||
|
||||
const isMovingInserter = gradientBarState.id === 'MOVING_INSERTER';
|
||||
const isInsertingControlPoint =
|
||||
gradientBarState.id === 'INSERTING_CONTROL_POINT';
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={ gradientPickerDomRef }
|
||||
className={ classnames(
|
||||
'components-custom-gradient-picker__gradient-bar',
|
||||
{ 'has-gradient': hasGradient }
|
||||
) }
|
||||
onMouseEnter={ onMouseEnterAndMove }
|
||||
onMouseMove={ onMouseEnterAndMove }
|
||||
// On radial gradients the bar should display a linear gradient.
|
||||
// On radial gradients the bar represents a slice of the gradient from the center until the outside.
|
||||
style={ {
|
||||
background:
|
||||
gradientAST.type === 'radial-gradient'
|
||||
? getLinearGradientRepresentationOfARadial(
|
||||
gradientAST
|
||||
)
|
||||
: gradientValue,
|
||||
} }
|
||||
onMouseLeave={ onMouseLeave }
|
||||
>
|
||||
<div className="components-custom-gradient-picker__markers-container">
|
||||
{ ( isMovingInserter || isInsertingControlPoint ) && (
|
||||
<InsertPoint
|
||||
insertPosition={ gradientBarState.insertPosition }
|
||||
onChange={ onGradientStructureChange }
|
||||
gradientAST={ gradientAST }
|
||||
onOpenInserter={ () => {
|
||||
gradientBarStateDispatch( {
|
||||
type: 'OPEN_INSERTER',
|
||||
} );
|
||||
} }
|
||||
onCloseInserter={ () => {
|
||||
gradientBarStateDispatch( {
|
||||
type: 'CLOSE_INSERTER',
|
||||
} );
|
||||
} }
|
||||
activePalette={ activePalette }
|
||||
/>
|
||||
) }
|
||||
<ControlPoints
|
||||
gradientPickerDomRef={ gradientPickerDomRef }
|
||||
ignoreMarkerPosition={
|
||||
isInsertingControlPoint
|
||||
? gradientBarState.insertPosition
|
||||
: undefined
|
||||
}
|
||||
markerPoints={ markerPoints }
|
||||
onChange={ onGradientStructureChange }
|
||||
gradientAST={ gradientAST }
|
||||
onStartControlPointChange={ () => {
|
||||
gradientBarStateDispatch( {
|
||||
type: 'START_CONTROL_CHANGE',
|
||||
} );
|
||||
} }
|
||||
onStopControlPointChange={ () => {
|
||||
gradientBarStateDispatch( {
|
||||
type: 'STOP_CONTROL_CHANGE',
|
||||
} );
|
||||
} }
|
||||
activePalette={ activePalette }
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,340 @@
|
||||
// Copyright (c) 2014 Rafael Caricio. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
export default function CustomGradientParser( code ) {
|
||||
var tokens = {
|
||||
linearGradient: /^(\-(webkit|o|ms|moz)\-)?(linear\-gradient)/i,
|
||||
repeatingLinearGradient: /^(\-(webkit|o|ms|moz)\-)?(repeating\-linear\-gradient)/i,
|
||||
radialGradient: /^(\-(webkit|o|ms|moz)\-)?(radial\-gradient)/i,
|
||||
repeatingRadialGradient: /^(\-(webkit|o|ms|moz)\-)?(repeating\-radial\-gradient)/i,
|
||||
sideOrCorner: /^to (left (top|bottom)|right (top|bottom)|left|right|top|bottom)/i,
|
||||
extentKeywords: /^(closest\-side|closest\-corner|farthest\-side|farthest\-corner|contain|cover)/,
|
||||
positionKeywords: /^(left|center|right|top|bottom)/i,
|
||||
pixelValue: /^(-?(([0-9]*\.[0-9]+)|([0-9]+\.?)))px/,
|
||||
percentageValue: /^(-?(([0-9]*\.[0-9]+)|([0-9]+\.?)))\%/,
|
||||
emValue: /^(-?(([0-9]*\.[0-9]+)|([0-9]+\.?)))em/,
|
||||
angleValue: /^(-?(([0-9]*\.[0-9]+)|([0-9]+\.?)))deg/,
|
||||
startCall: /^\(/,
|
||||
endCall: /^\)/,
|
||||
comma: /^,/,
|
||||
hexColor: /^\#([0-9a-fA-F]+)/,
|
||||
literalColor: /^([a-zA-Z]+)/,
|
||||
varColor: /^var([0-9a-zA-Z\\)\\(-]+)/,
|
||||
rgbColor: /^rgb/i,
|
||||
rgbaColor: /^rgba/i,
|
||||
number: /^(([0-9]*\.[0-9]+)|([0-9]+\.?))/
|
||||
};
|
||||
|
||||
var input = code.toString();
|
||||
|
||||
function error(msg) {
|
||||
var err = new Error(input + ': ' + msg);
|
||||
err.source = input;
|
||||
throw err;
|
||||
}
|
||||
|
||||
function getAST() {
|
||||
var ast = matchListDefinitions();
|
||||
|
||||
if (input.length > 0) {
|
||||
error('Invalid input not EOF');
|
||||
}
|
||||
|
||||
return ast;
|
||||
}
|
||||
|
||||
function matchListDefinitions() {
|
||||
return matchListing(matchDefinition);
|
||||
}
|
||||
|
||||
function matchDefinition() {
|
||||
return matchGradient(
|
||||
'linear-gradient',
|
||||
tokens.linearGradient,
|
||||
matchLinearOrientation) ||
|
||||
|
||||
matchGradient(
|
||||
'repeating-linear-gradient',
|
||||
tokens.repeatingLinearGradient,
|
||||
matchLinearOrientation) ||
|
||||
|
||||
matchGradient(
|
||||
'radial-gradient',
|
||||
tokens.radialGradient,
|
||||
matchListRadialOrientations) ||
|
||||
|
||||
matchGradient(
|
||||
'repeating-radial-gradient',
|
||||
tokens.repeatingRadialGradient,
|
||||
matchListRadialOrientations);
|
||||
}
|
||||
|
||||
function matchGradient(gradientType, pattern, orientationMatcher) {
|
||||
return matchCall(pattern, function(captures) {
|
||||
|
||||
var orientation = orientationMatcher();
|
||||
if (orientation) {
|
||||
if (!scan(tokens.comma)) {
|
||||
error('Missing comma before color stops');
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
type: gradientType,
|
||||
orientation: orientation,
|
||||
colorStops: matchListing(matchColorStop)
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function matchCall(pattern, callback) {
|
||||
var captures = scan(pattern);
|
||||
if (captures) {
|
||||
if (!scan(tokens.startCall)) {
|
||||
error('Missing (');
|
||||
}
|
||||
|
||||
var result = callback(captures);
|
||||
|
||||
if (!scan(tokens.endCall)) {
|
||||
error('Missing )');
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
function matchLinearOrientation() {
|
||||
return matchSideOrCorner() ||
|
||||
matchAngle();
|
||||
}
|
||||
|
||||
function matchSideOrCorner() {
|
||||
return match('directional', tokens.sideOrCorner, 1);
|
||||
}
|
||||
|
||||
function matchAngle() {
|
||||
return match('angular', tokens.angleValue, 1);
|
||||
}
|
||||
|
||||
function matchListRadialOrientations() {
|
||||
var radialOrientations,
|
||||
radialOrientation = matchRadialOrientation(),
|
||||
lookaheadCache;
|
||||
|
||||
if (radialOrientation) {
|
||||
radialOrientations = [];
|
||||
radialOrientations.push(radialOrientation);
|
||||
|
||||
lookaheadCache = input;
|
||||
if (scan(tokens.comma)) {
|
||||
radialOrientation = matchRadialOrientation();
|
||||
if (radialOrientation) {
|
||||
radialOrientations.push(radialOrientation);
|
||||
} else {
|
||||
input = lookaheadCache;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return radialOrientations;
|
||||
}
|
||||
|
||||
function matchRadialOrientation() {
|
||||
var radialType = matchCircle() ||
|
||||
matchEllipse();
|
||||
|
||||
if (radialType) {
|
||||
radialType.at = matchAtPosition();
|
||||
} else {
|
||||
var extent = matchExtentKeyword();
|
||||
if (extent) {
|
||||
radialType = extent;
|
||||
var positionAt = matchAtPosition();
|
||||
if (positionAt) {
|
||||
radialType.at = positionAt;
|
||||
}
|
||||
} else {
|
||||
var defaultPosition = matchPositioning();
|
||||
if (defaultPosition) {
|
||||
radialType = {
|
||||
type: 'default-radial',
|
||||
at: defaultPosition
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return radialType;
|
||||
}
|
||||
|
||||
function matchCircle() {
|
||||
var circle = match('shape', /^(circle)/i, 0);
|
||||
|
||||
if (circle) {
|
||||
circle.style = matchLength() || matchExtentKeyword();
|
||||
}
|
||||
|
||||
return circle;
|
||||
}
|
||||
|
||||
function matchEllipse() {
|
||||
var ellipse = match('shape', /^(ellipse)/i, 0);
|
||||
|
||||
if (ellipse) {
|
||||
ellipse.style = matchDistance() || matchExtentKeyword();
|
||||
}
|
||||
|
||||
return ellipse;
|
||||
}
|
||||
|
||||
function matchExtentKeyword() {
|
||||
return match('extent-keyword', tokens.extentKeywords, 1);
|
||||
}
|
||||
|
||||
function matchAtPosition() {
|
||||
if (match('position', /^at/, 0)) {
|
||||
var positioning = matchPositioning();
|
||||
|
||||
if (!positioning) {
|
||||
error('Missing positioning value');
|
||||
}
|
||||
|
||||
return positioning;
|
||||
}
|
||||
}
|
||||
|
||||
function matchPositioning() {
|
||||
var location = matchCoordinates();
|
||||
|
||||
if (location.x || location.y) {
|
||||
return {
|
||||
type: 'position',
|
||||
value: location
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function matchCoordinates() {
|
||||
return {
|
||||
x: matchDistance(),
|
||||
y: matchDistance()
|
||||
};
|
||||
}
|
||||
|
||||
function matchListing(matcher) {
|
||||
var captures = matcher(),
|
||||
result = [];
|
||||
|
||||
if (captures) {
|
||||
result.push(captures);
|
||||
while (scan(tokens.comma)) {
|
||||
captures = matcher();
|
||||
if (captures) {
|
||||
result.push(captures);
|
||||
} else {
|
||||
error('One extra comma');
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function matchColorStop() {
|
||||
var color = matchColor();
|
||||
|
||||
if (!color) {
|
||||
error('Expected color definition');
|
||||
}
|
||||
|
||||
color.length = matchDistance();
|
||||
return color;
|
||||
}
|
||||
|
||||
function matchColor() {
|
||||
return matchHexColor() ||
|
||||
matchVarColor() ||
|
||||
matchRGBAColor() ||
|
||||
matchRGBColor() ||
|
||||
matchLiteralColor();
|
||||
}
|
||||
|
||||
function matchLiteralColor() {
|
||||
return match('literal', tokens.literalColor, 0);
|
||||
}
|
||||
function matchVarColor() {
|
||||
return match('literal', tokens.varColor, 0);
|
||||
}
|
||||
function matchHexColor() {
|
||||
return match('hex', tokens.hexColor, 1);
|
||||
}
|
||||
function matchRGBColor() {
|
||||
return matchCall(tokens.rgbColor, function() {
|
||||
return {
|
||||
type: 'rgb',
|
||||
value: matchListing(matchNumber)
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function matchRGBAColor() {
|
||||
return matchCall(tokens.rgbaColor, function() {
|
||||
return {
|
||||
type: 'rgba',
|
||||
value: matchListing(matchNumber)
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function matchNumber() {
|
||||
return scan(tokens.number)[1];
|
||||
}
|
||||
|
||||
function matchDistance() {
|
||||
return match('%', tokens.percentageValue, 1) ||
|
||||
matchPositionKeyword() ||
|
||||
matchLength();
|
||||
}
|
||||
|
||||
function matchPositionKeyword() {
|
||||
return match('position-keyword', tokens.positionKeywords, 1);
|
||||
}
|
||||
|
||||
function matchLength() {
|
||||
return match('px', tokens.pixelValue, 1) ||
|
||||
match('em', tokens.emValue, 1);
|
||||
}
|
||||
|
||||
function match(type, pattern, captureIndex) {
|
||||
var captures = scan(pattern);
|
||||
if (captures) {
|
||||
return {
|
||||
type: type,
|
||||
value: captures[captureIndex]
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function scan(regexp) {
|
||||
var captures,
|
||||
blankCaptures;
|
||||
|
||||
blankCaptures = /^[\n\r\t\s]+/.exec(input);
|
||||
if (blankCaptures) {
|
||||
consume(blankCaptures[0].length);
|
||||
}
|
||||
|
||||
captures = regexp.exec(input);
|
||||
if (captures) {
|
||||
consume(captures[0].length);
|
||||
}
|
||||
|
||||
return captures;
|
||||
}
|
||||
|
||||
function consume(size) {
|
||||
input = input.substr(size);
|
||||
}
|
||||
return getAST();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/* jshint esversion: 6 */
|
||||
|
||||
const { Component, Fragment } = wp.element;
|
||||
import { isString } from "lodash";
|
||||
import KadenceColorPicker from "../../common/color-picker";
|
||||
import SwatchesControl from "../../common/swatches";
|
||||
|
||||
class KadenceGradientColorPicker extends Component {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.state = {
|
||||
color: this.props.color ? this.props.color : "",
|
||||
};
|
||||
}
|
||||
render() {
|
||||
const getColorValue = () => {
|
||||
let color;
|
||||
const paletteIndex = this.state.color?.match(/\d+$/)?.[0] - 1;
|
||||
if (
|
||||
undefined !== this.state.color &&
|
||||
"" !== this.state.color &&
|
||||
isString(this.state.color) &&
|
||||
this.state.color.includes("palette") &&
|
||||
this.props.activePalette &&
|
||||
this.props.activePalette[paletteIndex]
|
||||
) {
|
||||
color = this.props.activePalette[paletteIndex]?.color;
|
||||
} else {
|
||||
color = this.state.color;
|
||||
}
|
||||
return color;
|
||||
};
|
||||
return (
|
||||
<div className="kadence-background-color-wrap">
|
||||
<KadenceColorPicker
|
||||
color={getColorValue()}
|
||||
onChangeComplete={(color) => {
|
||||
let rgb = {
|
||||
type: "rgba",
|
||||
value: "",
|
||||
};
|
||||
if (undefined !== color.rgb) {
|
||||
this.setState({ color: color.rgb });
|
||||
rgb.value = color.rgb;
|
||||
} else {
|
||||
this.setState({ color: color.hex });
|
||||
rgb.type = "literal";
|
||||
rgb.value = color.hex;
|
||||
}
|
||||
|
||||
this.props.onChange(rgb);
|
||||
}}
|
||||
/>
|
||||
<SwatchesControl
|
||||
colors={this.props.activePalette}
|
||||
isPalette={
|
||||
undefined !== this.state.color &&
|
||||
"" !== this.state.color &&
|
||||
isString(this.state.color) &&
|
||||
this.state.color.includes("palette")
|
||||
? this.state.color
|
||||
: ""
|
||||
}
|
||||
onClick={(color, palette) => {
|
||||
this.setState({
|
||||
color: "var(--global-" + palette + ")",
|
||||
});
|
||||
let rgb = {
|
||||
type: "literal",
|
||||
value: "var(--global-" + palette + ")",
|
||||
};
|
||||
this.props.onChange(rgb);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
export default KadenceGradientColorPicker;
|
||||
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* WordPress dependencies
|
||||
*/
|
||||
import { withInstanceId } from '@wordpress/compose';
|
||||
import {
|
||||
Circle,
|
||||
LinearGradient,
|
||||
Path,
|
||||
RadialGradient,
|
||||
Stop,
|
||||
SVG,
|
||||
} from '@wordpress/primitives';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
export const LinearGradientIcon = withInstanceId( ( { instanceId } ) => {
|
||||
const linerGradientId = `linear-gradient-${ instanceId }`;
|
||||
return (
|
||||
<SVG
|
||||
fill="none"
|
||||
height="20"
|
||||
viewBox="0 0 20 20"
|
||||
width="20"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<LinearGradient
|
||||
id={ linerGradientId }
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="10"
|
||||
x2="10"
|
||||
y1="1"
|
||||
y2="19"
|
||||
>
|
||||
<Stop offset="0" stopColor="#000000" />
|
||||
<Stop offset="1" stopColor="#ffffff" />
|
||||
</LinearGradient>
|
||||
<Path d="m1 1h18v18h-18z" fill={ `url(#${ linerGradientId })` } />
|
||||
</SVG>
|
||||
);
|
||||
} );
|
||||
|
||||
export const RadialGradientIcon = withInstanceId( ( { instanceId } ) => {
|
||||
const radialGradientId = `radial-gradient-${ instanceId }`;
|
||||
return (
|
||||
<SVG
|
||||
fill="none"
|
||||
height="20"
|
||||
viewBox="0 0 20 20"
|
||||
width="20"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<RadialGradient
|
||||
id={ radialGradientId }
|
||||
cx="0"
|
||||
cy="0"
|
||||
gradientTransform="matrix(0 9 -9 0 10 10)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
r="1"
|
||||
>
|
||||
<Stop offset="0" stopColor="#000000" />
|
||||
<Stop offset="1" stopColor="#ffffff" />
|
||||
</RadialGradient>
|
||||
<Circle
|
||||
cx="10"
|
||||
cy="10"
|
||||
fill={ `url(#${ radialGradientId })` }
|
||||
r="9"
|
||||
/>
|
||||
</SVG>
|
||||
);
|
||||
} );
|
||||
@@ -0,0 +1,123 @@
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { get, omit } from 'lodash';
|
||||
|
||||
/**
|
||||
* WordPress dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { LinearGradientIcon, RadialGradientIcon } from './icons';
|
||||
import CustomGradientBar from './custom-gradient-bar';
|
||||
import { getGradientParsed } from './utils';
|
||||
import { serializeGradient } from './serializer';
|
||||
import {
|
||||
DEFAULT_LINEAR_GRADIENT_ANGLE,
|
||||
HORIZONTAL_GRADIENT_ORIENTATION,
|
||||
} from './constants';
|
||||
|
||||
const {
|
||||
ToolbarGroup,
|
||||
AnglePickerControl,
|
||||
BaseControl,
|
||||
} = wp.components;
|
||||
|
||||
const GradientAnglePicker = ( { gradientAST, hasGradient, onChange } ) => {
|
||||
const angle = get(
|
||||
gradientAST,
|
||||
[ 'orientation', 'value' ],
|
||||
DEFAULT_LINEAR_GRADIENT_ANGLE
|
||||
);
|
||||
const onAngleChange = ( newAngle ) => {
|
||||
onChange(
|
||||
serializeGradient( {
|
||||
...gradientAST,
|
||||
orientation: {
|
||||
type: 'angular',
|
||||
value: newAngle,
|
||||
},
|
||||
} )
|
||||
);
|
||||
};
|
||||
return (
|
||||
<AnglePickerControl
|
||||
value={ hasGradient ? angle : '' }
|
||||
onChange={ onAngleChange }
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const GradientTypePicker = ( { gradientAST, hasGradient, onChange } ) => {
|
||||
const { type } = gradientAST;
|
||||
const onSetLinearGradient = () => {
|
||||
onChange(
|
||||
serializeGradient( {
|
||||
...gradientAST,
|
||||
...( gradientAST.orientation
|
||||
? {}
|
||||
: { orientation: HORIZONTAL_GRADIENT_ORIENTATION } ),
|
||||
type: 'linear-gradient',
|
||||
} )
|
||||
);
|
||||
};
|
||||
|
||||
const onSetRadialGradient = () => {
|
||||
onChange(
|
||||
serializeGradient( {
|
||||
...omit( gradientAST, [ 'orientation' ] ),
|
||||
type: 'radial-gradient',
|
||||
} )
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<BaseControl className="components-custom-gradient-picker__type-picker">
|
||||
<BaseControl.VisualLabel>{ __( 'Type' ) }</BaseControl.VisualLabel>
|
||||
<ToolbarGroup
|
||||
className="components-custom-gradient-picker__toolbar"
|
||||
controls={ [
|
||||
{
|
||||
icon: <LinearGradientIcon />,
|
||||
title: __( 'Linear Gradient' ),
|
||||
isActive: hasGradient && type === 'linear-gradient',
|
||||
onClick: onSetLinearGradient,
|
||||
},
|
||||
{
|
||||
icon: <RadialGradientIcon />,
|
||||
title: __( 'Radial Gradient' ),
|
||||
isActive: hasGradient && type === 'radial-gradient',
|
||||
onClick: onSetRadialGradient,
|
||||
},
|
||||
] }
|
||||
/>
|
||||
</BaseControl>
|
||||
);
|
||||
};
|
||||
|
||||
export default function CustomGradientPicker( { value, onChange, activePalette } ) {
|
||||
const { gradientAST, hasGradient } = getGradientParsed( value );
|
||||
const { type } = gradientAST;
|
||||
return (
|
||||
<div className="components-custom-gradient-picker">
|
||||
<CustomGradientBar value={ value } onChange={ onChange } activePalette={ activePalette } />
|
||||
<div className="components-custom-gradient-picker__ui-line">
|
||||
<GradientTypePicker
|
||||
gradientAST={ gradientAST }
|
||||
hasGradient={ hasGradient }
|
||||
onChange={ onChange }
|
||||
/>
|
||||
{ type === 'linear-gradient' && (
|
||||
<GradientAnglePicker
|
||||
gradientAST={ gradientAST }
|
||||
hasGradient={ hasGradient }
|
||||
onChange={ onChange }
|
||||
/>
|
||||
) }
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { get, omit } from 'lodash';
|
||||
/**
|
||||
* WordPress dependencies
|
||||
*/
|
||||
import { PanelBody, RadioControl, RangeControl } from '@wordpress/components';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { useState } from '@wordpress/element';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { colorsUtils } from '../mobile/color-settings/utils';
|
||||
import { performLayoutAnimation } from '../mobile/layout-animation';
|
||||
import { getGradientParsed } from './utils';
|
||||
import { serializeGradient } from './serializer';
|
||||
import {
|
||||
DEFAULT_LINEAR_GRADIENT_ANGLE,
|
||||
HORIZONTAL_GRADIENT_ORIENTATION,
|
||||
} from './constants';
|
||||
import styles from './style.scss';
|
||||
|
||||
function CustomGradientPicker( { currentValue, setColor, isGradientColor } ) {
|
||||
const [ gradientOrientation, setGradientOrientation ] = useState(
|
||||
HORIZONTAL_GRADIENT_ORIENTATION
|
||||
);
|
||||
|
||||
const { getGradientType, gradients, gradientOptions } = colorsUtils;
|
||||
const { gradientAST } = getGradientParsed( currentValue );
|
||||
const gradientType = getGradientType( currentValue );
|
||||
|
||||
function isLinearGradient( type ) {
|
||||
return type === gradients.linear;
|
||||
}
|
||||
|
||||
function getGradientColor( type ) {
|
||||
const orientation = get( gradientAST, [ 'orientation' ] );
|
||||
|
||||
if ( orientation ) {
|
||||
setGradientOrientation( orientation );
|
||||
}
|
||||
|
||||
return serializeGradient(
|
||||
isLinearGradient( type )
|
||||
? {
|
||||
...gradientAST,
|
||||
...( gradientAST.orientation
|
||||
? {}
|
||||
: {
|
||||
orientation: gradientOrientation,
|
||||
} ),
|
||||
type,
|
||||
}
|
||||
: {
|
||||
...omit( gradientAST, [ 'orientation' ] ),
|
||||
type,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function onGradientTypeChange( type ) {
|
||||
const gradientColor = getGradientColor( type );
|
||||
performLayoutAnimation();
|
||||
setColor( gradientColor );
|
||||
}
|
||||
|
||||
function setGradientAngle( value ) {
|
||||
const gradientColor = serializeGradient( {
|
||||
...gradientAST,
|
||||
orientation: {
|
||||
type: 'angular',
|
||||
value,
|
||||
},
|
||||
} );
|
||||
|
||||
if ( isGradientColor && gradientColor !== currentValue ) {
|
||||
setColor( gradientColor );
|
||||
}
|
||||
}
|
||||
|
||||
function getGradientAngle() {
|
||||
return get(
|
||||
gradientAST,
|
||||
[ 'orientation', 'value' ],
|
||||
DEFAULT_LINEAR_GRADIENT_ANGLE
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<PanelBody title={ __( 'Gradient Type' ) }>
|
||||
<RadioControl
|
||||
selected={ gradientType }
|
||||
options={ gradientOptions }
|
||||
onChange={ onGradientTypeChange }
|
||||
/>
|
||||
</PanelBody>
|
||||
{ isLinearGradient( gradientType ) && (
|
||||
<PanelBody style={ styles.angleControl }>
|
||||
<RangeControl
|
||||
label={ __( 'Angle' ) }
|
||||
minimumValue={ 0 }
|
||||
maximumValue={ 360 }
|
||||
value={ getGradientAngle() }
|
||||
onChange={ setGradientAngle }
|
||||
/>
|
||||
</PanelBody>
|
||||
) }
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default CustomGradientPicker;
|
||||
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { compact, get } from 'lodash';
|
||||
|
||||
export function serializeGradientColor( { type, value } ) {
|
||||
if ( type === 'literal' || type === 'hex' ) {
|
||||
return value;
|
||||
}
|
||||
return `${ type }(${ value.join( ',' ) })`;
|
||||
}
|
||||
|
||||
export function serializeGradientPosition( { type, value } ) {
|
||||
return `${ value }${ type }`;
|
||||
}
|
||||
|
||||
export function serializeGradientColorStop( { type, value, length } ) {
|
||||
return `${ serializeGradientColor( {
|
||||
type,
|
||||
value,
|
||||
} ) } ${ serializeGradientPosition( length ) }`;
|
||||
}
|
||||
|
||||
export function serializeGradientOrientation( orientation ) {
|
||||
if ( ! orientation || orientation.type !== 'angular' ) {
|
||||
return;
|
||||
}
|
||||
return `${ orientation.value }deg`;
|
||||
}
|
||||
|
||||
export function serializeGradient( { type, orientation, colorStops } ) {
|
||||
const serializedOrientation = serializeGradientOrientation( orientation );
|
||||
//console.log( colorStops );
|
||||
const serializedColorStops = colorStops
|
||||
.sort( ( colorStop1, colorStop2 ) => {
|
||||
return (
|
||||
get( colorStop1, [ 'length', 'value' ], 0 ) -
|
||||
get( colorStop2, [ 'length', 'value' ], 0 )
|
||||
);
|
||||
} )
|
||||
.map( serializeGradientColorStop );
|
||||
|
||||
// console.log(`${ type }(${ compact( [
|
||||
// serializedOrientation,
|
||||
// ...serializedColorStops,
|
||||
// ] ).join( ',' ) })`);
|
||||
|
||||
|
||||
return `${ type }(${ compact( [
|
||||
serializedOrientation,
|
||||
...serializedColorStops,
|
||||
] ).join( ',' ) })`;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
.angleControl {
|
||||
padding-top: (if(variable-exists(grid-unit-20), $grid-unit-20, 20px) / 2);
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
@use 'sass:meta';
|
||||
|
||||
$components-custom-gradient-picker__padding: 3px; // 24px container, 18px handles inside, that leaves 6px padding, half of which is 3.
|
||||
|
||||
.components-custom-gradient-picker {
|
||||
margin-top: (if(meta.variable-exists(grid-unit-10), $grid-unit-10, 10px));
|
||||
}
|
||||
|
||||
.components-custom-gradient-picker__gradient-bar:not(.has-gradient) {
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
$button-size-small: 24px;
|
||||
$white: #fff;
|
||||
.components-custom-gradient-picker__gradient-bar {
|
||||
width: 100%;
|
||||
height: $button-size-small;
|
||||
border-radius: $button-size-small;
|
||||
margin-bottom: (if(meta.variable-exists(grid-unit-10), $grid-unit-10, 10px));
|
||||
padding-left: $components-custom-gradient-picker__padding;
|
||||
padding-right: $button-size-small - $components-custom-gradient-picker__padding;
|
||||
|
||||
.components-custom-gradient-picker__markers-container {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.components-custom-gradient-picker__insert-point {
|
||||
border-radius: 50%;
|
||||
background: $white;
|
||||
padding: 2px;
|
||||
min-width: $button-size-small;
|
||||
width: $button-size-small;
|
||||
height: $button-size-small;
|
||||
position: relative;
|
||||
|
||||
svg {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.components-custom-gradient-picker__control-point-button {
|
||||
border: 2px solid $white;
|
||||
border-radius: 50%;
|
||||
height: 18px;
|
||||
padding: 0;
|
||||
position: absolute;
|
||||
width: 18px;
|
||||
top: $components-custom-gradient-picker__padding;
|
||||
|
||||
&.is-active {
|
||||
background: #fafafa;
|
||||
color: #23282d;
|
||||
border-color: #999;
|
||||
box-shadow:
|
||||
0 0 0 1px $white,
|
||||
0 0 0 3px var(--wp-admin-theme-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.components-custom-gradient-picker__color-picker-popover .components-custom-gradient-picker__remove-control-point {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
display: block;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.components-custom-gradient-picker__inserter {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.components-custom-gradient-picker__liner-gradient-indicator {
|
||||
display: inline-block;
|
||||
flex: 0 auto;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.components-custom-gradient-picker__ui-line {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.components-custom-gradient-picker .components-custom-gradient-picker__ui-line {
|
||||
.components-base-control.components-angle-picker,
|
||||
.components-base-control.components-custom-gradient-picker__type-picker {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.components-custom-gradient-picker .components-custom-gradient-picker__toolbar {
|
||||
border: none;
|
||||
|
||||
// Work-around to target the inner button containers rendered by <ToolbarGroup />
|
||||
> div + div {
|
||||
margin-left: 1px;
|
||||
}
|
||||
|
||||
button {
|
||||
&.is-pressed {
|
||||
$dark-gray-200: #999;
|
||||
> svg {
|
||||
background: $white;
|
||||
border: 1px solid $dark-gray-200;
|
||||
border-radius: 2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import classnames from 'classnames';
|
||||
import { flatMap } from 'lodash';
|
||||
|
||||
/**
|
||||
* WordPress dependencies
|
||||
*/
|
||||
import { useContext } from '@wordpress/element';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import ToolbarButton from '../toolbar-button';
|
||||
import ToolbarGroupCollapsed from './toolbar-group-collapsed';
|
||||
import ToolbarContext from '../toolbar-context';
|
||||
|
||||
const ToolbarGroupContainer = ( { className, children, ...props } ) => (
|
||||
<div className={ className } { ...props }>
|
||||
{ children }
|
||||
</div>
|
||||
);
|
||||
|
||||
/**
|
||||
* Renders a collapsible group of controls
|
||||
*
|
||||
* The `controls` prop accepts an array of sets. A set is an array of controls.
|
||||
* Controls have the following shape:
|
||||
*
|
||||
* ```
|
||||
* {
|
||||
* icon: string,
|
||||
* title: string,
|
||||
* subscript: string,
|
||||
* onClick: Function,
|
||||
* isActive: boolean,
|
||||
* isDisabled: boolean
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* For convenience it is also possible to pass only an array of controls. It is
|
||||
* then assumed this is the only set.
|
||||
*
|
||||
* Either `controls` or `children` is required, otherwise this components
|
||||
* renders nothing.
|
||||
*
|
||||
* @param {Object} props Component props.
|
||||
* @param {Array} [props.controls] The controls to render in this toolbar.
|
||||
* @param {WPElement} [props.children] Any other things to render inside the toolbar besides the controls.
|
||||
* @param {string} [props.className] Class to set on the container div.
|
||||
* @param {boolean} [props.isCollapsed] Turns ToolbarGroup into a dropdown menu.
|
||||
* @param {string} [props.title] ARIA label for dropdown menu if is collapsed.
|
||||
*/
|
||||
function ToolbarGroup( {
|
||||
controls = [],
|
||||
children,
|
||||
className,
|
||||
isCollapsed,
|
||||
title,
|
||||
...props
|
||||
} ) {
|
||||
// It'll contain state if `ToolbarGroup` is being used within
|
||||
// `<Toolbar accessibilityLabel="label" />`
|
||||
const accessibleToolbarState = useContext( ToolbarContext );
|
||||
|
||||
if ( ( ! controls || ! controls.length ) && ! children ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const finalClassName = classnames(
|
||||
// Unfortunately, there's legacy code referencing to `.components-toolbar`
|
||||
// So we can't get rid of it
|
||||
accessibleToolbarState
|
||||
? 'components-toolbar-group'
|
||||
: 'components-toolbar',
|
||||
className
|
||||
);
|
||||
|
||||
// Normalize controls to nested array of objects (sets of controls)
|
||||
let controlSets = controls;
|
||||
if ( ! Array.isArray( controlSets[ 0 ] ) ) {
|
||||
controlSets = [ controlSets ];
|
||||
}
|
||||
|
||||
return (
|
||||
<ToolbarGroupContainer className={ finalClassName } { ...props }>
|
||||
{ flatMap( controlSets, ( controlSet, indexOfSet ) =>
|
||||
controlSet.map( ( control, indexOfControl ) => (
|
||||
<ToolbarButton
|
||||
key={ [ indexOfSet, indexOfControl ].join() }
|
||||
containerClassName={
|
||||
indexOfSet > 0 && indexOfControl === 0
|
||||
? 'has-left-divider'
|
||||
: null
|
||||
}
|
||||
{ ...control }
|
||||
/>
|
||||
) )
|
||||
) }
|
||||
{ children }
|
||||
</ToolbarGroupContainer>
|
||||
);
|
||||
}
|
||||
|
||||
export default ToolbarGroup;
|
||||
@@ -0,0 +1,296 @@
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { findIndex, map, some } from 'lodash';
|
||||
import gradientParser from 'gradient-parser';
|
||||
import CustomGradientParser from './custom-parser';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import {
|
||||
DEFAULT_GRADIENT,
|
||||
INSERT_POINT_WIDTH,
|
||||
MINIMUM_ABSOLUTE_LEFT_POSITION,
|
||||
MINIMUM_DISTANCE_BETWEEN_POINTS,
|
||||
KEYBOARD_CONTROL_POINT_VARIATION,
|
||||
HORIZONTAL_GRADIENT_ORIENTATION,
|
||||
} from './constants';
|
||||
import {
|
||||
serializeGradientColor,
|
||||
serializeGradientPosition,
|
||||
serializeGradient,
|
||||
} from './serializer';
|
||||
|
||||
function tinyColorRgbToGradientColorStop( { type, value } ) {
|
||||
//console.log( type );
|
||||
//console.log( value );
|
||||
if ( type === 'literal' ) {
|
||||
return {
|
||||
type: 'literal',
|
||||
value: value,
|
||||
};
|
||||
} else if ( type === 'rgb' ) {
|
||||
return {
|
||||
type: 'rgb',
|
||||
value: [ value.r, value.g, value.b ],
|
||||
};
|
||||
}
|
||||
return {
|
||||
type: 'rgba',
|
||||
value: [ value.r, value.g, value.b, value.a ],
|
||||
};
|
||||
}
|
||||
|
||||
export function getGradientWithColorStopAdded(
|
||||
gradientAST,
|
||||
relativePosition,
|
||||
rgbaColor
|
||||
) {
|
||||
const colorStop = tinyColorRgbToGradientColorStop( rgbaColor );
|
||||
colorStop.length = {
|
||||
type: '%',
|
||||
value: relativePosition,
|
||||
};
|
||||
return {
|
||||
...gradientAST,
|
||||
colorStops: [ ...gradientAST.colorStops, colorStop ],
|
||||
};
|
||||
}
|
||||
|
||||
export function getGradientWithPositionAtIndexChanged(
|
||||
gradientAST,
|
||||
index,
|
||||
relativePosition
|
||||
) {
|
||||
return {
|
||||
...gradientAST,
|
||||
colorStops: gradientAST.colorStops.map(
|
||||
( colorStop, colorStopIndex ) => {
|
||||
if ( colorStopIndex !== index ) {
|
||||
return colorStop;
|
||||
}
|
||||
return {
|
||||
...colorStop,
|
||||
length: {
|
||||
...colorStop.length,
|
||||
value: relativePosition,
|
||||
},
|
||||
};
|
||||
}
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
export function isControlPointOverlapping(
|
||||
gradientAST,
|
||||
position,
|
||||
initialIndex
|
||||
) {
|
||||
const initialPosition = parseInt(
|
||||
gradientAST.colorStops[ initialIndex ].length.value
|
||||
);
|
||||
const minPosition = Math.min( initialPosition, position );
|
||||
const maxPosition = Math.max( initialPosition, position );
|
||||
|
||||
return some( gradientAST.colorStops, ( { length }, index ) => {
|
||||
const itemPosition = parseInt( length.value );
|
||||
return (
|
||||
index !== initialIndex &&
|
||||
( Math.abs( itemPosition - position ) <
|
||||
MINIMUM_DISTANCE_BETWEEN_POINTS ||
|
||||
( minPosition < itemPosition && itemPosition < maxPosition ) )
|
||||
);
|
||||
} );
|
||||
}
|
||||
|
||||
function getGradientWithPositionAtIndexSummed(
|
||||
gradientAST,
|
||||
index,
|
||||
valueToSum
|
||||
) {
|
||||
const currentPosition = gradientAST.colorStops[ index ].length.value;
|
||||
const newPosition = Math.max(
|
||||
0,
|
||||
Math.min( 100, parseInt( currentPosition ) + valueToSum )
|
||||
);
|
||||
if ( isControlPointOverlapping( gradientAST, newPosition, index ) ) {
|
||||
return gradientAST;
|
||||
}
|
||||
return getGradientWithPositionAtIndexChanged(
|
||||
gradientAST,
|
||||
index,
|
||||
newPosition
|
||||
);
|
||||
}
|
||||
|
||||
export function getGradientWithPositionAtIndexIncreased( gradientAST, index ) {
|
||||
return getGradientWithPositionAtIndexSummed(
|
||||
gradientAST,
|
||||
index,
|
||||
KEYBOARD_CONTROL_POINT_VARIATION
|
||||
);
|
||||
}
|
||||
|
||||
export function getGradientWithPositionAtIndexDecreased( gradientAST, index ) {
|
||||
return getGradientWithPositionAtIndexSummed(
|
||||
gradientAST,
|
||||
index,
|
||||
-KEYBOARD_CONTROL_POINT_VARIATION
|
||||
);
|
||||
}
|
||||
|
||||
export function getGradientWithColorAtIndexChanged(
|
||||
gradientAST,
|
||||
index,
|
||||
rgbaColor
|
||||
) {
|
||||
return {
|
||||
...gradientAST,
|
||||
colorStops: gradientAST.colorStops.map(
|
||||
( colorStop, colorStopIndex ) => {
|
||||
if ( colorStopIndex !== index ) {
|
||||
return colorStop;
|
||||
}
|
||||
return {
|
||||
...colorStop,
|
||||
...tinyColorRgbToGradientColorStop( rgbaColor ),
|
||||
};
|
||||
}
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
export function getGradientWithColorAtPositionChanged(
|
||||
gradientAST,
|
||||
relativePositionValue,
|
||||
rgbaColor
|
||||
) {
|
||||
const index = findIndex( gradientAST.colorStops, ( colorStop ) => {
|
||||
return (
|
||||
colorStop &&
|
||||
colorStop.length &&
|
||||
colorStop.length.type === '%' &&
|
||||
colorStop.length.value === relativePositionValue.toString()
|
||||
);
|
||||
} );
|
||||
return getGradientWithColorAtIndexChanged( gradientAST, index, rgbaColor );
|
||||
}
|
||||
|
||||
export function getGradientWithControlPointRemoved( gradientAST, index ) {
|
||||
return {
|
||||
...gradientAST,
|
||||
colorStops: gradientAST.colorStops.filter( ( elem, elemIndex ) => {
|
||||
return elemIndex !== index;
|
||||
} ),
|
||||
};
|
||||
}
|
||||
|
||||
export function getHorizontalRelativeGradientPosition(
|
||||
mouseXCoordinate,
|
||||
containerElement,
|
||||
positionedElementWidth
|
||||
) {
|
||||
if ( ! containerElement ) {
|
||||
return;
|
||||
}
|
||||
const { x, width } = containerElement.getBoundingClientRect();
|
||||
const absolutePositionValue =
|
||||
mouseXCoordinate -
|
||||
x -
|
||||
MINIMUM_ABSOLUTE_LEFT_POSITION -
|
||||
positionedElementWidth / 2;
|
||||
const availableWidth =
|
||||
width - MINIMUM_ABSOLUTE_LEFT_POSITION - INSERT_POINT_WIDTH;
|
||||
return Math.round(
|
||||
Math.min(
|
||||
Math.max( ( absolutePositionValue * 100 ) / availableWidth, 0 ),
|
||||
100
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the marker points from a gradient AST.
|
||||
*
|
||||
* @param {Object} gradientAST An object representing the gradient AST.
|
||||
*
|
||||
* @return {Array.<{color: string, position: string, positionValue: number}>}
|
||||
* An array of markerPoint objects.
|
||||
* color: A string with the color code ready to be used in css style e.g: "rgba( 1, 2 , 3, 0.5)".
|
||||
* position: A string with the position ready to be used in css style e.g: "70%".
|
||||
* positionValue: A number with the relative position value e.g: 70.
|
||||
*/
|
||||
export function getMarkerPoints( gradientAST ) {
|
||||
if ( ! gradientAST ) {
|
||||
return [];
|
||||
}
|
||||
return map( gradientAST.colorStops, ( colorStop ) => {
|
||||
if (
|
||||
! colorStop ||
|
||||
! colorStop.length ||
|
||||
colorStop.length.type !== '%'
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
color: serializeGradientColor( colorStop ),
|
||||
position: serializeGradientPosition( colorStop.length ),
|
||||
positionValue: parseInt( colorStop.length.value ),
|
||||
};
|
||||
} );
|
||||
}
|
||||
|
||||
export function getLinearGradientRepresentationOfARadial( gradientAST ) {
|
||||
return serializeGradient( {
|
||||
type: 'linear-gradient',
|
||||
orientation: HORIZONTAL_GRADIENT_ORIENTATION,
|
||||
colorStops: gradientAST.colorStops,
|
||||
} );
|
||||
}
|
||||
|
||||
const DIRECTIONAL_ORIENTATION_ANGLE_MAP = {
|
||||
top: 0,
|
||||
'top right': 45,
|
||||
'right top': 45,
|
||||
right: 90,
|
||||
'right bottom': 135,
|
||||
'bottom right': 135,
|
||||
bottom: 180,
|
||||
'bottom left': 225,
|
||||
'left bottom': 225,
|
||||
left: 270,
|
||||
'top left': 315,
|
||||
'left top': 315,
|
||||
};
|
||||
|
||||
export function getGradientParsed( value ) {
|
||||
let hasGradient = !! value;
|
||||
// gradientAST will contain the gradient AST as parsed by gradient-parser npm module.
|
||||
// More information of its structure available at https://www.npmjs.com/package/gradient-parser#ast.
|
||||
let gradientAST;
|
||||
let gradientValue;
|
||||
try {
|
||||
gradientAST = CustomGradientParser( value || DEFAULT_GRADIENT )[ 0 ];
|
||||
gradientValue = value || DEFAULT_GRADIENT;
|
||||
} catch ( error ) {
|
||||
hasGradient = false;
|
||||
gradientAST = CustomGradientParser( DEFAULT_GRADIENT )[ 0 ];
|
||||
gradientValue = DEFAULT_GRADIENT;
|
||||
}
|
||||
|
||||
if (
|
||||
gradientAST.orientation &&
|
||||
gradientAST.orientation.type === 'directional'
|
||||
) {
|
||||
gradientAST.orientation.type = 'angular';
|
||||
gradientAST.orientation.value = DIRECTIONAL_ORIENTATION_ANGLE_MAP[
|
||||
gradientAST.orientation.value
|
||||
].toString();
|
||||
}
|
||||
return {
|
||||
hasGradient,
|
||||
gradientAST,
|
||||
gradientValue,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { map } from 'lodash';
|
||||
|
||||
/**
|
||||
* WordPress dependencies
|
||||
*/
|
||||
|
||||
import { __, sprintf } from '@wordpress/i18n';
|
||||
|
||||
const {
|
||||
useCallback,
|
||||
useMemo
|
||||
} = wp.element;
|
||||
const {
|
||||
BaseControl
|
||||
} = wp.components;
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import CircularOptionPicker from './circular-option-picker.js';
|
||||
import CustomGradientPicker from './custom-gradient-picker';
|
||||
|
||||
export default function KadenceGradientPicker( {
|
||||
className,
|
||||
gradients,
|
||||
onChange,
|
||||
value,
|
||||
clearable = true,
|
||||
disableCustomGradients = false,
|
||||
activePalette,
|
||||
} ) {
|
||||
const clearGradient = useCallback( () => onChange( undefined ), [
|
||||
onChange,
|
||||
] );
|
||||
const gradientOptions = useMemo( () => {
|
||||
return map( gradients, ( { gradient, name } ) => (
|
||||
<CircularOptionPicker.Option
|
||||
key={ gradient }
|
||||
value={ gradient }
|
||||
isSelected={ value === gradient }
|
||||
tooltipText={
|
||||
name ||
|
||||
// translators: %s: gradient code e.g: "linear-gradient(90deg, rgba(98,16,153,1) 0%, rgba(172,110,22,1) 100%);".
|
||||
sprintf( __( 'Gradient code: %s' ), gradient )
|
||||
}
|
||||
style={ { color: 'rgba( 0,0,0,0 )', background: gradient } }
|
||||
onClick={
|
||||
value === gradient
|
||||
? clearGradient
|
||||
: () => onChange( gradient )
|
||||
}
|
||||
aria-label={
|
||||
name
|
||||
? // translators: %s: The name of the gradient e.g: "Angular red to blue".
|
||||
sprintf( __( 'Gradient: %s' ), name )
|
||||
: // translators: %s: gradient code e.g: "linear-gradient(90deg, rgba(98,16,153,1) 0%, rgba(172,110,22,1) 100%);".
|
||||
sprintf( __( 'Gradient code: %s' ), gradient )
|
||||
}
|
||||
/>
|
||||
) );
|
||||
}, [ gradients, value, onChange, clearGradient ] );
|
||||
return (
|
||||
<CircularOptionPicker
|
||||
className={ className }
|
||||
options={ gradientOptions }
|
||||
actions={
|
||||
clearable && (
|
||||
<CircularOptionPicker.ButtonAction
|
||||
onClick={ clearGradient }
|
||||
>
|
||||
{ __( 'Clear' ) }
|
||||
</CircularOptionPicker.ButtonAction>
|
||||
)
|
||||
}
|
||||
>
|
||||
{ ! disableCustomGradients && (
|
||||
<CustomGradientPicker value={ value } onChange={ onChange } activePalette={ activePalette } />
|
||||
) }
|
||||
</CircularOptionPicker>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
/**
|
||||
* A dynamic control.
|
||||
*
|
||||
* @class
|
||||
* @augments wp.customize.Control
|
||||
* @augments wp.customize.Class
|
||||
*/
|
||||
export const baseControl = wp.customize.KadenceControl = wp.customize.Control.extend( {
|
||||
|
||||
initialize: function( id, options ) {
|
||||
var control = this,
|
||||
args = options || {};
|
||||
|
||||
args.params = args.params || {};
|
||||
if ( ! args.params.type ) {
|
||||
args.params.type = 'kadence-basic';
|
||||
}
|
||||
if ( ! args.params.content ) {
|
||||
args.params.content = jQuery( '<li></li>' );
|
||||
args.params.content.attr( 'id', 'customize-control-' + id.replace( /]/g, '' ).replace( /\[/g, '-' ) );
|
||||
args.params.content.attr( 'class', 'customize-control customize-control-' + args.params.type );
|
||||
}
|
||||
|
||||
control.propertyElements = [];
|
||||
wp.customize.Control.prototype.initialize.call( control, id, args );
|
||||
},
|
||||
|
||||
/**
|
||||
* Add bidirectional data binding links between inputs and the setting(s).
|
||||
*
|
||||
* This is copied from wp.customize.Control.prototype.initialize(). It
|
||||
* should be changed in Core to be applied once the control is embedded.
|
||||
*
|
||||
* @private
|
||||
* @returns {null}
|
||||
*/
|
||||
_setUpSettingRootLinks: function() {
|
||||
var control = this,
|
||||
nodes = control.container.find( '[data-customize-setting-link]' );
|
||||
|
||||
nodes.each( function() {
|
||||
var node = jQuery( this );
|
||||
|
||||
wp.customize( node.data( 'customizeSettingLink' ), function( setting ) {
|
||||
var element = new wp.customize.Element( node );
|
||||
control.elements.push( element );
|
||||
element.sync( setting );
|
||||
element.set( setting() );
|
||||
} );
|
||||
} );
|
||||
},
|
||||
|
||||
/**
|
||||
* Add bidirectional data binding links between inputs and the setting properties.
|
||||
*
|
||||
* @private
|
||||
* @returns {null}
|
||||
*/
|
||||
_setUpSettingPropertyLinks: function() {
|
||||
var control = this,
|
||||
nodes;
|
||||
|
||||
if ( ! control.setting ) {
|
||||
return;
|
||||
}
|
||||
|
||||
nodes = control.container.find( '[data-customize-setting-property-link]' );
|
||||
|
||||
nodes.each( function() {
|
||||
var node = jQuery( this ),
|
||||
element,
|
||||
propertyName = node.data( 'customizeSettingPropertyLink' );
|
||||
|
||||
element = new wp.customize.Element( node );
|
||||
control.propertyElements.push( element );
|
||||
element.set( control.setting()[ propertyName ] );
|
||||
|
||||
element.bind( function( newPropertyValue ) {
|
||||
var newSetting = control.setting();
|
||||
if ( newPropertyValue === newSetting[ propertyName ] ) {
|
||||
return;
|
||||
}
|
||||
newSetting = _.clone( newSetting );
|
||||
newSetting[ propertyName ] = newPropertyValue;
|
||||
control.setting.set( newSetting );
|
||||
} );
|
||||
control.setting.bind( function( newValue ) {
|
||||
if ( newValue[ propertyName ] !== element.get() ) {
|
||||
element.set( newValue[ propertyName ] );
|
||||
}
|
||||
} );
|
||||
} );
|
||||
},
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
ready: function() {
|
||||
var control = this;
|
||||
|
||||
control._setUpSettingRootLinks();
|
||||
control._setUpSettingPropertyLinks();
|
||||
|
||||
wp.customize.Control.prototype.ready.call( control );
|
||||
|
||||
control.deferred.embedded.done( function() {
|
||||
} );
|
||||
},
|
||||
|
||||
/**
|
||||
* Embed the control in the document.
|
||||
*
|
||||
* Override the embed() method to do nothing,
|
||||
* so that the control isn't embedded on load,
|
||||
* unless the containing section is already expanded.
|
||||
*
|
||||
* @returns {null}
|
||||
*/
|
||||
embed: function() {
|
||||
var control = this,
|
||||
sectionId = control.section();
|
||||
|
||||
if ( ! sectionId ) {
|
||||
return;
|
||||
}
|
||||
|
||||
wp.customize.section( sectionId, function( section ) {
|
||||
if ( section.expanded() || wp.customize.settings.autofocus.control === control.id ) {
|
||||
control.actuallyEmbed();
|
||||
} else {
|
||||
section.expanded.bind( function( expanded ) {
|
||||
if ( expanded ) {
|
||||
control.actuallyEmbed();
|
||||
}
|
||||
} );
|
||||
}
|
||||
} );
|
||||
},
|
||||
|
||||
/**
|
||||
* Deferred embedding of control when actually
|
||||
*
|
||||
* This function is called in Section.onChangeExpanded() so the control
|
||||
* will only get embedded when the Section is first expanded.
|
||||
*
|
||||
* @returns {null}
|
||||
*/
|
||||
actuallyEmbed: function() {
|
||||
var control = this;
|
||||
if ( 'resolved' === control.deferred.embedded.state() ) {
|
||||
return;
|
||||
}
|
||||
control.renderContent();
|
||||
control.deferred.embedded.resolve(); // This triggers control.ready().
|
||||
// Fire event after control is initialized.
|
||||
control.container.trigger( 'init' );
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a WP-style warning notice React element if a notice string is
|
||||
* provided via input_attrs.notice, otherwise returns null.
|
||||
* Call this inside any child component's render() to get universal notice support.
|
||||
*
|
||||
* @returns {wp.element.Element|null}
|
||||
*/
|
||||
renderNotice: function() {
|
||||
var control = this;
|
||||
if ( ! control.params.input_attrs || ! control.params.input_attrs.notice ) {
|
||||
return null;
|
||||
}
|
||||
return wp.element.createElement(
|
||||
'div',
|
||||
{ className: 'notice notice-warning kadence-control-notice' },
|
||||
wp.element.createElement( 'p', { dangerouslySetInnerHTML: { __html: control.params.input_attrs.notice } } )
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* This is not working with autofocus.
|
||||
*
|
||||
* @param {object} [args] Args.
|
||||
* @returns {null}
|
||||
*/
|
||||
focus: function( args ) {
|
||||
var control = this;
|
||||
control.actuallyEmbed();
|
||||
wp.customize.Control.prototype.focus.call( control, args );
|
||||
},
|
||||
|
||||
} );
|
||||
@@ -0,0 +1,553 @@
|
||||
/* 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 { __ } from '@wordpress/i18n';
|
||||
|
||||
const { ButtonGroup, Dashicon, Toolbar, ToolbarGroup, Tooltip, Button } = wp.components;
|
||||
/**
|
||||
* WordPress dependencies
|
||||
*/
|
||||
import { createRef, Component, Fragment } from '@wordpress/element';
|
||||
class BorderComponent extends Component {
|
||||
constructor() {
|
||||
super( ...arguments );
|
||||
this.updateValues = this.updateValues.bind( this );
|
||||
this.resetValues = this.resetValues.bind( this );
|
||||
this.handleChangeComplete = this.handleChangeComplete.bind( this );
|
||||
this.handleResponsiveChangeComplete = this.handleResponsiveChangeComplete.bind( this );
|
||||
this.getUnitButtons = this.getUnitButtons.bind( this );
|
||||
this.getResponsiveUnitButtons = this.getResponsiveUnitButtons.bind( this );
|
||||
this.createLevelControlToolbar = this.createLevelControlToolbar.bind( this );
|
||||
this.createResponsiveLevelControlToolbar = this.createResponsiveLevelControlToolbar.bind( this );
|
||||
this.getStyleButtons = this.getStyleButtons.bind( this );
|
||||
this.getResponsiveStyleButtons = this.getResponsiveStyleButtons.bind( this );
|
||||
this.createStyleControlToolbar = this.createStyleControlToolbar.bind( this );
|
||||
this.createResponsiveStyleControlToolbar = this.createResponsiveStyleControlToolbar.bind( this );
|
||||
let value = this.props.control.setting.get();
|
||||
let defaultParams = {
|
||||
min: {
|
||||
px: '0',
|
||||
em: '0',
|
||||
rem: '0',
|
||||
},
|
||||
max: {
|
||||
px: '300',
|
||||
em: '12',
|
||||
rem: '12',
|
||||
},
|
||||
step: {
|
||||
px: '1',
|
||||
em: '0.01',
|
||||
rem: '0.01',
|
||||
},
|
||||
units: ['px', 'em', 'rem'],
|
||||
styles: ['none', 'solid', 'dashed', 'dotted', 'double'],
|
||||
responsive:true,
|
||||
color:true,
|
||||
};
|
||||
this.controlParams = this.props.control.params.input_attrs ? {
|
||||
...defaultParams,
|
||||
...this.props.control.params.input_attrs,
|
||||
} : defaultParams;
|
||||
let responsiveDefault = {
|
||||
'desktop': {
|
||||
'width': '',
|
||||
'unit': 'px',
|
||||
'style': 'none',
|
||||
'color': ( this.controlParams.color ? '' : 'currentColor' ),
|
||||
}
|
||||
};
|
||||
let noneResponsiveDefault = {
|
||||
'width': '',
|
||||
'unit': 'px',
|
||||
'style': 'none',
|
||||
'color': ( this.controlParams.color ? '' : 'currentColor' ),
|
||||
};
|
||||
let baseDefault;
|
||||
if ( this.controlParams.responsive ) {
|
||||
baseDefault = responsiveDefault;
|
||||
} else {
|
||||
baseDefault = noneResponsiveDefault;
|
||||
}
|
||||
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',
|
||||
value: value,
|
||||
};
|
||||
this.anchorNodeRef = createRef();
|
||||
}
|
||||
handleResponsiveChangeComplete( color, isPalette, device ) {
|
||||
let value = this.state.value;
|
||||
if ( undefined === value[ device ] ) {
|
||||
value[ device ] = {
|
||||
'width': '',
|
||||
'unit': '',
|
||||
'style': '',
|
||||
'color': '',
|
||||
}
|
||||
}
|
||||
if ( isPalette ) {
|
||||
value[ device ].color = isPalette;
|
||||
} else if ( undefined !== color.rgb && undefined !== color.rgb.a && 1 !== color.rgb.a ) {
|
||||
value[ device ].color = 'rgba(' + color.rgb.r + ',' + color.rgb.g + ',' + color.rgb.b + ',' + color.rgb.a + ')';
|
||||
} else {
|
||||
value[ device ].color = color.hex;
|
||||
}
|
||||
this.updateValues( value );
|
||||
}
|
||||
handleChangeComplete( 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 data = this.props.control.params;
|
||||
let currentUnit;
|
||||
if ( this.controlParams.responsive ) {
|
||||
if ( undefined === this.state.value[ this.state.currentDevice ] ) {
|
||||
let largerDevice = ( this.state.currentDevice === 'mobile' ? 'tablet' : 'desktop' );
|
||||
if ( undefined !== this.state.value[largerDevice] && this.state.value[largerDevice].unit ) {
|
||||
currentUnit = this.state.value[largerDevice].unit;
|
||||
} else if ( 'tablet' === largerDevice && undefined !== this.state.value['desktop'] && this.state.value['desktop'].unit ) {
|
||||
currentUnit = this.state.value['desktop'].unit;
|
||||
}
|
||||
} else if ( undefined === this.state.value[ this.state.currentDevice ].unit ) {
|
||||
let largerDevice = ( this.state.currentDevice === 'mobile' ? 'tablet' : 'desktop' );
|
||||
if ( undefined !== this.state.value[largerDevice] && this.state.value[largerDevice].unit ) {
|
||||
currentUnit = this.state.value[largerDevice].unit;
|
||||
} else if ( 'tablet' === largerDevice && undefined !== this.state.value['desktop'] && this.state.value['desktop'].unit ) {
|
||||
currentUnit = this.state.value['desktop'].unit;
|
||||
}
|
||||
} else if ( '' === this.state.value[ this.state.currentDevice ].unit ) {
|
||||
let largerDevice = ( this.state.currentDevice === 'mobile' ? 'tablet' : 'desktop' );
|
||||
if ( undefined !== this.state.value[largerDevice] && this.state.value[largerDevice].unit ) {
|
||||
currentUnit = this.state.value[largerDevice].unit;
|
||||
} else if ( 'tablet' === largerDevice && undefined !== this.state.value['desktop'] && this.state.value['desktop'].unit ) {
|
||||
currentUnit = this.state.value['desktop'].unit;
|
||||
}
|
||||
} else if ( '' !== this.state.value[ this.state.currentDevice ].unit ) {
|
||||
currentUnit = this.state.value[ this.state.currentDevice ].unit
|
||||
}
|
||||
} else {
|
||||
currentUnit = ( undefined !== this.state.value.unit ? this.state.value.unit : 'px' );
|
||||
}
|
||||
let currentStyle;
|
||||
if ( this.controlParams.responsive ) {
|
||||
if ( undefined === this.state.value[ this.state.currentDevice ] ) {
|
||||
let largerDevice = ( this.state.currentDevice === 'mobile' ? 'tablet' : 'desktop' );
|
||||
if ( undefined !== this.state.value[largerDevice] && this.state.value[largerDevice]?.style ) {
|
||||
currentStyle = this.state.value[largerDevice].style;
|
||||
} else if ( 'tablet' === largerDevice && undefined !== this.state.value['desktop'] && this.state.value['desktop'].style ) {
|
||||
currentStyle = this.state.value['desktop'].style;
|
||||
}
|
||||
} else if ( undefined === this.state.value[ this.state.currentDevice ]?.style ) {
|
||||
let largerDevice = ( this.state.currentDevice === 'mobile' ? 'tablet' : 'desktop' );
|
||||
if ( undefined !== this.state.value[largerDevice] && this.state.value[largerDevice]?.style ) {
|
||||
currentStyle = this.state.value[largerDevice].style;
|
||||
} else if ( 'tablet' === largerDevice && undefined !== this.state.value['desktop'] && this.state.value['desktop'].style ) {
|
||||
currentStyle = this.state.value['desktop'].style;
|
||||
}
|
||||
} else if ( '' === this.state.value[ this.state.currentDevice ]?.style ) {
|
||||
let largerDevice = ( this.state.currentDevice === 'mobile' ? 'tablet' : 'desktop' );
|
||||
if ( undefined !== this.state.value[largerDevice] && this.state.value[largerDevice]?.style ) {
|
||||
currentStyle = this.state.value[largerDevice].style;
|
||||
} else if ( 'tablet' === largerDevice && undefined !== this.state.value['desktop'] && this.state.value['desktop'].style ) {
|
||||
currentStyle = this.state.value['desktop'].style;
|
||||
}
|
||||
} else if ( '' !== this.state.value[ this.state.currentDevice ]?.style ) {
|
||||
currentStyle = this.state.value[ this.state.currentDevice ].style
|
||||
}
|
||||
} else {
|
||||
currentStyle = ( undefined !== this.state.value.style ? this.state.value.style : 'none' );
|
||||
}
|
||||
const onResponsiveInputChange = ( event ) => {
|
||||
const newValue = Number( event.target.value );
|
||||
let value = this.state.value;
|
||||
if ( undefined === value[ this.state.currentDevice ] ) {
|
||||
value[ this.state.currentDevice ] = {
|
||||
'width': '',
|
||||
'unit': '',
|
||||
'style': '',
|
||||
'color': '',
|
||||
}
|
||||
}
|
||||
value[ this.state.currentDevice ].width = newValue;
|
||||
this.updateValues( value );
|
||||
}
|
||||
const onInputChange = ( event ) => {
|
||||
const newValue = ( '' !== event.target.value ? Number( event.target.value ) : '' );
|
||||
let value = this.state.value;
|
||||
value.width = newValue;
|
||||
this.updateValues( value );
|
||||
}
|
||||
const responsiveControlLabel = (
|
||||
<Fragment>
|
||||
{ this.state.currentDevice !== 'desktop' && (
|
||||
<Tooltip text={ __( 'Reset Device Values', 'kadence' ) }>
|
||||
<Button
|
||||
className="reset kadence-reset"
|
||||
disabled={ ( undefined === this.state.value[this.state.currentDevice] ) }
|
||||
onClick={ () => {
|
||||
let value = this.state.value;
|
||||
delete value[this.state.currentDevice];
|
||||
this.updateValues( value );
|
||||
} }
|
||||
>
|
||||
<Dashicon icon='image-rotate' />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
) }
|
||||
{ this.state.currentDevice === 'desktop' && (
|
||||
<Tooltip text={ __( 'Reset All Values', 'kadence' ) }>
|
||||
<Button
|
||||
className="reset kadence-reset"
|
||||
onClick={ () => {
|
||||
this.resetValues();
|
||||
} }
|
||||
>
|
||||
<Dashicon icon='image-rotate' />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
) }
|
||||
{ data.label &&
|
||||
data.label
|
||||
}
|
||||
</Fragment>
|
||||
);
|
||||
const controlLabel = (
|
||||
<Fragment>
|
||||
<Tooltip text={ __( 'Reset Values', 'kadence' ) }>
|
||||
<Button
|
||||
className="reset kadence-reset"
|
||||
disabled={ ( this.defaultValue === this.state.value ) }
|
||||
onClick={ () => {
|
||||
let value = this.state.value;
|
||||
value = this.defaultValue
|
||||
this.updateValues( value );
|
||||
} }
|
||||
>
|
||||
<Dashicon icon='image-rotate' />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
{ data.label &&
|
||||
data.label
|
||||
}
|
||||
</Fragment>
|
||||
);
|
||||
//console.log( this.state.colorPalette )
|
||||
return (
|
||||
<div ref={ this.anchorNodeRef } className="kadence-control-field kadence-border-control">
|
||||
{ this.controlParams.responsive && (
|
||||
<ResponsiveControl
|
||||
onChange={ ( currentDevice) => this.setState( { currentDevice } ) }
|
||||
controlLabel={ responsiveControlLabel }
|
||||
>
|
||||
{ 'none' !== currentStyle && (
|
||||
<Fragment>
|
||||
{ this.controlParams.color && (
|
||||
<ColorControl
|
||||
presetColors={ this.state.colorPalette }
|
||||
color={ ( undefined !== this.state.value[ this.state.currentDevice ] && this.state.value[ this.state.currentDevice ].color ? this.state.value[ this.state.currentDevice ].color : '' ) }
|
||||
usePalette={ true }
|
||||
tooltip={ __( 'Border Color' ) }
|
||||
onChangeComplete={ ( color, isPalette ) => this.handleResponsiveChangeComplete( color, isPalette, this.state.currentDevice ) }
|
||||
customizer={ this.props.customizer }
|
||||
controlRef={ this.anchorNodeRef }
|
||||
/>
|
||||
) }
|
||||
<input
|
||||
value={ ( undefined !== this.state.value[ this.state.currentDevice ] && undefined !== this.state.value[ this.state.currentDevice ]?.width ? this.state.value[ this.state.currentDevice ].width : '' ) }
|
||||
onChange={ onResponsiveInputChange }
|
||||
min={this.controlParams.min[currentUnit]}
|
||||
max={this.controlParams.max[currentUnit]}
|
||||
step={this.controlParams.step[currentUnit]}
|
||||
type="number"
|
||||
className="components-text-control__input"
|
||||
/>
|
||||
{ this.controlParams.units && (
|
||||
<div className="kadence-units">
|
||||
{ this.getResponsiveUnitButtons() }
|
||||
</div>
|
||||
) }
|
||||
</Fragment>
|
||||
) }
|
||||
{ this.controlParams.styles && (
|
||||
<div className="kadence-units kadence-style-options">
|
||||
{ this.getResponsiveStyleButtons() }
|
||||
</div>
|
||||
) }
|
||||
</ResponsiveControl>
|
||||
) }
|
||||
{ ! this.controlParams.responsive && (
|
||||
<Fragment>
|
||||
<div className="kadence-responsive-control-bar">
|
||||
<span className="customize-control-title">{ controlLabel }</span>
|
||||
</div>
|
||||
<div className="kadence-responsive-controls-content">
|
||||
{ 'none' !== currentStyle && (
|
||||
<Fragment>
|
||||
{ this.controlParams.color && (
|
||||
<ColorControl
|
||||
presetColors={ this.state.colorPalette }
|
||||
color={ ( undefined !== this.state.value.color && this.state.value.color ? this.state.value.color : '' ) }
|
||||
usePalette={ true }
|
||||
tooltip={ __( 'Border Color' ) }
|
||||
onChangeComplete={ ( color, isPalette ) => this.handleChangeComplete( color, isPalette ) }
|
||||
customizer={ this.props.customizer }
|
||||
controlRef={ this.anchorNodeRef }
|
||||
/>
|
||||
) }
|
||||
<input
|
||||
value={ ( undefined !== this.state.value && undefined !== this.state.value.width ? this.state.value.width : '' ) }
|
||||
onChange={ onInputChange }
|
||||
min={this.controlParams.min[currentUnit]}
|
||||
max={this.controlParams.max[currentUnit]}
|
||||
step={this.controlParams.step[currentUnit]}
|
||||
type="number"
|
||||
className="components-text-control__input"
|
||||
/>
|
||||
{ this.controlParams.units && (
|
||||
<div className="kadence-units">
|
||||
{ this.getUnitButtons() }
|
||||
</div>
|
||||
) }
|
||||
</Fragment>
|
||||
) }
|
||||
{ this.controlParams.styles && (
|
||||
<div className="kadence-units kadence-style-options">
|
||||
{ this.getStyleButtons() }
|
||||
</div>
|
||||
) }
|
||||
</div>
|
||||
</Fragment>
|
||||
) }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
getResponsiveStyleButtons() {
|
||||
let self = this;
|
||||
const { styles } = this.controlParams;
|
||||
let currentStyle;
|
||||
if ( undefined === this.state.value[ this.state.currentDevice ] ) {
|
||||
let largerDevice = ( this.state.currentDevice === 'mobile' ? 'tablet' : 'desktop' );
|
||||
if ( undefined !== this.state.value[largerDevice] && this.state.value[largerDevice]?.style ) {
|
||||
currentStyle = this.state.value[largerDevice].style;
|
||||
} else if ( 'tablet' === largerDevice && undefined !== this.state.value['desktop'] && this.state.value['desktop'].style ) {
|
||||
currentStyle = this.state.value['desktop'].style;
|
||||
}
|
||||
} else if ( undefined === this.state.value[ this.state.currentDevice ].style ) {
|
||||
let largerDevice = ( this.state.currentDevice === 'mobile' ? 'tablet' : 'desktop' );
|
||||
if ( undefined !== this.state.value[largerDevice] && this.state.value[largerDevice]?.style ) {
|
||||
currentStyle = this.state.value[largerDevice].style;
|
||||
} else if ( 'tablet' === largerDevice && undefined !== this.state.value['desktop'] && this.state.value['desktop'].style ) {
|
||||
currentStyle = this.state.value['desktop'].style;
|
||||
}
|
||||
} else if ( '' === this.state.value[ this.state.currentDevice ].style ) {
|
||||
let largerDevice = ( this.state.currentDevice === 'mobile' ? 'tablet' : 'desktop' );
|
||||
if ( undefined !== this.state.value[largerDevice] && this.state.value[largerDevice]?.style ) {
|
||||
currentStyle = this.state.value[largerDevice].style;
|
||||
} else if ( 'tablet' === largerDevice && undefined !== this.state.value['desktop'] && this.state.value['desktop'].style ) {
|
||||
currentStyle = this.state.value['desktop'].style;
|
||||
}
|
||||
} else if ( '' !== this.state.value[ this.state.currentDevice ].style ) {
|
||||
currentStyle = this.state.value[ this.state.currentDevice ].style
|
||||
}
|
||||
if ( styles.length === 1 ) {
|
||||
return ( <Button
|
||||
className="is-active is-single"
|
||||
isSmall
|
||||
disabled
|
||||
>{ Icons[ currentStyle ] }</Button> );
|
||||
}
|
||||
return <ToolbarGroup
|
||||
isCollapsed={ true }
|
||||
icon={ Icons[ currentStyle ] }
|
||||
label={ __( 'Style', 'kadence' ) }
|
||||
controls={ styles.map( ( style ) => this.createResponsiveStyleControlToolbar( style ) ) }
|
||||
/>
|
||||
}
|
||||
createResponsiveStyleControlToolbar( style ) {
|
||||
return [ {
|
||||
icon: Icons[ style ],
|
||||
isActive: ( undefined !== this.state.value[ this.state.currentDevice ] && undefined !== this.state.value[ this.state.currentDevice ].style && this.state.value[ this.state.currentDevice ].style === style ),
|
||||
onClick: () => {
|
||||
let value = this.state.value;
|
||||
if ( undefined === value[ this.state.currentDevice ] ) {
|
||||
value[ this.state.currentDevice ] = {
|
||||
'width': '',
|
||||
'unit': '',
|
||||
'style': '',
|
||||
'color': '',
|
||||
}
|
||||
}
|
||||
value[ this.state.currentDevice ].style = style;
|
||||
this.updateValues( value );
|
||||
},
|
||||
} ];
|
||||
};
|
||||
getStyleButtons() {
|
||||
let self = this;
|
||||
const { styles } = this.controlParams;
|
||||
let currentStyle;
|
||||
currentStyle = ( undefined !== this.state.value?.style ? this.state.value.style : 'none' );
|
||||
if ( styles.length === 1 ) {
|
||||
return ( <Button
|
||||
className="is-active is-single"
|
||||
isSmall
|
||||
disabled
|
||||
>{ Icons[ currentStyle ] }</Button> );
|
||||
}
|
||||
return <ToolbarGroup
|
||||
isCollapsed={ true }
|
||||
icon={ Icons[ currentStyle ] }
|
||||
label={ __( 'Style', 'kadence' ) }
|
||||
controls={ styles.map( ( style ) => this.createStyleControlToolbar( style ) ) }
|
||||
/>
|
||||
}
|
||||
createStyleControlToolbar( style ) {
|
||||
return [ {
|
||||
icon: Icons[ style ],
|
||||
isActive: ( undefined !== this.state.value && undefined !== this.state.value.style && this.state.value.style === style ),
|
||||
onClick: () => {
|
||||
let value = this.state.value;
|
||||
value.style = style;
|
||||
this.updateValues( value );
|
||||
},
|
||||
} ];
|
||||
};
|
||||
createResponsiveLevelControlToolbar( unit ) {
|
||||
return [ {
|
||||
icon: ( unit === '%' ? Icons.percent : Icons[ unit ] ),
|
||||
isActive: ( undefined !== this.state.value[ this.state.currentDevice ] && undefined !== this.state.value[ this.state.currentDevice ].unit && this.state.value[ this.state.currentDevice ].unit === unit ),
|
||||
onClick: () => {
|
||||
let value = this.state.value;
|
||||
if ( undefined === value[ this.state.currentDevice ] ) {
|
||||
value[ this.state.currentDevice ] = {
|
||||
'width': '',
|
||||
'unit': '',
|
||||
'style': '',
|
||||
'color': '',
|
||||
}
|
||||
}
|
||||
value[ this.state.currentDevice ].unit = unit;
|
||||
this.updateValues( value );
|
||||
},
|
||||
} ];
|
||||
};
|
||||
getResponsiveUnitButtons() {
|
||||
let self = this;
|
||||
const { units } = this.controlParams;
|
||||
let currentUnit;
|
||||
if ( undefined === self.state.value[ self.state.currentDevice ] ) {
|
||||
let largerDevice = ( self.state.currentDevice === 'mobile' ? 'tablet' : 'desktop' );
|
||||
if ( undefined !== this.state.value[largerDevice] && this.state.value[largerDevice].unit ) {
|
||||
currentUnit = this.state.value[largerDevice].unit;
|
||||
} else if ( 'tablet' === largerDevice && undefined !== this.state.value['desktop'] && this.state.value['desktop'].unit ) {
|
||||
currentUnit = this.state.value['desktop'].unit;
|
||||
}
|
||||
} else if ( undefined !== self.state.value[ self.state.currentDevice ].unit ) {
|
||||
let largerDevice = ( self.state.currentDevice === 'mobile' ? 'tablet' : 'desktop' );
|
||||
if ( undefined !== this.state.value[largerDevice] && this.state.value[largerDevice].unit ) {
|
||||
currentUnit = this.state.value[largerDevice].unit;
|
||||
} else if ( 'tablet' === largerDevice && undefined !== this.state.value['desktop'] && this.state.value['desktop'].unit ) {
|
||||
currentUnit = this.state.value['desktop'].unit;
|
||||
}
|
||||
} else if ( '' === self.state.value[ self.state.currentDevice ].unit ) {
|
||||
let largerDevice = ( self.state.currentDevice === 'mobile' ? 'tablet' : 'desktop' );
|
||||
if ( undefined !== this.state.value[largerDevice] && this.state.value[largerDevice].unit ) {
|
||||
currentUnit = this.state.value[largerDevice].unit;
|
||||
} else if ( 'tablet' === largerDevice && undefined !== this.state.value['desktop'] && this.state.value['desktop'].unit ) {
|
||||
currentUnit = this.state.value['desktop'].unit;
|
||||
}
|
||||
} else if ( '' !== self.state.value[ self.state.currentDevice ].unit ) {
|
||||
currentUnit = self.state.value[ self.state.currentDevice ].unit
|
||||
}
|
||||
if ( units.length === 1 ) {
|
||||
return ( <Button
|
||||
className="is-active is-single"
|
||||
isSmall
|
||||
disabled
|
||||
>{ ( '%' === currentUnit ? Icons.percent : Icons[ currentUnit ] ) }</Button> );
|
||||
}
|
||||
return <ToolbarGroup
|
||||
isCollapsed={ true }
|
||||
icon={ ( '%' === currentUnit ? Icons.percent : Icons[ currentUnit ] ) }
|
||||
label={ __( 'Unit', 'kadence' ) }
|
||||
controls={ units.map( ( unit ) => this.createResponsiveLevelControlToolbar( unit ) ) }
|
||||
/>
|
||||
}
|
||||
createLevelControlToolbar( unit ) {
|
||||
return [ {
|
||||
icon: ( unit === '%' ? Icons.percent : Icons[ unit ] ),
|
||||
isActive: ( undefined !== this.state.value && undefined !== this.state.value.unit && this.state.value.unit === unit ),
|
||||
onClick: () => {
|
||||
let value = this.state.value;
|
||||
value.unit = unit;
|
||||
this.updateValues( value );
|
||||
},
|
||||
} ];
|
||||
};
|
||||
getUnitButtons() {
|
||||
let self = this;
|
||||
const { units } = this.controlParams;
|
||||
let currentUnit;
|
||||
currentUnit = ( undefined !== this.state.value.unit ? this.state.value.unit : 'px' );
|
||||
if ( units.length === 1 ) {
|
||||
return ( <Button
|
||||
className="is-active is-single"
|
||||
isSmall
|
||||
disabled
|
||||
>{ ( '%' === currentUnit ? Icons.percent : Icons[ currentUnit ] ) }</Button> );
|
||||
}
|
||||
return <ToolbarGroup
|
||||
isCollapsed={ true }
|
||||
icon={ ( '%' === currentUnit ? Icons.percent : Icons[ currentUnit ] ) }
|
||||
label={ __( 'Unit', 'kadence' ) }
|
||||
controls={ units.map( ( unit ) => this.createLevelControlToolbar( unit ) ) }
|
||||
/>
|
||||
}
|
||||
updateValues( value ) {
|
||||
if ( value ) {
|
||||
this.setState( { value: value } );
|
||||
} else {
|
||||
this.setState( { value: this.defaultValue } );
|
||||
value = {};
|
||||
}
|
||||
if ( this.controlParams.responsive ) {
|
||||
value.flag = !this.props.control.setting.get().flag;
|
||||
}
|
||||
this.props.control.setting.set( {
|
||||
...{ flag: true },
|
||||
...value,
|
||||
} );
|
||||
}
|
||||
resetValues() {
|
||||
this.setState( { value: this.defaultValue } );
|
||||
this.props.control.setting.set( {} );
|
||||
}
|
||||
}
|
||||
|
||||
BorderComponent.propTypes = {
|
||||
control: PropTypes.object.isRequired,
|
||||
customizer: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
export default BorderComponent;
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createRoot } from '@wordpress/element';
|
||||
import BorderComponent from './border-component.js';
|
||||
|
||||
export const BorderControl = wp.customize.KadenceControl.extend( {
|
||||
renderContent: function renderContent() {
|
||||
let control = this;
|
||||
let root = createRoot( control.container[0] );
|
||||
root.render( <BorderComponent control={control} customizer={ wp.customize }/> );
|
||||
// ReactDOM.render(
|
||||
// <BorderComponent control={control} customizer={ wp.customize }/>,
|
||||
// control.container[0]
|
||||
// );
|
||||
}
|
||||
} );
|
||||
@@ -0,0 +1,522 @@
|
||||
/* 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 { __ } from '@wordpress/i18n';
|
||||
|
||||
const { ButtonGroup, Dashicon, Toolbar, ToolbarGroup, Tooltip, Button } = wp.components;
|
||||
|
||||
/**
|
||||
* WordPress dependencies
|
||||
*/
|
||||
import { createRef, Component, Fragment } from '@wordpress/element';
|
||||
class SingleBorderComponent extends Component {
|
||||
constructor() {
|
||||
super( ...arguments );
|
||||
this.updateValues = this.updateValues.bind( this );
|
||||
this.resetValues = this.resetValues.bind( this );
|
||||
this.handleChangeComplete = this.handleChangeComplete.bind( this );
|
||||
this.handleResponsiveChangeComplete = this.handleResponsiveChangeComplete.bind( this );
|
||||
this.getUnitButtons = this.getUnitButtons.bind( this );
|
||||
this.getResponsiveUnitButtons = this.getResponsiveUnitButtons.bind( this );
|
||||
this.createLevelControlToolbar = this.createLevelControlToolbar.bind( this );
|
||||
this.createResponsiveLevelControlToolbar = this.createResponsiveLevelControlToolbar.bind( this );
|
||||
this.getStyleButtons = this.getStyleButtons.bind( this );
|
||||
this.getResponsiveStyleButtons = this.getResponsiveStyleButtons.bind( this );
|
||||
this.createStyleControlToolbar = this.createStyleControlToolbar.bind( this );
|
||||
this.createResponsiveStyleControlToolbar = this.createResponsiveStyleControlToolbar.bind( this );
|
||||
let value = this.props.control.settings[this.props.item] ? this.props.control.settings[this.props.item].get() : [];
|
||||
let defaultParams = {
|
||||
min: {
|
||||
px: '0',
|
||||
em: '0',
|
||||
rem: '0',
|
||||
},
|
||||
max: {
|
||||
px: '300',
|
||||
em: '12',
|
||||
rem: '12',
|
||||
},
|
||||
step: {
|
||||
px: '1',
|
||||
em: '0.01',
|
||||
rem: '0.01',
|
||||
},
|
||||
units: ['px', 'em', 'rem'],
|
||||
styles: ['none', 'solid', 'dashed', 'dotted', 'double'],
|
||||
responsive:true,
|
||||
color:true,
|
||||
};
|
||||
this.controlParams = this.props.control.params.input_attrs ? {
|
||||
...defaultParams,
|
||||
...this.props.control.params.input_attrs,
|
||||
} : defaultParams;
|
||||
let responsiveDefault = {
|
||||
'desktop': {
|
||||
'width': '',
|
||||
'unit': 'px',
|
||||
'style': 'none',
|
||||
'color': ( this.controlParams.color ? '' : 'currentColor' ),
|
||||
}
|
||||
};
|
||||
let noneResponsiveDefault = {
|
||||
'width': '',
|
||||
'unit': 'px',
|
||||
'style': 'none',
|
||||
'color': ( this.controlParams.color ? '' : 'currentColor' ),
|
||||
};
|
||||
let baseDefault;
|
||||
if ( this.controlParams.responsive ) {
|
||||
baseDefault = responsiveDefault;
|
||||
} else {
|
||||
baseDefault = noneResponsiveDefault;
|
||||
}
|
||||
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',
|
||||
value: value,
|
||||
};
|
||||
this.anchorNodeRef = createRef();
|
||||
}
|
||||
handleResponsiveChangeComplete( color, isPalette, device ) {
|
||||
let value = this.state.value;
|
||||
if ( undefined === value[ device ] ) {
|
||||
value[ device ] = {
|
||||
'width': '',
|
||||
'unit': '',
|
||||
'style': '',
|
||||
'color': '',
|
||||
}
|
||||
}
|
||||
if ( isPalette ) {
|
||||
value[ device ].color = isPalette;
|
||||
} else if ( undefined !== color.rgb && undefined !== color.rgb.a && 1 !== color.rgb.a ) {
|
||||
value[ device ].color = 'rgba(' + color.rgb.r + ',' + color.rgb.g + ',' + color.rgb.b + ',' + color.rgb.a + ')';
|
||||
} else {
|
||||
value[ device ].color = color.hex;
|
||||
}
|
||||
this.updateValues( value );
|
||||
}
|
||||
handleChangeComplete( 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 data = this.props.control.params;
|
||||
let currentUnit;
|
||||
if ( this.controlParams.responsive ) {
|
||||
if ( undefined === this.state.value[ this.props.currentDevice ] ) {
|
||||
let largerDevice = ( this.props.currentDevice === 'mobile' ? 'tablet' : 'desktop' );
|
||||
if ( undefined !== this.state.value[largerDevice] && this.state.value[largerDevice].unit ) {
|
||||
currentUnit = this.state.value[largerDevice].unit;
|
||||
} else if ( 'tablet' === largerDevice && undefined !== this.state.value['desktop'] && this.state.value['desktop'].unit ) {
|
||||
currentUnit = this.state.value['desktop'].unit;
|
||||
}
|
||||
} else if ( undefined === this.state.value[ this.props.currentDevice ].unit ) {
|
||||
let largerDevice = ( this.props.currentDevice === 'mobile' ? 'tablet' : 'desktop' );
|
||||
if ( undefined !== this.state.value[largerDevice] && this.state.value[largerDevice].unit ) {
|
||||
currentUnit = this.state.value[largerDevice].unit;
|
||||
} else if ( 'tablet' === largerDevice && undefined !== this.state.value['desktop'] && this.state.value['desktop'].unit ) {
|
||||
currentUnit = this.state.value['desktop'].unit;
|
||||
}
|
||||
} else if ( '' === this.state.value[ this.props.currentDevice ].unit ) {
|
||||
let largerDevice = ( this.props.currentDevice === 'mobile' ? 'tablet' : 'desktop' );
|
||||
if ( undefined !== this.state.value[largerDevice] && this.state.value[largerDevice].unit ) {
|
||||
currentUnit = this.state.value[largerDevice].unit;
|
||||
} else if ( 'tablet' === largerDevice && undefined !== this.state.value['desktop'] && this.state.value['desktop'].unit ) {
|
||||
currentUnit = this.state.value['desktop'].unit;
|
||||
}
|
||||
} else if ( '' !== this.state.value[ this.props.currentDevice ].unit ) {
|
||||
currentUnit = this.state.value[ this.props.currentDevice ].unit
|
||||
}
|
||||
} else {
|
||||
currentUnit = ( undefined !== this.state.value.unit ? this.state.value.unit : 'px' );
|
||||
}
|
||||
let currentStyle;
|
||||
if ( this.controlParams.responsive ) {
|
||||
if ( undefined === this.state.value[ this.props.currentDevice ] ) {
|
||||
let largerDevice = ( this.props.currentDevice === 'mobile' ? 'tablet' : 'desktop' );
|
||||
if ( undefined !== this.state.value[largerDevice] && this.state.value[largerDevice].style ) {
|
||||
currentStyle = this.state.value[largerDevice].style;
|
||||
} else if ( 'tablet' === largerDevice && undefined !== this.state.value['desktop'] && this.state.value['desktop'].style ) {
|
||||
currentStyle = this.state.value['desktop'].style;
|
||||
}
|
||||
} else if ( undefined === this.state.value[ this.props.currentDevice ].style ) {
|
||||
let largerDevice = ( this.props.currentDevice === 'mobile' ? 'tablet' : 'desktop' );
|
||||
if ( undefined !== this.state.value[largerDevice] && this.state.value[largerDevice].style ) {
|
||||
currentStyle = this.state.value[largerDevice].style;
|
||||
} else if ( 'tablet' === largerDevice && undefined !== this.state.value['desktop'] && this.state.value['desktop'].style ) {
|
||||
currentStyle = this.state.value['desktop'].style;
|
||||
}
|
||||
} else if ( '' === this.state.value[ this.props.currentDevice ].style ) {
|
||||
let largerDevice = ( this.props.currentDevice === 'mobile' ? 'tablet' : 'desktop' );
|
||||
if ( undefined !== this.state.value[largerDevice] && this.state.value[largerDevice].style ) {
|
||||
currentStyle = this.state.value[largerDevice].style;
|
||||
} else if ( 'tablet' === largerDevice && undefined !== this.state.value['desktop'] && this.state.value['desktop'].style ) {
|
||||
currentStyle = this.state.value['desktop'].style;
|
||||
}
|
||||
} else if ( '' !== this.state.value[ this.props.currentDevice ].style ) {
|
||||
currentStyle = this.state.value[ this.props.currentDevice ].style
|
||||
}
|
||||
} else {
|
||||
currentStyle = ( undefined !== this.state.value.style ? this.state.value.style : 'none' );
|
||||
}
|
||||
const onResponsiveInputChange = ( event ) => {
|
||||
const newValue = Number( event.target.value );
|
||||
let value = this.state.value;
|
||||
if ( undefined === value[ this.props.currentDevice ] ) {
|
||||
value[ this.props.currentDevice ] = {
|
||||
'width': '',
|
||||
'unit': '',
|
||||
'style': '',
|
||||
'color': '',
|
||||
}
|
||||
}
|
||||
value[ this.props.currentDevice ].width = newValue;
|
||||
this.updateValues( value );
|
||||
}
|
||||
const onInputChange = ( event ) => {
|
||||
const newValue = ( '' !== event.target.value ? Number( event.target.value ) : '' );
|
||||
let value = this.state.value;
|
||||
value.width = newValue;
|
||||
this.updateValues( value );
|
||||
}
|
||||
let theIcon;
|
||||
if ( 'border_top' === this.props.item ) {
|
||||
theIcon = Icons.outlinetop;
|
||||
} else if ( 'border_left' === this.props.item ) {
|
||||
theIcon = Icons.outlineleft;
|
||||
} else if ( 'border_right' === this.props.item ) {
|
||||
theIcon = Icons.outlineright;
|
||||
} else if ( 'border_bottom' === this.props.item ) {
|
||||
theIcon = Icons.outlinebottom;
|
||||
}
|
||||
let isDisabled = true;
|
||||
if ( this.controlParams.responsive ) {
|
||||
if ( ( undefined !== this.state.value['tablet'] ) || ( undefined !== this.state.value['mobile'] ) ) {
|
||||
isDisabled = false;
|
||||
} else if ( ( 'none' !== this.state.value['desktop'].style ) || ( '' !== this.state.value['desktop'].color ) || ( '' !== this.state.value['desktop'].width ) || ( 'px' !== this.state.value['desktop'].unit ) ) {
|
||||
isDisabled = false;
|
||||
}
|
||||
}
|
||||
return (
|
||||
<div ref={this.anchorNodeRef} className="kadence-responsive-controls-content kadence-border-single-item">
|
||||
{ this.controlParams.responsive && (
|
||||
<Fragment>
|
||||
<Tooltip text={ __( 'Reset Values', 'kadence' ) }>
|
||||
<Button
|
||||
className="reset kadence-reset"
|
||||
disabled={ isDisabled }
|
||||
onClick={ () => {
|
||||
this.resetValues();
|
||||
} }
|
||||
>
|
||||
<Dashicon icon='image-rotate' />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<span class="border-icon">{ theIcon }</span>
|
||||
{ 'none' !== currentStyle && (
|
||||
<Fragment>
|
||||
{ this.controlParams.color && (
|
||||
<ColorControl
|
||||
presetColors={ this.state.colorPalette }
|
||||
color={ ( undefined !== this.state.value[ this.props.currentDevice ] && this.state.value[ this.props.currentDevice ].color ? this.state.value[ this.props.currentDevice ].color : '' ) }
|
||||
usePalette={ true }
|
||||
tooltip={ __( 'Border Color' ) }
|
||||
onChangeComplete={ ( color, isPalette ) => this.handleResponsiveChangeComplete( color, isPalette, this.props.currentDevice ) }
|
||||
customizer={ this.props.customizer }
|
||||
controlRef={ this.anchorNodeRef }
|
||||
/>
|
||||
) }
|
||||
<input
|
||||
value={ ( undefined !== this.state.value[ this.props.currentDevice ] && undefined !== this.state.value[ this.props.currentDevice ].width ? this.state.value[ this.props.currentDevice ].width : '' ) }
|
||||
onChange={ onResponsiveInputChange }
|
||||
min={this.controlParams.min[currentUnit]}
|
||||
max={this.controlParams.max[currentUnit]}
|
||||
step={this.controlParams.step[currentUnit]}
|
||||
type="number"
|
||||
className="components-text-control__input"
|
||||
/>
|
||||
{ this.controlParams.units && (
|
||||
<div className="kadence-units">
|
||||
{ this.getResponsiveUnitButtons() }
|
||||
</div>
|
||||
) }
|
||||
</Fragment>
|
||||
) }
|
||||
{ this.controlParams.styles && (
|
||||
<div className="kadence-units kadence-style-options">
|
||||
{ this.getResponsiveStyleButtons() }
|
||||
</div>
|
||||
) }
|
||||
</Fragment>
|
||||
) }
|
||||
{ ! this.controlParams.responsive && (
|
||||
<Fragment>
|
||||
{ 'none' !== currentStyle && (
|
||||
<Fragment>
|
||||
{ this.controlParams.color && (
|
||||
<ColorControl
|
||||
presetColors={ this.state.colorPalette }
|
||||
color={ ( undefined !== this.state.value.color && this.state.value.color ? this.state.value.color : '' ) }
|
||||
usePalette={ true }
|
||||
tooltip={ __( 'Border Color' ) }
|
||||
onChangeComplete={ ( color, isPalette ) => this.handleChangeComplete( color, isPalette ) }
|
||||
customizer={ this.props.customizer }
|
||||
controlRef={ this.anchorNodeRef }
|
||||
/>
|
||||
) }
|
||||
<input
|
||||
value={ ( undefined !== this.state.value && undefined !== this.state.value.width ? this.state.value.width : '' ) }
|
||||
onChange={ onInputChange }
|
||||
min={this.controlParams.min[currentUnit]}
|
||||
max={this.controlParams.max[currentUnit]}
|
||||
step={this.controlParams.step[currentUnit]}
|
||||
type="number"
|
||||
className="components-text-control__input"
|
||||
/>
|
||||
{ this.controlParams.units && (
|
||||
<div className="kadence-units">
|
||||
{ this.getUnitButtons() }
|
||||
</div>
|
||||
) }
|
||||
</Fragment>
|
||||
) }
|
||||
{ this.controlParams.styles && (
|
||||
<div className="kadence-units kadence-style-options">
|
||||
{ this.getStyleButtons() }
|
||||
</div>
|
||||
) }
|
||||
</Fragment>
|
||||
) }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
getResponsiveStyleButtons() {
|
||||
let self = this;
|
||||
const { styles } = this.controlParams;
|
||||
let currentStyle;
|
||||
if ( undefined === this.state.value[ this.props.currentDevice ] ) {
|
||||
let largerDevice = ( this.props.currentDevice === 'mobile' ? 'tablet' : 'desktop' );
|
||||
if ( undefined !== this.state.value[largerDevice] && this.state.value[largerDevice].style ) {
|
||||
currentStyle = this.state.value[largerDevice].style;
|
||||
} else if ( 'tablet' === largerDevice && undefined !== this.state.value['desktop'] && this.state.value['desktop'].style ) {
|
||||
currentStyle = this.state.value['desktop'].style;
|
||||
}
|
||||
} else if ( undefined === this.state.value[ this.props.currentDevice ].style ) {
|
||||
let largerDevice = ( this.props.currentDevice === 'mobile' ? 'tablet' : 'desktop' );
|
||||
if ( undefined !== this.state.value[largerDevice] && this.state.value[largerDevice].style ) {
|
||||
currentStyle = this.state.value[largerDevice].style;
|
||||
} else if ( 'tablet' === largerDevice && undefined !== this.state.value['desktop'] && this.state.value['desktop'].style ) {
|
||||
currentStyle = this.state.value['desktop'].style;
|
||||
}
|
||||
} else if ( '' === this.state.value[ this.props.currentDevice ].style ) {
|
||||
let largerDevice = ( this.props.currentDevice === 'mobile' ? 'tablet' : 'desktop' );
|
||||
if ( undefined !== this.state.value[largerDevice] && this.state.value[largerDevice].style ) {
|
||||
currentStyle = this.state.value[largerDevice].style;
|
||||
} else if ( 'tablet' === largerDevice && undefined !== this.state.value['desktop'] && this.state.value['desktop'].style ) {
|
||||
currentStyle = this.state.value['desktop'].style;
|
||||
}
|
||||
} else if ( '' !== this.state.value[ this.props.currentDevice ].style ) {
|
||||
currentStyle = this.state.value[ this.props.currentDevice ].style
|
||||
}
|
||||
if ( styles.length === 1 ) {
|
||||
return ( <Button
|
||||
className="is-active is-single"
|
||||
isSmall
|
||||
disabled
|
||||
>{ Icons[ currentStyle ] }</Button> );
|
||||
}
|
||||
return <ToolbarGroup
|
||||
isCollapsed={ true }
|
||||
icon={ Icons[ currentStyle ] }
|
||||
label={ __( 'Style', 'kadence' ) }
|
||||
controls={ styles.map( ( style ) => this.createResponsiveStyleControlToolbar( style ) ) }
|
||||
/>
|
||||
}
|
||||
createResponsiveStyleControlToolbar( style ) {
|
||||
return [ {
|
||||
icon: Icons[ style ],
|
||||
isActive: ( undefined !== this.state.value[ this.props.currentDevice ] && undefined !== this.state.value[ this.props.currentDevice ].style && this.state.value[ this.props.currentDevice ].style === style ),
|
||||
onClick: () => {
|
||||
let value = this.state.value;
|
||||
if ( undefined === value[ this.props.currentDevice ] ) {
|
||||
value[ this.props.currentDevice ] = {
|
||||
'width': '',
|
||||
'unit': '',
|
||||
'style': '',
|
||||
'color': '',
|
||||
}
|
||||
}
|
||||
value[ this.props.currentDevice ].style = style;
|
||||
this.updateValues( value );
|
||||
},
|
||||
} ];
|
||||
};
|
||||
getStyleButtons() {
|
||||
let self = this;
|
||||
const { styles } = this.controlParams;
|
||||
let currentStyle;
|
||||
currentStyle = ( undefined !== this.state.value.style ? this.state.value.style : 'none' );
|
||||
if ( styles.length === 1 ) {
|
||||
return ( <Button
|
||||
className="is-active is-single"
|
||||
isSmall
|
||||
disabled
|
||||
>{ Icons[ currentStyle ] }</Button> );
|
||||
}
|
||||
return <ToolbarGroup
|
||||
isCollapsed={ true }
|
||||
icon={ Icons[ currentStyle ] }
|
||||
label={ __( 'Style', 'kadence' ) }
|
||||
controls={ styles.map( ( style ) => this.createStyleControlToolbar( style ) ) }
|
||||
/>
|
||||
}
|
||||
createStyleControlToolbar( style ) {
|
||||
return [ {
|
||||
icon: Icons[ style ],
|
||||
isActive: ( undefined !== this.state.value && undefined !== this.state.value.style && this.state.value.style === style ),
|
||||
onClick: () => {
|
||||
let value = this.state.value;
|
||||
value.style = style;
|
||||
this.updateValues( value );
|
||||
},
|
||||
} ];
|
||||
};
|
||||
createResponsiveLevelControlToolbar( unit ) {
|
||||
return [ {
|
||||
icon: ( unit === '%' ? Icons.percent : Icons[ unit ] ),
|
||||
isActive: ( undefined !== this.state.value[ this.props.currentDevice ] && undefined !== this.state.value[ this.props.currentDevice ].unit && this.state.value[ this.props.currentDevice ].unit === unit ),
|
||||
onClick: () => {
|
||||
let value = this.state.value;
|
||||
if ( undefined === value[ this.props.currentDevice ] ) {
|
||||
value[ this.props.currentDevice ] = {
|
||||
'width': '',
|
||||
'unit': '',
|
||||
'style': '',
|
||||
'color': '',
|
||||
}
|
||||
}
|
||||
value[ this.props.currentDevice ].unit = unit;
|
||||
this.updateValues( value );
|
||||
},
|
||||
} ];
|
||||
};
|
||||
getResponsiveUnitButtons() {
|
||||
let self = this;
|
||||
const { units } = this.controlParams;
|
||||
let currentUnit;
|
||||
if ( undefined === self.state.value[ self.state.currentDevice ] ) {
|
||||
let largerDevice = ( self.state.currentDevice === 'mobile' ? 'tablet' : 'desktop' );
|
||||
if ( undefined !== this.state.value[largerDevice] && this.state.value[largerDevice].unit ) {
|
||||
currentUnit = this.state.value[largerDevice].unit;
|
||||
} else if ( 'tablet' === largerDevice && undefined !== this.state.value['desktop'] && this.state.value['desktop'].unit ) {
|
||||
currentUnit = this.state.value['desktop'].unit;
|
||||
}
|
||||
} else if ( undefined !== self.state.value[ self.state.currentDevice ].unit ) {
|
||||
let largerDevice = ( self.state.currentDevice === 'mobile' ? 'tablet' : 'desktop' );
|
||||
if ( undefined !== this.state.value[largerDevice] && this.state.value[largerDevice].unit ) {
|
||||
currentUnit = this.state.value[largerDevice].unit;
|
||||
} else if ( 'tablet' === largerDevice && undefined !== this.state.value['desktop'] && this.state.value['desktop'].unit ) {
|
||||
currentUnit = this.state.value['desktop'].unit;
|
||||
}
|
||||
} else if ( '' === self.state.value[ self.state.currentDevice ].unit ) {
|
||||
let largerDevice = ( self.state.currentDevice === 'mobile' ? 'tablet' : 'desktop' );
|
||||
if ( undefined !== this.state.value[largerDevice] && this.state.value[largerDevice].unit ) {
|
||||
currentUnit = this.state.value[largerDevice].unit;
|
||||
} else if ( 'tablet' === largerDevice && undefined !== this.state.value['desktop'] && this.state.value['desktop'].unit ) {
|
||||
currentUnit = this.state.value['desktop'].unit;
|
||||
}
|
||||
} else if ( '' !== self.state.value[ self.state.currentDevice ].unit ) {
|
||||
currentUnit = self.state.value[ self.state.currentDevice ].unit
|
||||
}
|
||||
if ( units.length === 1 ) {
|
||||
return ( <Button
|
||||
className="is-active is-single"
|
||||
isSmall
|
||||
disabled
|
||||
>{ ( '%' === currentUnit ? Icons.percent : Icons[ currentUnit ] ) }</Button> );
|
||||
}
|
||||
return <ToolbarGroup
|
||||
isCollapsed={ true }
|
||||
icon={ ( '%' === currentUnit ? Icons.percent : Icons[ currentUnit ] ) }
|
||||
label={ __( 'Unit', 'kadence' ) }
|
||||
controls={ units.map( ( unit ) => this.createResponsiveLevelControlToolbar( unit ) ) }
|
||||
/>
|
||||
}
|
||||
createLevelControlToolbar( unit ) {
|
||||
return [ {
|
||||
icon: ( unit === '%' ? Icons.percent : Icons[ unit ] ),
|
||||
isActive: ( undefined !== this.state.value && undefined !== this.state.value.unit && this.state.value.unit === unit ),
|
||||
onClick: () => {
|
||||
let value = this.state.value;
|
||||
value.unit = unit;
|
||||
this.updateValues( value );
|
||||
},
|
||||
} ];
|
||||
};
|
||||
getUnitButtons() {
|
||||
let self = this;
|
||||
const { units } = this.controlParams;
|
||||
let currentUnit;
|
||||
currentUnit = ( undefined !== this.state.value.unit ? this.state.value.unit : 'px' );
|
||||
if ( units.length === 1 ) {
|
||||
return ( <Button
|
||||
className="is-active is-single"
|
||||
isSmall
|
||||
disabled
|
||||
>{ ( '%' === currentUnit ? Icons.percent : Icons[ currentUnit ] ) }</Button> );
|
||||
}
|
||||
return <ToolbarGroup
|
||||
isCollapsed={ true }
|
||||
icon={ ( '%' === currentUnit ? Icons.percent : Icons[ currentUnit ] ) }
|
||||
label={ __( 'Unit', 'kadence' ) }
|
||||
controls={ units.map( ( unit ) => this.createLevelControlToolbar( unit ) ) }
|
||||
/>
|
||||
}
|
||||
resetValues() {
|
||||
const value = JSON.parse( JSON.stringify( this.defaultValue ) );
|
||||
this.setState( { value: value } );
|
||||
if ( this.controlParams.responsive ) {
|
||||
value.flag = !this.props.control.settings[this.props.item].get().flag;
|
||||
}
|
||||
this.props.control.settings[this.props.item].set( {
|
||||
...value,
|
||||
} );
|
||||
}
|
||||
updateValues( value ) {
|
||||
this.setState( { value: value } );
|
||||
if ( this.controlParams.responsive ) {
|
||||
value.flag = !this.props.control.settings[this.props.item].get().flag;
|
||||
}
|
||||
this.props.control.settings[this.props.item].set( {
|
||||
...this.props.control.settings[this.props.item].get(),
|
||||
...value,
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
SingleBorderComponent.propTypes = {
|
||||
control: PropTypes.object.isRequired,
|
||||
customizer: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
export default SingleBorderComponent;
|
||||
@@ -0,0 +1,182 @@
|
||||
/* jshint esversion: 6 */
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
|
||||
import ResponsiveControl from '../common/responsive.js';
|
||||
import Icons from '../common/icons.js';
|
||||
import SingleBorderComponent from './border-component';
|
||||
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
const { ButtonGroup, Dashicon, Toolbar, Tooltip, Button } = wp.components;
|
||||
|
||||
/**
|
||||
* WordPress dependencies
|
||||
*/
|
||||
import { Component, Fragment } from '@wordpress/element';
|
||||
class BordersComponent extends Component {
|
||||
constructor() {
|
||||
super( ...arguments );
|
||||
//this.updateValues = this.updateValues.bind( this );
|
||||
//this.resetValues = this.resetValues.bind( this );
|
||||
let defaultParams = {
|
||||
min: {
|
||||
px: '0',
|
||||
em: '0',
|
||||
rem: '0',
|
||||
},
|
||||
max: {
|
||||
px: '300',
|
||||
em: '12',
|
||||
rem: '12',
|
||||
},
|
||||
step: {
|
||||
px: '1',
|
||||
em: '0.01',
|
||||
rem: '0.01',
|
||||
},
|
||||
units: ['px', 'em', 'rem'],
|
||||
styles: ['none', 'solid', 'dashed', 'dotted', 'double'],
|
||||
responsive:true,
|
||||
color:true,
|
||||
};
|
||||
this.controlParams = this.props.control.params.input_attrs ? {
|
||||
...defaultParams,
|
||||
...this.props.control.params.input_attrs,
|
||||
} : defaultParams;
|
||||
let responsiveDefault = {
|
||||
'desktop': {
|
||||
'width': '',
|
||||
'unit': 'px',
|
||||
'style': 'none',
|
||||
'color': ( this.controlParams.color ? '' : 'currentColor' ),
|
||||
}
|
||||
};
|
||||
let noneResponsiveDefault = {
|
||||
'width': '',
|
||||
'unit': 'px',
|
||||
'style': 'none',
|
||||
'color': ( this.controlParams.color ? '' : 'currentColor' ),
|
||||
};
|
||||
let baseDefault;
|
||||
if ( this.controlParams.responsive ) {
|
||||
baseDefault = responsiveDefault;
|
||||
} else {
|
||||
baseDefault = noneResponsiveDefault;
|
||||
}
|
||||
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',
|
||||
value: value,
|
||||
};
|
||||
}
|
||||
render() {
|
||||
const data = this.props.control.params;
|
||||
const responsiveControlLabel = (
|
||||
<Fragment>
|
||||
{/* <Tooltip text={ __( 'Reset Values', 'kadence' ) }>
|
||||
<Button
|
||||
className="reset kadence-reset"
|
||||
disabled={ isDisabled }
|
||||
onClick={ () => {
|
||||
this.resetValues();
|
||||
} }
|
||||
>
|
||||
<Dashicon icon='image-rotate' />
|
||||
</Button>
|
||||
</Tooltip> */}
|
||||
{ data.label &&
|
||||
data.label
|
||||
}
|
||||
</Fragment>
|
||||
);
|
||||
const controlLabel = (
|
||||
<Fragment>
|
||||
{/* <Tooltip text={ __( 'Reset Values', 'kadence' ) }>
|
||||
<Button
|
||||
className="reset kadence-reset"
|
||||
disabled={ ( this.defaultValue === this.state.value ) }
|
||||
onClick={ () => {
|
||||
let value = this.state.value;
|
||||
value = this.defaultValue
|
||||
this.updateValues( value );
|
||||
} }
|
||||
>
|
||||
<Dashicon icon='image-rotate' />
|
||||
</Button>
|
||||
</Tooltip> */}
|
||||
{ data.label &&
|
||||
data.label
|
||||
}
|
||||
</Fragment>
|
||||
);
|
||||
return (
|
||||
<div className="kadence-control-field kadence-border-control">
|
||||
{ this.controlParams.responsive && (
|
||||
<ResponsiveControl
|
||||
onChange={ ( currentDevice ) => this.setState( { currentDevice } ) }
|
||||
controlLabel={ responsiveControlLabel }
|
||||
>
|
||||
{ Object.keys( this.props.control.params.settings ).map( ( item ) => {
|
||||
return (
|
||||
<SingleBorderComponent
|
||||
currentDevice={ this.state.currentDevice }
|
||||
item={ item }
|
||||
name={ this.props.control.params.settings[item] }
|
||||
customizer={ this.props.customizer }
|
||||
control={ this.props.control }
|
||||
/>
|
||||
);
|
||||
} ) }
|
||||
</ResponsiveControl>
|
||||
) }
|
||||
{ ! this.controlParams.responsive && (
|
||||
<Fragment>
|
||||
<div className="kadence-responsive-control-bar">
|
||||
<span className="customize-control-title">{ controlLabel }</span>
|
||||
</div>
|
||||
<div className="kadence-responsive-controls-content">
|
||||
<SingleBorderComponent
|
||||
currentDevice={ currentDevice }
|
||||
item={ 'border_top' }
|
||||
customizer={ this.props.customizer }
|
||||
/>
|
||||
</div>
|
||||
</Fragment>
|
||||
) }
|
||||
{ this.props.control.renderNotice() }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
// resetValues() {
|
||||
// Object.keys( this.props.control.params.settings ).map( ( item ) => {
|
||||
// this.props.control.settings[item].set( {
|
||||
// responsiveDefault
|
||||
// } );
|
||||
// } );
|
||||
// }
|
||||
// updateValues( value ) {
|
||||
// this.setState( { value: value } );
|
||||
// if ( this.controlParams.responsive ) {
|
||||
// value.flag = !this.props.control.setting.get().flag;
|
||||
// }
|
||||
// this.props.control.setting.set( {
|
||||
// ...this.props.control.setting.get(),
|
||||
// ...value,
|
||||
// } );
|
||||
// }
|
||||
}
|
||||
|
||||
BordersComponent.propTypes = {
|
||||
control: PropTypes.object.isRequired,
|
||||
customizer: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
export default BordersComponent;
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createRoot } from '@wordpress/element';
|
||||
import BordersComponent from './borders-component.js';
|
||||
|
||||
export const BordersControl = wp.customize.KadenceControl.extend( {
|
||||
renderContent: function renderContent() {
|
||||
let control = this;
|
||||
let root = createRoot( control.container[0] );
|
||||
root.render( <BordersComponent control={control} customizer={ wp.customize }/> );
|
||||
// ReactDOM.render(
|
||||
// <BordersComponent control={control} customizer={ wp.customize }/>,
|
||||
// control.container[0]
|
||||
// );
|
||||
}
|
||||
} );
|
||||
@@ -0,0 +1,634 @@
|
||||
/* 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 { __ } from "@wordpress/i18n";
|
||||
|
||||
const { ButtonGroup, Dashicon, Toolbar, Tooltip, Button, ToggleControl } =
|
||||
wp.components;
|
||||
|
||||
/**
|
||||
* WordPress dependencies
|
||||
*/
|
||||
import { createRef, Component, Fragment } from "@wordpress/element";
|
||||
class BoxshadowComponent extends Component {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.updateValues = this.updateValues.bind(this);
|
||||
this.handleChangeComplete = this.handleChangeComplete.bind(this);
|
||||
this.handleResponsiveChangeComplete =
|
||||
this.handleResponsiveChangeComplete.bind(this);
|
||||
let value = this.props.control.setting.get();
|
||||
let defaultParams = {
|
||||
responsive: false,
|
||||
};
|
||||
this.controlParams = this.props.control.params.input_attrs
|
||||
? {
|
||||
...defaultParams,
|
||||
...this.props.control.params.input_attrs,
|
||||
}
|
||||
: defaultParams;
|
||||
let responsiveDefault = {
|
||||
desktop: {
|
||||
color: "rgba(0,0,0,0.05)",
|
||||
hOffset: 0,
|
||||
vOffset: 15,
|
||||
blur: 15,
|
||||
spread: -10,
|
||||
inset: false,
|
||||
disabled: false,
|
||||
},
|
||||
};
|
||||
let noneResponsiveDefault = {
|
||||
color: "rgba(0,0,0,0.05)",
|
||||
hOffset: 0,
|
||||
vOffset: 15,
|
||||
blur: 15,
|
||||
spread: -10,
|
||||
inset: false,
|
||||
disabled: false,
|
||||
};
|
||||
let baseDefault;
|
||||
if (this.controlParams.responsive) {
|
||||
baseDefault = responsiveDefault;
|
||||
} else {
|
||||
baseDefault = noneResponsiveDefault;
|
||||
}
|
||||
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",
|
||||
value: value,
|
||||
};
|
||||
this.anchorNodeRef = createRef();
|
||||
}
|
||||
handleResponsiveChangeComplete(color, isPalette, device) {
|
||||
let value = this.state.value;
|
||||
if (undefined === value[device]) {
|
||||
value[device] = {
|
||||
color: "",
|
||||
hOffset: "",
|
||||
vOffset: "",
|
||||
blur: "",
|
||||
spread: "",
|
||||
inset: "",
|
||||
disabled: false,
|
||||
};
|
||||
}
|
||||
if (isPalette) {
|
||||
value[device].color = isPalette;
|
||||
} else if (
|
||||
undefined !== color.rgb &&
|
||||
undefined !== color.rgb.a &&
|
||||
1 !== color.rgb.a
|
||||
) {
|
||||
value[device].color =
|
||||
"rgba(" +
|
||||
color.rgb.r +
|
||||
"," +
|
||||
color.rgb.g +
|
||||
"," +
|
||||
color.rgb.b +
|
||||
"," +
|
||||
color.rgb.a +
|
||||
")";
|
||||
} else {
|
||||
value[device].color = color.hex;
|
||||
}
|
||||
this.updateValues(value);
|
||||
}
|
||||
handleChangeComplete(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 data = this.props.control.params;
|
||||
const onResponsiveInputChange = (event, setting) => {
|
||||
const newValue = Number(event.target.value);
|
||||
let value = this.state.value;
|
||||
if (undefined === value[this.state.currentDevice]) {
|
||||
value[this.state.currentDevice] = {
|
||||
color: "",
|
||||
hOffset: "",
|
||||
vOffset: "",
|
||||
blur: "",
|
||||
spread: "",
|
||||
inset: "",
|
||||
disabled: false,
|
||||
};
|
||||
}
|
||||
value[this.state.currentDevice][setting] = newValue;
|
||||
this.updateValues(value);
|
||||
};
|
||||
const onInputChange = (event, setting) => {
|
||||
const newValue =
|
||||
"" !== event.target.value ? Number(event.target.value) : "";
|
||||
let value = this.state.value;
|
||||
value[setting] = newValue;
|
||||
this.updateValues(value);
|
||||
};
|
||||
const onInsetChange = (newValue) => {
|
||||
let value = this.state.value;
|
||||
value.inset = newValue;
|
||||
this.updateValues(value);
|
||||
};
|
||||
const onDisableChange = (newValue) => {
|
||||
let value = this.state.value;
|
||||
value.disabled = newValue;
|
||||
this.updateValues(value);
|
||||
};
|
||||
const responsiveControlLabel = (
|
||||
<Fragment>
|
||||
{this.state.currentDevice !== "desktop" && (
|
||||
<Tooltip text={__("Reset Device Values", "kadence")}>
|
||||
<Button
|
||||
className="reset kadence-reset"
|
||||
disabled={
|
||||
undefined ===
|
||||
this.state.value[this.state.currentDevice]
|
||||
}
|
||||
onClick={() => {
|
||||
let value = this.state.value;
|
||||
delete value[this.state.currentDevice];
|
||||
this.updateValues(value);
|
||||
}}
|
||||
>
|
||||
<Dashicon icon="image-rotate" />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
)}
|
||||
{data.label && data.label}
|
||||
</Fragment>
|
||||
);
|
||||
const controlLabel = (
|
||||
<Fragment>
|
||||
<Tooltip text={__("Reset Values", "kadence")}>
|
||||
<Button
|
||||
className="reset kadence-reset"
|
||||
disabled={this.defaultValue === this.state.value}
|
||||
onClick={() => {
|
||||
let value = this.state.value;
|
||||
value = this.defaultValue;
|
||||
this.updateValues(value);
|
||||
}}
|
||||
>
|
||||
<Dashicon icon="image-rotate" />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
{data.label && data.label}
|
||||
</Fragment>
|
||||
);
|
||||
return (
|
||||
<div
|
||||
ref={this.anchorNodeRef}
|
||||
className="kadence-control-field kadence-boxshadow-control kadence-border-control"
|
||||
>
|
||||
{this.controlParams.responsive && (
|
||||
<ResponsiveControl
|
||||
onChange={(currentDevice) =>
|
||||
this.setState({ currentDevice })
|
||||
}
|
||||
controlLabel={responsiveControlLabel}
|
||||
>
|
||||
{!this.state.value.disabled && (
|
||||
<>
|
||||
<div className="kt-box-color-settings kt-box-shadow-subset">
|
||||
<p className="kt-box-shadow-title">
|
||||
{__("Color")}
|
||||
</p>
|
||||
<ColorControl
|
||||
presetColors={this.state.colorPalette}
|
||||
color={
|
||||
undefined !==
|
||||
this.state.value.color &&
|
||||
this.state.value.color
|
||||
? this.state.value.color
|
||||
: ""
|
||||
}
|
||||
usePalette={true}
|
||||
tooltip={__("Border Color")}
|
||||
onChangeComplete={(color, isPalette) =>
|
||||
this.handleChangeComplete(
|
||||
color,
|
||||
isPalette
|
||||
)
|
||||
}
|
||||
customizer={this.props.customizer}
|
||||
controlRef={this.anchorNodeRef}
|
||||
/>
|
||||
</div>
|
||||
<div className="kt-box-x-settings kt-box-shadow-subset">
|
||||
<p className="kt-box-shadow-title">
|
||||
{__("X")}
|
||||
</p>
|
||||
<div className="components-base-control kt-boxshadow-number-input">
|
||||
<div className="components-base-control__field">
|
||||
<input
|
||||
value={
|
||||
undefined !==
|
||||
this.state.value &&
|
||||
undefined !==
|
||||
this.state.value.hOffset
|
||||
? this.state.value
|
||||
.hOffset
|
||||
: ""
|
||||
}
|
||||
onChange={(event) =>
|
||||
onInputChange(
|
||||
event,
|
||||
"hOffset"
|
||||
)
|
||||
}
|
||||
min={-200}
|
||||
max={200}
|
||||
step={1}
|
||||
type="number"
|
||||
className="components-text-control__input"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="kt-box-y-settings kt-box-shadow-subset">
|
||||
<p className="kt-box-shadow-title">
|
||||
{__("Y")}
|
||||
</p>
|
||||
<div className="components-base-control kt-boxshadow-number-input">
|
||||
<div className="components-base-control__field">
|
||||
<input
|
||||
value={
|
||||
undefined !==
|
||||
this.state.value &&
|
||||
undefined !==
|
||||
this.state.value.vOffset
|
||||
? this.state.value
|
||||
.vOffset
|
||||
: ""
|
||||
}
|
||||
onChange={(event) =>
|
||||
onInputChange(
|
||||
event,
|
||||
"vOffset"
|
||||
)
|
||||
}
|
||||
min={-200}
|
||||
max={200}
|
||||
step={1}
|
||||
type="number"
|
||||
className="components-text-control__input"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="kt-box-x-settings kt-box-shadow-subset">
|
||||
<p className="kt-box-shadow-title">
|
||||
{__("Blur")}
|
||||
</p>
|
||||
<div className="components-base-control kt-boxshadow-number-input">
|
||||
<div className="components-base-control__field">
|
||||
<input
|
||||
value={
|
||||
undefined !==
|
||||
this.state.value &&
|
||||
undefined !==
|
||||
this.state.value.blur
|
||||
? this.state.value.blur
|
||||
: ""
|
||||
}
|
||||
onChange={(event) =>
|
||||
onInputChange(event, "blur")
|
||||
}
|
||||
min={0}
|
||||
max={200}
|
||||
step={1}
|
||||
type="number"
|
||||
className="components-text-control__input"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="kt-box-y-settings kt-box-shadow-subset">
|
||||
<p className="kt-box-shadow-title">
|
||||
{__("Spread")}
|
||||
</p>
|
||||
<div className="components-base-control kt-boxshadow-number-input">
|
||||
<div className="components-base-control__field">
|
||||
<input
|
||||
value={
|
||||
undefined !==
|
||||
this.state.value &&
|
||||
undefined !==
|
||||
this.state.value.spread
|
||||
? this.state.value
|
||||
.spread
|
||||
: ""
|
||||
}
|
||||
onChange={(event) =>
|
||||
onInputChange(
|
||||
event,
|
||||
"spread"
|
||||
)
|
||||
}
|
||||
min={-200}
|
||||
max={200}
|
||||
step={1}
|
||||
type="number"
|
||||
className="components-text-control__input"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="kt-box-inset-settings">
|
||||
<ToggleControl
|
||||
label={__("Inset")}
|
||||
checked={
|
||||
undefined !== this.state.value &&
|
||||
undefined !== this.state.value.inset
|
||||
? this.state.value.inset
|
||||
: false
|
||||
}
|
||||
onChange={(value) =>
|
||||
this.props.onInsetChange(value)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
<div className="kt-box-disable-settings">
|
||||
<ToggleControl
|
||||
label={__("Disable")}
|
||||
checked={
|
||||
undefined !== this.state.value &&
|
||||
undefined !== this.state.value.disabled
|
||||
? this.state.value.disabled
|
||||
: false
|
||||
}
|
||||
onChange={(value) =>
|
||||
this.props.onDisableChange(value)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</ResponsiveControl>
|
||||
)}
|
||||
{!this.controlParams.responsive && (
|
||||
<Fragment>
|
||||
<div className="kadence-responsive-control-bar">
|
||||
<span className="customize-control-title">
|
||||
{controlLabel}
|
||||
</span>
|
||||
</div>
|
||||
{!this.state.value.disabled && (
|
||||
<div className="kadence-responsive-controls-content">
|
||||
<Fragment>
|
||||
<div className="kt-box-color-settings kt-box-shadow-subset">
|
||||
<p className="kt-box-shadow-title">
|
||||
{__("Color")}
|
||||
</p>
|
||||
<ColorControl
|
||||
presetColors={
|
||||
this.state.colorPalette
|
||||
}
|
||||
color={
|
||||
undefined !==
|
||||
this.state.value.color &&
|
||||
this.state.value.color
|
||||
? this.state.value.color
|
||||
: ""
|
||||
}
|
||||
usePalette={true}
|
||||
tooltip={__("Border Color")}
|
||||
onChangeComplete={(
|
||||
color,
|
||||
isPalette
|
||||
) =>
|
||||
this.handleChangeComplete(
|
||||
color,
|
||||
isPalette
|
||||
)
|
||||
}
|
||||
customizer={this.props.customizer}
|
||||
controlRef={this.anchorNodeRef}
|
||||
/>
|
||||
</div>
|
||||
<div className="kt-box-x-settings kt-box-shadow-subset">
|
||||
<p className="kt-box-shadow-title">
|
||||
{__("X")}
|
||||
</p>
|
||||
<div className="components-base-control kt-boxshadow-number-input">
|
||||
<div className="components-base-control__field">
|
||||
<input
|
||||
value={
|
||||
undefined !==
|
||||
this.state.value &&
|
||||
undefined !==
|
||||
this.state.value
|
||||
.hOffset
|
||||
? this.state.value
|
||||
.hOffset
|
||||
: ""
|
||||
}
|
||||
onChange={(event) =>
|
||||
onInputChange(
|
||||
event,
|
||||
"hOffset"
|
||||
)
|
||||
}
|
||||
min={-200}
|
||||
max={200}
|
||||
step={1}
|
||||
type="number"
|
||||
className="components-text-control__input"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="kt-box-y-settings kt-box-shadow-subset">
|
||||
<p className="kt-box-shadow-title">
|
||||
{__("Y")}
|
||||
</p>
|
||||
<div className="components-base-control kt-boxshadow-number-input">
|
||||
<div className="components-base-control__field">
|
||||
<input
|
||||
value={
|
||||
undefined !==
|
||||
this.state.value &&
|
||||
undefined !==
|
||||
this.state.value
|
||||
.vOffset
|
||||
? this.state.value
|
||||
.vOffset
|
||||
: ""
|
||||
}
|
||||
onChange={(event) =>
|
||||
onInputChange(
|
||||
event,
|
||||
"vOffset"
|
||||
)
|
||||
}
|
||||
min={-200}
|
||||
max={200}
|
||||
step={1}
|
||||
type="number"
|
||||
className="components-text-control__input"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="kt-box-x-settings kt-box-shadow-subset">
|
||||
<p className="kt-box-shadow-title">
|
||||
{__("Blur")}
|
||||
</p>
|
||||
<div className="components-base-control kt-boxshadow-number-input">
|
||||
<div className="components-base-control__field">
|
||||
<input
|
||||
value={
|
||||
undefined !==
|
||||
this.state.value &&
|
||||
undefined !==
|
||||
this.state.value
|
||||
.blur
|
||||
? this.state.value
|
||||
.blur
|
||||
: ""
|
||||
}
|
||||
onChange={(event) =>
|
||||
onInputChange(
|
||||
event,
|
||||
"blur"
|
||||
)
|
||||
}
|
||||
min={0}
|
||||
max={200}
|
||||
step={1}
|
||||
type="number"
|
||||
className="components-text-control__input"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="kt-box-y-settings kt-box-shadow-subset">
|
||||
<p className="kt-box-shadow-title">
|
||||
{__("Spread")}
|
||||
</p>
|
||||
<div className="components-base-control kt-boxshadow-number-input">
|
||||
<div className="components-base-control__field">
|
||||
<input
|
||||
value={
|
||||
undefined !==
|
||||
this.state.value &&
|
||||
undefined !==
|
||||
this.state.value
|
||||
.spread
|
||||
? this.state.value
|
||||
.spread
|
||||
: ""
|
||||
}
|
||||
onChange={(event) =>
|
||||
onInputChange(
|
||||
event,
|
||||
"spread"
|
||||
)
|
||||
}
|
||||
min={-200}
|
||||
max={200}
|
||||
step={1}
|
||||
type="number"
|
||||
className="components-text-control__input"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Fragment>
|
||||
</div>
|
||||
)}
|
||||
<div className="kadence-responsive-controls-content">
|
||||
{!this.state.value.disabled && (
|
||||
<div className="kt-box-inset-settings">
|
||||
<ToggleControl
|
||||
label={__("Inset")}
|
||||
checked={
|
||||
undefined !== this.state.value &&
|
||||
undefined !==
|
||||
this.state.value.inset &&
|
||||
this.state.value.inset
|
||||
? true
|
||||
: false
|
||||
}
|
||||
onChange={(value) =>
|
||||
onInsetChange(value)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div className="kt-box-disable-settings">
|
||||
<ToggleControl
|
||||
label={__("Disable")}
|
||||
checked={
|
||||
undefined !== this.state.value &&
|
||||
undefined !==
|
||||
this.state.value.disabled &&
|
||||
this.state.value.disabled
|
||||
? true
|
||||
: false
|
||||
}
|
||||
onChange={(value) => onDisableChange(value)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Fragment>
|
||||
)}
|
||||
{ this.props.control.renderNotice() }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
updateValues(value) {
|
||||
this.setState({ value: value });
|
||||
if (this.controlParams.responsive) {
|
||||
value.flag = !this.props.control.setting.get().flag;
|
||||
}
|
||||
this.props.control.setting.set({
|
||||
...this.props.control.setting.get(),
|
||||
...value,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
BoxshadowComponent.propTypes = {
|
||||
control: PropTypes.object.isRequired,
|
||||
customizer: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default BoxshadowComponent;
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createRoot } from '@wordpress/element';
|
||||
import BoxShadowComponent from './boxshadow-component.js';
|
||||
|
||||
export const BoxShadowControl = wp.customize.KadenceControl.extend( {
|
||||
renderContent: function renderContent() {
|
||||
let control = this;
|
||||
let root = createRoot( control.container[0] );
|
||||
root.render( <BoxShadowComponent control={control} customizer={ wp.customize }/> );
|
||||
// ReactDOM.render(
|
||||
// <BoxShadowComponent control={control} customizer={ wp.customize }/>,
|
||||
// control.container[0]
|
||||
// );
|
||||
}
|
||||
} );
|
||||
@@ -0,0 +1,595 @@
|
||||
@import "variables.scss";
|
||||
.customize-control-kadence_builder_control {
|
||||
border:0 !important;
|
||||
}
|
||||
// Areas
|
||||
.kadence-builder-items {
|
||||
padding: 10px 20px;
|
||||
}
|
||||
.kadence-builder-sortable-panel {
|
||||
min-height: 44px;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
align-items: center;
|
||||
}
|
||||
.kadence-builder-item {
|
||||
line-height: 32px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: auto;
|
||||
min-width: 80px;
|
||||
background: white;
|
||||
position: relative;
|
||||
border: 1px solid $color-gray-500;
|
||||
white-space: nowrap;
|
||||
position: relative;
|
||||
cursor: grab;
|
||||
margin: 0 4px;
|
||||
padding: 0 12px;
|
||||
border-radius: 3px;
|
||||
> .kadence-builder-item-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
right: 0;
|
||||
cursor: pointer;
|
||||
margin-right: -10px;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
color:$color-gray-600;
|
||||
background: transparent;
|
||||
border: 0;
|
||||
padding: 0;
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
.kadence-builder-item.sortable-ghost {
|
||||
opacity: 0.4;
|
||||
box-shadow: none;
|
||||
opacity: 0.6;
|
||||
font-size: 0;
|
||||
border: 1px dashed #9c9c9c;
|
||||
background: rgba(0, 0, 0, 0.015);
|
||||
background: rgba(0, 124, 186, 0.25);
|
||||
.kadence-builder-item-icon {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.kadence-builder-item.sortable-drag {
|
||||
box-shadow: 0 5px 20px -5px rgba(104, 104, 104, 0.4), inset 3px 0px 0px $color-primary;
|
||||
z-index: 999999 !important;
|
||||
.kadence-builder-item-icon:not(.kadence-move-icon) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.kadence-builder-item-start {
|
||||
margin-bottom:10px;
|
||||
min-height: 34px;
|
||||
display: flex;
|
||||
.kadence-builder-item {
|
||||
flex:1; display:flex; width: 100%;
|
||||
box-sizing: border-box;
|
||||
&.sortable-drag {
|
||||
width:auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
#accordion-section-kadence_customizer_header_builder {
|
||||
display: none !important;
|
||||
}
|
||||
#accordion-section-kadence_customizer_footer_builder {
|
||||
display: none !important;
|
||||
}
|
||||
// Tabs
|
||||
.kadence-build-tabs {
|
||||
border-bottom:4px solid #ddd;
|
||||
margin: 0;
|
||||
padding-top: 9px;
|
||||
padding-bottom: 0;
|
||||
line-height: inherit;
|
||||
display: flex;
|
||||
padding: 0 12px;
|
||||
}
|
||||
.kadence-build-tabs .nav-tab {
|
||||
font-size:14px;
|
||||
line-height:20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
font-style: normal;
|
||||
text-transform: uppercase;
|
||||
height: 40px;
|
||||
margin: 0;
|
||||
margin-bottom: -4px;
|
||||
padding: 0 18px;
|
||||
cursor: pointer;
|
||||
border: 0;
|
||||
box-sizing: content-box;
|
||||
border-bottom:4px solid #ddd;
|
||||
border-radius: 0;
|
||||
border-top-left-radius: 2px;
|
||||
border-top-right-radius: 2px;
|
||||
.dashicons.dashicons-desktop {
|
||||
font-size: 14px;
|
||||
height: auto;
|
||||
}
|
||||
&:not(.nav-tab-active):hover {
|
||||
background: #e5e5e5 !important;
|
||||
color: #444 !important;
|
||||
border-bottom-color: #f9f9f9;
|
||||
}
|
||||
&:hover {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
&:not(:first-child) {
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
.kadence-build-tabs .nav-tab.nav-tab-active {
|
||||
border-bottom-color: #007cba;
|
||||
background: #f9f9f9;
|
||||
color:#000;
|
||||
}
|
||||
// Builder Container Area
|
||||
#customize-theme-controls #sub-accordion-section-kadence_customizer_header_builder, #customize-theme-controls #sub-accordion-section-kadence_customizer_footer_builder {
|
||||
position: fixed !important;
|
||||
top: auto;
|
||||
left: 300px;
|
||||
right: 0;
|
||||
min-height: 0;
|
||||
background: #eee;
|
||||
border-top: 1px solid $color-gray-500;
|
||||
bottom: 0;
|
||||
visibility: visible;
|
||||
height: auto;
|
||||
width: auto;
|
||||
padding:0;
|
||||
max-height: 60%;
|
||||
overflow: auto;
|
||||
transform: translateY(100%);
|
||||
transition: transform 0.1s ease;
|
||||
backface-visibility: hidden;
|
||||
}
|
||||
@media ( min-width: 1660px ) {
|
||||
#customize-theme-controls #sub-accordion-section-kadence_customizer_header_builder, #customize-theme-controls #sub-accordion-section-kadence_customizer_footer_builder {
|
||||
left: 18%;
|
||||
}
|
||||
}
|
||||
@media ( max-width: 1659px ) {
|
||||
.rtl {
|
||||
#customize-theme-controls #sub-accordion-section-kadence_customizer_header_builder, #customize-theme-controls #sub-accordion-section-kadence_customizer_footer_builder {
|
||||
right: 300px;
|
||||
left:0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#customize-theme-controls #sub-accordion-section-kadence_customizer_header_builder.kadence-builder-active, #customize-theme-controls #sub-accordion-section-kadence_customizer_footer_builder.kadence-footer-builder-active {
|
||||
transform: translateY(0%);
|
||||
visibility: visible;
|
||||
overflow: visible;
|
||||
}
|
||||
#customize-theme-controls #sub-accordion-section-kadence_customizer_header_builder.kadence-builder-active.kadence-builder-hide, #customize-theme-controls #sub-accordion-section-kadence_customizer_footer_builder.kadence-footer-builder-active.kadence-builder-hide {
|
||||
transform: translateY(100%) !important;
|
||||
overflow: visible;
|
||||
}
|
||||
.kadence-builder-active > li.customize-section-description-container, .kadence-footer-builder-active > li.customize-section-description-container {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.kadence-builder-areas .kadence-builder-group-horizontal {
|
||||
display: flex;
|
||||
margin-bottom: 15px;
|
||||
border: 1px dashed $color-gray-500;
|
||||
background:#f7f7f7;
|
||||
.kadence-builder-area {
|
||||
display: flex;
|
||||
}
|
||||
.kadence-builder-area-left, .kadence-builder-area-right {
|
||||
flex: 1 1 0%;
|
||||
}
|
||||
.kadence-builder-area-right .kadence-builder-drop-right, .kadence-builder-drop-left_center {
|
||||
justify-content:flex-end;
|
||||
}
|
||||
.kadence-builder-drop-left_center, .kadence-builder-drop-right_center {
|
||||
width: 0px;
|
||||
flex: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
.kadence-builder-area-center {
|
||||
min-width: 80px;
|
||||
border-left: 1px dashed $color-gray-500;
|
||||
border-right: 1px dashed $color-gray-500;
|
||||
.kadence-builder-sortable-panel {
|
||||
justify-content:center;
|
||||
}
|
||||
}
|
||||
.kadence-builder-area-center.kadence-dragging-dropzones {
|
||||
min-width: 120px;
|
||||
}
|
||||
}
|
||||
.kadence-builder-areas.has-center-items {
|
||||
.kadence-builder-drop-left_center, .kadence-builder-drop-right_center {
|
||||
width: auto;
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
}
|
||||
.kadence-dragging-dropzones .kadence-builder-drop-left_center {
|
||||
min-width: 100px;
|
||||
border-left: 1px dashed $color-gray-500;
|
||||
}
|
||||
.kadence-dragging-dropzones .kadence-builder-drop-right_center {
|
||||
min-width: 100px;
|
||||
border-right: 1px dashed $color-gray-500;
|
||||
}
|
||||
.kadence-builder-area-center {
|
||||
min-width: 120px;
|
||||
border-left: 1px dashed $color-gray-500;
|
||||
border-right: 1px dashed $color-gray-500;
|
||||
}
|
||||
}
|
||||
.kadence-builder-areas .kadence-small-label {
|
||||
display: none;
|
||||
}
|
||||
.kadence-builder-areas.popup-vertical-group {
|
||||
width: 200px;
|
||||
padding-right: 20px;
|
||||
.kadence-builder-group {
|
||||
height: 100%;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
.kadence-builder-areas.popup-vertical-group .kadence-builder-area {
|
||||
flex: auto;
|
||||
flex-direction: column;
|
||||
.kadence-builder-sortable-panel {
|
||||
min-height: 115px;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
flex-wrap: wrap;
|
||||
.kadence-builder-item {
|
||||
width: 90%;
|
||||
margin-top: 4px;
|
||||
margin-bottom: 4px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
}
|
||||
.kadence-builder-item-start button.kadence-builder-item {
|
||||
border:1px dashed #bbb;
|
||||
background: #f2f2f2;
|
||||
cursor: pointer;
|
||||
box-shadow:none !important;
|
||||
}
|
||||
.kadence-builder-item-start button.kadence-builder-item:hover {
|
||||
border:1px dashed #a2a2a2;
|
||||
background: #f9f9f9 !important;
|
||||
}
|
||||
// Footer.
|
||||
.kadence-footer-builder-is-active .in-sub-panel:not( .section-open ) ul#sub-accordion-section-kadence_customizer_footer_layout,
|
||||
.kadence-builder-is-active .in-sub-panel:not( .section-open ) ul#sub-accordion-section-kadence_customizer_header_layout {
|
||||
transform: none;
|
||||
height: auto;
|
||||
visibility: visible;
|
||||
top: 75px;
|
||||
}
|
||||
.kadence-footer-builder-is-active .in-sub-panel:not( .section-open ) ul#sub-accordion-section-kadence_customizer_footer_layout .customize-section-description-container.section-meta,
|
||||
.kadence-builder-is-active .in-sub-panel:not( .section-open ) ul#sub-accordion-section-kadence_customizer_header_layout .customize-section-description-container.section-meta {
|
||||
display: none;
|
||||
}
|
||||
.kadence-footer-builder-is-active .in-sub-panel:not( .section-open ) #sub-accordion-section-kadence_customizer_footer_layout .customize-section-description-container,
|
||||
.kadence-builder-is-active .in-sub-panel:not( .section-open ) ul#sub-accordion-section-kadence_customizer_header_layout .customize-section-description-container {
|
||||
display: none;
|
||||
}
|
||||
.kadence-footer-builder-is-active .in-sub-panel:not( .section-open ) #sub-accordion-panel-kadence_customizer_footer .accordion-section.control-section,
|
||||
.kadence-builder-is-active .in-sub-panel:not( .section-open ) #sub-accordion-panel-kadence_customizer_header .accordion-section.control-section {
|
||||
display: none !important;
|
||||
}
|
||||
.kadence-footer-builder-is-active .preview-desktop #customize-preview, .kadence-footer-builder-is-active .preview-tablet #customize-preview, .kadence-builder-is-active .preview-desktop #customize-preview, .kadence-builder-is-active .preview-tablet #customize-preview {
|
||||
height: auto;
|
||||
}
|
||||
#customize-control-header_mobile_items .kadence-builder-items {
|
||||
display: flex;
|
||||
}
|
||||
#customize-control-header_mobile_items .kadence-builder-row-items {
|
||||
flex: 1;
|
||||
}
|
||||
.customize-control-kadence_builder_control .kadence-builder-items.kadence-builder-items-with-popup {
|
||||
display: flex;
|
||||
.kadence-builder-row-items {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
.kadence-builder-areas button.components-button.kadence-row-actions {
|
||||
background: $color-primary;
|
||||
color: #c8dbe4;
|
||||
text-transform: uppercase;
|
||||
font-size: 10px;
|
||||
height: auto;
|
||||
line-height: 26px;
|
||||
border-radius: 0;
|
||||
position: absolute;
|
||||
top: -26px;
|
||||
border:0;
|
||||
opacity: 0;
|
||||
height: 26px;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
z-index: 10;
|
||||
}
|
||||
.kadence-builder-areas:hover button.components-button.kadence-row-actions {
|
||||
opacity: 1;
|
||||
}
|
||||
.kadence-builder-areas button.components-button.kadence-row-actions svg {
|
||||
width: 10px;
|
||||
margin-left: 8px;
|
||||
}
|
||||
.kadence-builder-areas button.components-button.kadence-row-actions .dashicons {
|
||||
width: 10px;
|
||||
font-size: 10px;
|
||||
height: 10px;
|
||||
margin-left: 8px;
|
||||
}
|
||||
.kadence-builder-areas button.components-button.kadence-row-actions:hover, .kadence-builder-areas button.components-button.kadence-row-actions:focus {
|
||||
background: $color-primary !important;
|
||||
color: white !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
.kadence-builder-areas {
|
||||
position: relative;
|
||||
}
|
||||
.kadence-builder-areas:hover .kadence-builder-group-horizontal {
|
||||
border: 1px solid $color-primary;
|
||||
}
|
||||
.kadence-builder-group.kadence-builder-group-horizontal[data-setting="bottom"] {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.footer-column-row .kadence-builder-area {
|
||||
flex: 1;
|
||||
border-right: 1px dashed #A0AEC0;
|
||||
.kadence-builder-sortable-panel {
|
||||
justify-content: center;
|
||||
}
|
||||
&:first-child .kadence-builder-sortable-panel {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
&:last-child .kadence-builder-sortable-panel {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
}
|
||||
.footer-column-row .kadence-builder-area:last-child {
|
||||
border-right: 0;
|
||||
}
|
||||
#sub-accordion-section-kadence_customizer_footer_builder .customize-control-kadence_blank_control .kadence-builder-tab-toggle {
|
||||
top: -4px;
|
||||
}
|
||||
#sub-accordion-section-kadence_customizer_footer_builder .customize-control-kadence_blank_control .kadence-builder-show-button.kadence-builder-tab-toggle {
|
||||
top: auto;
|
||||
}
|
||||
.footer-row-columns-2 {
|
||||
&.footer-row-layout-left-golden {
|
||||
.kadence-builder-area-1 {
|
||||
flex: 0 1 66.67%;
|
||||
}
|
||||
.kadence-builder-area-2 {
|
||||
flex: 0 1 33.33%;
|
||||
}
|
||||
}
|
||||
&.footer-row-layout-right-golden {
|
||||
.kadence-builder-area-1 {
|
||||
flex: 0 1 33.33%;
|
||||
}
|
||||
.kadence-builder-area-2 {
|
||||
flex: 0 1 66.67%;
|
||||
}
|
||||
}
|
||||
}
|
||||
.footer-row-columns-3 {
|
||||
&.footer-row-layout-left-half {
|
||||
.kadence-builder-area {
|
||||
flex: 0 1 25%;
|
||||
}
|
||||
.kadence-builder-area-1 {
|
||||
flex: 0 1 50%;
|
||||
}
|
||||
}
|
||||
&.footer-row-layout-right-half {
|
||||
.kadence-builder-area {
|
||||
flex: 0 1 25%;
|
||||
}
|
||||
.kadence-builder-area-3 {
|
||||
flex: 0 1 50%;
|
||||
}
|
||||
}
|
||||
&.footer-row-layout-center-half {
|
||||
.kadence-builder-area {
|
||||
flex: 0 1 25%;
|
||||
}
|
||||
.kadence-builder-area-2 {
|
||||
flex: 0 1 50%;
|
||||
}
|
||||
}
|
||||
&.footer-row-layout-center-wide {
|
||||
.kadence-builder-area {
|
||||
flex: 0 1 20%;
|
||||
}
|
||||
.kadence-builder-area-2 {
|
||||
flex: 0 1 60%;
|
||||
}
|
||||
}
|
||||
&.footer-row-layout-center-exwide {
|
||||
.kadence-builder-area {
|
||||
flex: 0 1 15%;
|
||||
}
|
||||
.kadence-builder-area-2 {
|
||||
flex: 0 1 70%;
|
||||
}
|
||||
}
|
||||
}
|
||||
.footer-row-columns-4 {
|
||||
&.footer-row-layout-left-forty {
|
||||
.kadence-builder-area {
|
||||
flex: 1;
|
||||
}
|
||||
.kadence-builder-area-1 {
|
||||
flex: 2;
|
||||
}
|
||||
}
|
||||
&.footer-row-layout-right-forty {
|
||||
.kadence-builder-area {
|
||||
flex: 1;
|
||||
}
|
||||
.kadence-builder-area-4 {
|
||||
flex: 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
.footer-column-row.footer-row-columns-1 .kadence-builder-area:last-child .kadence-builder-sortable-panel {
|
||||
justify-content: center;
|
||||
}
|
||||
.kadence-builder-areas.footer-row-direction-column .kadence-builder-group-horizontal .kadence-builder-area .kadence-builder-drop {
|
||||
flex-direction: column;
|
||||
align-items: normal;
|
||||
}
|
||||
.kadence-builder-areas.footer-row-direction-column .kadence-builder-group-horizontal .kadence-builder-area .kadence-builder-drop .kadence-builder-item {
|
||||
margin: 4px;
|
||||
}
|
||||
.kadence-builder-item-start .kadence-builder-item {
|
||||
border-left:3px solid $color-primary;
|
||||
}
|
||||
.kadence-builder-item-start button.kadence-builder-item {
|
||||
border: 1px solid #fff;
|
||||
background: #fff;
|
||||
}
|
||||
.kadence-builder-item-start button.kadence-builder-item:hover {
|
||||
border: 1px solid #fff;
|
||||
background: #fff !important;
|
||||
}
|
||||
|
||||
.kadence-builder-item-start .kadence-builder-item:hover>.kadence-builder-item-icon {
|
||||
color: $color-primary;
|
||||
}
|
||||
.kadence-builder-item>.kadence-builder-item-icon.kadence-move-icon {
|
||||
margin-left: -10px;
|
||||
transform: rotate(90deg);
|
||||
margin-right: 0;
|
||||
cursor: grab;
|
||||
width: 18px;
|
||||
opacity: 0.7;
|
||||
}
|
||||
.kadence-builder-item-text {
|
||||
flex-grow: 1;
|
||||
}
|
||||
.kadence-builder-item-start.kadence-move-item .kadence-builder-item {
|
||||
justify-content:flex-start
|
||||
}
|
||||
.customize-control:not(.customize-control-kadence_blank_control) + .customize-control#customize-control-header_mobile_available_items {
|
||||
padding-top: 0;
|
||||
border-top: 0;
|
||||
}
|
||||
.kadence-available-items-pool {
|
||||
min-width: 80px;
|
||||
border: 1px dashed #A0AEC0;
|
||||
padding: 20px 10px 10px;
|
||||
}
|
||||
.kadence-available-items-title {
|
||||
padding: 10px 0;
|
||||
}
|
||||
.kadence-builder-item>.kadence-builder-item-icon.kadence-builder-item-focus-icon svg {width: 14px;}
|
||||
.kadence-builder-item>.kadence-builder-item-icon.kadence-builder-item-focus-icon .dashicon {
|
||||
font-size: 14px;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
.kadence-builder-area .kadence-builder-add-item {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
.kadence-builder-area {
|
||||
position: relative;
|
||||
.kadence-builder-item {
|
||||
z-index: 10;
|
||||
}
|
||||
}
|
||||
.kadence-builder-area .kadence-builder-item-add-icon {
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
background: transparent;
|
||||
border: 0;
|
||||
height: auto;
|
||||
width: auto;
|
||||
padding: 0;
|
||||
min-width: 100%;
|
||||
z-index: 1;
|
||||
transition: all .2s ease-in-out;
|
||||
color:transparent !important;
|
||||
&:hover, &:focus {
|
||||
color:#444 !important;
|
||||
background: rgba(0, 124, 186, 0.05)!important;
|
||||
box-shadow: none !important;
|
||||
border:0 !important;
|
||||
}
|
||||
}
|
||||
.components-popover.kadence-popover-add-builder.components-animate__appear {
|
||||
left: 50% !important;
|
||||
top: 0 !important;
|
||||
position: absolute;
|
||||
bottom: auto;
|
||||
}
|
||||
.components-popover__content .kadence-popover-builder-list .kadence-radio-container-control {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
grid-gap: 10px;
|
||||
width: 300px;
|
||||
}
|
||||
.kadence-popover-builder-list {
|
||||
padding: 0 10px;
|
||||
.kadence-radio-container-control button.components-button.is-tertiary {
|
||||
font-size: 10px;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
.kadence-builder-area .kadence-builder-item-add-icon svg {
|
||||
margin-top: 5px;
|
||||
}
|
||||
.kadence-builder-area-center .kadence-builder-drop-center .kadence-builder-item:first-child {
|
||||
margin-left: 25px;
|
||||
}
|
||||
.kadence-builder-area-center .kadence-builder-drop-center .kadence-builder-item:last-child {
|
||||
margin-right: 25px;
|
||||
}
|
||||
.kadence-builder-areas.has-center-items .kadence-builder-add-item.center-on-right {
|
||||
right:50%;
|
||||
}
|
||||
.kadence-builder-areas.has-center-items .kadence-builder-add-item.center-on-right .kadence-builder-item-add-icon {
|
||||
text-align:right;
|
||||
padding-right:30px;
|
||||
}
|
||||
.kadence-builder-areas.has-center-items .kadence-builder-add-item.center-on-left {
|
||||
left:50%;
|
||||
}
|
||||
.kadence-builder-areas.has-center-items .kadence-builder-add-item.center-on-left .kadence-builder-item-add-icon {
|
||||
text-align:left;
|
||||
padding-left:30px;
|
||||
}
|
||||
.kadence-builder-area .kadence-builder-add-item.left-center-on-left, .kadence-builder-area .kadence-builder-add-item.right-center-on-right {
|
||||
display: none;
|
||||
}
|
||||
.kadence-builder-areas.has-center-items .kadence-builder-add-item.left-center-on-left {
|
||||
display:block;
|
||||
right: 50%;
|
||||
}
|
||||
.kadence-builder-areas.has-center-items .kadence-builder-add-item.right-center-on-right {
|
||||
display:block;
|
||||
left: 50%;
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
/* jshint esversion: 6 */
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
import Icons from '../common/icons.js';
|
||||
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
const { ButtonGroup, Dashicon, Tooltip, Button } = wp.components;
|
||||
|
||||
const { Component, Fragment } = wp.element;
|
||||
class CheckIconComponent extends Component {
|
||||
constructor() {
|
||||
super( ...arguments );
|
||||
this.updateValues = this.updateValues.bind( this );
|
||||
let value = this.props.control.setting.get();
|
||||
let defaultParams = {
|
||||
options: {
|
||||
desktop: {
|
||||
name: __( 'Desktop', 'kadence' ),
|
||||
icon: 'desktop',
|
||||
},
|
||||
tablet: {
|
||||
name: __( 'Tablet', 'kadence' ),
|
||||
icon: 'tablet',
|
||||
},
|
||||
mobile: {
|
||||
name: __( 'Mobile', 'kadence' ),
|
||||
icon: 'smartphone',
|
||||
},
|
||||
},
|
||||
};
|
||||
this.controlParams = this.props.control.params.input_attrs ? {
|
||||
...defaultParams,
|
||||
...this.props.control.params.input_attrs,
|
||||
} : defaultParams;
|
||||
let baseDefault = {
|
||||
'mobile': true,
|
||||
'tablet': true,
|
||||
'desktop': true,
|
||||
};
|
||||
this.defaultValue = this.props.control.params.default ? this.props.control.params.default : baseDefault;
|
||||
value = value ? {
|
||||
...JSON.parse( JSON.stringify( this.defaultValue ) ),
|
||||
...value
|
||||
} : JSON.parse( JSON.stringify( this.defaultValue ) );
|
||||
this.state = {
|
||||
value: value,
|
||||
};
|
||||
}
|
||||
render() {
|
||||
const controlLabel = (
|
||||
<Fragment>
|
||||
<Tooltip text={ __( 'Reset Values', 'kadence' ) }>
|
||||
<Button
|
||||
className="reset kadence-reset"
|
||||
disabled={ ( this.state.value == this.defaultValue ) }
|
||||
onClick={ () => {
|
||||
let value = this.defaultValue;
|
||||
this.setState( { value: this.defaultValue } );
|
||||
this.updateValues( value );
|
||||
} }
|
||||
>
|
||||
<Dashicon icon='image-rotate' />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
{ this.props.control.params.label &&
|
||||
this.props.control.params.label
|
||||
}
|
||||
</Fragment>
|
||||
);
|
||||
return (
|
||||
<div className="kadence-control-field kadence-radio-icon-control">
|
||||
<div className="kadence-responsive-control-bar">
|
||||
<span className="customize-control-title">{ controlLabel }</span>
|
||||
</div>
|
||||
<ButtonGroup className="kadence-radio-container-control">
|
||||
{ Object.keys( this.controlParams.options ).map( ( item ) => {
|
||||
return (
|
||||
<Fragment>
|
||||
<Tooltip text={ this.controlParams.options[ item ].name }>
|
||||
<Button
|
||||
isTertiary
|
||||
className={ ( true === this.state.value[ item ] ?
|
||||
'active-radio ' :
|
||||
'' ) + item }
|
||||
onClick={ () => {
|
||||
let value = this.state.value;
|
||||
if( value[ item ] ) {
|
||||
value[ item ] = false;
|
||||
} else {
|
||||
value[ item ] = true;
|
||||
}
|
||||
this.setState( { value: value });
|
||||
this.updateValues( value );
|
||||
} }
|
||||
>
|
||||
{ this.controlParams.options[ item ].icon && (
|
||||
<span className="kadence-radio-icon">
|
||||
{ <Dashicon icon={this.controlParams.options[ item ].icon}/> }
|
||||
</span>
|
||||
) }
|
||||
{ ! this.controlParams.options[ item ].icon && (
|
||||
<span className="kadence-radio-name">
|
||||
{ this.controlParams.options[ item ].name }
|
||||
</span>
|
||||
) }
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Fragment>
|
||||
);
|
||||
} )}
|
||||
</ButtonGroup>
|
||||
{ this.props.control.renderNotice() }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
updateValues( value ) {
|
||||
this.props.control.setting.set( {
|
||||
...this.props.control.setting.get(),
|
||||
...value,
|
||||
flag: !this.props.control.setting.get().flag
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
CheckIconComponent.propTypes = {
|
||||
control: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
export default CheckIconComponent;
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createRoot } from '@wordpress/element';
|
||||
import CheckIconComponent from './check-icon-component.js';
|
||||
|
||||
export const CheckIconControl = wp.customize.KadenceControl.extend( {
|
||||
renderContent: function renderContent() {
|
||||
let control = this;
|
||||
let root = createRoot( control.container[0] );
|
||||
root.render( <CheckIconComponent control={control}/> );
|
||||
// ReactDOM.render(
|
||||
// <CheckIconComponent control={control}/>,
|
||||
// control.container[0]
|
||||
// );
|
||||
}
|
||||
} );
|
||||
@@ -0,0 +1,169 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
const { SelectControl } = wp.components;
|
||||
import ColorControl from '../common/color.js';
|
||||
/**
|
||||
* WordPress dependencies
|
||||
*/
|
||||
import { createRef, Component, Fragment } from '@wordpress/element';
|
||||
|
||||
class ColorLinkComponent extends Component {
|
||||
constructor(props) {
|
||||
super( props );
|
||||
this.handleChangeComplete = this.handleChangeComplete.bind( this );
|
||||
this.updateValues = this.updateValues.bind( this );
|
||||
let value = this.props.control.setting.get();
|
||||
let baseDefault = {
|
||||
'highlight': '',
|
||||
'highlight-alt': '',
|
||||
'highlight-alt2': '',
|
||||
'style': 'standard',
|
||||
};
|
||||
this.defaultValue = this.props.control.params.default ? {
|
||||
...baseDefault,
|
||||
...this.props.control.params.default
|
||||
} : baseDefault;
|
||||
value = value ? {
|
||||
...this.defaultValue,
|
||||
...value
|
||||
} : this.defaultValue;
|
||||
let defaultParams = {
|
||||
colors: {
|
||||
'highlight': {
|
||||
tooltip: __( 'Initial', 'kadence' ),
|
||||
palette: true,
|
||||
},
|
||||
'highlight-alt': {
|
||||
tooltip: __( 'Hover', 'kadence' ),
|
||||
palette: true,
|
||||
},
|
||||
'highlight-alt2': {
|
||||
tooltip: __( 'Text Alt', 'kadence' ),
|
||||
palette: true,
|
||||
},
|
||||
},
|
||||
styles: {
|
||||
'standard': {
|
||||
label: __( 'Standard (underline)', 'kadence' ),
|
||||
},
|
||||
'color-underline': {
|
||||
label: __( 'Highlight Underline', 'kadence' ),
|
||||
},
|
||||
'no-underline': {
|
||||
label: __( 'No Underline', 'kadence' ),
|
||||
},
|
||||
'hover-background': {
|
||||
label: __( 'Background on Hover', 'kadence' ),
|
||||
},
|
||||
'offset-background': {
|
||||
label: __( 'Offset Background', 'kadence' ),
|
||||
},
|
||||
},
|
||||
};
|
||||
this.controlParams = this.props.control.params.input_attrs ? {
|
||||
...defaultParams,
|
||||
...this.props.control.params.input_attrs,
|
||||
} : defaultParams;
|
||||
const palette = JSON.parse( this.props.customizer.control( 'kadence_color_palette' ).setting.get() );
|
||||
this.state = {
|
||||
value: value,
|
||||
colorPalette: palette,
|
||||
};
|
||||
this.anchorNodeRef = createRef();
|
||||
}
|
||||
handleChangeComplete( color, isPalette, item ) {
|
||||
let value = this.state.value;
|
||||
if ( isPalette ) {
|
||||
value[ item ] = isPalette;
|
||||
} else if ( undefined !== color.rgb && undefined !== color.rgb.a && 1 !== color.rgb.a ) {
|
||||
value[ item ] = 'rgba(' + color.rgb.r + ',' + color.rgb.g + ',' + color.rgb.b + ',' + color.rgb.a + ')';
|
||||
} else {
|
||||
value[ item ] = color.hex;
|
||||
}
|
||||
document.documentElement.style.setProperty('--global-palette-' + item, value[ item ] );
|
||||
this.updateValues( value );
|
||||
}
|
||||
|
||||
render() {
|
||||
const styleOptions = Object.keys( this.controlParams.styles ).map( ( item ) => {
|
||||
return ( { label: this.controlParams.styles[ item ].label, value: item } );
|
||||
} );
|
||||
const hoverBackgroundColors = {
|
||||
'highlight': {
|
||||
tooltip: __( 'Initial/Background', 'kadence' ),
|
||||
palette: true,
|
||||
},
|
||||
'highlight-alt': {
|
||||
tooltip: __( 'Unused', 'kadence' ),
|
||||
palette: true,
|
||||
},
|
||||
'highlight-alt2': {
|
||||
tooltip: __( 'Text Hover', 'kadence' ),
|
||||
palette: true,
|
||||
},
|
||||
};
|
||||
|
||||
// Use special color labels for hover background;
|
||||
const colorsToUse = this.state.value.style === 'hover-background' ? hoverBackgroundColors : this.controlParams.colors;
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<div className="kadence-control-field kadence-color-control kadence-link-color-control">
|
||||
<span className="customize-control-title">
|
||||
{ __( 'Link Style', 'kadence' ) }
|
||||
</span>
|
||||
<SelectControl
|
||||
value={ this.state.value.style }
|
||||
options={ styleOptions }
|
||||
onChange={ ( val ) => {
|
||||
let value = this.state.value;
|
||||
value.style = val;
|
||||
this.updateValues( value );
|
||||
} }
|
||||
/>
|
||||
</div>
|
||||
<div ref={ this.anchorNodeRef } className="kadence-control-field kadence-color-control kadence-link-color-control">
|
||||
{
|
||||
this.props.control.params.label &&
|
||||
<span className="customize-control-title">
|
||||
{ this.props.control.params.label }
|
||||
</span>
|
||||
}
|
||||
{ Object.keys( colorsToUse ).map( ( item ) => {
|
||||
if ( ( this.state.value.style === 'standard' || this.state.value.style === 'color-underline' || this.state.value.style === 'no-underline' ) && item === 'highlight-alt2' ) {
|
||||
return;
|
||||
}
|
||||
return (
|
||||
<ColorControl
|
||||
key={ item }
|
||||
presetColors={ this.state.colorPalette }
|
||||
color={ ( undefined !== this.state.value[ item ] && this.state.value[ item ] ? this.state.value[ item ] : '' ) }
|
||||
usePalette={ ( undefined !== colorsToUse[ item ] && undefined !== colorsToUse[ item ].palette && '' !== colorsToUse[ item ].palette ? colorsToUse[ item ].palette : true ) }
|
||||
tooltip={ ( undefined !== colorsToUse[ item ] && undefined !== colorsToUse[ item ].tooltip ? colorsToUse[ item ].tooltip : '' ) }
|
||||
onChangeComplete={ ( color, isPalette ) => this.handleChangeComplete( color, isPalette, item ) }
|
||||
customizer={ this.props.customizer }
|
||||
controlRef={ this.anchorNodeRef }
|
||||
/>
|
||||
)
|
||||
} ) }
|
||||
</div>
|
||||
{ this.props.control.renderNotice() }
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
updateValues( value ) {
|
||||
this.setState( { value: value } );
|
||||
this.props.control.setting.set( {
|
||||
...this.props.control.setting.get(),
|
||||
...value,
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
ColorLinkComponent.propTypes = {
|
||||
control: PropTypes.object.isRequired,
|
||||
customizer: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
export default ColorLinkComponent;
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createRoot } from '@wordpress/element';
|
||||
import ColorLinkComponent from './color-link-component.js';
|
||||
|
||||
export const ColorLinkControl = wp.customize.KadenceControl.extend( {
|
||||
renderContent: function renderContent() {
|
||||
let control = this;
|
||||
let root = createRoot( control.container[0] );
|
||||
root.render( <ColorLinkComponent control={control} customizer={ wp.customize }/> );
|
||||
// ReactDOM.render(
|
||||
// <ColorLinkComponent control={control} customizer={ wp.customize }/>,
|
||||
// control.container[0]
|
||||
// );
|
||||
}
|
||||
} );
|
||||
@@ -0,0 +1,176 @@
|
||||
import PropTypes from "prop-types";
|
||||
import { isEqual } from "lodash";
|
||||
import { __ } from "@wordpress/i18n";
|
||||
const { Tooltip, Button, Dashicon } = wp.components;
|
||||
/**
|
||||
* WordPress dependencies
|
||||
*/
|
||||
import { createRef, Component, Fragment } from "@wordpress/element";
|
||||
import ColorControl from "../common/color.js";
|
||||
|
||||
class ColorComponent extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.handleChangeComplete = this.handleChangeComplete.bind(this);
|
||||
this.updateValues = this.updateValues.bind(this);
|
||||
let value = this.props.control.setting.get();
|
||||
let baseDefault = {
|
||||
color: "",
|
||||
hover: "",
|
||||
};
|
||||
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));
|
||||
let defaultParams = {
|
||||
colors: {
|
||||
color: {
|
||||
tooltip: __("Color", "kadence"),
|
||||
palette: true,
|
||||
},
|
||||
hover: {
|
||||
tooltip: __("Hover Color", "kadence"),
|
||||
palette: true,
|
||||
},
|
||||
},
|
||||
allowGradient: false,
|
||||
};
|
||||
this.controlParams = this.props.control.params.input_attrs
|
||||
? {
|
||||
...defaultParams,
|
||||
...this.props.control.params.input_attrs,
|
||||
}
|
||||
: defaultParams;
|
||||
const palette = JSON.parse(
|
||||
this.props.customizer.control("kadence_color_palette").setting.get()
|
||||
);
|
||||
//console.log( palette );
|
||||
this.state = {
|
||||
value: value,
|
||||
colorPalette: palette,
|
||||
};
|
||||
this.anchorNodeRef = createRef();
|
||||
}
|
||||
handleChangeComplete(color, isPalette, item) {
|
||||
let value = this.state.value;
|
||||
if (isPalette) {
|
||||
value[item] = isPalette;
|
||||
} else if (typeof color === "string" || color instanceof String) {
|
||||
value[item] = color;
|
||||
} else if (
|
||||
undefined !== color.rgb &&
|
||||
undefined !== color.rgb.a &&
|
||||
1 !== color.rgb.a
|
||||
) {
|
||||
value[item] =
|
||||
"rgba(" +
|
||||
color.rgb.r +
|
||||
"," +
|
||||
color.rgb.g +
|
||||
"," +
|
||||
color.rgb.b +
|
||||
"," +
|
||||
color.rgb.a +
|
||||
")";
|
||||
} else {
|
||||
value[item] = color.hex;
|
||||
}
|
||||
this.updateValues(value);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div
|
||||
ref={this.anchorNodeRef}
|
||||
className="kadence-control-field kadence-color-control"
|
||||
>
|
||||
<span className="customize-control-title">
|
||||
<Fragment>
|
||||
<Tooltip text={__("Reset Values", "kadence")}>
|
||||
<Button
|
||||
className="reset kadence-reset"
|
||||
disabled={
|
||||
JSON.stringify(this.state.value) ===
|
||||
JSON.stringify(this.defaultValue)
|
||||
}
|
||||
onClick={() => {
|
||||
let value = JSON.parse(
|
||||
JSON.stringify(this.defaultValue)
|
||||
);
|
||||
this.updateValues(value);
|
||||
}}
|
||||
>
|
||||
<Dashicon icon="image-rotate" />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
{this.props.control.params.label &&
|
||||
this.props.control.params.label}
|
||||
</Fragment>
|
||||
</span>
|
||||
{Object.keys(this.controlParams.colors).map((item) => {
|
||||
return (
|
||||
<ColorControl
|
||||
key={item}
|
||||
presetColors={this.state.colorPalette}
|
||||
color={
|
||||
undefined !== this.state.value[item] &&
|
||||
this.state.value[item]
|
||||
? this.state.value[item]
|
||||
: ""
|
||||
}
|
||||
usePalette={
|
||||
undefined !== this.controlParams.colors[item] &&
|
||||
undefined !==
|
||||
this.controlParams.colors[item].palette &&
|
||||
"" !== this.controlParams.colors[item].palette
|
||||
? this.controlParams.colors[item].palette
|
||||
: true
|
||||
}
|
||||
tooltip={
|
||||
undefined !== this.controlParams.colors[item] &&
|
||||
undefined !==
|
||||
this.controlParams.colors[item].tooltip
|
||||
? this.controlParams.colors[item].tooltip
|
||||
: ""
|
||||
}
|
||||
onChangeComplete={(color, isPalette) =>
|
||||
this.handleChangeComplete(
|
||||
color,
|
||||
isPalette,
|
||||
item
|
||||
)
|
||||
}
|
||||
customizer={this.props.customizer}
|
||||
allowGradient={this.controlParams.allowGradient}
|
||||
controlRef={this.anchorNodeRef}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
{ this.props.control.renderNotice() }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
updateValues(value) {
|
||||
this.setState({ value: value });
|
||||
this.props.control.setting.set({
|
||||
...this.props.control.setting.get(),
|
||||
...value,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ColorComponent.propTypes = {
|
||||
control: PropTypes.object.isRequired,
|
||||
customizer: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default ColorComponent;
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createRoot } from '@wordpress/element';
|
||||
import ColorComponent from './color-component.js';
|
||||
|
||||
export const ColorControl = wp.customize.KadenceControl.extend( {
|
||||
renderContent: function renderContent() {
|
||||
let control = this;
|
||||
let root = createRoot( control.container[0] );
|
||||
root.render( <ColorComponent control={control} customizer={ wp.customize }/> );
|
||||
// ReactDOM.render(
|
||||
// <ColorComponent control={control} customizer={ wp.customize }/>,
|
||||
// control.container[0]
|
||||
// );
|
||||
}
|
||||
} );
|
||||
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* function to return string with capital letter.
|
||||
* @param {string} string the word string.
|
||||
* @returns {string} with capital letter.
|
||||
*/
|
||||
export default function capitalizeFirstLetter( string ) {
|
||||
return string.charAt( 0 ).toUpperCase() + string.slice( 1 );
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
import color from 'react-color/lib/helpers/color'
|
||||
|
||||
import { EditableInput } from 'react-color/lib/components/common'
|
||||
const {
|
||||
Component,
|
||||
Fragment
|
||||
} = wp.element;
|
||||
const {
|
||||
Dashicon,
|
||||
} = wp.components;
|
||||
class PickerFields extends Component {
|
||||
constructor(props) {
|
||||
super( props );
|
||||
this.toggleViews = this.toggleViews.bind( this );
|
||||
this.handleChange = this.handleChange.bind( this );
|
||||
this.state = {
|
||||
view: 'rgb',
|
||||
};
|
||||
}
|
||||
toggleViews() {
|
||||
if ( this.state.view === 'hsl' ) {
|
||||
this.setState({ view: 'rgb' })
|
||||
} else if (this.state.view === 'rgb') {
|
||||
this.setState({ view: 'hsl' })
|
||||
}
|
||||
}
|
||||
handleChange(data, e) {
|
||||
if (data.hex) {
|
||||
color.isValidHex(data.hex) && this.props.onChange({
|
||||
hex: data.hex,
|
||||
source: 'hex',
|
||||
}, e)
|
||||
} else if (data.r || data.g || data.b) {
|
||||
this.props.onChange({
|
||||
r: data.r || this.props.rgb.r,
|
||||
g: data.g || this.props.rgb.g,
|
||||
b: data.b || this.props.rgb.b,
|
||||
a: this.props.rgb.a,
|
||||
source: 'rgb',
|
||||
}, e)
|
||||
} else if (data.a) {
|
||||
if (data.a < 0) {
|
||||
data.a = 0
|
||||
} else if (data.a > 1) {
|
||||
data.a = 1
|
||||
}
|
||||
|
||||
this.props.onChange({
|
||||
h: this.props.hsl.h,
|
||||
s: this.props.hsl.s,
|
||||
l: this.props.hsl.l,
|
||||
a: Math.round(data.a * 100) / 100,
|
||||
source: 'rgb',
|
||||
}, e)
|
||||
} else if (data.h || data.s || data.l) {
|
||||
// Remove any occurances of '%'.
|
||||
if (typeof(data.s) === 'string') { data.s = data.s.replace('%', '') }
|
||||
if (typeof(data.l) === 'string') { data.l = data.l.replace('%', '') }
|
||||
this.props.onChange({
|
||||
h: data.h || this.props.hsl.h || 0,
|
||||
s: Number((data.s && data.s / 100) || this.props.hsl.s || 0.0 ),
|
||||
l: Number((data.l && data.l / 100) || this.props.hsl.l || 0.0 ),
|
||||
a: Math.round(data.a * 100) / 100 || this.props.rgb.a || 1,
|
||||
source: 'hsl',
|
||||
}, e)
|
||||
}
|
||||
}
|
||||
render() {
|
||||
const styles = {
|
||||
fields: {
|
||||
display: 'flex',
|
||||
paddingTop: '4px',
|
||||
},
|
||||
single: {
|
||||
flex: '1',
|
||||
paddingLeft: '6px',
|
||||
},
|
||||
alpha: {
|
||||
flex: '1',
|
||||
paddingLeft: '6px',
|
||||
},
|
||||
double: {
|
||||
flex: '2',
|
||||
},
|
||||
input: {
|
||||
width: '100%',
|
||||
padding: '4px 10% 3px',
|
||||
border: 'none',
|
||||
borderRadius: '2px',
|
||||
boxShadow: 'rgb(218, 218, 218) 0px 0px 0px 1px inset',
|
||||
fontSize: '11px',
|
||||
},
|
||||
label: {
|
||||
display: 'block',
|
||||
textAlign: 'center',
|
||||
fontSize: '11px',
|
||||
color: '#222',
|
||||
paddingTop: '3px',
|
||||
paddingBottom: '4px',
|
||||
textTransform: 'capitalize',
|
||||
},
|
||||
toggle: {
|
||||
width: '32px',
|
||||
textAlign: 'right',
|
||||
position: 'relative',
|
||||
},
|
||||
}
|
||||
return (
|
||||
<div style={ styles.fields } className="flexbox-fix">
|
||||
<div style={ styles.double }>
|
||||
<EditableInput
|
||||
style={{ input: styles.input, label: styles.label }}
|
||||
label="hex"
|
||||
value={ this.props.hex.replace('#', '') }
|
||||
onChange={ this.handleChange }
|
||||
/>
|
||||
</div>
|
||||
{ this.state.view === 'rgb' && (
|
||||
<Fragment>
|
||||
<div style={ styles.single }>
|
||||
<EditableInput
|
||||
style={{ input: styles.input, label: styles.label }}
|
||||
label="r"
|
||||
value={ this.props.rgb.r }
|
||||
onChange={ this.handleChange }
|
||||
dragLabel="true"
|
||||
dragMax="255"
|
||||
/>
|
||||
</div>
|
||||
<div style={ styles.single }>
|
||||
<EditableInput
|
||||
style={{ input: styles.input, label: styles.label }}
|
||||
label="g"
|
||||
value={ this.props.rgb.g }
|
||||
onChange={ this.handleChange }
|
||||
dragLabel="true"
|
||||
dragMax="255"
|
||||
/>
|
||||
</div>
|
||||
<div style={ styles.single }>
|
||||
<EditableInput
|
||||
style={{ input: styles.input, label: styles.label }}
|
||||
label="b"
|
||||
value={ this.props.rgb.b }
|
||||
onChange={ this.handleChange }
|
||||
dragLabel="true"
|
||||
dragMax="255"
|
||||
/>
|
||||
</div>
|
||||
<div style={ styles.alpha }>
|
||||
<EditableInput
|
||||
style={{ input: styles.input, label: styles.label }}
|
||||
label="a"
|
||||
value={ this.props.rgb.a }
|
||||
arrowOffset={ 0.01 }
|
||||
onChange={ this.handleChange }
|
||||
/>
|
||||
</div>
|
||||
</Fragment>
|
||||
) }
|
||||
{ this.state.view === 'hsl' && (
|
||||
<Fragment>
|
||||
<div style={ styles.single }>
|
||||
<EditableInput
|
||||
style={{ input: styles.input, label: styles.label }}
|
||||
label="h"
|
||||
value={ Math.round(this.props.hsl.h) }
|
||||
onChange={ this.handleChange }
|
||||
dragLabel="true"
|
||||
dragMax="359"
|
||||
/>
|
||||
</div>
|
||||
<div style={ styles.single }>
|
||||
<EditableInput
|
||||
style={{ input: styles.input, label: styles.label }}
|
||||
label="s"
|
||||
value={ `${ Math.round( this.props.hsl.s * 100 ) }` }
|
||||
onChange={ this.handleChange }
|
||||
/>
|
||||
</div>
|
||||
<div style={ styles.single }>
|
||||
<EditableInput
|
||||
style={{ input: styles.input, label: styles.label }}
|
||||
label="l"
|
||||
value={ `${ Math.round(this.props.hsl.l * 100) }` }
|
||||
onChange={ this.handleChange }
|
||||
/>
|
||||
</div>
|
||||
<div style={ styles.alpha }>
|
||||
<EditableInput
|
||||
style={{ input: styles.input, label: styles.label }}
|
||||
label="a"
|
||||
value={ this.props.hsl.a }
|
||||
arrowOffset={ 0.01 }
|
||||
onChange={ this.handleChange }
|
||||
/>
|
||||
</div>
|
||||
</Fragment>
|
||||
) }
|
||||
<div style={ styles.toggle }>
|
||||
<div className="toggle-icons" style={ styles.icon } onClick={ this.toggleViews } ref={ (icon) => this.icon = icon }>
|
||||
<Dashicon icon="arrow-up-alt2" />
|
||||
<Dashicon icon="arrow-down-alt2" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
export default PickerFields
|
||||
@@ -0,0 +1,128 @@
|
||||
import { CustomPicker } from 'react-color'
|
||||
import { EditableInput, Hue, Saturation, Alpha, Checkboard } from 'react-color/lib/components/common'
|
||||
import { ChromePointerCircle } from 'react-color/lib/components/chrome/ChromePointerCircle'
|
||||
import { ChromePointer } from 'react-color/lib/components/chrome/ChromePointer'
|
||||
import PickerFields from './color-picker-fields'
|
||||
|
||||
export const KadenceColorPicker = ({ rgb, hex, hsv, hsl, onChange, renderers }) => {
|
||||
const styles = {
|
||||
picker: {
|
||||
width: 300,
|
||||
position: 'relative',
|
||||
marginBottom: 10,
|
||||
},
|
||||
hue: {
|
||||
height: 10,
|
||||
position: 'relative',
|
||||
marginBottom: '8px',
|
||||
},
|
||||
Hue: {
|
||||
radius: '2px',
|
||||
},
|
||||
alpha: {
|
||||
height: '10px',
|
||||
position: 'relative',
|
||||
},
|
||||
Alpha: {
|
||||
radius: '2px',
|
||||
},
|
||||
input: {
|
||||
height: 34,
|
||||
border: `1px solid ${ hex }`,
|
||||
paddingLeft: 10,
|
||||
},
|
||||
body: {
|
||||
padding: '10px 0',
|
||||
},
|
||||
controls: {
|
||||
display: 'flex',
|
||||
},
|
||||
color: {
|
||||
width: '30px',
|
||||
height: '30px',
|
||||
position: 'relative',
|
||||
marginTop: '3px',
|
||||
marginLeft: '10px',
|
||||
borderRadius: '50%',
|
||||
overflow: 'hidden',
|
||||
},
|
||||
activeColor: {
|
||||
position: 'absolute',
|
||||
left:0,
|
||||
right:0,
|
||||
top:0,
|
||||
bottom:0,
|
||||
borderRadius: '50%',
|
||||
background: `rgba(${ rgb.r },${ rgb.g },${ rgb.b },${ rgb.a })`,
|
||||
boxShadow: 'inset 0 0 0 1px rgba(0,0,0,.1)',
|
||||
},
|
||||
swatch: {
|
||||
width: 54,
|
||||
height: 38,
|
||||
background: hex,
|
||||
},
|
||||
sliders: {
|
||||
padding: '4px 0',
|
||||
flex: '1',
|
||||
},
|
||||
saturation: {
|
||||
width: '100%',
|
||||
paddingBottom: '40%',
|
||||
position: 'relative',
|
||||
overflow: 'hidden',
|
||||
},
|
||||
Saturation: {
|
||||
radius: '2px 2px 0 0',
|
||||
shadow: 'inset 0 0 0 1px rgba(0,0,0,.15), inset 0 0 4px rgba(0,0,0,.25)',
|
||||
},
|
||||
}
|
||||
return (
|
||||
<div style={ styles.picker } className={ 'kadence-picker' }>
|
||||
<div style={ styles.saturation }>
|
||||
<Saturation
|
||||
style={ styles.Saturation }
|
||||
hsl={ hsl }
|
||||
hsv={ hsv }
|
||||
pointer={ ChromePointerCircle }
|
||||
onChange={ onChange }
|
||||
/>
|
||||
</div>
|
||||
<div style={ styles.body }>
|
||||
<div style={ styles.controls } className="flexbox-fix">
|
||||
<div style={ styles.sliders }>
|
||||
<div style={ styles.hue }>
|
||||
<Hue
|
||||
style={ styles.Hue }
|
||||
hsl={ hsl }
|
||||
onChange={ onChange }
|
||||
pointer={ ChromePointer }
|
||||
/>
|
||||
</div>
|
||||
<div style={ styles.alpha }>
|
||||
<Alpha
|
||||
style={ styles.Alpha }
|
||||
rgb={ rgb }
|
||||
hsl={ hsl }
|
||||
renderers={ renderers }
|
||||
pointer={ ChromePointer }
|
||||
onChange={ onChange }
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div style={ styles.color }>
|
||||
<Checkboard />
|
||||
<div style={ styles.activeColor } />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<PickerFields
|
||||
rgb={ rgb }
|
||||
hsl={ hsl }
|
||||
hex={ hex }
|
||||
onChange={ onChange }
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default CustomPicker(KadenceColorPicker)
|
||||
@@ -0,0 +1,752 @@
|
||||
import PropTypes from "prop-types";
|
||||
import SwatchesControl from "./swatches";
|
||||
import KadenceColorPicker from "./color-picker";
|
||||
import Icons from "./icons";
|
||||
import { __ } from "@wordpress/i18n";
|
||||
const { Component, Fragment } = wp.element;
|
||||
const {
|
||||
Button,
|
||||
Popover,
|
||||
Dashicon,
|
||||
ColorIndicator,
|
||||
Tooltip,
|
||||
Icon,
|
||||
TabPanel,
|
||||
GradientPicker,
|
||||
__experimentalGradientPicker,
|
||||
} = wp.components;
|
||||
import KadenceGradientPicker from "../gradient-control/index.js";
|
||||
|
||||
class ColorControl extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.onChangeState = this.onChangeState.bind(this);
|
||||
this.onChangeComplete = this.onChangeComplete.bind(this);
|
||||
this.onChangeGradientComplete =
|
||||
this.onChangeGradientComplete.bind(this);
|
||||
this.state = {
|
||||
isVisible: false,
|
||||
refresh: false,
|
||||
stateColor: this.props.color,
|
||||
color: this.props.color,
|
||||
isPalette:
|
||||
this.props.color &&
|
||||
this.props.color.includes("palette") &&
|
||||
!this.props.color.includes("gradient")
|
||||
? true
|
||||
: false,
|
||||
palette:
|
||||
this.props.presetColors && this.props.presetColors
|
||||
? this.props.presetColors
|
||||
: [],
|
||||
activePalette:
|
||||
this.props.presetColors && this.props.presetColors.active
|
||||
? this.props.presetColors.active
|
||||
: "palette",
|
||||
supportGradient:
|
||||
undefined === GradientPicker &&
|
||||
undefined === __experimentalGradientPicker
|
||||
? false
|
||||
: true,
|
||||
showSyncMessage: true,
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
// Helper function to check if we should show sync message
|
||||
const shouldShowSyncMessage = () => {
|
||||
return (
|
||||
this.props.paletteName === "palette10" &&
|
||||
this.props.color === "#FfFfFf" &&
|
||||
this.state.showSyncMessage === true
|
||||
);
|
||||
};
|
||||
|
||||
const shouldShowResyncMessage = () => {
|
||||
return (
|
||||
this.props.paletteName === "palette10" &&
|
||||
this.props.color !== "#FfFfFf" &&
|
||||
this.state.showSyncMessage === false
|
||||
);
|
||||
};
|
||||
|
||||
const toggleVisible = () => {
|
||||
if (this.props.usePalette) {
|
||||
const updateColors = JSON.parse(
|
||||
this.props.customizer
|
||||
.control("kadence_color_palette")
|
||||
.setting.get()
|
||||
);
|
||||
const active =
|
||||
updateColors && updateColors.active
|
||||
? updateColors.active
|
||||
: "palette";
|
||||
this.setState({ palette: updateColors, activePalette: active });
|
||||
}
|
||||
if (this.state.refresh === true) {
|
||||
this.setState({ refresh: false });
|
||||
} else {
|
||||
this.setState({ refresh: true });
|
||||
}
|
||||
this.setState({ isVisible: true });
|
||||
};
|
||||
|
||||
const toggleClose = () => {
|
||||
if (this.state.isVisible === true) {
|
||||
this.setState({ isVisible: false });
|
||||
}
|
||||
};
|
||||
|
||||
const position = this.props.position
|
||||
? this.props.position
|
||||
: "bottom right";
|
||||
const showingGradient =
|
||||
this.props.allowGradient && this.state.supportGradient
|
||||
? true
|
||||
: false;
|
||||
|
||||
const syncMessageContent = () => {
|
||||
return (
|
||||
<div
|
||||
className="kadence-sync-message"
|
||||
style={{ padding: "16px", textAlign: "center" }}
|
||||
>
|
||||
<p>
|
||||
{__(
|
||||
"This color is currently linked as the compliment to your accent color.",
|
||||
"kadence"
|
||||
)}
|
||||
</p>
|
||||
<Button
|
||||
onClick={() =>
|
||||
this.setState({ showSyncMessage: false })
|
||||
}
|
||||
variant="secondary"
|
||||
isSmall
|
||||
>
|
||||
{__("Unlink Color", "kadence")}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const resyncMessageContent = () => {
|
||||
return (
|
||||
<div
|
||||
className="kadence-sync-message"
|
||||
style={{ padding: "16px", textAlign: "center" }}
|
||||
>
|
||||
<Button
|
||||
onClick={() => {
|
||||
this.setState({ showSyncMessage: true });
|
||||
this.onChangeState({ hex: "#FfFfFf" }, "");
|
||||
this.props.onChangeComplete({ hex: "#FfFfFf" }, "");
|
||||
}}
|
||||
variant="secondary"
|
||||
isSmall
|
||||
>
|
||||
{__("Link Color", "kadence")}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
const paletteIndexRegex = this.state.color?.match(/\d+$/)?.[0] - 1;
|
||||
const paletteIndex = this.state.isPalette
|
||||
? paletteIndexRegex
|
||||
: undefined;
|
||||
return (
|
||||
<div
|
||||
className={"kadence-color-picker-wrap " + this.props.className}
|
||||
>
|
||||
{this.props.colorDefault &&
|
||||
this.props.color &&
|
||||
this.props.color !== this.props.colorDefault && (
|
||||
<Tooltip text={__("Clear")}>
|
||||
<span className="tooltip-clear">
|
||||
<Button
|
||||
className="components-color-palette__clear"
|
||||
type="button"
|
||||
onClick={() => {
|
||||
this.setState({
|
||||
color: this.props.colorDefault,
|
||||
isPalette: "",
|
||||
});
|
||||
this.props.onChangeComplete("", "");
|
||||
}}
|
||||
isSmall
|
||||
>
|
||||
<Dashicon icon="redo" />
|
||||
</Button>
|
||||
</span>
|
||||
</Tooltip>
|
||||
)}
|
||||
{showingGradient && (
|
||||
<Fragment>
|
||||
{this.state.isVisible && (
|
||||
<Popover
|
||||
position={position}
|
||||
inline={true}
|
||||
anchor={
|
||||
undefined !==
|
||||
this.props?.controlRef?.current
|
||||
? this.props.controlRef.current
|
||||
: undefined
|
||||
}
|
||||
className="kadence-popover-color kadence-popover-color-gradient kadence-customizer-popover"
|
||||
onClose={toggleClose}
|
||||
>
|
||||
{shouldShowSyncMessage() ? (
|
||||
syncMessageContent()
|
||||
) : (
|
||||
<TabPanel
|
||||
className="kadence-popover-tabs kadence-background-tabs"
|
||||
activeClass="active-tab"
|
||||
initialTabName={
|
||||
this.state.color &&
|
||||
this.state.color.includes(
|
||||
"gradient"
|
||||
)
|
||||
? "gradient"
|
||||
: "color"
|
||||
}
|
||||
tabs={[
|
||||
{
|
||||
name: "color",
|
||||
title: __("Color", "kadence"),
|
||||
className:
|
||||
"kadence-color-background",
|
||||
},
|
||||
{
|
||||
name: "gradient",
|
||||
title: __(
|
||||
"Gradient",
|
||||
"kadence"
|
||||
),
|
||||
className:
|
||||
"kadence-gradient-background",
|
||||
},
|
||||
]}
|
||||
>
|
||||
{(tab) => {
|
||||
let tabout;
|
||||
if (tab.name) {
|
||||
if ("gradient" === tab.name) {
|
||||
tabout = (
|
||||
<Fragment>
|
||||
<KadenceGradientPicker
|
||||
value={
|
||||
this.state
|
||||
.color &&
|
||||
this.state.color.includes(
|
||||
"gradient"
|
||||
)
|
||||
? this
|
||||
.state
|
||||
.color
|
||||
: ""
|
||||
}
|
||||
onChange={(
|
||||
gradient
|
||||
) =>
|
||||
this.onChangeGradientComplete(
|
||||
gradient
|
||||
)
|
||||
}
|
||||
activePalette={
|
||||
this.state
|
||||
.palette &&
|
||||
this.state
|
||||
.palette[
|
||||
this
|
||||
.state
|
||||
.activePalette
|
||||
]
|
||||
? this
|
||||
.state
|
||||
.palette[
|
||||
this
|
||||
.state
|
||||
.activePalette
|
||||
]
|
||||
: []
|
||||
}
|
||||
/>
|
||||
</Fragment>
|
||||
);
|
||||
} else {
|
||||
tabout = (
|
||||
<Fragment>
|
||||
{this.state
|
||||
.refresh && (
|
||||
<Fragment>
|
||||
<KadenceColorPicker
|
||||
color={
|
||||
this
|
||||
.state
|
||||
.isPalette &&
|
||||
this
|
||||
.state
|
||||
.palette
|
||||
.palette &&
|
||||
this
|
||||
.state
|
||||
.palette
|
||||
.palette[
|
||||
paletteIndex
|
||||
]
|
||||
? this
|
||||
.state
|
||||
.palette
|
||||
.palette[
|
||||
paletteIndex
|
||||
]
|
||||
?.color
|
||||
: this
|
||||
.state
|
||||
.color
|
||||
}
|
||||
onChange={(
|
||||
color
|
||||
) =>
|
||||
this.onChangeState(
|
||||
color,
|
||||
""
|
||||
)
|
||||
}
|
||||
onChangeComplete={(
|
||||
color
|
||||
) =>
|
||||
this.onChangeComplete(
|
||||
color,
|
||||
""
|
||||
)
|
||||
}
|
||||
/>
|
||||
{this.props
|
||||
.usePalette && (
|
||||
<SwatchesControl
|
||||
colors={
|
||||
this
|
||||
.state
|
||||
.palette &&
|
||||
this
|
||||
.state
|
||||
.palette[
|
||||
this
|
||||
.state
|
||||
.activePalette
|
||||
]
|
||||
? this
|
||||
.state
|
||||
.palette[
|
||||
this
|
||||
.state
|
||||
.activePalette
|
||||
]
|
||||
: []
|
||||
}
|
||||
isPalette={
|
||||
this
|
||||
.state
|
||||
.isPalette
|
||||
? this
|
||||
.state
|
||||
.color
|
||||
: ""
|
||||
}
|
||||
onClick={(
|
||||
color,
|
||||
palette
|
||||
) =>
|
||||
this.onChangeComplete(
|
||||
color,
|
||||
palette
|
||||
)
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</Fragment>
|
||||
)}
|
||||
{!this.state
|
||||
.refresh && (
|
||||
<Fragment>
|
||||
<KadenceColorPicker
|
||||
//presetColors={ [] }
|
||||
color={
|
||||
this
|
||||
.state
|
||||
.isPalette &&
|
||||
this
|
||||
.state
|
||||
.palette[
|
||||
this
|
||||
.state
|
||||
.activePalette
|
||||
] &&
|
||||
this
|
||||
.state
|
||||
.palette[
|
||||
this
|
||||
.state
|
||||
.activePalette
|
||||
][
|
||||
paletteIndex
|
||||
]
|
||||
? this
|
||||
.state
|
||||
.palette[
|
||||
this
|
||||
.state
|
||||
.activePalette
|
||||
][
|
||||
paletteIndex
|
||||
]
|
||||
?.color
|
||||
: this
|
||||
.state
|
||||
.color
|
||||
}
|
||||
onChange={(
|
||||
color
|
||||
) =>
|
||||
this.onChangeState(
|
||||
color,
|
||||
""
|
||||
)
|
||||
}
|
||||
onChangeComplete={(
|
||||
color
|
||||
) =>
|
||||
this.onChangeComplete(
|
||||
color,
|
||||
""
|
||||
)
|
||||
}
|
||||
//width={ 300 }
|
||||
//styles={ styleing }
|
||||
/>
|
||||
{this.props
|
||||
.usePalette && (
|
||||
<SwatchesControl
|
||||
colors={
|
||||
this
|
||||
.state
|
||||
.palette &&
|
||||
this
|
||||
.state
|
||||
.palette[
|
||||
this
|
||||
.state
|
||||
.activePalette
|
||||
]
|
||||
? this
|
||||
.state
|
||||
.palette[
|
||||
this
|
||||
.state
|
||||
.activePalette
|
||||
]
|
||||
: []
|
||||
}
|
||||
isPalette={
|
||||
this
|
||||
.state
|
||||
.isPalette
|
||||
? this
|
||||
.state
|
||||
.color
|
||||
: ""
|
||||
}
|
||||
onClick={(
|
||||
color,
|
||||
palette
|
||||
) =>
|
||||
this.onChangeComplete(
|
||||
color,
|
||||
palette
|
||||
)
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</Fragment>
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
{tabout}
|
||||
{shouldShowResyncMessage()
|
||||
? resyncMessageContent()
|
||||
: ""}
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
</TabPanel>
|
||||
)}
|
||||
</Popover>
|
||||
)}
|
||||
</Fragment>
|
||||
)}
|
||||
{!showingGradient && (
|
||||
<Fragment>
|
||||
{this.state.isVisible && this.state.refresh && (
|
||||
<Popover
|
||||
position="top right"
|
||||
inline={true}
|
||||
anchor={
|
||||
undefined !==
|
||||
this.props?.controlRef?.current
|
||||
? this.props.controlRef.current
|
||||
: undefined
|
||||
}
|
||||
className="kadence-popover-color kadence-customizer-popover"
|
||||
onClose={toggleClose}
|
||||
>
|
||||
{shouldShowSyncMessage() ? (
|
||||
syncMessageContent()
|
||||
) : (
|
||||
<Fragment>
|
||||
<KadenceColorPicker
|
||||
color={
|
||||
this.state.isPalette &&
|
||||
this.state.palette.palette &&
|
||||
this.state.palette.palette[
|
||||
paletteIndex
|
||||
]
|
||||
? this.state.palette
|
||||
.palette[
|
||||
paletteIndex
|
||||
]?.color
|
||||
: this.state.color
|
||||
}
|
||||
onChange={(color) =>
|
||||
this.onChangeState(color, "")
|
||||
}
|
||||
onChangeComplete={(color) =>
|
||||
this.onChangeComplete(color, "")
|
||||
}
|
||||
/>
|
||||
{this.props.usePalette && (
|
||||
<SwatchesControl
|
||||
colors={
|
||||
this.state.palette &&
|
||||
this.state.palette[
|
||||
this.state.activePalette
|
||||
]
|
||||
? this.state.palette[
|
||||
this.state
|
||||
.activePalette
|
||||
]
|
||||
: []
|
||||
}
|
||||
isPalette={
|
||||
this.state.isPalette
|
||||
? this.state.color
|
||||
: ""
|
||||
}
|
||||
onClick={(color, palette) =>
|
||||
this.onChangeComplete(
|
||||
color,
|
||||
palette
|
||||
)
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{shouldShowResyncMessage()
|
||||
? resyncMessageContent()
|
||||
: ""}
|
||||
</Fragment>
|
||||
)}
|
||||
</Popover>
|
||||
)}
|
||||
{this.state.isVisible && !this.state.refresh && (
|
||||
<Popover
|
||||
position={position}
|
||||
inline={true}
|
||||
anchor={
|
||||
undefined !==
|
||||
this.props?.controlRef?.current
|
||||
? this.props.controlRef.current
|
||||
: undefined
|
||||
}
|
||||
className="kadence-popover-color kadence-customizer-popover"
|
||||
onClose={toggleClose}
|
||||
>
|
||||
{shouldShowSyncMessage() ? (
|
||||
syncMessageContent()
|
||||
) : (
|
||||
<Fragment>
|
||||
<KadenceColorPicker
|
||||
//presetColors={ [] }
|
||||
color={
|
||||
this.state.isPalette &&
|
||||
this.state.palette[
|
||||
this.state.activePalette
|
||||
] &&
|
||||
this.state.palette[
|
||||
this.state.activePalette
|
||||
][paletteIndex]
|
||||
? this.state.palette[
|
||||
this.state
|
||||
.activePalette
|
||||
][paletteIndex]?.color
|
||||
: this.state.color
|
||||
}
|
||||
onChange={(color) =>
|
||||
this.onChangeState(color, "")
|
||||
}
|
||||
onChangeComplete={(color) =>
|
||||
this.onChangeComplete(color, "")
|
||||
}
|
||||
//width={ 300 }
|
||||
//styles={ styleing }
|
||||
/>
|
||||
{this.props.usePalette && (
|
||||
<SwatchesControl
|
||||
colors={
|
||||
this.state.palette &&
|
||||
this.state.palette[
|
||||
this.state.activePalette
|
||||
]
|
||||
? this.state.palette[
|
||||
this.state
|
||||
.activePalette
|
||||
]
|
||||
: []
|
||||
}
|
||||
isPalette={
|
||||
this.state.isPalette
|
||||
? this.state.color
|
||||
: ""
|
||||
}
|
||||
onClick={(color, palette) =>
|
||||
this.onChangeComplete(
|
||||
color,
|
||||
palette
|
||||
)
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{shouldShowResyncMessage()
|
||||
? resyncMessageContent()
|
||||
: ""}
|
||||
</Fragment>
|
||||
)}
|
||||
</Popover>
|
||||
)}
|
||||
</Fragment>
|
||||
)}
|
||||
<Tooltip
|
||||
text={
|
||||
this.props.tooltip
|
||||
? this.props.tooltip
|
||||
: __("Select Color", "kadence")
|
||||
}
|
||||
>
|
||||
<div className="color-button-wrap">
|
||||
<Button
|
||||
className={"kadence-color-icon-indicate"}
|
||||
onClick={() => {
|
||||
this.state.isVisible
|
||||
? toggleClose()
|
||||
: toggleVisible();
|
||||
}}
|
||||
disabled={this.props.disabled}
|
||||
>
|
||||
<ColorIndicator
|
||||
className="kadence-advanced-color-indicate"
|
||||
colorValue={
|
||||
this.state.isPalette
|
||||
? "var(--global-" +
|
||||
this.props.color +
|
||||
")"
|
||||
: this.props.color
|
||||
}
|
||||
/>
|
||||
{this.state.isPalette && (
|
||||
<Icon className="dashicon" icon={Icons.globe} />
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
</Tooltip>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
onChangeState(color, palette) {
|
||||
let newColor;
|
||||
if (palette) {
|
||||
newColor = palette;
|
||||
} else if (
|
||||
undefined !== color.rgb &&
|
||||
undefined !== color.rgb.a &&
|
||||
1 !== color.rgb.a
|
||||
) {
|
||||
newColor =
|
||||
"rgba(" +
|
||||
color.rgb.r +
|
||||
"," +
|
||||
color.rgb.g +
|
||||
"," +
|
||||
color.rgb.b +
|
||||
"," +
|
||||
color.rgb.a +
|
||||
")";
|
||||
} else {
|
||||
newColor = color.hex;
|
||||
}
|
||||
this.setState({ color: newColor, isPalette: palette ? true : false });
|
||||
if (undefined !== this.props.onChange) {
|
||||
this.props.onChange(color, palette);
|
||||
}
|
||||
}
|
||||
onChangeGradientComplete(gradient) {
|
||||
let newColor;
|
||||
if (undefined === gradient) {
|
||||
newColor = "";
|
||||
} else {
|
||||
newColor = gradient;
|
||||
}
|
||||
this.setState({ color: newColor, isPalette: false });
|
||||
this.props.onChangeComplete(newColor, "");
|
||||
}
|
||||
onChangeComplete(color, palette) {
|
||||
let newColor;
|
||||
if (palette) {
|
||||
newColor = palette;
|
||||
} else if (
|
||||
undefined !== color.rgb &&
|
||||
undefined !== color.rgb.a &&
|
||||
1 !== color.rgb.a
|
||||
) {
|
||||
newColor =
|
||||
"rgba(" +
|
||||
color.rgb.r +
|
||||
"," +
|
||||
color.rgb.g +
|
||||
"," +
|
||||
color.rgb.b +
|
||||
"," +
|
||||
color.rgb.a +
|
||||
")";
|
||||
} else {
|
||||
newColor = color.hex;
|
||||
}
|
||||
this.setState({ color: newColor, isPalette: palette ? true : false });
|
||||
this.props.onChangeComplete(color, palette);
|
||||
}
|
||||
}
|
||||
|
||||
ColorControl.propTypes = {
|
||||
color: PropTypes.string,
|
||||
usePalette: PropTypes.bool,
|
||||
palette: PropTypes.string,
|
||||
presetColors: PropTypes.array,
|
||||
onChangeComplete: PropTypes.func,
|
||||
onChange: PropTypes.func,
|
||||
customizer: PropTypes.object,
|
||||
};
|
||||
|
||||
export default ColorControl;
|
||||
@@ -0,0 +1,92 @@
|
||||
if ( kadencegooglefonts === undefined ) {
|
||||
var kadencegooglefonts = [];
|
||||
}
|
||||
const {
|
||||
Component,
|
||||
} = wp.element;
|
||||
import PropTypes from "prop-types";
|
||||
import WebFont from "webfontloader";
|
||||
const statuses = {
|
||||
inactive: 'inactive',
|
||||
active: 'active',
|
||||
loading: 'loading',
|
||||
};
|
||||
|
||||
const noop = () => {};
|
||||
|
||||
class KadenceWebfontLoader extends Component {
|
||||
constructor(props) {
|
||||
super( props );
|
||||
this.handleLoading = this.handleLoading.bind( this );
|
||||
this.handleActive = this.handleActive.bind( this );
|
||||
this.addFont = this.addFont.bind( this );
|
||||
this.handleInactive = this.handleInactive.bind( this );
|
||||
this.loadFonts = this.loadFonts.bind( this );
|
||||
this.state = {
|
||||
status: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
addFont( font ) {
|
||||
if ( ! kadencegooglefonts.includes( font ) ) {
|
||||
kadencegooglefonts.push( font );
|
||||
}
|
||||
};
|
||||
|
||||
handleLoading() {
|
||||
this.setState( { status: statuses.loading } );
|
||||
};
|
||||
|
||||
handleActive() {
|
||||
this.setState( { status: statuses.active } );
|
||||
};
|
||||
|
||||
handleInactive() {
|
||||
this.setState( { status: statuses.inactive } );
|
||||
};
|
||||
|
||||
loadFonts() {
|
||||
//if ( ! this.state.fonts.includes( this.props.config.google.families[ 0 ] ) ) {
|
||||
if ( ! kadencegooglefonts.includes( this.props.config.google.families[ 0 ] ) ) {
|
||||
WebFont.load( {
|
||||
...this.props.config,
|
||||
loading: this.handleLoading,
|
||||
active: this.handleActive,
|
||||
inactive: this.handleInactive,
|
||||
} );
|
||||
this.addFont( this.props.config.google.families[ 0 ] );
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.loadFonts();
|
||||
}
|
||||
|
||||
componentDidUpdate( prevProps, prevState ) {
|
||||
const { onStatus, config } = this.props;
|
||||
|
||||
if ( prevState.status !== this.state.status ) {
|
||||
onStatus( this.state.status );
|
||||
}
|
||||
if ( prevProps.config !== config ) {
|
||||
this.loadFonts();
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { children } = this.props;
|
||||
return children || null;
|
||||
}
|
||||
}
|
||||
|
||||
KadenceWebfontLoader.propTypes = {
|
||||
config: PropTypes.object.isRequired,
|
||||
children: PropTypes.element,
|
||||
onStatus: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
KadenceWebfontLoader.defaultProps = {
|
||||
onStatus: noop,
|
||||
};
|
||||
|
||||
export default KadenceWebfontLoader;
|
||||
1360
wp-content/themes/kadence/inc/customizer/react/src/common/icons.js
Normal file
1360
wp-content/themes/kadence/inc/customizer/react/src/common/icons.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,93 @@
|
||||
const { RangeControl } = wp.components;
|
||||
const { useInstanceId } = wp.compose;
|
||||
|
||||
/**
|
||||
* Build the Measure controls
|
||||
* @returns {object} Measure settings.
|
||||
*/
|
||||
export default function KadenceRange({
|
||||
label,
|
||||
onChange,
|
||||
value = "",
|
||||
className = "",
|
||||
step = 1,
|
||||
max = 100,
|
||||
min = 0,
|
||||
beforeIcon = "",
|
||||
help = "",
|
||||
}) {
|
||||
const onChangInput = (event) => {
|
||||
if (event.target.value === "") {
|
||||
onChange(undefined);
|
||||
return;
|
||||
}
|
||||
const newValue = Number(event.target.value);
|
||||
if (newValue === "") {
|
||||
onChange(undefined);
|
||||
return;
|
||||
}
|
||||
if (min < -0.1) {
|
||||
if (newValue > max) {
|
||||
onChange(max);
|
||||
} else if (newValue < min && newValue !== "-") {
|
||||
onChange(min);
|
||||
} else {
|
||||
onChange(newValue);
|
||||
}
|
||||
} else {
|
||||
if (newValue > max) {
|
||||
onChange(max);
|
||||
} else if (newValue < -0.1) {
|
||||
onChange(min);
|
||||
} else {
|
||||
onChange(newValue);
|
||||
}
|
||||
}
|
||||
};
|
||||
const id = useInstanceId(KadenceRange, "inspector-kadence-range");
|
||||
return [
|
||||
onChange && (
|
||||
<div
|
||||
className={`components-base-control kadence-range-control${
|
||||
className ? " " + className : ""
|
||||
}`}
|
||||
>
|
||||
{label && (
|
||||
<label
|
||||
htmlFor={id}
|
||||
className="components-base-control__label"
|
||||
>
|
||||
{label}
|
||||
</label>
|
||||
)}
|
||||
<div className={"kadence-range-control-inner"}>
|
||||
<RangeControl
|
||||
className={"kadence-range-control-range"}
|
||||
beforeIcon={beforeIcon}
|
||||
value={value}
|
||||
onChange={(newVal) => onChange(newVal)}
|
||||
min={min}
|
||||
max={max}
|
||||
step={step}
|
||||
help={help}
|
||||
withInputField={false}
|
||||
/>
|
||||
<div className="components-base-control kt-range-number-input">
|
||||
<div className="components-base-control__field">
|
||||
<input
|
||||
value={value}
|
||||
onChange={onChangInput}
|
||||
min={min}
|
||||
max={max}
|
||||
id={id}
|
||||
step={step}
|
||||
type="number"
|
||||
className="components-text-control__input"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
import PropTypes from "prop-types";
|
||||
import Icons from "./icons";
|
||||
import { __ } from "@wordpress/i18n";
|
||||
const { Component, Fragment } = wp.element;
|
||||
const { Button, Dashicon, Tooltip, ButtonGroup, Icon } = wp.components;
|
||||
|
||||
class ResponsiveControl extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
view:
|
||||
undefined !== this.props.deviceSize
|
||||
? this.props.deviceSize
|
||||
: "desktop",
|
||||
};
|
||||
this.linkResponsiveButtons();
|
||||
}
|
||||
|
||||
render() {
|
||||
let { view } = this.state,
|
||||
deviceMap = {
|
||||
desktop: {
|
||||
tooltip: __("Desktop", "kadence"),
|
||||
icon: <Icon icon={Icons.desktop} />,
|
||||
},
|
||||
tablet: {
|
||||
tooltip: __("Tablet", "kadence"),
|
||||
icon: <Icon icon={Icons.tablet} />,
|
||||
},
|
||||
mobile: {
|
||||
tooltip: __("Mobile", "kadence"),
|
||||
icon: <Icon icon={Icons.smartphone} />,
|
||||
},
|
||||
};
|
||||
return (
|
||||
<Fragment>
|
||||
<div className={"kadence-responsive-control-bar"}>
|
||||
{this.props.controlLabel && (
|
||||
<span className="customize-control-title">
|
||||
{this.props.controlLabel}
|
||||
</span>
|
||||
)}
|
||||
{this.props.advancedControls && (
|
||||
<div className="advanced-controls">
|
||||
<ButtonGroup>
|
||||
<Tooltip
|
||||
text={__("Clamp Font Size", "kadence")}
|
||||
>
|
||||
<Button
|
||||
isTertiary
|
||||
onClick={() => {
|
||||
this.props.onAdvancedChange();
|
||||
}}
|
||||
isPressed={this.props.advanced}
|
||||
>
|
||||
<Dashicon icon="admin-settings" />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</ButtonGroup>
|
||||
</div>
|
||||
)}
|
||||
{!this.props.hideResponsive && (
|
||||
<div className="floating-controls">
|
||||
{this.props.tooltip && (
|
||||
<ButtonGroup>
|
||||
{Object.keys(deviceMap).map((device) => {
|
||||
return (
|
||||
<Tooltip
|
||||
text={deviceMap[device].tooltip}
|
||||
>
|
||||
<Button
|
||||
isTertiary
|
||||
className={
|
||||
(device === view
|
||||
? "active-device "
|
||||
: "") + device
|
||||
}
|
||||
onClick={() => {
|
||||
let event =
|
||||
new CustomEvent(
|
||||
"kadenceChangedRepsonsivePreview",
|
||||
{
|
||||
detail: device,
|
||||
}
|
||||
);
|
||||
document.dispatchEvent(
|
||||
event
|
||||
);
|
||||
}}
|
||||
>
|
||||
{deviceMap[device].icon}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
);
|
||||
})}
|
||||
</ButtonGroup>
|
||||
)}
|
||||
{!this.props.tooltip && (
|
||||
<ButtonGroup>
|
||||
{Object.keys(deviceMap).map((device) => {
|
||||
return (
|
||||
<Button
|
||||
isTertiary
|
||||
className={
|
||||
(device === view
|
||||
? "active-device "
|
||||
: "") + device
|
||||
}
|
||||
onClick={() => {
|
||||
let event = new CustomEvent(
|
||||
"kadenceChangedRepsonsivePreview",
|
||||
{
|
||||
detail: device,
|
||||
}
|
||||
);
|
||||
document.dispatchEvent(
|
||||
event
|
||||
);
|
||||
}}
|
||||
>
|
||||
{deviceMap[device].icon}
|
||||
</Button>
|
||||
);
|
||||
})}
|
||||
</ButtonGroup>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="kadence-responsive-controls-content">
|
||||
{this.props.children}
|
||||
</div>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
changeViewType(device) {
|
||||
this.setState({ view: device });
|
||||
wp.customize.previewedDevice(device);
|
||||
this.props.onChange(device);
|
||||
}
|
||||
|
||||
linkResponsiveButtons() {
|
||||
let self = this;
|
||||
document.addEventListener(
|
||||
"kadenceChangedRepsonsivePreview",
|
||||
function (e) {
|
||||
self.changeViewType(e.detail);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ResponsiveControl.propTypes = {
|
||||
onChange: PropTypes.func,
|
||||
controlLabel: PropTypes.string,
|
||||
};
|
||||
ResponsiveControl.defaultProps = {
|
||||
tooltip: true,
|
||||
};
|
||||
|
||||
export default ResponsiveControl;
|
||||
@@ -0,0 +1,104 @@
|
||||
import PropTypes from "prop-types";
|
||||
import Icons from "./icons";
|
||||
import { __ } from "@wordpress/i18n";
|
||||
const { Component, Fragment } = wp.element;
|
||||
const { Button, Popover, Dashicon, ColorIndicator, Tooltip, Icon } =
|
||||
wp.components;
|
||||
// /**
|
||||
// * WordPress dependencies
|
||||
// */
|
||||
// import { site, Icon } from '@wordpress/icons';
|
||||
|
||||
export const SwatchesControl = ({
|
||||
colors,
|
||||
isPalette,
|
||||
onClick = () => {},
|
||||
circleSize,
|
||||
circleSpacing,
|
||||
}) => {
|
||||
const handleClick = (color, swatch) => {
|
||||
onClick(
|
||||
{
|
||||
hex: color,
|
||||
},
|
||||
swatch
|
||||
);
|
||||
};
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
paddingBottom: "15px",
|
||||
}}
|
||||
className="kadence-swatches-wrap"
|
||||
>
|
||||
{colors.map((colorObjOrString) => {
|
||||
const c =
|
||||
typeof colorObjOrString === "string"
|
||||
? { color: colorObjOrString }
|
||||
: colorObjOrString;
|
||||
const key = `${c.color}${c.slug || ""}`;
|
||||
return (
|
||||
<div
|
||||
key={key}
|
||||
style={{
|
||||
width: circleSize,
|
||||
height: circleSize,
|
||||
marginBottom: 0,
|
||||
transform: "scale(1)",
|
||||
transition: "100ms transform ease",
|
||||
}}
|
||||
className="kadence-swatche-item-wrap"
|
||||
>
|
||||
<Button
|
||||
className={`kadence-swatch-item ${
|
||||
isPalette === c.slug
|
||||
? "swatch-active"
|
||||
: "swatch-inactive"
|
||||
}`}
|
||||
style={{
|
||||
height: "100%",
|
||||
width: "100%",
|
||||
border: "1px solid rgb(218, 218, 218)",
|
||||
borderRadius: "50%",
|
||||
color:
|
||||
c.slug === "palette10"
|
||||
? "var(--global-palette10)"
|
||||
: `${c.color}`,
|
||||
boxShadow: `inset 0 0 0 ${circleSize / 2}px`,
|
||||
transition: "100ms box-shadow ease",
|
||||
}}
|
||||
onClick={() => handleClick(c.color, c.slug)}
|
||||
tabIndex={0}
|
||||
>
|
||||
{/* <Icon
|
||||
className="dashicon"
|
||||
icon={ site }
|
||||
/> */}
|
||||
<Icon className="dashicon" icon={Icons.globe} />
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
SwatchesControl.defaultProps = {
|
||||
circleSize: 26,
|
||||
circleSpacing: 15,
|
||||
};
|
||||
|
||||
SwatchesControl.propTypes = {
|
||||
colors: PropTypes.arrayOf(
|
||||
PropTypes.oneOfType([
|
||||
PropTypes.string,
|
||||
PropTypes.shape({
|
||||
color: PropTypes.string,
|
||||
slug: PropTypes.string,
|
||||
name: PropTypes.string,
|
||||
}),
|
||||
])
|
||||
).isRequired,
|
||||
isPalette: PropTypes.string,
|
||||
};
|
||||
|
||||
export default SwatchesControl;
|
||||
@@ -0,0 +1,314 @@
|
||||
/* jshint esversion: 6 */
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
import ResponsiveControl from '../common/responsive.js';
|
||||
import Icons from '../common/icons.js';
|
||||
import { ReactSortable } from "react-sortablejs";
|
||||
import uniqueId from 'lodash/uniqueId';
|
||||
|
||||
import ItemComponent from './item-component';
|
||||
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
const { ButtonGroup, Dashicon, Tooltip, Popover, Button, SelectControl } = wp.components;
|
||||
|
||||
const { Component, Fragment } = wp.element;
|
||||
class ContactComponent extends Component {
|
||||
constructor() {
|
||||
super( ...arguments );
|
||||
this.updateValues = this.updateValues.bind( this );
|
||||
this.onDragEnd = this.onDragEnd.bind( this );
|
||||
this.onDragStart = this.onDragStart.bind( this );
|
||||
this.onDragStop = this.onDragStop.bind( this );
|
||||
this.removeItem = this.removeItem.bind( this );
|
||||
this.saveArrayUpdate = this.saveArrayUpdate.bind( this );
|
||||
this.toggleEnableItem = this.toggleEnableItem.bind( this );
|
||||
this.onChangeIcon = this.onChangeIcon.bind( this );
|
||||
this.onChangeLabel = this.onChangeLabel.bind( this );
|
||||
this.onChangeLink = this.onChangeLink.bind( this );
|
||||
this.onChangeURL = this.onChangeURL.bind( this );
|
||||
this.onChangeAttachment = this.onChangeAttachment.bind( this );
|
||||
this.onChangeWidth = this.onChangeWidth.bind( this );
|
||||
this.onChangeSource = this.onChangeSource.bind( this );
|
||||
this.addItem = this.addItem.bind( this );
|
||||
let value = this.props.control.setting.get();
|
||||
let baseDefault = {
|
||||
'items': [
|
||||
{
|
||||
'id': 'phone',
|
||||
'enabled': true,
|
||||
'source': 'icon',
|
||||
'url': '',
|
||||
'imageid': '',
|
||||
'width': 24,
|
||||
'link': '',
|
||||
'icon': 'mobile',
|
||||
'label': '444-546-8765',
|
||||
},
|
||||
{
|
||||
'id': 'hours',
|
||||
'enabled': true,
|
||||
'source': 'icon',
|
||||
'url': '',
|
||||
'imageid': '',
|
||||
'width': 24,
|
||||
'link': '',
|
||||
'icon': 'hours',
|
||||
'label': 'Mon - Fri: 8AM - 5PM',
|
||||
}
|
||||
],
|
||||
};
|
||||
this.defaultValue = this.props.control.params.default ? {
|
||||
...baseDefault,
|
||||
...this.props.control.params.default
|
||||
} : baseDefault;
|
||||
value = value ? {
|
||||
...this.defaultValue,
|
||||
...value
|
||||
} : this.defaultValue;
|
||||
let defaultParams = {
|
||||
'group' : 'contact_item_group',
|
||||
'options': [
|
||||
{ value: 'phone', label: __( 'Phone', 'kadence' ), content: __( '444-546-8765', 'kadence' ) },
|
||||
{ value: 'hours', label: __( 'Hours', 'kadence' ), content: __( 'Mon - Fri: 8AM - 5PM', 'kadence' ) },
|
||||
{ value: 'email', label: __( 'Email', 'kadence' ), content: __( 'example@example.com', 'kadence' ) },
|
||||
{ value: 'location', label: __( 'Address', 'kadence' ), content: __( '4560 example street', 'kadence' ) },
|
||||
],
|
||||
};
|
||||
this.controlParams = this.props.control.params.input_attrs ? {
|
||||
...defaultParams,
|
||||
...this.props.control.params.input_attrs,
|
||||
} : defaultParams;
|
||||
let availibleContactOptions = [];
|
||||
this.controlParams.options.map( ( option ) => {
|
||||
if ( ! value.items.some( obj => obj.id === option.value ) ) {
|
||||
availibleContactOptions.push( option );
|
||||
}
|
||||
} );
|
||||
this.state = {
|
||||
value: value,
|
||||
isVisible: false,
|
||||
control: ( undefined !== availibleContactOptions[0] && undefined !== availibleContactOptions[0].value ? availibleContactOptions[0].value : '' ),
|
||||
};
|
||||
}
|
||||
onDragStart() {
|
||||
var dropzones = document.querySelectorAll( '.kadence-builder-area' );
|
||||
var i;
|
||||
for (i = 0; i < dropzones.length; ++i) {
|
||||
dropzones[i].classList.add( 'kadence-dragging-dropzones' );
|
||||
}
|
||||
}
|
||||
onDragStop() {
|
||||
var dropzones = document.querySelectorAll( '.kadence-builder-area' );
|
||||
var i;
|
||||
for (i = 0; i < dropzones.length; ++i) {
|
||||
dropzones[i].classList.remove( 'kadence-dragging-dropzones' );
|
||||
}
|
||||
}
|
||||
saveArrayUpdate( value, index ) {
|
||||
let updateState = this.state.value;
|
||||
let items = updateState.items;
|
||||
|
||||
const newItems = items.map( ( item, thisIndex ) => {
|
||||
if ( index === thisIndex ) {
|
||||
item = { ...item, ...value };
|
||||
}
|
||||
|
||||
return item;
|
||||
} );
|
||||
updateState.items = newItems;
|
||||
this.setState( { value: updateState } );
|
||||
this.updateValues( updateState );
|
||||
}
|
||||
toggleEnableItem( value, itemIndex ) {
|
||||
this.saveArrayUpdate( { enabled: value }, itemIndex );
|
||||
}
|
||||
onChangeLabel( value, itemIndex ) {
|
||||
this.saveArrayUpdate( { label: value }, itemIndex );
|
||||
}
|
||||
onChangeLink( value, itemIndex ) {
|
||||
this.saveArrayUpdate( { link: value }, itemIndex );
|
||||
}
|
||||
onChangeIcon( value, itemIndex ) {
|
||||
this.saveArrayUpdate( { icon: value }, itemIndex );
|
||||
}
|
||||
onChangeURL( value, itemIndex ) {
|
||||
this.saveArrayUpdate( { url: value }, itemIndex );
|
||||
}
|
||||
onChangeAttachment( value, itemIndex ) {
|
||||
this.saveArrayUpdate( { imageid: value }, itemIndex );
|
||||
}
|
||||
onChangeWidth( value, itemIndex ) {
|
||||
this.saveArrayUpdate( { width: value }, itemIndex );
|
||||
}
|
||||
onChangeSource( value, itemIndex ) {
|
||||
this.saveArrayUpdate( { source: value }, itemIndex );
|
||||
}
|
||||
removeItem( itemIndex ) {
|
||||
let updateState = this.state.value;
|
||||
let update = updateState.items;
|
||||
let updateItems = [];
|
||||
{ update.length > 0 && (
|
||||
update.map( ( old, index ) => {
|
||||
if ( itemIndex !== index ) {
|
||||
updateItems.push( old );
|
||||
}
|
||||
} )
|
||||
) };
|
||||
updateState.items = updateItems;
|
||||
this.setState( { value: updateState } );
|
||||
this.updateValues( updateState );
|
||||
}
|
||||
addItem() {
|
||||
const itemControl = this.state.control;
|
||||
this.setState( { isVisible: false } );
|
||||
if ( itemControl ) {
|
||||
let updateState = this.state.value;
|
||||
let update = updateState.items;
|
||||
const itemLabel = this.controlParams.options.filter(function(o){return o.value === itemControl;} );
|
||||
let newItem = {
|
||||
'id': itemControl,
|
||||
'enabled': true,
|
||||
'source': 'icon',
|
||||
'url': '',
|
||||
'imageid': '',
|
||||
'width': 24,
|
||||
'link': '',
|
||||
'icon': itemControl,
|
||||
'label': itemLabel[0].content,
|
||||
};
|
||||
update.push( newItem );
|
||||
updateState.items = update;
|
||||
let availibleContactOptions = [];
|
||||
this.controlParams.options.map( ( option ) => {
|
||||
if ( ! update.some( obj => obj.id === option.value ) ) {
|
||||
availibleContactOptions.push( option );
|
||||
}
|
||||
} );
|
||||
this.setState( { control: ( undefined !== availibleContactOptions[0] && undefined !== availibleContactOptions[0].value ? availibleContactOptions[0].value : '' ) } );
|
||||
this.setState( { value: updateState } );
|
||||
this.updateValues( updateState );
|
||||
}
|
||||
}
|
||||
onDragEnd( items ) {
|
||||
let updateState = this.state.value;
|
||||
let update = updateState.items;
|
||||
let updateItems = [];
|
||||
{ items.length > 0 && (
|
||||
items.map( ( item ) => {
|
||||
update.filter( obj => {
|
||||
if ( obj.id === item.id ) {
|
||||
updateItems.push( obj );
|
||||
}
|
||||
} )
|
||||
} )
|
||||
) };
|
||||
if ( ! this.arraysEqual( update, updateItems ) ) {
|
||||
update.items = updateItems;
|
||||
updateState.items = updateItems;
|
||||
this.setState( { value: updateState } );
|
||||
this.updateValues( updateState );
|
||||
}
|
||||
}
|
||||
arraysEqual( a, b ) {
|
||||
if (a === b) return true;
|
||||
if (a == null || b == null) return false;
|
||||
if (a.length != b.length) return false;
|
||||
for (var i = 0; i < a.length; ++i) {
|
||||
if (a[i] !== b[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
render() {
|
||||
const currentList = ( typeof this.state.value != "undefined" && this.state.value.items != null && this.state.value.items.length != null && this.state.value.items.length > 0 ? this.state.value.items : [] );
|
||||
let theItems = [];
|
||||
{ currentList.length > 0 && (
|
||||
currentList.map( ( item ) => {
|
||||
theItems.push(
|
||||
{
|
||||
id: item.id,
|
||||
}
|
||||
)
|
||||
} )
|
||||
) };
|
||||
const availibleContactOptions = [];
|
||||
this.controlParams.options.map( ( option ) => {
|
||||
if ( ! theItems.some( obj => obj.id === option.value ) ) {
|
||||
availibleContactOptions.push( option );
|
||||
}
|
||||
} )
|
||||
const toggleClose = () => {
|
||||
if ( this.state.isVisible === true ) {
|
||||
this.setState( { isVisible: false } );
|
||||
}
|
||||
};
|
||||
return (
|
||||
<div className="kadence-control-field kadence-sorter-items">
|
||||
<div className="kadence-sorter-row">
|
||||
<ReactSortable animation={100} onStart={ () => this.onDragStop() } onEnd={ () => this.onDragStop() } group={ this.controlParams.group } className={ `kadence-sorter-drop kadence-sorter-sortable-panel kadence-sorter-drop-${ this.controlParams.group } kadence-sorter-drop-social_item_group` } handle={ '.kadence-sorter-item-panel-header' } list={ theItems } setList={ ( newState ) => this.onDragEnd( newState ) } >
|
||||
{ currentList.length > 0 && (
|
||||
currentList.map( ( item, index ) => {
|
||||
return <ItemComponent removeItem={ ( remove ) => this.removeItem( remove ) } toggleEnabled={ ( enable, itemIndex ) => this.toggleEnableItem( enable, itemIndex ) } onChangeLabel={ ( label, itemIndex ) => this.onChangeLabel( label, itemIndex ) } onChangeLink={ ( link, itemIndex ) => this.onChangeLink( link, itemIndex ) } onChangeSource={ ( source, itemIndex ) => this.onChangeSource( source, itemIndex ) } onChangeWidth={ ( width, itemIndex ) => this.onChangeWidth( width, itemIndex ) } onChangeURL={ ( url, itemIndex ) => this.onChangeURL( url, itemIndex ) } onChangeAttachment={ ( imageid, itemIndex ) => this.onChangeAttachment( imageid, itemIndex ) } onChangeIcon={ ( icon, itemIndex ) => this.onChangeIcon( icon, itemIndex ) } key={ item.id } index={ index } item={ item } controlParams={ this.controlParams } />;
|
||||
} )
|
||||
) }
|
||||
</ReactSortable>
|
||||
</div>
|
||||
{ undefined !== availibleContactOptions[0] && undefined !== availibleContactOptions[0].value && (
|
||||
<div className="kadence-contact-add-area kadence-social-add-area">
|
||||
{ this.state.isVisible && (
|
||||
<Popover position="top right" className="kadence-popover-color kadence-popover-contact kadence-customizer-popover" onClose={ toggleClose }>
|
||||
<div className="kadence-popover-contact-list kadence-popover-social-list">
|
||||
<ButtonGroup className="kadence-radio-container-control">
|
||||
{ availibleContactOptions.map( ( item, index ) => {
|
||||
return (
|
||||
<Fragment>
|
||||
<Button
|
||||
isTertiary
|
||||
className={ 'contact-radio-btn' }
|
||||
onClick={ () => {
|
||||
this.setState( { control: availibleContactOptions[index].value } );
|
||||
this.state.control = availibleContactOptions[index].value;
|
||||
this.addItem();
|
||||
} }
|
||||
>
|
||||
{ availibleContactOptions[index].label && (
|
||||
availibleContactOptions[index].label
|
||||
) }
|
||||
</Button>
|
||||
</Fragment>
|
||||
);
|
||||
} ) }
|
||||
</ButtonGroup>
|
||||
</div>
|
||||
</Popover>
|
||||
) }
|
||||
<Button
|
||||
className="kadence-sorter-add-item"
|
||||
isPrimary
|
||||
onClick={ () => {
|
||||
this.setState( { isVisible: true } );
|
||||
} }
|
||||
>
|
||||
{ __( 'Add Contact', 'kadence' ) }
|
||||
<Dashicon icon="plus"/>
|
||||
</Button>
|
||||
</div>
|
||||
) }
|
||||
{ this.props.control.renderNotice() }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
updateValues( value ) {
|
||||
this.props.control.setting.set( {
|
||||
...this.props.control.setting.get(),
|
||||
...value,
|
||||
flag: !this.props.control.setting.get().flag
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
ContactComponent.propTypes = {
|
||||
control: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default ContactComponent;
|
||||
@@ -0,0 +1,11 @@
|
||||
import { createRoot } from '@wordpress/element';
|
||||
import ContactComponent from './contact-component.js';
|
||||
|
||||
export const ContactControl = wp.customize.KadenceControl.extend( {
|
||||
renderContent: function renderContent() {
|
||||
let control = this;
|
||||
let root = createRoot( control.container[0] );
|
||||
root.render( <ContactComponent control={ control } /> );
|
||||
// ReactDOM.render( <ContactComponent control={ control } />, control.container[0] );
|
||||
}
|
||||
} );
|
||||
@@ -0,0 +1,99 @@
|
||||
const ContactIcons = {
|
||||
email: <svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
>
|
||||
<path d="M15 2H1c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h14c.55 0 1-.45 1-1V3c0-.55-.45-1-1-1zM5.831 9.773l-3 2.182a.559.559 0 01-.785-.124.563.563 0 01.124-.786l3-2.182a.563.563 0 01.662.91zm8.124 2.058a.563.563 0 01-.785.124l-3-2.182a.563.563 0 01.662-.91l3 2.182a.563.563 0 01.124.786zm-.124-6.876l-5.5 4a.562.562 0 01-.662 0l-5.5-4a.563.563 0 01.662-.91L8 7.804l5.169-3.759a.563.563 0 01.662.91z"></path>
|
||||
</svg>,
|
||||
emailAlt: <svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="28"
|
||||
height="28"
|
||||
viewBox="0 0 28 28"
|
||||
>
|
||||
<path d="M28 11.094V23.5c0 1.375-1.125 2.5-2.5 2.5h-23A2.507 2.507 0 010 23.5V11.094c.469.516 1 .969 1.578 1.359 2.594 1.766 5.219 3.531 7.766 5.391 1.313.969 2.938 2.156 4.641 2.156h.031c1.703 0 3.328-1.188 4.641-2.156 2.547-1.844 5.172-3.625 7.781-5.391a9.278 9.278 0 001.563-1.359zM28 6.5c0 1.75-1.297 3.328-2.672 4.281-2.438 1.687-4.891 3.375-7.313 5.078-1.016.703-2.734 2.141-4 2.141h-.031c-1.266 0-2.984-1.437-4-2.141-2.422-1.703-4.875-3.391-7.297-5.078-1.109-.75-2.688-2.516-2.688-3.938 0-1.531.828-2.844 2.5-2.844h23c1.359 0 2.5 1.125 2.5 2.5z"></path>
|
||||
</svg>,
|
||||
emailAlt2: <svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M3 7.921l8.427 5.899c.34.235.795.246 1.147 0L21 7.921V18c0 .272-.11.521-.295.705S20.272 19 20 19H4c-.272 0-.521-.11-.705-.295S3 18.272 3 18zM1 5.983V18c0 .828.34 1.579.88 2.12S3.172 21 4 21h16c.828 0 1.579-.34 2.12-.88S23 18.828 23 18V6.012v-.03a2.995 2.995 0 00-.88-2.102A2.998 2.998 0 0020 3H4c-.828 0-1.579.34-2.12.88A2.995 2.995 0 001 5.983zm19.894-.429L12 11.779 3.106 5.554a.999.999 0 01.188-.259A.994.994 0 014 5h16a1.016 1.016 0 01.893.554z"></path>
|
||||
</svg>,
|
||||
phone:<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="12"
|
||||
height="28"
|
||||
viewBox="0 0 12 28"
|
||||
>
|
||||
<path d="M7.25 22c0-.688-.562-1.25-1.25-1.25s-1.25.562-1.25 1.25.562 1.25 1.25 1.25 1.25-.562 1.25-1.25zm3.25-2.5v-11c0-.266-.234-.5-.5-.5H2c-.266 0-.5.234-.5.5v11c0 .266.234.5.5.5h8c.266 0 .5-.234.5-.5zm-3-13.25A.246.246 0 007.25 6h-2.5c-.141 0-.25.109-.25.25s.109.25.25.25h2.5c.141 0 .25-.109.25-.25zM12 6v16c0 1.094-.906 2-2 2H2c-1.094 0-2-.906-2-2V6c0-1.094.906-2 2-2h8c1.094 0 2 .906 2 2z"></path>
|
||||
</svg>,
|
||||
phoneAlt:<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M7 1a2.997 2.997 0 00-3 3v16a2.997 2.997 0 003 3h10a2.997 2.997 0 003-3V4a2.997 2.997 0 00-3-3zm0 2h10c.276 0 .525.111.707.293S18 3.724 18 4v16c0 .276-.111.525-.293.707S17.276 21 17 21H7c-.276 0-.525-.111-.707-.293S6 20.276 6 20V4c0-.276.111-.525.293-.707S6.724 3 7 3zm5 16a1 1 0 100-2 1 1 0 000 2z"></path>
|
||||
</svg>,
|
||||
phoneAlt2: <svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="28"
|
||||
viewBox="0 0 24 28"
|
||||
>
|
||||
<path d="M20 18.641c0-.078 0-.172-.031-.25-.094-.281-2.375-1.437-2.812-1.687-.297-.172-.656-.516-1.016-.516-.688 0-1.703 2.047-2.312 2.047-.313 0-.703-.281-.984-.438-2.063-1.156-3.484-2.578-4.641-4.641-.156-.281-.438-.672-.438-.984 0-.609 2.047-1.625 2.047-2.312 0-.359-.344-.719-.516-1.016-.25-.438-1.406-2.719-1.687-2.812-.078-.031-.172-.031-.25-.031-.406 0-1.203.187-1.578.344-1.031.469-1.781 2.438-1.781 3.516 0 1.047.422 2 .781 2.969 1.25 3.422 4.969 7.141 8.391 8.391.969.359 1.922.781 2.969.781 1.078 0 3.047-.75 3.516-1.781.156-.375.344-1.172.344-1.578zM24 6.5v15c0 2.484-2.016 4.5-4.5 4.5h-15A4.502 4.502 0 010 21.5v-15C0 4.016 2.016 2 4.5 2h15C21.984 2 24 4.016 24 6.5z"></path>
|
||||
</svg>,
|
||||
hours: <svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="28"
|
||||
viewBox="0 0 24 28"
|
||||
>
|
||||
<path d="M14 8.5v7c0 .281-.219.5-.5.5h-5a.494.494 0 01-.5-.5v-1c0-.281.219-.5.5-.5H12V8.5c0-.281.219-.5.5-.5h1c.281 0 .5.219.5.5zm6.5 5.5c0-4.688-3.813-8.5-8.5-8.5S3.5 9.313 3.5 14s3.813 8.5 8.5 8.5 8.5-3.813 8.5-8.5zm3.5 0c0 6.625-5.375 12-12 12S0 20.625 0 14 5.375 2 12 2s12 5.375 12 12z"></path>
|
||||
</svg>,
|
||||
hoursAlt: <svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M23 12c0-3.037-1.232-5.789-3.222-7.778S15.037 1 12 1 6.211 2.232 4.222 4.222 1 8.963 1 12s1.232 5.789 3.222 7.778S8.963 23 12 23s5.789-1.232 7.778-3.222S23 15.037 23 12zm-2 0c0 2.486-1.006 4.734-2.636 6.364S14.486 21 12 21s-4.734-1.006-6.364-2.636S3 14.486 3 12s1.006-4.734 2.636-6.364S9.514 3 12 3s4.734 1.006 6.364 2.636S21 9.514 21 12zM11 6v6a1 1 0 00.553.894l4 2a1 1 0 00.895-1.789L13 11.382V6a1 1 0 00-2 0z"></path>
|
||||
</svg>,
|
||||
hoursAlt2: <svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
>
|
||||
<path d="M8 0a8 8 0 100 16A8 8 0 008 0zm2.293 11.707L7 8.414V4h2v3.586l2.707 2.707-1.414 1.414z"></path>
|
||||
</svg>,
|
||||
location: <svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="28"
|
||||
viewBox="0 0 16 28"
|
||||
>
|
||||
<path d="M12 10c0-2.203-1.797-4-4-4s-4 1.797-4 4 1.797 4 4 4 4-1.797 4-4zm4 0c0 .953-.109 1.937-.516 2.797L9.796 24.891C9.468 25.579 8.749 26 7.999 26s-1.469-.422-1.781-1.109L.515 12.797C.109 11.938-.001 10.953-.001 10c0-4.422 3.578-8 8-8s8 3.578 8 8z"></path>
|
||||
</svg>,
|
||||
locationAlt: <svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M22 10c0-2.761-1.12-5.263-2.929-7.071S14.761 0 12 0 6.737 1.12 4.929 2.929 2 7.239 2 10c0 .569.053 1.128.15 1.676.274 1.548.899 3.004 1.682 4.32 2.732 4.591 7.613 7.836 7.613 7.836.331.217.765.229 1.109 0 0 0 4.882-3.245 7.613-7.836.783-1.316 1.408-2.772 1.682-4.32A9.506 9.506 0 0022 10zm-2 0c0 .444-.041.887-.119 1.328-.221 1.25-.737 2.478-1.432 3.646-1.912 3.214-5.036 5.747-6.369 6.74-1.398-.916-4.588-3.477-6.53-6.74-.695-1.168-1.211-2.396-1.432-3.646A7.713 7.713 0 014 10c0-2.209.894-4.208 2.343-5.657S9.791 2 12 2s4.208.894 5.657 2.343S20 7.791 20 10zm-4 0c0-1.104-.449-2.106-1.172-2.828a3.994 3.994 0 00-5.656 0 3.994 3.994 0 000 5.656 3.994 3.994 0 005.656 0A3.994 3.994 0 0016 10zm-2 0c0 .553-.223 1.051-.586 1.414S12.553 12 12 12s-1.051-.223-1.414-.586S10 10.553 10 10s.223-1.051.586-1.414S11.447 8 12 8s1.051.223 1.414.586S14 9.447 14 10z"></path>
|
||||
</svg>,
|
||||
locationAlt2: <svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
>
|
||||
<path d="M8 0a5 5 0 00-5 5c0 5 5 9 5 9s5-4 5-9a5 5 0 00-5-5zm0 8a3 3 0 110-6 3 3 0 010 6zm4.285 2.9a16.57 16.57 0 01-.682.988l.108.052c.76.38 1.101.806 1.101 1.059s-.34.679-1.101 1.059c-.957.479-2.31.753-3.712.753s-2.754-.275-3.712-.753c-.76-.38-1.101-.806-1.101-1.059s.34-.679 1.101-1.059l.108-.052c-.231-.31-.461-.64-.682-.988-1.061.541-1.715 1.282-1.715 2.1 0 1.657 2.686 3 6 3s6-1.343 6-3c0-.817-.654-1.558-1.715-2.1z"></path>
|
||||
</svg>,
|
||||
};
|
||||
export default ContactIcons;
|
||||
@@ -0,0 +1,203 @@
|
||||
/* jshint esversion: 6 */
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
import ContactIcons from './icons.js';
|
||||
import FontIconPicker from '@fonticonpicker/react-fonticonpicker';
|
||||
|
||||
import { __ } from '@wordpress/i18n';
|
||||
const { MediaUpload } = wp.blockEditor;
|
||||
const { ButtonGroup, Dashicon, Tooltip, TextControl, Button, TabPanel, RangeControl, Placeholder } = wp.components;
|
||||
|
||||
const { Component, Fragment } = wp.element;
|
||||
class ItemComponent extends Component {
|
||||
constructor() {
|
||||
super( ...arguments );
|
||||
this.state = {
|
||||
open: false,
|
||||
};
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div className="kadence-sorter-item" data-id={ this.props.item.id } key={ this.props.item.id }>
|
||||
<div className="kadence-sorter-item-panel-header">
|
||||
<Tooltip text={ __( 'Toggle Item Visibility', 'kadence' ) }>
|
||||
<Button
|
||||
className={ `kadence-sorter-visiblity ${ ( this.props.item.enabled ? 'item-is-visible' : 'item-is-hidden' ) }`}
|
||||
onClick={ () => {
|
||||
this.props.toggleEnabled( ( this.props.item.enabled ? false : true ), this.props.index );
|
||||
} }
|
||||
>
|
||||
{ ContactIcons[this.props.item.id] }
|
||||
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<span className="kadence-sorter-title">
|
||||
{ ( undefined !== this.props.item.label && '' !== this.props.item.label ? this.props.item.label : __( 'Contact Item', 'kadence' ) ) }
|
||||
</span>
|
||||
<Tooltip text={ __( 'Expand Item Controls', 'kadence' ) }>
|
||||
<Button
|
||||
className="kadence-sorter-item-expand"
|
||||
onClick={ () => {
|
||||
this.setState( { open: ( this.state.open ? false : true ) } )
|
||||
} }
|
||||
>
|
||||
<Dashicon icon={ ( this.state.open ? 'arrow-up-alt2' : 'arrow-down-alt2' ) }/>
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
{ this.state.open && (
|
||||
<div className="kadence-sorter-item-panel-content">
|
||||
<TabPanel className="sortable-style-tabs kadence-contact-type"
|
||||
activeClass="active-tab"
|
||||
initialTabName={ ( undefined !== this.props.item.source ? this.props.item.source : 'icon' ) }
|
||||
onSelect={ ( value ) => this.props.onChangeSource( value, this.props.index ) }
|
||||
tabs={ [
|
||||
{
|
||||
name: 'icon',
|
||||
title: __( 'Icon', 'kadence' ),
|
||||
},
|
||||
{
|
||||
name: 'image',
|
||||
title: __( 'Image', 'kadence' ),
|
||||
},
|
||||
] }>
|
||||
{
|
||||
( tab ) => {
|
||||
let tabout;
|
||||
if ( tab.name ) {
|
||||
if ( 'image' === tab.name ) {
|
||||
tabout = (
|
||||
<Fragment>
|
||||
{ ! this.props.item.url && (
|
||||
<div className="attachment-media-view">
|
||||
<MediaUpload
|
||||
onSelect={ ( imageData ) => {
|
||||
this.props.onChangeURL( imageData.url, this.props.index );
|
||||
this.props.onChangeAttachment( imageData.id, this.props.index );
|
||||
} }
|
||||
allowedTypes={ ['image'] }
|
||||
render={ ( { open } ) => (
|
||||
<Button className="button-add-media" isSecondary onClick={ open }>
|
||||
{ __( 'Add Image', 'kadence' )}
|
||||
</Button>
|
||||
) }
|
||||
/>
|
||||
</div>
|
||||
) }
|
||||
{ this.props.item.url && (
|
||||
<div className="contact-custom-image">
|
||||
<div className="kadence-Contact-image">
|
||||
<img className="kadence-Contact-image-preview" src={ this.props.item.url } />
|
||||
</div>
|
||||
<Button
|
||||
className='remove-image'
|
||||
isDestructive
|
||||
onClick={ () => {
|
||||
this.props.onChangeURL( '', this.props.index );
|
||||
this.props.onChangeAttachment( '', this.props.index );
|
||||
} }
|
||||
>
|
||||
{ __( 'Remove Image', 'kadence' ) }
|
||||
<Dashicon icon='no'/>
|
||||
</Button>
|
||||
</div>
|
||||
) }
|
||||
<RangeControl
|
||||
label={ __( 'Max Width (px)', 'kadence' ) }
|
||||
value={ ( undefined !== this.props.item.width ? this.props.item.width : 24 ) }
|
||||
onChange={ ( value ) => {
|
||||
this.props.onChangeWidth( value, this.props.index );
|
||||
} }
|
||||
step={ 1 }
|
||||
min={ 2 }
|
||||
max={ 100 }
|
||||
/>
|
||||
</Fragment>
|
||||
);
|
||||
} else {
|
||||
tabout = (
|
||||
<Fragment>
|
||||
<ButtonGroup className="kadence-radio-container-control">
|
||||
<Button
|
||||
isTertiary
|
||||
className={ ( this.props.item.id === ( undefined !== this.props.item.icon ? this.props.item.icon : this.props.item.id ) ?
|
||||
'active-radio ' :
|
||||
'' ) + 'svg-icon-' + this.props.item.id }
|
||||
onClick={ () => {
|
||||
this.props.onChangeIcon( this.props.item.id, this.props.index );
|
||||
} }
|
||||
>
|
||||
<span className="kadence-radio-icon">
|
||||
{ ContactIcons[this.props.item.id] }
|
||||
</span>
|
||||
</Button>
|
||||
{ ContactIcons[ this.props.item.id + 'Alt' ] && (
|
||||
<Button
|
||||
isTertiary
|
||||
className={ ( this.props.item.id + 'Alt' === ( undefined !== this.props.item.icon ? this.props.item.icon : this.props.item.id ) ?
|
||||
'active-radio ' :
|
||||
'' ) + 'svg-icon-' + this.props.item.id + 'Alt' }
|
||||
onClick={ () => {
|
||||
this.props.onChangeIcon( this.props.item.id + 'Alt', this.props.index );
|
||||
} }
|
||||
>
|
||||
<span className="kadence-radio-icon">
|
||||
{ ContactIcons[ this.props.item.id + 'Alt' ] }
|
||||
</span>
|
||||
</Button>
|
||||
) }
|
||||
{ ContactIcons[ this.props.item.id + 'Alt2' ] && (
|
||||
<Button
|
||||
isTertiary
|
||||
className={ ( this.props.item.id + 'Alt2' === ( undefined !== this.props.item.icon ? this.props.item.icon : this.props.item.id ) ?
|
||||
'active-radio ' :
|
||||
'' ) + 'svg-icon-' + this.props.item.id + 'Alt2' }
|
||||
onClick={ () => {
|
||||
this.props.onChangeIcon( this.props.item.id + 'Alt2', this.props.index );
|
||||
} }
|
||||
>
|
||||
<span className="kadence-radio-icon">
|
||||
{ ContactIcons[ this.props.item.id + 'Alt2' ] }
|
||||
</span>
|
||||
</Button>
|
||||
)}
|
||||
</ButtonGroup>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
return <div>{ tabout }</div>;
|
||||
}
|
||||
}
|
||||
</TabPanel>
|
||||
<TextControl
|
||||
label={ __( 'Item Label', 'kadence' ) }
|
||||
value={ this.props.item.label ? this.props.item.label : '' }
|
||||
onChange={ ( value ) => {
|
||||
this.props.onChangeLabel( value, this.props.index );
|
||||
} }
|
||||
/>
|
||||
<TextControl
|
||||
label={ __( 'Item Link', 'kadence' ) }
|
||||
value={ this.props.item.link ? this.props.item.link : '' }
|
||||
onChange={ ( value ) => {
|
||||
this.props.onChangeLink( value, this.props.index );
|
||||
} }
|
||||
/>
|
||||
<Button
|
||||
className="kadence-sorter-item-remove"
|
||||
isDestructive
|
||||
onClick={ () => {
|
||||
this.props.removeItem( this.props.index );
|
||||
} }
|
||||
>
|
||||
{ __( 'Remove Item', 'kadence' ) }
|
||||
<Dashicon icon="no-alt"/>
|
||||
</Button>
|
||||
</div>
|
||||
) }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
export default ItemComponent;
|
||||
2196
wp-content/themes/kadence/inc/customizer/react/src/controls.scss
Normal file
2196
wp-content/themes/kadence/inc/customizer/react/src/controls.scss
Normal file
File diff suppressed because it is too large
Load Diff
433
wp-content/themes/kadence/inc/customizer/react/src/customizer.js
Normal file
433
wp-content/themes/kadence/inc/customizer/react/src/customizer.js
Normal file
@@ -0,0 +1,433 @@
|
||||
( function( $, api ) {
|
||||
var $window = $( window ),
|
||||
$document = $( document ),
|
||||
$body = $( 'body' );
|
||||
/**
|
||||
* API on ready event handlers
|
||||
*
|
||||
* All handlers need to be inside the 'ready' state.
|
||||
*/
|
||||
wp.customize.bind( 'ready', function() {
|
||||
$( 'input[name=kadence-flush-local-fonts-button]' ).on( 'click', function( e ) {
|
||||
var data = {
|
||||
wp_customize: 'on',
|
||||
action: 'kadence_flush_fonts_folder',
|
||||
nonce: kadenceCustomizerControlsData.flushFonts
|
||||
};
|
||||
$( 'input[name=kadence-flush-local-fonts-button]' ).attr('disabled', 'disabled');
|
||||
|
||||
$.post( ajaxurl, data, function ( response ) {
|
||||
if ( response && response.success ) {
|
||||
$( 'input[name=kadence-flush-local-fonts-button]' ).val( 'Successfully Flushed' );
|
||||
} else {
|
||||
$( 'input[name=kadence-flush-local-fonts-button]' ).val( 'Failed, Reload Page and Try Again' );
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
wp.customize.state.create( 'kadenceTab' );
|
||||
wp.customize.state( 'kadenceTab' ).set( 'general' );
|
||||
wp.customize.sectionConstructor['kadence_section_pro'] = wp.customize.Section.extend( {
|
||||
|
||||
// No events for this type of section.
|
||||
attachEvents: () => {},
|
||||
|
||||
// Always make the section active.
|
||||
isContextuallyActive: () => {
|
||||
return true;
|
||||
}
|
||||
} );
|
||||
|
||||
|
||||
// Set handler when custom responsive toggle is clicked.
|
||||
$( '#customize-theme-controls' ).on( 'click', '.kadence-build-tabs-button:not(.kadence-nav-tabs-button)', function( e ) {
|
||||
e.preventDefault();
|
||||
|
||||
wp.customize.previewedDevice.set( $( this ).attr( 'data-device' ) );
|
||||
});
|
||||
// Set handler when custom responsive toggle is clicked.
|
||||
$( '#customize-theme-controls' ).on( 'click', '.kadence-compontent-tabs-button:not(.kadence-nav-tabs-button)', function( e ) {
|
||||
e.preventDefault();
|
||||
|
||||
wp.customize.state( 'kadenceTab' ).set( $( this ).attr( 'data-tab' ) );
|
||||
});
|
||||
var setCustomTabElementsDisplay = function() {
|
||||
var tabState = wp.customize.state( 'kadenceTab' ).get(),
|
||||
$tabs = $( '.kadence-compontent-tabs-button:not(.kadence-nav-tabs-button)' );
|
||||
$tabs.removeClass( 'nav-tab-active' ).filter( '.kadence-' + tabState + '-tab' ).addClass( 'nav-tab-active' );
|
||||
}
|
||||
// Refresh all responsive elements when previewedDevice is changed.
|
||||
wp.customize.state( 'kadenceTab' ).bind( setCustomTabElementsDisplay );
|
||||
|
||||
$( '#customize-theme-controls' ).on( 'click', 'customize-section-back', function( e ) {
|
||||
wp.customize.state( 'kadenceTab' ).set( 'general' );
|
||||
});
|
||||
if ( kadenceCustomizerControlsData && kadenceCustomizerControlsData.contexts ) {
|
||||
/**
|
||||
* Active callback script (JS version)
|
||||
* ref: https://make.xwp.co/2016/07/24/dependently-contextual-customizer-controls/
|
||||
*/
|
||||
_.each( kadenceCustomizerControlsData.contexts, function( rules, key ) {
|
||||
var getSetting = function( settingName ) {
|
||||
// Get the dependent setting.
|
||||
switch ( settingName ) {
|
||||
case '__device':
|
||||
return wp.customize.previewedDevice;
|
||||
break;
|
||||
case '__current_tab':
|
||||
return wp.customize.state( 'kadenceTab' );
|
||||
break;
|
||||
default:
|
||||
// Check if we have an extra source in the mix
|
||||
if ( kadenceCustomizerControlsData.source ) {
|
||||
// Check if this setting might be powered by the extra source.
|
||||
if ( wp.customize( kadenceCustomizerControlsData.source + '[' + settingName + ']' ) ) {
|
||||
return wp.customize( kadenceCustomizerControlsData.source + '[' + settingName + ']' );
|
||||
} else {
|
||||
return wp.customize( settingName );
|
||||
}
|
||||
}
|
||||
return wp.customize( settingName );
|
||||
break;
|
||||
}
|
||||
}
|
||||
var initContext = function( element ) {
|
||||
// Main function returning the conditional value
|
||||
var isDisplayed = function() {
|
||||
var displayed = false,
|
||||
relation = rules['relation'];
|
||||
|
||||
// Fallback invalid relation type to "AND".
|
||||
// Assign default displayed to true for "AND" relation type.
|
||||
if ( 'OR' !== relation ) {
|
||||
relation = 'AND';
|
||||
displayed = true;
|
||||
}
|
||||
|
||||
// Each rule iteration
|
||||
_.each( rules, function( rule, i ) {
|
||||
// Skip "relation" property.
|
||||
if ( 'relation' == i ) return;
|
||||
|
||||
// If in "AND" relation and "displayed" already flagged as false, skip the rest rules.
|
||||
if ( 'AND' == relation && false == displayed ) return;
|
||||
|
||||
// Skip if no setting propery found.
|
||||
if ( undefined === rule['setting'] ) return;
|
||||
|
||||
var result = false,
|
||||
setting = getSetting( rule['setting'] );
|
||||
// Only process the rule if dependent setting is found.
|
||||
// Otherwise leave the result to "false".
|
||||
if ( undefined !== setting ) {
|
||||
var operator = rule['operator'],
|
||||
comparedValue = rule['value'],
|
||||
currentValue = setting.get();
|
||||
if ( undefined == operator || '=' == operator ) {
|
||||
operator = '==';
|
||||
}
|
||||
|
||||
if ( 'sub_object_contains' === operator ) {
|
||||
if ( undefined !== currentValue[ rule['sub_key'] ] ) {
|
||||
currentValue = currentValue[ rule['sub_key'] ];
|
||||
}
|
||||
}
|
||||
if ( 'sub_object_does_not_contain' === operator ) {
|
||||
if ( undefined !== currentValue[ rule['sub_key'] ] ) {
|
||||
currentValue = currentValue[ rule['sub_key'] ];
|
||||
}
|
||||
}
|
||||
switch ( operator ) {
|
||||
case '>':
|
||||
result = currentValue > comparedValue;
|
||||
break;
|
||||
|
||||
case '<':
|
||||
result = currentValue < comparedValue;
|
||||
break;
|
||||
|
||||
case '>=':
|
||||
result = currentValue >= comparedValue;
|
||||
break;
|
||||
|
||||
case '<=':
|
||||
result = currentValue <= comparedValue;
|
||||
break;
|
||||
|
||||
case 'in':
|
||||
result = 0 <= comparedValue.indexOf( currentValue );
|
||||
break;
|
||||
|
||||
case 'not_in':
|
||||
result = 0 > comparedValue.indexOf( currentValue );
|
||||
break;
|
||||
|
||||
case 'contain':
|
||||
//result = ( currentValue.includes( comparedValue ) );
|
||||
result = 0 <= currentValue.indexOf( comparedValue );
|
||||
break;
|
||||
|
||||
case 'not_contain':
|
||||
result = 0 > currentValue.indexOf( comparedValue );
|
||||
break;
|
||||
|
||||
case 'in':
|
||||
result = 0 <= comparedValue.indexOf( currentValue );
|
||||
break;
|
||||
|
||||
case 'array_includes':
|
||||
result = currentValue.includes( comparedValue );
|
||||
break;
|
||||
case 'sub_object_does_not_contain':
|
||||
if ( rule['responsive'] ) {
|
||||
result = true;
|
||||
{ Object.keys( { 'desktop':'', 'tablet':'', 'mobile':'' } ).map( ( device ) => {
|
||||
if ( currentValue[ device ].includes( comparedValue ) ) {
|
||||
result = false;
|
||||
}
|
||||
} ) }
|
||||
} else {
|
||||
result = ! currentValue.includes( comparedValue );
|
||||
}
|
||||
break;
|
||||
case 'sub_object_contains':
|
||||
if ( rule['responsive'] ) {
|
||||
{ Object.keys( { 'desktop':'', 'tablet':'', 'mobile':'' } ).map( ( device ) => {
|
||||
if ( currentValue[ device ].includes( comparedValue ) ) {
|
||||
result = true;
|
||||
}
|
||||
} ) }
|
||||
} else {
|
||||
result = currentValue.includes( comparedValue );
|
||||
}
|
||||
break;
|
||||
|
||||
case 'empty':
|
||||
result = (currentValue === undefined || currentValue == null || currentValue.length <= 0);
|
||||
//result = 0 == currentValue.length;
|
||||
break;
|
||||
|
||||
case '!empty':
|
||||
result = typeof currentValue !== 'undefined' && undefined !== currentValue && null !== currentValue && '' !== currentValue;
|
||||
//result = 0 < currentValue.length;
|
||||
break;
|
||||
case '!=':
|
||||
result = comparedValue !== currentValue;
|
||||
//result = 0 < currentValue.length;
|
||||
break;
|
||||
case 'load_italic':
|
||||
result = false;
|
||||
if ( currentValue['family'] && currentValue['google'] && currentValue['variant'] ) {
|
||||
if ( 0 > currentValue['variant'].indexOf( 'italic' ) ) {
|
||||
if ( kadenceCustomizerControlsData.gfontvars && kadenceCustomizerControlsData.gfontvars[ currentValue['family'] ] && kadenceCustomizerControlsData.gfontvars[ currentValue['family'] ].v && kadenceCustomizerControlsData.gfontvars[ currentValue['family'] ].v.includes( 'italic' ) ) {
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
result = comparedValue == currentValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Combine to the final result.
|
||||
switch ( relation ) {
|
||||
case 'OR':
|
||||
displayed = displayed || result;
|
||||
break;
|
||||
|
||||
default:
|
||||
displayed = displayed && result;
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
return displayed;
|
||||
};
|
||||
|
||||
// Wrapper function for binding purpose
|
||||
var setActiveState = function() {
|
||||
element.active.set( isDisplayed() );
|
||||
};
|
||||
|
||||
// Setting changes bind
|
||||
_.each( rules, function( rule, i ) {
|
||||
// Skip "relation" property.
|
||||
if ( 'relation' == i ) return;
|
||||
var setting = getSetting( rule['setting'] );
|
||||
|
||||
if ( undefined !== setting ) {
|
||||
// Bind the setting for future use.
|
||||
setting.bind( setActiveState );
|
||||
}
|
||||
});
|
||||
|
||||
// Initial run
|
||||
element.active.validate = isDisplayed;
|
||||
setActiveState();
|
||||
};
|
||||
|
||||
if ( 0 == key.indexOf( 'kadence_customizer' ) ) {
|
||||
wp.customize.section( key, initContext );
|
||||
} else {
|
||||
wp.customize.control( key, initContext );
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Set all custom responsive toggles and fieldsets.
|
||||
var setCustomResponsiveElementsDisplay = function() {
|
||||
var device = wp.customize.previewedDevice.get(),
|
||||
$tabs = $( '.kadence-build-tabs-button.nav-tab' );
|
||||
$tabs.removeClass( 'nav-tab-active' ).filter( '.preview-' + device ).addClass( 'nav-tab-active' );
|
||||
}
|
||||
// Refresh all responsive elements when previewedDevice is changed.
|
||||
wp.customize.previewedDevice.bind( setCustomResponsiveElementsDisplay );
|
||||
|
||||
// Refresh all responsive elements when any section is expanded.
|
||||
// This is required to set responsive elements on newly added controls inside the section.
|
||||
wp.customize.section.each(function ( section ) {
|
||||
section.expanded.bind( setCustomResponsiveElementsDisplay );
|
||||
});
|
||||
|
||||
/**
|
||||
* Resize Preview Frame when show / hide Builder.
|
||||
*/
|
||||
var resizePreviewer = function() {
|
||||
var $section = $( '.control-section.kadence-builder-active' );
|
||||
var $footer = $( '.control-section.kadence-footer-builder-active' );
|
||||
if ( $body.hasClass( 'kadence-builder-is-active' ) || $body.hasClass( 'kadence-footer-builder-is-active' ) ) {
|
||||
if ( $body.hasClass( 'kadence-footer-builder-is-active' ) && 0 < $footer.length && ! $footer.hasClass( 'kadence-builder-hide' ) ) {
|
||||
setTimeout(function() {
|
||||
wp.customize.previewer.container.css( 'bottom', $footer.outerHeight() + 'px' );
|
||||
}, 250);
|
||||
} else if ( $body.hasClass( 'kadence-builder-is-active' ) && 0 < $section.length && ! $section.hasClass( 'kadence-builder-hide' ) ) {
|
||||
setTimeout(function() {
|
||||
wp.customize.previewer.container.css({ "bottom" : $section.outerHeight() + 'px' });
|
||||
}, 250);
|
||||
} else {
|
||||
wp.customize.previewer.container.css( 'bottom', '');
|
||||
}
|
||||
} else {
|
||||
wp.customize.previewer.container.css( 'bottom', '');
|
||||
}
|
||||
}
|
||||
$window.on( 'resize', resizePreviewer );
|
||||
wp.customize.previewedDevice.bind(function( device ) {
|
||||
setTimeout(function() {
|
||||
resizePreviewer();
|
||||
}, 250 );
|
||||
});
|
||||
var reloadPreviewer = function() {
|
||||
$( wp.customize.previewer.container ).find( 'iframe' ).css( 'position', 'static' );
|
||||
$( wp.customize.previewer.container ).find( 'iframe' ).css( 'position', 'absolute' );
|
||||
}
|
||||
wp.customize.previewer.bind( 'ready', reloadPreviewer );
|
||||
/**
|
||||
* Init Header & Footer Builder
|
||||
*/
|
||||
var initHeaderBuilderPanel = function( panel ) {
|
||||
var section = wp.customize.section( 'kadence_customizer_header_builder' );
|
||||
if ( section ) {
|
||||
var $section = section.contentContainer,
|
||||
section_layout = wp.customize.section( 'kadence_customizer_header_layout' );
|
||||
// If Header panel is expanded, add class to the body tag (for CSS styling).
|
||||
panel.expanded.bind(function( isExpanded ) {
|
||||
_.each(section.controls(), function( control ) {
|
||||
if ( 'resolved' === control.deferred.embedded.state() ) {
|
||||
return;
|
||||
}
|
||||
control.renderContent();
|
||||
control.deferred.embedded.resolve(); // This triggers control.ready().
|
||||
|
||||
// Fire event after control is initialized.
|
||||
control.container.trigger( 'init' );
|
||||
});
|
||||
|
||||
if ( isExpanded ) {
|
||||
$body.addClass( 'kadence-builder-is-active' );
|
||||
$section.addClass( 'kadence-builder-active' );
|
||||
$section.css('display', 'none').height();
|
||||
$section.css('display', 'block');
|
||||
} else {
|
||||
$body.removeClass( 'kadence-builder-is-active' );
|
||||
$section.removeClass( 'kadence-builder-active' );
|
||||
}
|
||||
_.each(section_layout.controls(), function( control ) {
|
||||
if ( 'resolved' === control.deferred.embedded.state() ) {
|
||||
return;
|
||||
}
|
||||
control.renderContent();
|
||||
control.deferred.embedded.resolve(); // This triggers control.ready().
|
||||
|
||||
// Fire event after control is initialized.
|
||||
control.container.trigger( 'init' );
|
||||
});
|
||||
resizePreviewer();
|
||||
});
|
||||
// Attach callback to builder toggle.
|
||||
$section.on( 'click', '.kadence-builder-tab-toggle', function( e ) {
|
||||
e.preventDefault();
|
||||
$section.toggleClass( 'kadence-builder-hide' );
|
||||
resizePreviewer();
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
wp.customize.panel( 'kadence_customizer_header', initHeaderBuilderPanel );
|
||||
/**
|
||||
* Init Header & Footer Builder
|
||||
*/
|
||||
var initFooterBuilderPanel = function( panel ) {
|
||||
var section = wp.customize.section( 'kadence_customizer_footer_builder' );
|
||||
if ( section ) {
|
||||
var $section = section.contentContainer,
|
||||
section_layout = wp.customize.section( 'kadence_customizer_footer_layout' );
|
||||
// If Header panel is expanded, add class to the body tag (for CSS styling).
|
||||
panel.expanded.bind(function( isExpanded ) {
|
||||
_.each(section.controls(), function( control ) {
|
||||
if ( 'resolved' === control.deferred.embedded.state() ) {
|
||||
return;
|
||||
}
|
||||
control.renderContent();
|
||||
control.deferred.embedded.resolve(); // This triggers control.ready().
|
||||
|
||||
// Fire event after control is initialized.
|
||||
control.container.trigger( 'init' );
|
||||
});
|
||||
|
||||
if ( isExpanded ) {
|
||||
$body.addClass( 'kadence-footer-builder-is-active' );
|
||||
$section.addClass( 'kadence-footer-builder-active' );
|
||||
$section.css('display', 'none').height();
|
||||
$section.css('display', 'block');
|
||||
} else {
|
||||
$body.removeClass( 'kadence-footer-builder-is-active' );
|
||||
$section.removeClass( 'kadence-footer-builder-active' );
|
||||
}
|
||||
_.each(section_layout.controls(), function( control ) {
|
||||
if ( 'resolved' === control.deferred.embedded.state() ) {
|
||||
return;
|
||||
}
|
||||
control.renderContent();
|
||||
control.deferred.embedded.resolve(); // This triggers control.ready().
|
||||
|
||||
// Fire event after control is initialized.
|
||||
control.container.trigger( 'init' );
|
||||
});
|
||||
resizePreviewer();
|
||||
});
|
||||
// Attach callback to builder toggle.
|
||||
$section.on( 'click', '.kadence-builder-tab-toggle', function( e ) {
|
||||
e.preventDefault();
|
||||
$section.toggleClass( 'kadence-builder-hide' );
|
||||
resizePreviewer();
|
||||
} );
|
||||
}
|
||||
|
||||
};
|
||||
wp.customize.panel( 'kadence_customizer_footer', initFooterBuilderPanel );
|
||||
});
|
||||
|
||||
} )( jQuery, wp );
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createRoot } from '@wordpress/element';
|
||||
import EditorComponent from './editor-component.js';
|
||||
|
||||
export const EditorControl = wp.customize.KadenceControl.extend( {
|
||||
renderContent: function renderContent() {
|
||||
let control = this;
|
||||
let root = createRoot( control.container[0] );
|
||||
root.render( <EditorComponent control={control} customizer={ wp.customize } /> );
|
||||
// ReactDOM.render(
|
||||
// <EditorComponent control={control} customizer={ wp.customize } />,
|
||||
// control.container[0]
|
||||
// );
|
||||
}
|
||||
} );
|
||||
@@ -0,0 +1,95 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import debounce from 'lodash/debounce';
|
||||
|
||||
import { __ } from '@wordpress/i18n';
|
||||
const { Component } = wp.element;
|
||||
|
||||
class EditorComponent extends Component {
|
||||
constructor(props) {
|
||||
super( props );
|
||||
this.updateValues = this.updateValues.bind( this );
|
||||
this.triggerChangeIfDirty = this.triggerChangeIfDirty.bind( this );
|
||||
this.onInit = this.onInit.bind( this );
|
||||
let value = props.control.setting.get();
|
||||
this.state = {
|
||||
value,
|
||||
editor:{},
|
||||
restoreTextMode: false,
|
||||
};
|
||||
let defaultParams = {
|
||||
id: 'header_html',
|
||||
toolbar1: 'bold,italic,bullist,numlist,link',
|
||||
toolbar2: '',
|
||||
};
|
||||
this.controlParams = this.props.control.params.input_attrs ? {
|
||||
...defaultParams,
|
||||
...this.props.control.params.input_attrs,
|
||||
} : defaultParams;
|
||||
this.defaultValue = props.control.params.default || '';
|
||||
}
|
||||
componentDidMount() {
|
||||
if ( window.tinymce.get( this.controlParams.id ) ) {
|
||||
this.setState( { restoreTextMode: window.tinymce.get( this.controlParams.id ).isHidden() } );
|
||||
window.wp.oldEditor.remove( this.controlParams.id );
|
||||
}
|
||||
window.wp.oldEditor.initialize( this.controlParams.id, {
|
||||
tinymce: {
|
||||
wpautop: true,
|
||||
toolbar1: this.controlParams.toolbar1,
|
||||
toolbar2: this.controlParams.toolbar2,
|
||||
},
|
||||
quicktags: true,
|
||||
mediaButtons: true,
|
||||
} );
|
||||
const editor = window.tinymce.get( this.controlParams.id );
|
||||
if ( editor.initialized ) {
|
||||
this.onInit();
|
||||
} else {
|
||||
editor.on( 'init', this.onInit );
|
||||
}
|
||||
}
|
||||
onInit() {
|
||||
const editor = window.tinymce.get( this.controlParams.id );
|
||||
if ( this.state.restoreTextMode ) {
|
||||
window.switchEditors.go( this.controlParams.id, 'html' );
|
||||
}
|
||||
editor.on( 'NodeChange', debounce( this.triggerChangeIfDirty, 250 ) );
|
||||
|
||||
this.setState( { editor: editor } );
|
||||
}
|
||||
triggerChangeIfDirty() {
|
||||
this.updateValues( window.wp.oldEditor.getContent( this.controlParams.id ) );
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div className="kadence-control-field kadence-editor-control">
|
||||
{ this.props.control.params.label && (
|
||||
<span className="customize-control-title">{ this.props.control.params.label }</span>
|
||||
) }
|
||||
<textarea
|
||||
className="kadence-control-tinymce-editor wp-editor-area"
|
||||
id={ this.controlParams.id }
|
||||
value={ this.state.value }
|
||||
onChange={ ( { target: { value } } ) => {
|
||||
this.updateValues(value);
|
||||
} }
|
||||
/>
|
||||
{ this.props.control.params.description && (
|
||||
<span className="customize-control-description">{ this.props.control.params.description }</span>
|
||||
) }
|
||||
{ this.props.control.renderNotice() }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
updateValues(value) {
|
||||
this.setState( { value: value } );
|
||||
this.props.control.setting.set( value );
|
||||
}
|
||||
}
|
||||
|
||||
EditorComponent.propTypes = {
|
||||
control: PropTypes.object.isRequired,
|
||||
customizer: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default EditorComponent;
|
||||
@@ -0,0 +1,11 @@
|
||||
import { createRoot } from '@wordpress/element';
|
||||
import FocusButtonComponent from './focus-button-component';
|
||||
|
||||
export const FocusButtonControl = wp.customize.KadenceControl.extend( {
|
||||
renderContent: function renderContent() {
|
||||
let control = this;
|
||||
let root = createRoot( control.container[0] );
|
||||
root.render( <FocusButtonComponent control={ control } customizer={ wp.customize } /> );
|
||||
// ReactDOM.render( <FocusButtonComponent control={ control } customizer={ wp.customize } />, control.container[0] );
|
||||
}
|
||||
} );
|
||||
@@ -0,0 +1,54 @@
|
||||
/* jshint esversion: 6 */
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
import ResponsiveControl from '../common/responsive.js';
|
||||
import Icons from '../common/icons.js';
|
||||
import { ReactSortable } from "react-sortablejs";
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
const { ButtonGroup, Dashicon, Tooltip, Button } = wp.components;
|
||||
|
||||
const { Component, Fragment } = wp.element;
|
||||
class FocusButtonComponent extends Component {
|
||||
constructor() {
|
||||
super( ...arguments );
|
||||
this.focusPanel = this.focusPanel.bind( this );
|
||||
let defaultParams = {
|
||||
'section': '',
|
||||
|
||||
};
|
||||
this.controlParams = this.props.control.params.input_attrs ? {
|
||||
...defaultParams,
|
||||
...this.props.control.params.input_attrs,
|
||||
} : defaultParams;
|
||||
}
|
||||
focusPanel( section ) {
|
||||
if ( undefined !== this.props.customizer.section( section ) ) {
|
||||
this.props.customizer.section( section ).focus();
|
||||
}
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div className="kadence-control-field kadence-available-items">
|
||||
<div className={ 'kadence-builder-item-start' }>
|
||||
<Button className="kadence-builder-item" onClick={ () => this.focusPanel( this.controlParams.section ) } data-section={ this.controlParams.section }>
|
||||
{ ( this.props.control.params.label ? this.props.control.params.label : '' ) }
|
||||
<span
|
||||
className="kadence-builder-item-icon"
|
||||
>
|
||||
<Dashicon icon="arrow-right-alt2"/>
|
||||
</span>
|
||||
</Button>
|
||||
</div>
|
||||
{ this.props.control.renderNotice() }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
FocusButtonComponent.propTypes = {
|
||||
control: PropTypes.object.isRequired,
|
||||
customizer: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
export default FocusButtonComponent;
|
||||
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* WordPress dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
export const DEFAULT_GRADIENT =
|
||||
'linear-gradient(135deg, rgb(6, 147, 227) 0%, rgb(20, 39, 109) 100%)';
|
||||
|
||||
export const DEFAULT_LINEAR_GRADIENT_ANGLE = 180;
|
||||
|
||||
export const HORIZONTAL_GRADIENT_ORIENTATION = {
|
||||
type: 'angular',
|
||||
value: 90,
|
||||
};
|
||||
export const DEFAULT_RADIAL_GRADIENT_POSITION = 'center center';
|
||||
|
||||
export const RADIAL_GRADIENT_ORIENTATION = [ {
|
||||
type: 'shape',
|
||||
value: 'ellipse',
|
||||
at: {
|
||||
type: 'position',
|
||||
value: {
|
||||
x: {
|
||||
type: 'position-keyword',
|
||||
value: 'center'
|
||||
},
|
||||
y: {
|
||||
type: 'position-keyword',
|
||||
value: 'center'
|
||||
}
|
||||
}
|
||||
}
|
||||
} ];
|
||||
|
||||
export const DEFAULT_RADIAL_GRADIENT_SHAPE = 'ellipse';
|
||||
export const GRADIENT_OPTIONS = [
|
||||
{ value: 'linear-gradient', label: __( 'Linear', 'kadence-blocks' ) },
|
||||
{ value: 'radial-gradient', label: __( 'Radial', 'kadence-blocks' ) },
|
||||
];
|
||||
|
||||
export const GRADIENT_POSITION_OPTIONS = [
|
||||
{ value: 'center top', label: __( 'Center Top', 'kadence-blocks' ) },
|
||||
{ value: 'center center', label: __( 'Center Center', 'kadence-blocks' ) },
|
||||
{ value: 'center bottom', label: __( 'Center Bottom', 'kadence-blocks' ) },
|
||||
{ value: 'left top', label: __( 'Left Top', 'kadence-blocks' ) },
|
||||
{ value: 'left center', label: __( 'Left Center', 'kadence-blocks' ) },
|
||||
{ value: 'left bottom', label: __( 'Left Bottom', 'kadence-blocks' ) },
|
||||
{ value: 'right top', label: __( 'Right Top', 'kadence-blocks' ) },
|
||||
{ value: 'right center', label: __( 'Right Center', 'kadence-blocks' ) },
|
||||
{ value: 'right bottom', label: __( 'Right Bottom', 'kadence-blocks' ) },
|
||||
];
|
||||
|
||||
export const DIRECTIONAL_ORIENTATION_ANGLE_MAP = {
|
||||
top: 0,
|
||||
'top right': 45,
|
||||
'right top': 45,
|
||||
right: 90,
|
||||
'right bottom': 135,
|
||||
'bottom right': 135,
|
||||
bottom: 180,
|
||||
'bottom left': 225,
|
||||
'left bottom': 225,
|
||||
left: 270,
|
||||
'top left': 315,
|
||||
'left top': 315,
|
||||
};
|
||||
@@ -0,0 +1,216 @@
|
||||
.components-custom-gradient-picker__item {
|
||||
display: block;
|
||||
flex:5 1 0%;
|
||||
max-height: 100%;
|
||||
max-width: 100%;
|
||||
min-height: 0px;
|
||||
min-width: 0px;
|
||||
.kadence-controls-content {
|
||||
gap: 12px;
|
||||
}
|
||||
.kadence-controls-content .components-base-control {
|
||||
margin-bottom: 0;
|
||||
flex: 10 0 0;
|
||||
}
|
||||
.kadence-control-toggle-advanced.only-icon {
|
||||
flex: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 10px;
|
||||
font-weight: 600;
|
||||
font-style: normal;
|
||||
text-transform: uppercase;
|
||||
height: 30px;
|
||||
line-height: 1.2;
|
||||
border: 1px solid #CBD5E0;
|
||||
border-radius: 2px;
|
||||
background: transparent;
|
||||
color: #4A5568;
|
||||
padding: 4px;
|
||||
box-shadow: none;
|
||||
white-space: normal;
|
||||
svg {
|
||||
width: 20px;
|
||||
}
|
||||
&.is-primary {
|
||||
border-color: var(--wp-admin-theme-color, #00669b);
|
||||
background: var(--wp-admin-theme-color, #00669b);
|
||||
color: #fff;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
.block-editor-block-inspector .components-custom-gradient-picker__item .kadence-select-large .components-select-control__input {
|
||||
height: 40px;
|
||||
min-height: 40px;
|
||||
}
|
||||
.kadence-gradient-position-control .kadence-gradient-position_header .kadence-gradient-position__label {
|
||||
margin: 0px 0px 8px;
|
||||
display:block;
|
||||
}
|
||||
.kadence-gradient-position-control .components-unit-control-wrapper {
|
||||
flex-grow: 1;
|
||||
}
|
||||
// .kadence-gradient-control .components-custom-gradient-picker__gradient-bar .components-custom-gradient-picker__control-point-button {
|
||||
// border-radius: 50%;
|
||||
// width: 30px;
|
||||
// height: 30px;
|
||||
// bottom: 100%;
|
||||
// top: auto;
|
||||
// margin-left: -15px;
|
||||
// }
|
||||
.kadence-gradient-control .components-custom-gradient-picker__gradient-bar .components-custom-gradient-picker__control-point-dropdown {
|
||||
position: absolute;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
top: 16px;
|
||||
display: flex;
|
||||
}
|
||||
.kadence-gradient-control .components-custom-gradient-picker__gradient-bar .components-custom-gradient-picker__control-point-button {
|
||||
height: inherit;
|
||||
width: inherit;
|
||||
border-radius: 50%;
|
||||
padding: 0;
|
||||
box-shadow: inset 0 0 0 var(--wp-admin-border-width-focus) #fff,0 0 2px 0 rgba(0, 0, 0, 0.25);
|
||||
outline: 2px solid transparent;
|
||||
position: static;
|
||||
top: auto;
|
||||
}
|
||||
// $grid-unit-20: 20px;
|
||||
// $grid-unit-60: 40px;
|
||||
// $radius-block-ui: 4px;
|
||||
// $grid-unit-15: 15px;
|
||||
// $grid-unit-30: 30px;
|
||||
// $grid-unit-10: 10px;
|
||||
// $border-width-tab: 1px;
|
||||
// $components-custom-gradient-picker__padding: $grid-unit-20; // 48px container, 16px handles inside, that leaves 32px padding, half of which is 1å6.
|
||||
|
||||
// .components-custom-gradient-picker {
|
||||
// &:not(.is-next-has-no-margin) {
|
||||
// margin-top: $grid-unit-15;
|
||||
// margin-bottom: $grid-unit-30;
|
||||
// }
|
||||
// }
|
||||
|
||||
// .components-custom-gradient-picker__gradient-bar:not(.has-gradient) {
|
||||
// opacity: 0.4;
|
||||
// }
|
||||
.kadence-gradient-control .components-custom-gradient-picker__gradient-bar:not(.has-gradient) {
|
||||
opacity: 0.4;
|
||||
}
|
||||
.kadence-select-no-margin-after {
|
||||
|
||||
}
|
||||
.kadence-gradient-control {
|
||||
.components-custom-gradient-picker__ui-line .components-base-control {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.components-custom-gradient-picker__ui-line .components-base-control .components-base-control__field {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
.kadence-gradient-control .components-custom-gradient-picker__gradient-bar {
|
||||
border-radius: 2px;
|
||||
width: 100%;
|
||||
height: 48px;
|
||||
margin-bottom: 16px;
|
||||
padding-right: 0;
|
||||
|
||||
.components-custom-gradient-picker__markers-container {
|
||||
position: relative;
|
||||
width: calc(100% - 48px);
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.components-custom-gradient-picker__control-point-dropdown {
|
||||
position: absolute;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
top: 16px;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.components-custom-gradient-picker__insert-point-dropdown {
|
||||
position: relative;
|
||||
|
||||
// Same size as the .components-custom-gradient-picker__control-point-dropdown parent
|
||||
height: inherit;
|
||||
width: inherit;
|
||||
min-width: 16px;
|
||||
border-radius: 50%;
|
||||
|
||||
background: #fff;
|
||||
padding: 2px;
|
||||
|
||||
color: #111;
|
||||
|
||||
svg {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
.kadence-gradient-control .components-angle-picker-control .components-input-control__container .components-input-control__input {
|
||||
height: 32px;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
// .components-custom-gradient-picker__control-point-button {
|
||||
// // Same size as the .components-custom-gradient-picker__control-point-dropdown parent
|
||||
// height: inherit;
|
||||
// width: inherit;
|
||||
// border-radius: 50%;
|
||||
// padding: 0;
|
||||
|
||||
// // Shadow and stroke.
|
||||
// box-shadow: inset 0 0 0 var(--wp-admin-border-width-focus) #fff, 0 0 4px 0 rgba(#000, 0.25);
|
||||
|
||||
// // Windows High Contrast mode will show this outline, but not the box-shadow.
|
||||
// outline: 2px solid transparent;
|
||||
|
||||
// &:focus,
|
||||
// &.is-active {
|
||||
// box-shadow: inset 0 0 0 calc(var(--wp-admin-border-width-focus) * 2) #fff, 0 0 4px 0 rgba(#000, 0.25);
|
||||
|
||||
// // Windows High Contrast mode will show this outline, but not the box-shadow.
|
||||
// outline: $border-width-tab solid transparent;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// .components-custom-gradient-picker__remove-control-point-wrapper {
|
||||
// padding-bottom: $grid-unit-10;
|
||||
// }
|
||||
|
||||
// .components-custom-gradient-picker__inserter {
|
||||
// /*rtl:ignore*/
|
||||
// direction: ltr;
|
||||
// }
|
||||
|
||||
// .components-custom-gradient-picker__liner-gradient-indicator {
|
||||
// display: inline-block;
|
||||
// flex: 0 auto;
|
||||
// width: 20px;
|
||||
// height: 20px;
|
||||
// }
|
||||
|
||||
// .components-custom-gradient-picker .components-custom-gradient-picker__toolbar {
|
||||
// border: none;
|
||||
|
||||
// // Work-around to target the inner button containers rendered by <ToolbarGroup />
|
||||
// > div + div {
|
||||
// margin-left: 1px;
|
||||
// }
|
||||
|
||||
// button {
|
||||
// &.is-pressed {
|
||||
// > svg {
|
||||
// background: #fff;
|
||||
// border: 1px solid #565656;
|
||||
// border-radius: 2px;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
@@ -0,0 +1,10 @@
|
||||
export const GRADIENT_MARKERS_WIDTH = 16;
|
||||
export const INSERT_POINT_WIDTH = 16;
|
||||
export const MINIMUM_DISTANCE_BETWEEN_INSERTER_AND_POINT = 10;
|
||||
export const MINIMUM_DISTANCE_BETWEEN_POINTS = 0;
|
||||
export const MINIMUM_SIGNIFICANT_MOVE = 5;
|
||||
|
||||
export const KEYBOARD_CONTROL_POINT_VARIATION =
|
||||
MINIMUM_DISTANCE_BETWEEN_INSERTER_AND_POINT;
|
||||
export const MINIMUM_DISTANCE_BETWEEN_INSERTER_AND_MARKER =
|
||||
( INSERT_POINT_WIDTH + GRADIENT_MARKERS_WIDTH ) / 2;
|
||||
@@ -0,0 +1,864 @@
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import classnames from "classnames";
|
||||
import { colord } from "colord";
|
||||
import { map } from "lodash";
|
||||
|
||||
/**
|
||||
* WordPress dependencies
|
||||
*/
|
||||
import { useSetting } from "@wordpress/block-editor";
|
||||
import { useInstanceId, useMergeRefs } from "@wordpress/compose";
|
||||
import { useEffect, useRef, useState, useMemo } from "@wordpress/element";
|
||||
import { __, sprintf } from "@wordpress/i18n";
|
||||
import { plus } from "@wordpress/icons";
|
||||
const globeIcon = (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fillRule="evenodd"
|
||||
strokeLinejoin="round"
|
||||
strokeMiterlimit="2"
|
||||
clipRule="evenodd"
|
||||
viewBox="0 0 20 20"
|
||||
>
|
||||
<path fill="none" d="M0 0H20V20H0z"></path>
|
||||
<path
|
||||
fillRule="nonzero"
|
||||
d="M10 1a9 9 0 10.001 18.001A9 9 0 0010 1zm3.46 11.95c0 1.47-.8 3.3-4.06 4.7.3-4.17-2.52-3.69-3.2-5A3.25 3.25 0 018 10.1c-1.552-.266-3-.96-4.18-2 .05.47.28.904.64 1.21a4.18 4.18 0 01-1.94-1.5 7.94 7.94 0 017.25-5.63c-.84 1.38-1.5 4.13 0 5.57C8.23 8 7.26 6 6.41 6.79c-1.13 1.06.33 2.51 3.42 3.08 3.29.59 3.66 1.58 3.63 3.08zm1.34-4c-.32-1.11.62-2.23 1.69-3.14a7.27 7.27 0 01.84 6.68c-.77-1.89-2.17-2.32-2.53-3.57v.03z"
|
||||
></path>
|
||||
</svg>
|
||||
);
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
// import { HStack } from '../../h-stack';
|
||||
// import { ColorPicker } from '../../color-picker';
|
||||
// import { VisuallyHidden } from '../../visually-hidden';
|
||||
import ColorPicker from "../../common/color-picker";
|
||||
import {
|
||||
__experimentalHStack as HStack,
|
||||
Button,
|
||||
VisuallyHidden,
|
||||
Popover,
|
||||
Dashicon,
|
||||
Tooltip,
|
||||
Icon,
|
||||
} from "@wordpress/components";
|
||||
import {
|
||||
addControlPoint,
|
||||
clampPercent,
|
||||
removeControlPoint,
|
||||
updateControlPointColor,
|
||||
updateControlPointColorByPosition,
|
||||
updateControlPointPosition,
|
||||
getHorizontalRelativeGradientPosition,
|
||||
} from "./utils";
|
||||
import {
|
||||
MINIMUM_SIGNIFICANT_MOVE,
|
||||
KEYBOARD_CONTROL_POINT_VARIATION,
|
||||
} from "./constants";
|
||||
|
||||
function useObservableState(initialState, onStateChange) {
|
||||
const [state, setState] = useState(initialState);
|
||||
return [
|
||||
state,
|
||||
(value) => {
|
||||
setState(value);
|
||||
if (onStateChange) {
|
||||
onStateChange(value);
|
||||
}
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
function CustomDropdown(props) {
|
||||
const {
|
||||
renderContent,
|
||||
renderToggle,
|
||||
className,
|
||||
contentClassName,
|
||||
expandOnMobile,
|
||||
headerTitle,
|
||||
focusOnMount,
|
||||
position,
|
||||
popoverProps,
|
||||
onClose,
|
||||
onToggle,
|
||||
style,
|
||||
popoverRef,
|
||||
} = props;
|
||||
// Use internal state instead of a ref to make sure that the component
|
||||
// re-renders when the popover's anchor updates.
|
||||
const [fallbackPopoverAnchor, setFallbackPopoverAnchor] = useState(null);
|
||||
const containerRef = useRef();
|
||||
const [isOpen, setIsOpen] = useObservableState(false, onToggle);
|
||||
|
||||
useEffect(
|
||||
() => () => {
|
||||
if (onToggle && isOpen) {
|
||||
onToggle(false);
|
||||
}
|
||||
},
|
||||
[onToggle, isOpen]
|
||||
);
|
||||
|
||||
function toggle() {
|
||||
setIsOpen(!isOpen);
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the popover when focus leaves it unless the toggle was pressed or
|
||||
* focus has moved to a separate dialog. The former is to let the toggle
|
||||
* handle closing the popover and the latter is to preserve presence in
|
||||
* case a dialog has opened, allowing focus to return when it's dismissed.
|
||||
*/
|
||||
function closeIfFocusOutside() {
|
||||
const { ownerDocument } = containerRef.current;
|
||||
const dialog = ownerDocument.activeElement.closest('[role="dialog"]');
|
||||
if (
|
||||
!containerRef.current.contains(ownerDocument.activeElement) &&
|
||||
(!dialog || dialog.contains(containerRef.current))
|
||||
) {
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
function close() {
|
||||
if (onClose) {
|
||||
onClose();
|
||||
}
|
||||
setIsOpen(false);
|
||||
}
|
||||
|
||||
const args = { isOpen, onToggle: toggle, onClose: close };
|
||||
const popoverPropsHaveAnchor =
|
||||
!!popoverProps?.anchor ||
|
||||
// Note: `anchorRef`, `getAnchorRect` and `anchorRect` are deprecated and
|
||||
// be removed from `Popover` from WordPress 6.3
|
||||
!!popoverProps?.anchorRef ||
|
||||
!!popoverProps?.getAnchorRect ||
|
||||
!!popoverProps?.anchorRect;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classnames("components-dropdown", className)}
|
||||
ref={useMergeRefs([setFallbackPopoverAnchor, containerRef])}
|
||||
// Some UAs focus the closest focusable parent when the toggle is
|
||||
// clicked. Making this div focusable ensures such UAs will focus
|
||||
// it and `closeIfFocusOutside` can tell if the toggle was clicked.
|
||||
tabIndex="-1"
|
||||
style={style}
|
||||
>
|
||||
{renderToggle(args)}
|
||||
{isOpen && (
|
||||
<Popover
|
||||
position={position}
|
||||
onClose={close}
|
||||
onFocusOutside={closeIfFocusOutside}
|
||||
expandOnMobile={expandOnMobile}
|
||||
headerTitle={headerTitle}
|
||||
focusOnMount={focusOnMount}
|
||||
// This value is used to ensure that the dropdowns
|
||||
// align with the editor header by default.
|
||||
offset={13}
|
||||
anchorRef={
|
||||
!popoverPropsHaveAnchor ? popoverRef.current : undefined
|
||||
}
|
||||
anchor={
|
||||
!popoverPropsHaveAnchor
|
||||
? fallbackPopoverAnchor
|
||||
: undefined
|
||||
}
|
||||
{...popoverProps}
|
||||
className={classnames(
|
||||
"components-dropdown__content",
|
||||
popoverProps ? popoverProps.className : undefined,
|
||||
contentClassName
|
||||
)}
|
||||
>
|
||||
{renderContent(args)}
|
||||
</Popover>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function CustomColorPickerDropdown({
|
||||
isRenderedInSidebar,
|
||||
popoverProps: receivedPopoverProps,
|
||||
...props
|
||||
}) {
|
||||
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 (
|
||||
<CustomDropdown
|
||||
contentClassName="components-color-palette__custom-color-dropdown-content kadence-pop-color-popover"
|
||||
popoverProps={popoverProps}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function ControlPointButton({ isOpen, position, color, ...additionalProps }) {
|
||||
const instanceId = useInstanceId(ControlPointButton);
|
||||
const descriptionId = `components-custom-gradient-picker__control-point-button-description-${instanceId}`;
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
aria-label={sprintf(
|
||||
// translators: %1$s: gradient position e.g: 70, %2$s: gradient color code e.g: rgb(52,121,151).
|
||||
__(
|
||||
"Gradient control point at position %1$s%% with color code %2$s."
|
||||
),
|
||||
position,
|
||||
color
|
||||
)}
|
||||
aria-describedby={descriptionId}
|
||||
aria-haspopup="true"
|
||||
aria-expanded={isOpen}
|
||||
className={classnames(
|
||||
"components-custom-gradient-picker__control-point-button",
|
||||
{
|
||||
"is-active": isOpen,
|
||||
}
|
||||
)}
|
||||
{...additionalProps}
|
||||
/>
|
||||
<VisuallyHidden id={descriptionId}>
|
||||
{__(
|
||||
"Use your left or right arrow keys or drag and drop with the mouse to change the gradient position. Press the button to change the color or remove the control point."
|
||||
)}
|
||||
</VisuallyHidden>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function GradientColorPickerDropdown({
|
||||
popoverRef,
|
||||
isRenderedInSidebar,
|
||||
className,
|
||||
...props
|
||||
}) {
|
||||
// Open the popover below the gradient control/insertion point
|
||||
const popoverProps = useMemo(
|
||||
() => ({
|
||||
placement: "bottom",
|
||||
offset: 8,
|
||||
flip: false,
|
||||
}),
|
||||
[]
|
||||
);
|
||||
|
||||
const mergedClassName = classnames(
|
||||
"components-custom-gradient-picker__control-point-dropdown",
|
||||
className
|
||||
);
|
||||
|
||||
return (
|
||||
<CustomColorPickerDropdown
|
||||
isRenderedInSidebar={isRenderedInSidebar}
|
||||
popoverRef={popoverRef}
|
||||
popoverProps={popoverProps}
|
||||
className={mergedClassName}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
function getReadableColor(value, colors) {
|
||||
if (!value) {
|
||||
return "";
|
||||
}
|
||||
if (!colors) {
|
||||
return value;
|
||||
}
|
||||
if (value.startsWith("var(--global-")) {
|
||||
let slug = value.replace("var(--global-", "");
|
||||
slug = slug.substring(0, 9);
|
||||
slug = slug.replace(",", "");
|
||||
const found = colors.find((option) => option.slug === slug);
|
||||
if (found) {
|
||||
return found.color;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
function ControlPoints({
|
||||
disableRemove,
|
||||
gradientPickerDomRef,
|
||||
ignoreMarkerPosition,
|
||||
value: controlPoints,
|
||||
onChange,
|
||||
onStartControlPointChange,
|
||||
onStopControlPointChange,
|
||||
isRenderedInSidebar,
|
||||
popoverRef,
|
||||
activePalette,
|
||||
}) {
|
||||
const controlPointMoveState = useRef();
|
||||
|
||||
const onMouseMove = (event) => {
|
||||
const relativePosition = getHorizontalRelativeGradientPosition(
|
||||
event.clientX,
|
||||
gradientPickerDomRef.current
|
||||
);
|
||||
const { initialPosition, index, significantMoveHappened } =
|
||||
controlPointMoveState.current;
|
||||
if (
|
||||
!significantMoveHappened &&
|
||||
Math.abs(initialPosition - relativePosition) >=
|
||||
MINIMUM_SIGNIFICANT_MOVE
|
||||
) {
|
||||
controlPointMoveState.current.significantMoveHappened = true;
|
||||
}
|
||||
|
||||
onChange(
|
||||
updateControlPointPosition(controlPoints, index, relativePosition)
|
||||
);
|
||||
};
|
||||
|
||||
const cleanEventListeners = () => {
|
||||
if (
|
||||
window &&
|
||||
window.removeEventListener &&
|
||||
controlPointMoveState.current &&
|
||||
controlPointMoveState.current.listenersActivated
|
||||
) {
|
||||
window.removeEventListener("mousemove", onMouseMove);
|
||||
window.removeEventListener("mouseup", cleanEventListeners);
|
||||
onStopControlPointChange();
|
||||
controlPointMoveState.current.listenersActivated = false;
|
||||
}
|
||||
};
|
||||
|
||||
// Adding `cleanEventListeners` to the dependency array below requires the function itself to be wrapped in a `useCallback`
|
||||
// This memoization would prevent the event listeners from being properly cleaned.
|
||||
// Instead, we'll pass a ref to the function in our `useEffect` so `cleanEventListeners` itself is no longer a dependency.
|
||||
const cleanEventListenersRef = useRef();
|
||||
cleanEventListenersRef.current = cleanEventListeners;
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
cleanEventListenersRef.current();
|
||||
};
|
||||
}, []);
|
||||
const disableCustomColors = false;
|
||||
const colors = activePalette ? activePalette : useSetting("color.palette");
|
||||
return controlPoints.map((point, index) => {
|
||||
const initialPosition = point?.position;
|
||||
const pointColor = getReadableColor(point.color, colors);
|
||||
return (
|
||||
ignoreMarkerPosition !== initialPosition && (
|
||||
<GradientColorPickerDropdown
|
||||
isRenderedInSidebar={isRenderedInSidebar}
|
||||
key={index}
|
||||
popoverRef={popoverRef}
|
||||
onClose={onStopControlPointChange}
|
||||
renderToggle={({ isOpen, onToggle }) => (
|
||||
<ControlPointButton
|
||||
key={index}
|
||||
onClick={() => {
|
||||
if (
|
||||
controlPointMoveState.current &&
|
||||
controlPointMoveState.current
|
||||
.significantMoveHappened
|
||||
) {
|
||||
return;
|
||||
}
|
||||
if (isOpen) {
|
||||
onStopControlPointChange();
|
||||
} else {
|
||||
onStartControlPointChange();
|
||||
}
|
||||
onToggle();
|
||||
}}
|
||||
onMouseDown={() => {
|
||||
if (window && window.addEventListener) {
|
||||
controlPointMoveState.current = {
|
||||
initialPosition,
|
||||
index,
|
||||
significantMoveHappened: false,
|
||||
listenersActivated: true,
|
||||
};
|
||||
onStartControlPointChange();
|
||||
window.addEventListener(
|
||||
"mousemove",
|
||||
onMouseMove
|
||||
);
|
||||
window.addEventListener(
|
||||
"mouseup",
|
||||
cleanEventListeners
|
||||
);
|
||||
}
|
||||
}}
|
||||
onKeyDown={(event) => {
|
||||
if (event.code === "ArrowLeft") {
|
||||
// Stop propagation of the key press event to avoid focus moving
|
||||
// to another editor area.
|
||||
event.stopPropagation();
|
||||
onChange(
|
||||
updateControlPointPosition(
|
||||
controlPoints,
|
||||
index,
|
||||
clampPercent(
|
||||
point.position -
|
||||
KEYBOARD_CONTROL_POINT_VARIATION
|
||||
)
|
||||
)
|
||||
);
|
||||
} else if (event.code === "ArrowRight") {
|
||||
// Stop propagation of the key press event to avoid focus moving
|
||||
// to another editor area.
|
||||
event.stopPropagation();
|
||||
onChange(
|
||||
updateControlPointPosition(
|
||||
controlPoints,
|
||||
index,
|
||||
clampPercent(
|
||||
point.position +
|
||||
KEYBOARD_CONTROL_POINT_VARIATION
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}}
|
||||
isOpen={isOpen}
|
||||
position={point.position}
|
||||
color={point.color}
|
||||
/>
|
||||
)}
|
||||
renderContent={({ onClose }) => (
|
||||
<div className="kadence-pop-gradient-color-picker">
|
||||
<HStack
|
||||
className="components-custom-gradient-picker__remove-control-point-wrapper"
|
||||
alignment="center"
|
||||
>
|
||||
<Button
|
||||
onClick={() => {
|
||||
onClose();
|
||||
}}
|
||||
variant="link"
|
||||
>
|
||||
{__("Close Color Picker", "kadence")}
|
||||
</Button>
|
||||
</HStack>
|
||||
{!disableCustomColors && (
|
||||
<ColorPicker
|
||||
color={pointColor}
|
||||
onChange={(color) => {
|
||||
onChange(
|
||||
updateControlPointColor(
|
||||
controlPoints,
|
||||
index,
|
||||
colord(color.rgb).toRgbString()
|
||||
)
|
||||
);
|
||||
}}
|
||||
onChangeComplete={(color) => {
|
||||
onChange(
|
||||
updateControlPointColor(
|
||||
controlPoints,
|
||||
index,
|
||||
colord(color.rgb).toRgbString()
|
||||
)
|
||||
);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{colors && (
|
||||
<>
|
||||
<div
|
||||
style={{
|
||||
paddingTop: "15px",
|
||||
paddingBottom: "15px",
|
||||
}}
|
||||
className="kadence-swatches-wrap"
|
||||
>
|
||||
{map(
|
||||
colors,
|
||||
({ color, slug, name }) => {
|
||||
const key = `${color}${
|
||||
slug || ""
|
||||
}`;
|
||||
const palette = slug.replace(
|
||||
"theme-",
|
||||
""
|
||||
);
|
||||
const isActive =
|
||||
slug.startsWith(
|
||||
"palette"
|
||||
) && pointColor === color;
|
||||
return (
|
||||
<div
|
||||
key={key}
|
||||
style={{
|
||||
width: 26,
|
||||
height: 26,
|
||||
marginBottom: 0,
|
||||
transform:
|
||||
"scale(1)",
|
||||
transition:
|
||||
"100ms transform ease",
|
||||
}}
|
||||
className="kadence-swatche-item-wrap"
|
||||
>
|
||||
<Button
|
||||
className={`kadence-swatch-item ${
|
||||
isActive
|
||||
? "swatch-active"
|
||||
: "swatch-inactive"
|
||||
}`}
|
||||
style={{
|
||||
height: "100%",
|
||||
width: "100%",
|
||||
border: "1px solid rgb(218, 218, 218)",
|
||||
borderRadius:
|
||||
"50%",
|
||||
color:
|
||||
slug ===
|
||||
"palette10"
|
||||
? "var(--global-palette10)"
|
||||
: `${color}`,
|
||||
boxShadow: `inset 0 0 0 ${
|
||||
26 / 2
|
||||
}px`,
|
||||
transition:
|
||||
"100ms box-shadow ease",
|
||||
}}
|
||||
onClick={() => {
|
||||
if (
|
||||
slug.startsWith(
|
||||
"palette"
|
||||
)
|
||||
) {
|
||||
onChange(
|
||||
updateControlPointColor(
|
||||
controlPoints,
|
||||
index,
|
||||
"var(--global-" +
|
||||
palette +
|
||||
"," +
|
||||
color +
|
||||
")"
|
||||
)
|
||||
);
|
||||
} else {
|
||||
onChange(
|
||||
updateControlPointColor(
|
||||
controlPoints,
|
||||
index,
|
||||
colord(
|
||||
color
|
||||
).toRgbString()
|
||||
)
|
||||
);
|
||||
}
|
||||
}}
|
||||
tabIndex={0}
|
||||
>
|
||||
<Icon
|
||||
className="dashicon"
|
||||
icon={globeIcon}
|
||||
/>
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
{!disableRemove && controlPoints.length > 2 && (
|
||||
<HStack
|
||||
className="components-custom-gradient-picker__remove-control-point-wrapper"
|
||||
alignment="center"
|
||||
>
|
||||
<Button
|
||||
onClick={() => {
|
||||
onChange(
|
||||
removeControlPoint(
|
||||
controlPoints,
|
||||
index
|
||||
)
|
||||
);
|
||||
onClose();
|
||||
}}
|
||||
variant="link"
|
||||
>
|
||||
{__("Remove Control Point", "kadence")}
|
||||
</Button>
|
||||
</HStack>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
style={{
|
||||
left: `${point.position}%`,
|
||||
transform: "translateX( -50% )",
|
||||
}}
|
||||
/>
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function InsertPoint({
|
||||
value: controlPoints,
|
||||
onChange,
|
||||
onOpenInserter,
|
||||
onCloseInserter,
|
||||
insertPosition,
|
||||
isRenderedInSidebar,
|
||||
activePalette,
|
||||
popoverRef,
|
||||
}) {
|
||||
const [alreadyInsertedPoint, setAlreadyInsertedPoint] = useState(false);
|
||||
const disableCustomColors = false;
|
||||
const colors = activePalette ? activePalette : useSetting("color.palette");
|
||||
const [tempColor, setTempColor] = useState("");
|
||||
const pointColor = getReadableColor(tempColor, colors);
|
||||
return (
|
||||
<GradientColorPickerDropdown
|
||||
isRenderedInSidebar={isRenderedInSidebar}
|
||||
popoverRef={popoverRef}
|
||||
className="components-custom-gradient-picker__inserter"
|
||||
onClose={() => {
|
||||
onCloseInserter();
|
||||
}}
|
||||
renderToggle={({ isOpen, onToggle }) => (
|
||||
<Button
|
||||
aria-expanded={isOpen}
|
||||
aria-haspopup="true"
|
||||
onClick={() => {
|
||||
if (isOpen) {
|
||||
onCloseInserter();
|
||||
} else {
|
||||
setAlreadyInsertedPoint(false);
|
||||
onOpenInserter();
|
||||
}
|
||||
onToggle();
|
||||
}}
|
||||
className="components-custom-gradient-picker__insert-point-dropdown"
|
||||
icon={plus}
|
||||
/>
|
||||
)}
|
||||
renderContent={() => (
|
||||
<div className="kadence-pop-gradient-color-picker">
|
||||
<HStack
|
||||
className="components-custom-gradient-picker__remove-control-point-wrapper"
|
||||
alignment="center"
|
||||
>
|
||||
<Button
|
||||
onClick={() => {
|
||||
onCloseInserter();
|
||||
}}
|
||||
variant="link"
|
||||
>
|
||||
{__("Close Color Picker", "kadence")}
|
||||
</Button>
|
||||
</HStack>
|
||||
{!disableCustomColors && (
|
||||
<ColorPicker
|
||||
color={pointColor}
|
||||
onChange={(color) => {
|
||||
setTempColor(colord(color.rgb).toRgbString());
|
||||
if (!alreadyInsertedPoint) {
|
||||
onChange(
|
||||
addControlPoint(
|
||||
controlPoints,
|
||||
insertPosition,
|
||||
colord(color.rgb).toRgbString()
|
||||
)
|
||||
);
|
||||
setAlreadyInsertedPoint(true);
|
||||
} else {
|
||||
onChange(
|
||||
updateControlPointColorByPosition(
|
||||
controlPoints,
|
||||
insertPosition,
|
||||
colord(color.rgb).toRgbString()
|
||||
)
|
||||
);
|
||||
}
|
||||
}}
|
||||
onChangeComplete={(color) => {
|
||||
setTempColor(colord(color.rgb).toRgbString());
|
||||
if (!alreadyInsertedPoint) {
|
||||
onChange(
|
||||
addControlPoint(
|
||||
controlPoints,
|
||||
insertPosition,
|
||||
colord(color.rgb).toRgbString()
|
||||
)
|
||||
);
|
||||
setAlreadyInsertedPoint(true);
|
||||
} else {
|
||||
onChange(
|
||||
updateControlPointColorByPosition(
|
||||
controlPoints,
|
||||
insertPosition,
|
||||
colord(color.rgb).toRgbString()
|
||||
)
|
||||
);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{colors && (
|
||||
<div
|
||||
style={{
|
||||
paddingTop: "15px",
|
||||
paddingBottom: "15px",
|
||||
}}
|
||||
className="kadence-swatches-wrap"
|
||||
>
|
||||
{map(colors, ({ color, slug, name }) => {
|
||||
const key = `${color}${slug || ""}`;
|
||||
const palette = slug.replace("theme-", "");
|
||||
const isActive =
|
||||
slug.startsWith("palette") &&
|
||||
pointColor === color;
|
||||
return (
|
||||
<div
|
||||
key={key}
|
||||
style={{
|
||||
width: 26,
|
||||
height: 26,
|
||||
marginBottom: 0,
|
||||
transform: "scale(1)",
|
||||
transition: "100ms transform ease",
|
||||
}}
|
||||
className="kadence-swatche-item-wrap"
|
||||
>
|
||||
<Button
|
||||
className={`kadence-swatch-item ${
|
||||
isActive
|
||||
? "swatch-active"
|
||||
: "swatch-inactive"
|
||||
}`}
|
||||
style={{
|
||||
height: "100%",
|
||||
width: "100%",
|
||||
border: "1px solid rgb(218, 218, 218)",
|
||||
borderRadius: "50%",
|
||||
color:
|
||||
slug === "palette10"
|
||||
? "var(--global-palette10)"
|
||||
: `${color}`,
|
||||
boxShadow: `inset 0 0 0 ${
|
||||
26 / 2
|
||||
}px`,
|
||||
transition:
|
||||
"100ms box-shadow ease",
|
||||
}}
|
||||
onClick={() => {
|
||||
setTempColor(
|
||||
colord(color).toRgbString()
|
||||
);
|
||||
if (!alreadyInsertedPoint) {
|
||||
if (
|
||||
slug.startsWith(
|
||||
"palette"
|
||||
)
|
||||
) {
|
||||
onChange(
|
||||
addControlPoint(
|
||||
controlPoints,
|
||||
insertPosition,
|
||||
"var(--global-" +
|
||||
palette +
|
||||
"," +
|
||||
color +
|
||||
")"
|
||||
)
|
||||
);
|
||||
} else {
|
||||
onChange(
|
||||
addControlPoint(
|
||||
controlPoints,
|
||||
insertPosition,
|
||||
colord(
|
||||
color
|
||||
).toRgbString()
|
||||
)
|
||||
);
|
||||
}
|
||||
setAlreadyInsertedPoint(
|
||||
true
|
||||
);
|
||||
} else {
|
||||
if (
|
||||
slug.startsWith(
|
||||
"palette"
|
||||
)
|
||||
) {
|
||||
onChange(
|
||||
updateControlPointColorByPosition(
|
||||
controlPoints,
|
||||
insertPosition,
|
||||
"var(--global-" +
|
||||
palette +
|
||||
"," +
|
||||
color +
|
||||
")"
|
||||
)
|
||||
);
|
||||
} else {
|
||||
onChange(
|
||||
updateControlPointColorByPosition(
|
||||
controlPoints,
|
||||
insertPosition,
|
||||
colord(
|
||||
color
|
||||
).toRgbString()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}}
|
||||
tabIndex={0}
|
||||
>
|
||||
<Icon
|
||||
className="dashicon"
|
||||
icon={globeIcon}
|
||||
/>
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
style={
|
||||
insertPosition !== null
|
||||
? {
|
||||
left: `${insertPosition}%`,
|
||||
transform: "translateX( -50% )",
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
ControlPoints.InsertPoint = InsertPoint;
|
||||
|
||||
export default ControlPoints;
|
||||
@@ -0,0 +1,183 @@
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
|
||||
import { some } from 'lodash';
|
||||
import classnames from 'classnames';
|
||||
|
||||
/**
|
||||
* WordPress dependencies
|
||||
*/
|
||||
import { useRef, useReducer } from '@wordpress/element';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import ControlPoints from './control-points';
|
||||
import { getHorizontalRelativeGradientPosition } from './utils';
|
||||
import { MINIMUM_DISTANCE_BETWEEN_INSERTER_AND_POINT } from './constants';
|
||||
|
||||
function customGradientBarReducer( state, action ) {
|
||||
switch ( action.type ) {
|
||||
case 'MOVE_INSERTER':
|
||||
if ( state.id === 'IDLE' || state.id === 'MOVING_INSERTER' ) {
|
||||
return {
|
||||
id: 'MOVING_INSERTER',
|
||||
insertPosition: action.insertPosition,
|
||||
};
|
||||
}
|
||||
break;
|
||||
case 'STOP_INSERTER_MOVE':
|
||||
if ( state.id === 'MOVING_INSERTER' ) {
|
||||
return {
|
||||
id: 'IDLE',
|
||||
};
|
||||
}
|
||||
break;
|
||||
case 'OPEN_INSERTER':
|
||||
if ( state.id === 'MOVING_INSERTER' ) {
|
||||
return {
|
||||
id: 'INSERTING_CONTROL_POINT',
|
||||
insertPosition: state.insertPosition,
|
||||
};
|
||||
}
|
||||
break;
|
||||
case 'CLOSE_INSERTER':
|
||||
if ( state.id === 'INSERTING_CONTROL_POINT' ) {
|
||||
return {
|
||||
id: 'IDLE',
|
||||
};
|
||||
}
|
||||
break;
|
||||
case 'START_CONTROL_CHANGE':
|
||||
if ( state.id === 'IDLE' ) {
|
||||
return {
|
||||
id: 'MOVING_CONTROL_POINT',
|
||||
};
|
||||
}
|
||||
break;
|
||||
case 'STOP_CONTROL_CHANGE':
|
||||
if ( state.id === 'MOVING_CONTROL_POINT' ) {
|
||||
return {
|
||||
id: 'IDLE',
|
||||
};
|
||||
}
|
||||
break;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
const customGradientBarReducerInitialState = { id: 'IDLE' };
|
||||
|
||||
export default function CustomGradientBar( {
|
||||
background,
|
||||
hasGradient,
|
||||
value: controlPoints,
|
||||
onChange,
|
||||
disableInserter = false,
|
||||
isRenderedInSidebar,
|
||||
activePalette,
|
||||
} ) {
|
||||
const gradientMarkersContainerDomRef = useRef();
|
||||
|
||||
const [ gradientBarState, gradientBarStateDispatch ] = useReducer(
|
||||
customGradientBarReducer,
|
||||
customGradientBarReducerInitialState
|
||||
);
|
||||
const popoverRef = useRef();
|
||||
const onMouseEnterAndMove = ( event ) => {
|
||||
const insertPosition = getHorizontalRelativeGradientPosition(
|
||||
event.clientX,
|
||||
gradientMarkersContainerDomRef.current
|
||||
);
|
||||
|
||||
// If the insert point is close to an existing control point don't show it.
|
||||
if (
|
||||
some( controlPoints, ( { position } ) => {
|
||||
return (
|
||||
Math.abs( insertPosition - position ) <
|
||||
MINIMUM_DISTANCE_BETWEEN_INSERTER_AND_POINT
|
||||
);
|
||||
} )
|
||||
) {
|
||||
if ( gradientBarState.id === 'MOVING_INSERTER' ) {
|
||||
gradientBarStateDispatch( { type: 'STOP_INSERTER_MOVE' } );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
gradientBarStateDispatch( { type: 'MOVE_INSERTER', insertPosition } );
|
||||
};
|
||||
|
||||
const onMouseLeave = () => {
|
||||
gradientBarStateDispatch( { type: 'STOP_INSERTER_MOVE' } );
|
||||
};
|
||||
|
||||
const isMovingInserter = gradientBarState.id === 'MOVING_INSERTER';
|
||||
const isInsertingControlPoint =
|
||||
gradientBarState.id === 'INSERTING_CONTROL_POINT';
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={ popoverRef }
|
||||
className={ classnames(
|
||||
'components-custom-gradient-picker__gradient-bar',
|
||||
{ 'has-gradient': hasGradient }
|
||||
) }
|
||||
onMouseEnter={ onMouseEnterAndMove }
|
||||
onMouseMove={ onMouseEnterAndMove }
|
||||
style={ { background } }
|
||||
onMouseLeave={ onMouseLeave }
|
||||
>
|
||||
<div
|
||||
ref={ gradientMarkersContainerDomRef }
|
||||
className="components-custom-gradient-picker__markers-container"
|
||||
>
|
||||
{ ! disableInserter &&
|
||||
( isMovingInserter || isInsertingControlPoint ) && (
|
||||
<ControlPoints.InsertPoint
|
||||
isRenderedInSidebar={ isRenderedInSidebar }
|
||||
insertPosition={ gradientBarState.insertPosition }
|
||||
value={ controlPoints }
|
||||
onChange={ onChange }
|
||||
activePalette={ activePalette }
|
||||
popoverRef={ popoverRef }
|
||||
onOpenInserter={ () => {
|
||||
gradientBarStateDispatch( {
|
||||
type: 'OPEN_INSERTER',
|
||||
} );
|
||||
} }
|
||||
onCloseInserter={ () => {
|
||||
gradientBarStateDispatch( {
|
||||
type: 'CLOSE_INSERTER',
|
||||
} );
|
||||
} }
|
||||
/>
|
||||
) }
|
||||
<ControlPoints
|
||||
isRenderedInSidebar={ isRenderedInSidebar }
|
||||
activePalette={ activePalette }
|
||||
disableRemove={ disableInserter }
|
||||
gradientPickerDomRef={ gradientMarkersContainerDomRef }
|
||||
ignoreMarkerPosition={
|
||||
isInsertingControlPoint
|
||||
? gradientBarState.insertPosition
|
||||
: undefined
|
||||
}
|
||||
value={ controlPoints }
|
||||
onChange={ onChange }
|
||||
popoverRef={ popoverRef }
|
||||
onStartControlPointChange={ () => {
|
||||
gradientBarStateDispatch( {
|
||||
type: 'START_CONTROL_CHANGE',
|
||||
} );
|
||||
} }
|
||||
onStopControlPointChange={ () => {
|
||||
gradientBarStateDispatch( {
|
||||
type: 'STOP_CONTROL_CHANGE',
|
||||
} );
|
||||
} }
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { MINIMUM_DISTANCE_BETWEEN_POINTS } from './constants';
|
||||
|
||||
/**
|
||||
* Control point for the gradient bar.
|
||||
*
|
||||
* @typedef {Object} ControlPoint
|
||||
* @property {string} color Color of the control point.
|
||||
* @property {number} position Integer position of the control point as a percentage.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Color as parsed from the gradient by gradient-parser.
|
||||
*
|
||||
* @typedef {Object} Color
|
||||
* @property {string} r Red component.
|
||||
* @property {string} g Green component.
|
||||
* @property {string} b Green component.
|
||||
* @property {string} [a] Optional alpha component.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Clamps a number between 0 and 100.
|
||||
*
|
||||
* @param {number} value Value to clamp.
|
||||
*
|
||||
* @return {number} Value clamped between 0 and 100.
|
||||
*/
|
||||
export function clampPercent( value ) {
|
||||
return Math.max( 0, Math.min( 100, value ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a control point is overlapping with another.
|
||||
*
|
||||
* @param {ControlPoint[]} value Array of control points.
|
||||
* @param {number} initialIndex Index of the position to test.
|
||||
* @param {number} newPosition New position of the control point.
|
||||
* @param {number} minDistance Distance considered to be overlapping.
|
||||
*
|
||||
* @return {boolean} True if the point is overlapping.
|
||||
*/
|
||||
export function isOverlapping(
|
||||
value,
|
||||
initialIndex,
|
||||
newPosition,
|
||||
minDistance = MINIMUM_DISTANCE_BETWEEN_POINTS
|
||||
) {
|
||||
const initialPosition = value[ initialIndex ].position;
|
||||
const minPosition = Math.min( initialPosition, newPosition );
|
||||
const maxPosition = Math.max( initialPosition, newPosition );
|
||||
|
||||
return value.some( ( { position }, index ) => {
|
||||
return (
|
||||
index !== initialIndex &&
|
||||
( Math.abs( position - newPosition ) < minDistance ||
|
||||
( minPosition < position && position < maxPosition ) )
|
||||
);
|
||||
} );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a control point from an array and returns the new array.
|
||||
*
|
||||
* @param {ControlPoint[]} points Array of control points.
|
||||
* @param {number} position Position to insert the new point.
|
||||
* @param {Color} color Color to update the control point at index.
|
||||
*
|
||||
* @return {ControlPoint[]} New array of control points.
|
||||
*/
|
||||
export function addControlPoint( points, position, color ) {
|
||||
const nextIndex = points.findIndex(
|
||||
( point ) => point.position > position
|
||||
);
|
||||
const newPoint = { color, position };
|
||||
const newPoints = points.slice();
|
||||
newPoints.splice( nextIndex - 1, 0, newPoint );
|
||||
return newPoints;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a control point from an array and returns the new array.
|
||||
*
|
||||
* @param {ControlPoint[]} points Array of control points.
|
||||
* @param {number} index Index to remove.
|
||||
*
|
||||
* @return {ControlPoint[]} New array of control points.
|
||||
*/
|
||||
export function removeControlPoint( points, index ) {
|
||||
return points.filter( ( point, pointIndex ) => {
|
||||
return pointIndex !== index;
|
||||
} );
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a control point from an array and returns the new array.
|
||||
*
|
||||
* @param {ControlPoint[]} points Array of control points.
|
||||
* @param {number} index Index to update.
|
||||
* @param {ControlPoint[]} newPoint New control point to replace the index.
|
||||
*
|
||||
* @return {ControlPoint[]} New array of control points.
|
||||
*/
|
||||
export function updateControlPoint( points, index, newPoint ) {
|
||||
const newValue = points.slice();
|
||||
newValue[ index ] = newPoint;
|
||||
return newValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the position of a control point from an array and returns the new array.
|
||||
*
|
||||
* @param {ControlPoint[]} points Array of control points.
|
||||
* @param {number} index Index to update.
|
||||
* @param {number} newPosition Position to move the control point at index.
|
||||
*
|
||||
* @return {ControlPoint[]} New array of control points.
|
||||
*/
|
||||
export function updateControlPointPosition( points, index, newPosition ) {
|
||||
if ( isOverlapping( points, index, newPosition ) ) {
|
||||
return points;
|
||||
}
|
||||
const newPoint = {
|
||||
...points[ index ],
|
||||
position: newPosition,
|
||||
};
|
||||
return updateControlPoint( points, index, newPoint );
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the position of a control point from an array and returns the new array.
|
||||
*
|
||||
* @param {ControlPoint[]} points Array of control points.
|
||||
* @param {number} index Index to update.
|
||||
* @param {Color} newColor Color to update the control point at index.
|
||||
*
|
||||
* @return {ControlPoint[]} New array of control points.
|
||||
*/
|
||||
export function updateControlPointColor( points, index, newColor ) {
|
||||
const newPoint = {
|
||||
...points[ index ],
|
||||
color: newColor,
|
||||
};
|
||||
return updateControlPoint( points, index, newPoint );
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the position of a control point from an array and returns the new array.
|
||||
*
|
||||
* @param {ControlPoint[]} points Array of control points.
|
||||
* @param {number} position Position of the color stop.
|
||||
* @param {string} newColor Color to update the control point at index.
|
||||
*
|
||||
* @return {ControlPoint[]} New array of control points.
|
||||
*/
|
||||
export function updateControlPointColorByPosition(
|
||||
points,
|
||||
position,
|
||||
newColor
|
||||
) {
|
||||
const index = points.findIndex( ( point ) => point.position === position );
|
||||
return updateControlPointColor( points, index, newColor );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the horizontal coordinate when dragging a control point with the mouse.
|
||||
*
|
||||
* @param {number} mouseXCoordinate Horizontal coordinate of the mouse position.
|
||||
* @param {Element} containerElement Container for the gradient picker.
|
||||
*
|
||||
* @return {number} Whole number percentage from the left.
|
||||
*/
|
||||
export function getHorizontalRelativeGradientPosition(
|
||||
mouseXCoordinate,
|
||||
containerElement
|
||||
) {
|
||||
if ( ! containerElement ) {
|
||||
return;
|
||||
}
|
||||
const { x, width } = containerElement.getBoundingClientRect();
|
||||
const absolutePositionValue = mouseXCoordinate - x;
|
||||
return Math.round(
|
||||
clampPercent( ( absolutePositionValue * 100 ) / width )
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,443 @@
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import classnames from 'classnames';
|
||||
|
||||
//import './editor.scss';
|
||||
/**
|
||||
* WordPress dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { AnglePickerControl, Flex, FlexItem,__experimentalUnitControl as UnitControl, SelectControl, Button } from '@wordpress/components';
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { settings } from '@wordpress/icons';
|
||||
import CustomGradientBar from './gradient-bar';
|
||||
import {
|
||||
getGradientAstWithDefault,
|
||||
getLinearGradientRepresentation,
|
||||
getGradientAstWithControlPoints,
|
||||
getStopCssColor,
|
||||
} from './utils';
|
||||
import { serializeGradient } from './serializer';
|
||||
import {
|
||||
DEFAULT_LINEAR_GRADIENT_ANGLE,
|
||||
HORIZONTAL_GRADIENT_ORIENTATION,
|
||||
GRADIENT_OPTIONS,
|
||||
RADIAL_GRADIENT_ORIENTATION,
|
||||
DEFAULT_GRADIENT,
|
||||
DEFAULT_RADIAL_GRADIENT_POSITION,
|
||||
GRADIENT_POSITION_OPTIONS,
|
||||
DEFAULT_RADIAL_GRADIENT_SHAPE,
|
||||
} from './constants';
|
||||
// import {
|
||||
// AccessoryWrapper,
|
||||
// SelectWrapper,
|
||||
// } from './styles/custom-gradient-picker-styles';
|
||||
|
||||
const GradientAnglePicker = ( { gradientAST, hasGradient, onChange } ) => {
|
||||
const angle =
|
||||
gradientAST?.orientation?.value ?? DEFAULT_LINEAR_GRADIENT_ANGLE;
|
||||
const onAngleChange = ( newAngle ) => {
|
||||
onChange(
|
||||
serializeGradient( {
|
||||
...gradientAST,
|
||||
orientation: {
|
||||
type: 'angular',
|
||||
value: newAngle,
|
||||
},
|
||||
} )
|
||||
);
|
||||
};
|
||||
return (
|
||||
<AnglePickerControl
|
||||
__nextHasNoMarginBottom
|
||||
onChange={ onAngleChange }
|
||||
labelPosition="top"
|
||||
value={ hasGradient ? angle : '' }
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const GradientTypePicker = ( { gradientAST, hasGradient, onChange } ) => {
|
||||
const { type } = gradientAST;
|
||||
const onSetLinearGradient = () => {
|
||||
onChange(
|
||||
serializeGradient( {
|
||||
...gradientAST,
|
||||
...( { orientation: HORIZONTAL_GRADIENT_ORIENTATION } ),
|
||||
type: 'linear-gradient',
|
||||
} )
|
||||
);
|
||||
};
|
||||
|
||||
const onSetRadialGradient = () => {
|
||||
onChange(
|
||||
serializeGradient( {
|
||||
...gradientAST,
|
||||
...( { orientation: RADIAL_GRADIENT_ORIENTATION, }),
|
||||
type: 'radial-gradient',
|
||||
} )
|
||||
);
|
||||
};
|
||||
|
||||
const handleOnChange = ( next ) => {
|
||||
if ( next === 'linear-gradient' ) {
|
||||
onSetLinearGradient();
|
||||
}
|
||||
if ( next === 'radial-gradient' ) {
|
||||
onSetRadialGradient();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<SelectControl
|
||||
className="components-custom-gradient-picker__type-picker kadence-select-large"
|
||||
label={ __( 'Type' ) }
|
||||
labelPosition="top"
|
||||
onChange={ handleOnChange }
|
||||
options={ GRADIENT_OPTIONS }
|
||||
//size="__unstable-large"
|
||||
value={ hasGradient && type }
|
||||
/>
|
||||
);
|
||||
};
|
||||
const GradientPositionPicker = ( { gradientAST, hasGradient, onChange } ) => {
|
||||
let position = DEFAULT_RADIAL_GRADIENT_POSITION;
|
||||
let positionLeft = '50%';
|
||||
let positionTop = '50%';
|
||||
let positionType = 'position-keyword';
|
||||
if ( gradientAST?.orientation && gradientAST?.orientation[0]?.at?.value?.x?.value ) {
|
||||
positionType = gradientAST.orientation[0].at.value.x.type;
|
||||
if ( positionType !== 'position-keyword' ) {
|
||||
position = gradientAST.orientation[0].at.value.x.value + '% ' + gradientAST.orientation[0].at.value.y.value + '%';
|
||||
positionLeft = gradientAST.orientation[0].at.value.x.value + '%';
|
||||
positionTop = gradientAST.orientation[0].at.value.y.value + '%';
|
||||
} else {
|
||||
position = gradientAST.orientation[0].at.value.x.value + ' ' + gradientAST.orientation[0].at.value.y.value;
|
||||
}
|
||||
}
|
||||
const onPositionChange = ( newPosition ) => {
|
||||
const positionArray = newPosition.split( ' ' );
|
||||
onChange(
|
||||
serializeGradient( {
|
||||
...gradientAST,
|
||||
orientation: [ {
|
||||
type: 'shape',
|
||||
value: gradientAST.orientation[0].value,
|
||||
at: {
|
||||
type: 'position',
|
||||
value: {
|
||||
x: {
|
||||
type: 'position-keyword',
|
||||
value: ( undefined !== positionArray[0] && positionArray[0] ? positionArray[0] : 'center' )
|
||||
},
|
||||
y: {
|
||||
type: 'position-keyword',
|
||||
value: ( undefined !== positionArray[1] && positionArray[1] ? positionArray[1] : 'center' )
|
||||
}
|
||||
}
|
||||
}
|
||||
} ],
|
||||
} )
|
||||
);
|
||||
};
|
||||
const onLeftPositionChange = ( left ) => {
|
||||
onChange(
|
||||
serializeGradient( {
|
||||
...gradientAST,
|
||||
orientation: [ {
|
||||
type: 'shape',
|
||||
value: gradientAST.orientation[0].value,
|
||||
at: {
|
||||
type: 'position',
|
||||
value: {
|
||||
x: {
|
||||
type: '%',
|
||||
value: parseInt( left, 10 ),
|
||||
},
|
||||
y: gradientAST.orientation[0].at.value.y,
|
||||
}
|
||||
}
|
||||
} ],
|
||||
} )
|
||||
);
|
||||
};
|
||||
const onTopPositionChange = ( top ) => {
|
||||
onChange(
|
||||
serializeGradient( {
|
||||
...gradientAST,
|
||||
orientation: [ {
|
||||
type: 'shape',
|
||||
value: gradientAST.orientation[0].value,
|
||||
at: {
|
||||
type: 'position',
|
||||
value: {
|
||||
x: gradientAST.orientation[0].at.value.x,
|
||||
y: {
|
||||
type: '%',
|
||||
value: parseInt( top, 10 ),
|
||||
}
|
||||
}
|
||||
}
|
||||
} ],
|
||||
} )
|
||||
);
|
||||
};
|
||||
|
||||
const onPositionTypeChange = ( type ) => {
|
||||
const positionArray = position.split( ' ' );
|
||||
let positionX = '%' === type ? 50 : 'center';
|
||||
let positionY = '%' === type ? 50 : 'center';
|
||||
if ( positionArray[0] ) {
|
||||
switch ( positionArray[ 0 ] ) {
|
||||
case 'left':
|
||||
positionX = 0;
|
||||
break;
|
||||
case 'right':
|
||||
positionX = '100';
|
||||
break;
|
||||
case 'center':
|
||||
positionX = 50;
|
||||
break;
|
||||
case 0:
|
||||
positionY = 'left';
|
||||
break;
|
||||
case 100:
|
||||
positionY = 'right';
|
||||
break;
|
||||
case 50:
|
||||
positionY = 'center';
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( positionArray[1] ) {
|
||||
switch ( positionArray[ 1 ] ) {
|
||||
case 'top':
|
||||
positionY = 0;
|
||||
break;
|
||||
case 'bottom':
|
||||
positionY = 100;
|
||||
break;
|
||||
case 'center':
|
||||
positionY = 50;
|
||||
break;
|
||||
case 0:
|
||||
positionY = 'top';
|
||||
break;
|
||||
case 100:
|
||||
positionY = 'bottom';
|
||||
break;
|
||||
case 50:
|
||||
positionY = 'center';
|
||||
break;
|
||||
}
|
||||
}
|
||||
onChange(
|
||||
serializeGradient( {
|
||||
...gradientAST,
|
||||
orientation: [ {
|
||||
type: 'shape',
|
||||
value: gradientAST.orientation[0].value,
|
||||
at: {
|
||||
type: 'position',
|
||||
value: {
|
||||
x: {
|
||||
type: type,
|
||||
value: positionX
|
||||
},
|
||||
y: {
|
||||
type: type,
|
||||
value: positionY
|
||||
}
|
||||
}
|
||||
}
|
||||
} ],
|
||||
} )
|
||||
);
|
||||
};
|
||||
if ( ! hasGradient ) {
|
||||
return;
|
||||
}
|
||||
return (
|
||||
<div className={ `components-base-control kadence-gradient-position-control` }>
|
||||
<Flex
|
||||
justify="space-between"
|
||||
className={ 'kadence-gradient-position_header' }
|
||||
>
|
||||
<FlexItem>
|
||||
<label className="kadence-gradient-position__label">{ __( 'Position', 'kadence-blocks' ) }</label>
|
||||
</FlexItem>
|
||||
</Flex>
|
||||
{ positionType === 'position-keyword' && (
|
||||
<div className={ 'kadence-controls-content' }>
|
||||
<SelectControl
|
||||
className="components-custom-gradient-picker__position-picker"
|
||||
// label={ __( 'Position', 'kadence-blocks' ) }
|
||||
// labelPosition="top"
|
||||
onChange={ onPositionChange }
|
||||
options={ GRADIENT_POSITION_OPTIONS }
|
||||
value={ position }
|
||||
/>
|
||||
<Button
|
||||
className={'kadence-control-toggle-advanced only-icon'}
|
||||
label={ __( 'Set custom position', 'kadence-blocks' ) }
|
||||
icon={ settings }
|
||||
onClick={ () => onPositionTypeChange( '%' ) }
|
||||
isPressed={ false }
|
||||
isTertiary={ true }
|
||||
/>
|
||||
</div>
|
||||
) }
|
||||
{ positionType !== 'position-keyword' && (
|
||||
<div className={ 'kadence-controls-content' }>
|
||||
<UnitControl
|
||||
labelPosition="left"
|
||||
label={ __( 'Left', 'kadence-blocks' ) }
|
||||
max={ 100 }
|
||||
min={ 0 }
|
||||
units={ [ { value: '%', label: '%' } ] }
|
||||
value={ positionLeft }
|
||||
onChange={ onLeftPositionChange }
|
||||
/>
|
||||
<UnitControl
|
||||
labelPosition="left"
|
||||
label={ __( 'Top', 'kadence-blocks' ) }
|
||||
max={ 100 }
|
||||
min={ 0 }
|
||||
value={ positionTop }
|
||||
units={ [ { value: '%', label: '%' } ] }
|
||||
onChange={ onTopPositionChange }
|
||||
/>
|
||||
<Button
|
||||
className={'kadence-control-toggle-advanced only-icon'}
|
||||
label={ __( 'Set standard position', 'kadence-blocks' ) }
|
||||
icon={ settings }
|
||||
onClick={ () => onPositionTypeChange( 'position-keyword' ) }
|
||||
isPrimary={true}
|
||||
isPressed={ true }
|
||||
/>
|
||||
</div>
|
||||
) }
|
||||
</div>
|
||||
);
|
||||
};
|
||||
const GradientShapePicker = ( { gradientAST, hasGradient, onChange } ) => {
|
||||
let shape = DEFAULT_RADIAL_GRADIENT_SHAPE;
|
||||
if ( gradientAST?.orientation && gradientAST?.orientation[0]?.type === 'shape' && gradientAST?.orientation[0]?.value ) {
|
||||
shape = gradientAST.orientation[0].value;
|
||||
}
|
||||
const onShapeChange = ( newShape ) => {
|
||||
onChange(
|
||||
serializeGradient( {
|
||||
...gradientAST,
|
||||
orientation: [ {
|
||||
type: 'shape',
|
||||
value: newShape,
|
||||
at: gradientAST.orientation[0].at,
|
||||
} ],
|
||||
} )
|
||||
);
|
||||
};
|
||||
return (
|
||||
<SelectControl
|
||||
className="components-custom-gradient-picker__shape-picker kadence-select-large"
|
||||
label={ __( 'Shape', 'kadence-blocks' ) }
|
||||
labelPosition="top"
|
||||
onChange={ onShapeChange }
|
||||
options={ [
|
||||
{ value: 'ellipse', label: __( 'Ellipse', 'kadence-blocks' ) },
|
||||
{ value: 'circle', label: __( 'Circle', 'kadence-blocks' ) },
|
||||
] }
|
||||
value={ hasGradient && shape }
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default function CustomGradientPicker( {
|
||||
value,
|
||||
onChange,
|
||||
isRenderedInSidebar = false,
|
||||
activePalette = [],
|
||||
} ) {
|
||||
const gradientAST = getGradientAstWithDefault( value );
|
||||
// On radial gradients the bar should display a linear gradient.
|
||||
// On radial gradients the bar represents a slice of the gradient from the center until the outside.
|
||||
// On liner gradients the bar represents the color stops from left to right independently of the angle.
|
||||
const background = getLinearGradientRepresentation( gradientAST );
|
||||
const hasGradient = gradientAST.value !== DEFAULT_GRADIENT;
|
||||
// Control points color option may be hex from presets, custom colors will be rgb.
|
||||
// The position should always be a percentage.
|
||||
const controlPoints = gradientAST.colorStops.map( ( colorStop ) => ( {
|
||||
color: getStopCssColor( colorStop ),
|
||||
position: parseInt( colorStop.length.value ),
|
||||
} ) );
|
||||
return (
|
||||
<div className={ 'components-base-control components-custom-gradient-picker kadence-gradient-control' }>
|
||||
<div className='wrap-components-custom-gradient-picker'>
|
||||
<CustomGradientBar
|
||||
isRenderedInSidebar={isRenderedInSidebar}
|
||||
background={ background }
|
||||
hasGradient={ hasGradient }
|
||||
value={ controlPoints }
|
||||
activePalette={ activePalette }
|
||||
onChange={ ( newControlPoints ) => {
|
||||
onChange(
|
||||
serializeGradient(
|
||||
getGradientAstWithControlPoints(
|
||||
gradientAST,
|
||||
newControlPoints
|
||||
)
|
||||
)
|
||||
);
|
||||
} }
|
||||
/>
|
||||
</div>
|
||||
<Flex
|
||||
gap={ 3 }
|
||||
className="components-custom-gradient-picker__ui-line"
|
||||
>
|
||||
<div className='components-custom-gradient-picker__item components-custom-gradient-picker-type'>
|
||||
<GradientTypePicker
|
||||
gradientAST={ gradientAST }
|
||||
hasGradient={ hasGradient }
|
||||
onChange={ onChange }
|
||||
/>
|
||||
</div>
|
||||
{ gradientAST.type === 'linear-gradient' && (
|
||||
<div className='components-custom-gradient-picker__item components-custom-gradient-picker-angle'>
|
||||
<GradientAnglePicker
|
||||
gradientAST={ gradientAST }
|
||||
hasGradient={ hasGradient }
|
||||
onChange={ onChange }
|
||||
/>
|
||||
</div>
|
||||
) }
|
||||
{ gradientAST.type === 'radial-gradient' && (
|
||||
<div className='components-custom-gradient-picker__item components-custom-gradient-picker-shape'>
|
||||
<GradientShapePicker
|
||||
gradientAST={ gradientAST }
|
||||
hasGradient={ hasGradient }
|
||||
onChange={ onChange }
|
||||
/>
|
||||
</div>
|
||||
) }
|
||||
</Flex>
|
||||
{ gradientAST.type === 'radial-gradient' && (
|
||||
<Flex
|
||||
gap={ 3 }
|
||||
className="components-custom-gradient-picker__ui-line"
|
||||
>
|
||||
<div className='components-custom-gradient-picker__item components-custom-gradient-picker-position'>
|
||||
<GradientPositionPicker
|
||||
gradientAST={ gradientAST }
|
||||
hasGradient={ hasGradient }
|
||||
onChange={ onChange }
|
||||
/>
|
||||
</div>
|
||||
</Flex>
|
||||
) }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,517 @@
|
||||
// Copyright (c) 2014 Rafael Caricio. All rights reserved.
|
||||
// Use of this source code is governed by (The MIT License).
|
||||
|
||||
var GradientParser = (GradientParser || {});
|
||||
|
||||
GradientParser.stringify = (function() {
|
||||
|
||||
var visitor = {
|
||||
|
||||
'visit_linear-gradient': function(node) {
|
||||
return visitor.visit_gradient(node);
|
||||
},
|
||||
|
||||
'visit_repeating-linear-gradient': function(node) {
|
||||
return visitor.visit_gradient(node);
|
||||
},
|
||||
|
||||
'visit_radial-gradient': function(node) {
|
||||
return visitor.visit_gradient(node);
|
||||
},
|
||||
|
||||
'visit_repeating-radial-gradient': function(node) {
|
||||
return visitor.visit_gradient(node);
|
||||
},
|
||||
|
||||
'visit_gradient': function(node) {
|
||||
var orientation = visitor.visit(node.orientation);
|
||||
if (orientation) {
|
||||
orientation += ', ';
|
||||
}
|
||||
|
||||
return node.type + '(' + orientation + visitor.visit(node.colorStops) + ')';
|
||||
},
|
||||
|
||||
'visit_shape': function(node) {
|
||||
var result = node.value,
|
||||
at = visitor.visit(node.at),
|
||||
style = visitor.visit(node.style);
|
||||
|
||||
if (style) {
|
||||
result += ' ' + style;
|
||||
}
|
||||
|
||||
if (at) {
|
||||
result += ' at ' + at;
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
'visit_default-radial': function(node) {
|
||||
var result = '',
|
||||
at = visitor.visit(node.at);
|
||||
|
||||
if (at) {
|
||||
result += at;
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
'visit_extent-keyword': function(node) {
|
||||
var result = node.value,
|
||||
at = visitor.visit(node.at);
|
||||
|
||||
if (at) {
|
||||
result += ' at ' + at;
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
'visit_position-keyword': function(node) {
|
||||
return node.value;
|
||||
},
|
||||
|
||||
'visit_position': function(node) {
|
||||
return visitor.visit(node.value.x) + ' ' + visitor.visit(node.value.y);
|
||||
},
|
||||
|
||||
'visit_%': function(node) {
|
||||
return node.value + '%';
|
||||
},
|
||||
|
||||
'visit_em': function(node) {
|
||||
return node.value + 'em';
|
||||
},
|
||||
|
||||
'visit_px': function(node) {
|
||||
return node.value + 'px';
|
||||
},
|
||||
|
||||
'visit_literal': function(node) {
|
||||
return visitor.visit_color(node.value, node);
|
||||
},
|
||||
|
||||
'visit_hex': function(node) {
|
||||
return visitor.visit_color('#' + node.value, node);
|
||||
},
|
||||
|
||||
'visit_rgb': function(node) {
|
||||
return visitor.visit_color('rgb(' + node.value.join(', ') + ')', node);
|
||||
},
|
||||
|
||||
'visit_rgba': function(node) {
|
||||
return visitor.visit_color('rgba(' + node.value.join(', ') + ')', node);
|
||||
},
|
||||
|
||||
'visit_color': function(resultColor, node) {
|
||||
var result = resultColor,
|
||||
length = visitor.visit(node.length);
|
||||
|
||||
if (length) {
|
||||
result += ' ' + length;
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
'visit_angular': function(node) {
|
||||
return node.value + 'deg';
|
||||
},
|
||||
|
||||
'visit_directional': function(node) {
|
||||
return 'to ' + node.value;
|
||||
},
|
||||
|
||||
'visit_array': function(elements) {
|
||||
var result = '',
|
||||
size = elements.length;
|
||||
|
||||
elements.forEach(function(element, i) {
|
||||
result += visitor.visit(element);
|
||||
if (i < size - 1) {
|
||||
result += ', ';
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
'visit': function(element) {
|
||||
if (!element) {
|
||||
return '';
|
||||
}
|
||||
var result = '';
|
||||
|
||||
if (element instanceof Array) {
|
||||
return visitor.visit_array(element, result);
|
||||
} else if (element.type) {
|
||||
var nodeVisitor = visitor['visit_' + element.type];
|
||||
if (nodeVisitor) {
|
||||
return nodeVisitor(element);
|
||||
} else {
|
||||
throw Error('Missing visitor visit_' + element.type);
|
||||
}
|
||||
} else {
|
||||
throw Error('Invalid node.');
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
return function(root) {
|
||||
return visitor.visit(root);
|
||||
};
|
||||
})();
|
||||
|
||||
// Copyright (c) 2014 Rafael Caricio. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
var GradientParser = (GradientParser || {});
|
||||
|
||||
GradientParser.parse = (function() {
|
||||
|
||||
var tokens = {
|
||||
linearGradient: /^(\-(webkit|o|ms|moz)\-)?(linear\-gradient)/i,
|
||||
repeatingLinearGradient: /^(\-(webkit|o|ms|moz)\-)?(repeating\-linear\-gradient)/i,
|
||||
radialGradient: /^(\-(webkit|o|ms|moz)\-)?(radial\-gradient)/i,
|
||||
repeatingRadialGradient: /^(\-(webkit|o|ms|moz)\-)?(repeating\-radial\-gradient)/i,
|
||||
sideOrCorner: /^to (left (top|bottom)|right (top|bottom)|left|right|top|bottom)/i,
|
||||
extentKeywords: /^(closest\-side|closest\-corner|farthest\-side|farthest\-corner|contain|cover)/,
|
||||
positionKeywords: /^(left|center|right|top|bottom)/i,
|
||||
pixelValue: /^(-?(([0-9]*\.[0-9]+)|([0-9]+\.?)))px/,
|
||||
percentageValue: /^(-?(([0-9]*\.[0-9]+)|([0-9]+\.?)))\%/,
|
||||
emValue: /^(-?(([0-9]*\.[0-9]+)|([0-9]+\.?)))em/,
|
||||
angleValue: /^(-?(([0-9]*\.[0-9]+)|([0-9]+\.?)))deg/,
|
||||
startCall: /^\(/,
|
||||
endCall: /^\)/,
|
||||
comma: /^,/,
|
||||
hexColor: /^\#([0-9a-fA-F]+)/,
|
||||
literalColor: /^([a-zA-Z]+)/,
|
||||
rgbColor: /^rgb/i,
|
||||
rgbaColor: /^rgba/i,
|
||||
varColor: /^var/i,
|
||||
number: /^(([0-9]*\.[0-9]+)|([0-9]+\.?))/,
|
||||
variable: /var\(([a-zA-Z-0-9_#,\s]+)\)/
|
||||
};
|
||||
|
||||
var input = '';
|
||||
|
||||
function error(msg) {
|
||||
var err = new Error(input + ': ' + msg);
|
||||
err.source = input;
|
||||
throw err;
|
||||
}
|
||||
|
||||
function getAST() {
|
||||
var ast = matchListDefinitions();
|
||||
|
||||
if (input.length > 0) {
|
||||
error('Invalid input not EOF');
|
||||
}
|
||||
|
||||
return ast;
|
||||
}
|
||||
|
||||
function matchListDefinitions() {
|
||||
return matchListing(matchDefinition);
|
||||
}
|
||||
|
||||
function matchDefinition() {
|
||||
return matchGradient(
|
||||
'linear-gradient',
|
||||
tokens.linearGradient,
|
||||
matchLinearOrientation) ||
|
||||
|
||||
matchGradient(
|
||||
'repeating-linear-gradient',
|
||||
tokens.repeatingLinearGradient,
|
||||
matchLinearOrientation) ||
|
||||
|
||||
matchGradient(
|
||||
'radial-gradient',
|
||||
tokens.radialGradient,
|
||||
matchListRadialOrientations) ||
|
||||
|
||||
matchGradient(
|
||||
'repeating-radial-gradient',
|
||||
tokens.repeatingRadialGradient,
|
||||
matchListRadialOrientations);
|
||||
}
|
||||
|
||||
function matchGradient(gradientType, pattern, orientationMatcher) {
|
||||
return matchCall(pattern, function(captures) {
|
||||
|
||||
var orientation = orientationMatcher();
|
||||
if (orientation) {
|
||||
if (!scan(tokens.comma)) {
|
||||
error('Missing comma before color stops');
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
type: gradientType,
|
||||
orientation: orientation,
|
||||
colorStops: matchListing(matchColorStop)
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function matchCall(pattern, callback) {
|
||||
var captures = scan(pattern);
|
||||
|
||||
if (captures) {
|
||||
if (!scan(tokens.startCall)) {
|
||||
error('Missing (');
|
||||
}
|
||||
|
||||
var result = callback(captures);
|
||||
if (!scan(tokens.endCall)) {
|
||||
error('Missing )');
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
function matchLinearOrientation() {
|
||||
return matchSideOrCorner() ||
|
||||
matchAngle();
|
||||
}
|
||||
|
||||
function matchSideOrCorner() {
|
||||
return match('directional', tokens.sideOrCorner, 1);
|
||||
}
|
||||
|
||||
function matchAngle() {
|
||||
return match('angular', tokens.angleValue, 1);
|
||||
}
|
||||
|
||||
function matchListRadialOrientations() {
|
||||
var radialOrientations,
|
||||
radialOrientation = matchRadialOrientation(),
|
||||
lookaheadCache;
|
||||
if (radialOrientation) {
|
||||
radialOrientations = [];
|
||||
radialOrientations.push(radialOrientation);
|
||||
|
||||
lookaheadCache = input;
|
||||
if (scan(tokens.comma)) {
|
||||
radialOrientation = matchRadialOrientation();
|
||||
if (radialOrientation) {
|
||||
radialOrientations.push(radialOrientation);
|
||||
} else {
|
||||
input = lookaheadCache;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return radialOrientations;
|
||||
}
|
||||
|
||||
function matchRadialOrientation() {
|
||||
var radialType = matchCircle() ||
|
||||
matchEllipse();
|
||||
|
||||
if (radialType) {
|
||||
radialType.at = matchAtPosition();
|
||||
} else {
|
||||
var extent = matchExtentKeyword();
|
||||
if (extent) {
|
||||
radialType = extent;
|
||||
var positionAt = matchAtPosition();
|
||||
if (positionAt) {
|
||||
radialType.at = positionAt;
|
||||
}
|
||||
} else {
|
||||
var defaultPosition = matchPositioning();
|
||||
if (defaultPosition) {
|
||||
radialType = {
|
||||
type: 'default-radial',
|
||||
at: defaultPosition
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return radialType;
|
||||
}
|
||||
|
||||
function matchCircle() {
|
||||
var circle = match('shape', /^(circle)/i, 0);
|
||||
|
||||
if (circle) {
|
||||
circle.style = matchLength() || matchExtentKeyword();
|
||||
}
|
||||
|
||||
return circle;
|
||||
}
|
||||
|
||||
function matchEllipse() {
|
||||
var ellipse = match('shape', /^(ellipse)/i, 0);
|
||||
|
||||
if (ellipse) {
|
||||
ellipse.style = matchDistance() || matchExtentKeyword();
|
||||
}
|
||||
|
||||
return ellipse;
|
||||
}
|
||||
|
||||
function matchExtentKeyword() {
|
||||
return match('extent-keyword', tokens.extentKeywords, 1);
|
||||
}
|
||||
|
||||
function matchAtPosition() {
|
||||
if (match('position', /^at/, 0)) {
|
||||
var positioning = matchPositioning();
|
||||
|
||||
if (!positioning) {
|
||||
error('Missing positioning value');
|
||||
}
|
||||
|
||||
return positioning;
|
||||
}
|
||||
}
|
||||
|
||||
function matchPositioning() {
|
||||
var location = matchCoordinates();
|
||||
|
||||
if (location.x || location.y) {
|
||||
return {
|
||||
type: 'position',
|
||||
value: location
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function matchCoordinates() {
|
||||
return {
|
||||
x: matchDistance(),
|
||||
y: matchDistance()
|
||||
};
|
||||
}
|
||||
|
||||
function matchListing(matcher) {
|
||||
var captures = matcher(),
|
||||
result = [];
|
||||
|
||||
if (captures) {
|
||||
result.push(captures);
|
||||
while (scan(tokens.comma)) {
|
||||
captures = matcher();
|
||||
if (captures) {
|
||||
result.push(captures);
|
||||
} else {
|
||||
error('One extra comma');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function matchColorStop() {
|
||||
var color = matchColor();
|
||||
|
||||
if (!color) {
|
||||
error('Expected color definition');
|
||||
}
|
||||
|
||||
color.length = matchDistance();
|
||||
return color;
|
||||
}
|
||||
|
||||
function matchColor() {
|
||||
return matchHexColor() ||
|
||||
matchRGBAColor() ||
|
||||
matchRGBColor() ||
|
||||
matchVARColor() ||
|
||||
matchLiteralColor();
|
||||
}
|
||||
|
||||
function matchLiteralColor() {
|
||||
return match('literal', tokens.literalColor, 0);
|
||||
}
|
||||
|
||||
function matchVARColor() {
|
||||
return match('literal', tokens.variable, 0);
|
||||
}
|
||||
|
||||
function matchHexColor() {
|
||||
return match('hex', tokens.hexColor, 1);
|
||||
}
|
||||
|
||||
function matchRGBColor() {
|
||||
return matchCall(tokens.rgbColor, function() {
|
||||
return {
|
||||
type: 'rgb',
|
||||
value: matchListing(matchNumber)
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function matchRGBAColor() {
|
||||
return matchCall(tokens.rgbaColor, function() {
|
||||
return {
|
||||
type: 'rgba',
|
||||
value: matchListing(matchNumber)
|
||||
};
|
||||
});
|
||||
}
|
||||
function matchNumber() {
|
||||
return scan(tokens.number)[1];
|
||||
}
|
||||
|
||||
function matchDistance() {
|
||||
return match('%', tokens.percentageValue, 1) ||
|
||||
matchPositionKeyword() ||
|
||||
matchLength();
|
||||
}
|
||||
|
||||
function matchPositionKeyword() {
|
||||
return match('position-keyword', tokens.positionKeywords, 1);
|
||||
}
|
||||
|
||||
function matchLength() {
|
||||
return match('px', tokens.pixelValue, 1) ||
|
||||
match('em', tokens.emValue, 1);
|
||||
}
|
||||
|
||||
function match(type, pattern, captureIndex) {
|
||||
var captures = scan(pattern);
|
||||
if (captures) {
|
||||
return {
|
||||
type: type,
|
||||
value: captures[captureIndex]
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function scan(regexp) {
|
||||
var captures,
|
||||
blankCaptures;
|
||||
|
||||
blankCaptures = /^[\n\r\t\s]+/.exec(input);
|
||||
if (blankCaptures) {
|
||||
consume(blankCaptures[0].length);
|
||||
}
|
||||
captures = regexp.exec(input);
|
||||
if (captures) {
|
||||
consume(captures[0].length);
|
||||
}
|
||||
|
||||
return captures;
|
||||
}
|
||||
|
||||
function consume(size) {
|
||||
input = input.substr(size);
|
||||
}
|
||||
|
||||
return function(code) {
|
||||
input = code.toString();
|
||||
return getAST();
|
||||
};
|
||||
})();
|
||||
|
||||
exports.parse = GradientParser.parse;
|
||||
exports.stringify = GradientParser.stringify;
|
||||
@@ -0,0 +1,55 @@
|
||||
export function serializeGradientColor( { type, value } ) {
|
||||
if ( type === 'literal' ) {
|
||||
return value;
|
||||
}
|
||||
if ( type === 'hex' ) {
|
||||
return `#${ value }`;
|
||||
}
|
||||
return `${ type }(${ value.join( ',' ) })`;
|
||||
}
|
||||
|
||||
export function serializeGradientPosition( position ) {
|
||||
if ( ! position ) {
|
||||
return '';
|
||||
}
|
||||
const { value, type } = position;
|
||||
return `${ value }${ type }`;
|
||||
}
|
||||
|
||||
export function serializeGradientColorStop( { type, value, length } ) {
|
||||
return `${ serializeGradientColor( {
|
||||
type,
|
||||
value,
|
||||
} ) } ${ serializeGradientPosition( length ) }`;
|
||||
}
|
||||
|
||||
export function serializeGradientOrientation( type, orientation ) {
|
||||
if ( 'radial-gradient' === type ) {
|
||||
if ( ! orientation || ! orientation[0] || orientation[0].type !== 'shape' ) {
|
||||
return;
|
||||
}
|
||||
if ( '%' === orientation[0].at.value.x.type ) {
|
||||
return `${ orientation[0].value } at ${ orientation[0].at.value.x.value }% ${ orientation[0].at.value.y.value }%`;
|
||||
}
|
||||
return `${ orientation[0].value } at ${ orientation[0].at.value.x.value } ${ orientation[0].at.value.y.value }`;
|
||||
}
|
||||
if ( ! orientation || orientation.type !== 'angular' ) {
|
||||
return;
|
||||
}
|
||||
return `${ orientation.value }deg`;
|
||||
}
|
||||
|
||||
export function serializeGradient( { type, orientation, colorStops } ) {
|
||||
const serializedOrientation = serializeGradientOrientation( type, orientation );
|
||||
const serializedColorStops = colorStops
|
||||
.sort( ( colorStop1, colorStop2 ) => {
|
||||
return (
|
||||
( colorStop1?.length?.value ?? 0 ) -
|
||||
( colorStop2?.length?.value ?? 0 )
|
||||
);
|
||||
} )
|
||||
.map( serializeGradientColorStop );
|
||||
return `${ type }(${ [ serializedOrientation, ...serializedColorStops ]
|
||||
.filter( Boolean )
|
||||
.join( ',' ) })`;
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import gradientParser from './parser';
|
||||
import { colord, extend } from 'colord';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import {
|
||||
DEFAULT_GRADIENT,
|
||||
HORIZONTAL_GRADIENT_ORIENTATION,
|
||||
DIRECTIONAL_ORIENTATION_ANGLE_MAP,
|
||||
} from './constants';
|
||||
import { serializeGradient } from './serializer';
|
||||
|
||||
|
||||
export function getLinearGradientRepresentation( gradientAST ) {
|
||||
return serializeGradient( {
|
||||
type: 'linear-gradient',
|
||||
orientation: HORIZONTAL_GRADIENT_ORIENTATION,
|
||||
colorStops: gradientAST.colorStops,
|
||||
} );
|
||||
}
|
||||
|
||||
function hasUnsupportedLength( item ) {
|
||||
return item.length === undefined || item.length.type !== '%';
|
||||
}
|
||||
|
||||
export function getGradientAstWithDefault( value ) {
|
||||
// gradientAST will contain the gradient AST as parsed by gradient-parser npm module.
|
||||
// More information of its structure available at https://www.npmjs.com/package/gradient-parser#ast.
|
||||
let gradientAST;
|
||||
try {
|
||||
gradientAST = gradientParser.parse( value )[ 0 ];
|
||||
gradientAST.value = value;
|
||||
} catch ( error ) {
|
||||
gradientAST = gradientParser.parse( DEFAULT_GRADIENT )[ 0 ];
|
||||
gradientAST.value = DEFAULT_GRADIENT;
|
||||
}
|
||||
|
||||
if ( gradientAST.orientation?.type === 'directional' ) {
|
||||
gradientAST.orientation.type = 'angular';
|
||||
gradientAST.orientation.value =
|
||||
DIRECTIONAL_ORIENTATION_ANGLE_MAP[
|
||||
gradientAST.orientation.value
|
||||
].toString();
|
||||
}
|
||||
|
||||
if ( gradientAST.colorStops.some( hasUnsupportedLength ) ) {
|
||||
const { colorStops } = gradientAST;
|
||||
const step = 100 / ( colorStops.length - 1 );
|
||||
colorStops.forEach( ( stop, index ) => {
|
||||
stop.length = {
|
||||
value: step * index,
|
||||
type: '%',
|
||||
};
|
||||
} );
|
||||
gradientAST.value = serializeGradient( gradientAST );
|
||||
}
|
||||
|
||||
return gradientAST;
|
||||
}
|
||||
|
||||
export function getGradientAstWithControlPoints(
|
||||
gradientAST,
|
||||
newControlPoints
|
||||
) {
|
||||
return {
|
||||
...gradientAST,
|
||||
colorStops: newControlPoints.map( ( { position, color } ) => {
|
||||
if ( color.startsWith( 'var(' ) ) {
|
||||
return {
|
||||
length: {
|
||||
type: '%',
|
||||
value: position?.toString(),
|
||||
},
|
||||
type: 'literal',
|
||||
value: color,
|
||||
};
|
||||
}
|
||||
const { r, g, b, a } = colord( color ).toRgb();
|
||||
return {
|
||||
length: {
|
||||
type: '%',
|
||||
value: position?.toString(),
|
||||
},
|
||||
type: a < 1 ? 'rgba' : 'rgb',
|
||||
value: a < 1 ? [ r, g, b, a ] : [ r, g, b ],
|
||||
};
|
||||
} ),
|
||||
};
|
||||
}
|
||||
|
||||
export function getStopCssColor( colorStop ) {
|
||||
switch ( colorStop.type ) {
|
||||
case 'hex':
|
||||
return `#${ colorStop.value }`;
|
||||
case 'literal':
|
||||
return colorStop.value;
|
||||
case 'rgb':
|
||||
case 'rgba':
|
||||
return `${ colorStop.type }(${ colorStop.value.join( ',' ) })`;
|
||||
default:
|
||||
// Should be unreachable if passing an AST from gradient-parser.
|
||||
// See https://github.com/rafaelcaricio/gradient-parser#ast.
|
||||
return 'transparent';
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
68
wp-content/themes/kadence/inc/customizer/react/src/index.js
Normal file
68
wp-content/themes/kadence/inc/customizer/react/src/index.js
Normal file
@@ -0,0 +1,68 @@
|
||||
/* global wp */
|
||||
import { Base } from './customizer.js';
|
||||
import { BaseControl } from './base/control.js';
|
||||
import { ColorControl } from './color/control.js';
|
||||
import { PaletteControl } from './palette/control.js';
|
||||
import { RangeControl } from './range/control.js';
|
||||
import { SwitchControl } from './switch/control.js';
|
||||
import { RadioIconControl } from './radio-icon/control.js';
|
||||
import { MultiRadioIconControl } from './multi-radio-icon/control.js';
|
||||
import { BuilderControl } from './layout-builder/control.js';
|
||||
import { AvailableControl } from './available/control.js';
|
||||
import { BackgroundControl } from './background/control.js';
|
||||
import { BorderControl } from './border/control.js';
|
||||
import { BordersControl } from './borders/control.js';
|
||||
import { TypographyControl } from './typography/control.js';
|
||||
import { TitleControl } from './title/control.js';
|
||||
import { FocusButtonControl } from './focus-button/control.js';
|
||||
import { ColorLinkControl } from './color-link/control.js';
|
||||
import { TextControl } from './text/control.js';
|
||||
import { TextareaControl } from './textarea/control.js';
|
||||
import { MeasureControl } from './measure/control.js';
|
||||
import { EditorControl } from './editor/control.js';
|
||||
import { SocialControl } from './social/control.js';
|
||||
import { ContactControl } from './contact/control.js';
|
||||
import { CheckIconControl } from './check-icon/control.js';
|
||||
import { SelectControl } from './select/control.js';
|
||||
import { SorterControl } from './sorter/control.js';
|
||||
import { RowControl } from './row-layout/control.js';
|
||||
import { TabsControl } from './tabs/control.js';
|
||||
import { BoxShadowControl } from './boxshadow/control.js';
|
||||
|
||||
wp.customize.controlConstructor.kadence_shadow_control = BoxShadowControl;
|
||||
wp.customize.controlConstructor.kadence_tab_control = TabsControl;
|
||||
wp.customize.controlConstructor.kadence_borders_control = BordersControl;
|
||||
wp.customize.controlConstructor.kadence_row_control = RowControl;
|
||||
wp.customize.controlConstructor.kadence_sorter_control = SorterControl;
|
||||
wp.customize.controlConstructor.kadence_select_control = SelectControl;
|
||||
wp.customize.controlConstructor.kadence_check_icon_control = CheckIconControl;
|
||||
wp.customize.controlConstructor.kadence_contact_control = ContactControl;
|
||||
wp.customize.controlConstructor.kadence_social_control = SocialControl;
|
||||
wp.customize.controlConstructor.kadence_editor_control = EditorControl;
|
||||
wp.customize.controlConstructor.kadence_measure_control = MeasureControl;
|
||||
wp.customize.controlConstructor.kadence_text_control = TextControl;
|
||||
wp.customize.controlConstructor.kadence_textarea_control = TextareaControl;
|
||||
wp.customize.controlConstructor.kadence_color_link_control = ColorLinkControl;
|
||||
wp.customize.controlConstructor.kadence_focus_button_control = FocusButtonControl;
|
||||
wp.customize.controlConstructor.kadence_title_control = TitleControl;
|
||||
wp.customize.controlConstructor.kadence_typography_control = TypographyControl;
|
||||
wp.customize.controlConstructor.kadence_border_control = BorderControl;
|
||||
wp.customize.controlConstructor.kadence_background_control = BackgroundControl;
|
||||
wp.customize.controlConstructor.kadence_color_palette_control = PaletteControl;
|
||||
wp.customize.controlConstructor.kadence_available_control = AvailableControl;
|
||||
wp.customize.controlConstructor.kadence_builder_control = BuilderControl;
|
||||
wp.customize.controlConstructor.kadence_color_control = ColorControl;
|
||||
wp.customize.controlConstructor.kadence_range_control = RangeControl;
|
||||
wp.customize.controlConstructor.kadence_switch_control = SwitchControl;
|
||||
wp.customize.controlConstructor.kadence_radio_icon_control = RadioIconControl;
|
||||
wp.customize.controlConstructor.kadence_multi_radio_icon_control = MultiRadioIconControl;
|
||||
|
||||
window.addEventListener( 'load', () => {
|
||||
let deviceButtons = document.querySelector('#customize-footer-actions .devices' );
|
||||
deviceButtons.addEventListener( 'click', function(e) {
|
||||
let event = new CustomEvent( 'kadenceChangedRepsonsivePreview', {
|
||||
'detail': e.target.dataset.device
|
||||
} );
|
||||
document.dispatchEvent( event );
|
||||
} );
|
||||
} );
|
||||
@@ -0,0 +1,101 @@
|
||||
/* jshint esversion: 6 */
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
import ResponsiveControl from '../common/responsive.js';
|
||||
import Icons from '../common/icons.js';
|
||||
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
const { ButtonGroup, Dashicon, Popover, Tooltip, Button } = wp.components;
|
||||
|
||||
const { Component, Fragment } = wp.element;
|
||||
class AddComponent extends Component {
|
||||
constructor() {
|
||||
super( ...arguments );
|
||||
this.addItem = this.addItem.bind( this );
|
||||
this.state = {
|
||||
isVisible: false,
|
||||
}
|
||||
}
|
||||
addItem( item, row, column ) {
|
||||
this.setState( { isVisible: false } );
|
||||
let updateItems = this.props.list;
|
||||
let theitem = [ {
|
||||
id: item,
|
||||
} ];
|
||||
updateItems.push( {
|
||||
id: item,
|
||||
});
|
||||
this.props.setList( updateItems );
|
||||
}
|
||||
render() {
|
||||
const renderItems = ( item, row, column ) => {
|
||||
let available = true;
|
||||
this.props.controlParams.rows.map( ( zone ) => {
|
||||
Object.keys( this.props.settings[zone] ).map( ( area ) => {
|
||||
if ( this.props.settings[zone][area].includes( item ) ) {
|
||||
available = false;
|
||||
}
|
||||
} );
|
||||
} );
|
||||
return (
|
||||
<Fragment>
|
||||
{ available && (
|
||||
<Button
|
||||
isTertiary
|
||||
className={ 'builder-add-btn' }
|
||||
onClick={ () => {
|
||||
this.addItem( item, row, column );
|
||||
} }
|
||||
>
|
||||
{ ( undefined !== this.props.choices[ item ] && undefined !== this.props.choices[ item ].name ? this.props.choices[ item ].name : '' ) }
|
||||
</Button>
|
||||
) }
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
const toggleClose = () => {
|
||||
if ( this.state.isVisible === true ) {
|
||||
this.setState( { isVisible: false } );
|
||||
}
|
||||
};
|
||||
let classForAdd = 'kadence-builder-add-item';
|
||||
|
||||
if ( 'header_desktop_items' === this.props.controlParams.group && 'right' === this.props.location ) {
|
||||
classForAdd = classForAdd + ' center-on-left';
|
||||
}
|
||||
if ( 'header_desktop_items' === this.props.controlParams.group && 'left' === this.props.location ) {
|
||||
classForAdd = classForAdd + ' center-on-right';
|
||||
}
|
||||
if ( 'header_desktop_items' === this.props.controlParams.group && 'left_center' === this.props.location ) {
|
||||
classForAdd = classForAdd + ' right-center-on-right';
|
||||
}
|
||||
if ( 'header_desktop_items' === this.props.controlParams.group && 'right_center' === this.props.location ) {
|
||||
classForAdd = classForAdd + ' left-center-on-left';
|
||||
}
|
||||
return (
|
||||
<div className={ classForAdd } key={ this.props.id }>
|
||||
{ this.state.isVisible && (
|
||||
<Popover position="top" inline={true} className="kadence-popover-add-builder" onClose={ toggleClose }>
|
||||
<div className="kadence-popover-builder-list">
|
||||
<ButtonGroup className="kadence-radio-container-control">
|
||||
{ Object.keys( this.props.choices ).map( ( item ) => {
|
||||
return renderItems( item, this.props.row, this.props.column );
|
||||
} ) }
|
||||
</ButtonGroup>
|
||||
</div>
|
||||
</Popover>
|
||||
) }
|
||||
<Button
|
||||
className="kadence-builder-item-add-icon"
|
||||
onClick={ () => {
|
||||
this.setState( { isVisible: true } );
|
||||
} }
|
||||
>
|
||||
<Dashicon icon="plus"/>
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
export default AddComponent;
|
||||
@@ -0,0 +1,239 @@
|
||||
/* jshint esversion: 6 */
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
import ResponsiveControl from '../common/responsive.js';
|
||||
import Icons from '../common/icons.js';
|
||||
|
||||
import RowComponent from './row-component';
|
||||
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
const { ButtonGroup, Dashicon, Tooltip, Button } = wp.components;
|
||||
|
||||
const { Component, Fragment } = wp.element;
|
||||
class BuilderComponent extends Component {
|
||||
constructor() {
|
||||
super( ...arguments );
|
||||
this.updateValues = this.updateValues.bind( this );
|
||||
this.onDragEnd = this.onDragEnd.bind( this );
|
||||
this.onAddItem = this.onAddItem.bind( this );
|
||||
this.onDragStart = this.onDragStart.bind( this );
|
||||
this.onDragStop = this.onDragStop.bind( this );
|
||||
this.removeItem = this.removeItem.bind( this );
|
||||
this.focusPanel = this.focusPanel.bind( this );
|
||||
this.focusItem = this.focusItem.bind( this );
|
||||
this.onFooterUpdate = this.onFooterUpdate.bind( this );
|
||||
this.linkColumns();
|
||||
let value = this.props.control.setting.get();
|
||||
let baseDefault = {};
|
||||
this.defaultValue = this.props.control.params.default ? {
|
||||
...baseDefault,
|
||||
...this.props.control.params.default
|
||||
} : baseDefault;
|
||||
value = value ? {
|
||||
...this.defaultValue,
|
||||
...value
|
||||
} : this.defaultValue;
|
||||
let defaultParams = {};
|
||||
this.controlParams = this.props.control.params.input_attrs ? {
|
||||
...defaultParams,
|
||||
...this.props.control.params.input_attrs,
|
||||
} : defaultParams;
|
||||
this.choices = ( kadenceCustomizerControlsData && kadenceCustomizerControlsData.choices && kadenceCustomizerControlsData.choices[ this.controlParams.group ] ? kadenceCustomizerControlsData.choices[ this.controlParams.group ] : [] );
|
||||
this.state = {
|
||||
value: value,
|
||||
};
|
||||
}
|
||||
onDragStart() {
|
||||
var dropzones = document.querySelectorAll( '.kadence-builder-area' );
|
||||
var i;
|
||||
for (i = 0; i < dropzones.length; ++i) {
|
||||
dropzones[i].classList.add( 'kadence-dragging-dropzones' );
|
||||
}
|
||||
}
|
||||
onDragStop() {
|
||||
var dropzones = document.querySelectorAll( '.kadence-builder-area' );
|
||||
var i;
|
||||
for (i = 0; i < dropzones.length; ++i) {
|
||||
dropzones[i].classList.remove( 'kadence-dragging-dropzones' );
|
||||
}
|
||||
}
|
||||
removeItem( item, row, zone ) {
|
||||
let updateState = this.state.value;
|
||||
let update = updateState[ row ];
|
||||
let updateItems = [];
|
||||
{ update[ zone ].length > 0 && (
|
||||
update[ zone ].map( ( old ) => {
|
||||
if ( item !== old ) {
|
||||
updateItems.push( old );
|
||||
}
|
||||
} )
|
||||
) };
|
||||
if ( 'header_desktop_items' === this.controlParams.group && row + '_center' === zone && updateItems.length === 0 ) {
|
||||
if ( update[ row + '_left_center' ].length > 0 ) {
|
||||
update[ row + '_left_center' ].map( ( move ) => {
|
||||
updateState[ row ][ row + '_left' ].push( move );
|
||||
} )
|
||||
updateState[ row ][ row + '_left_center' ] = [];
|
||||
}
|
||||
if ( update[ row + '_right_center' ].length > 0 ) {
|
||||
update[ row + '_right_center' ].map( ( move ) => {
|
||||
updateState[ row ][ row + '_right' ].push( move );
|
||||
} )
|
||||
updateState[ row ][ row + '_right_center' ] = [];
|
||||
}
|
||||
}
|
||||
update[ zone ] = updateItems;
|
||||
updateState[ row ][ zone ] = updateItems;
|
||||
this.setState( { value: updateState } );
|
||||
this.updateValues( updateState );
|
||||
let event = new CustomEvent(
|
||||
'kadenceRemovedBuilderItem', {
|
||||
'detail': this.controlParams.group
|
||||
} );
|
||||
document.dispatchEvent( event );
|
||||
}
|
||||
onDragEnd( row, zone, items ) {
|
||||
let updateState = this.state.value;
|
||||
let update = updateState[ row ];
|
||||
let updateItems = [];
|
||||
{ items.length > 0 && (
|
||||
items.map( ( item ) => {
|
||||
updateItems.push( item.id );
|
||||
} )
|
||||
) };
|
||||
if ( ! this.arraysEqual( update[ zone ], updateItems ) ) {
|
||||
if ( 'header_desktop_items' === this.controlParams.group && row + '_center' === zone && updateItems.length === 0 ) {
|
||||
if ( undefined !== update[ row + '_left_center' ] && update[ row + '_left_center' ].length > 0 ) {
|
||||
update[ row + '_left_center' ].map( ( move ) => {
|
||||
updateState[ row ][ row + '_left' ].push( move );
|
||||
} )
|
||||
updateState[ row ][ row + '_left_center' ] = [];
|
||||
}
|
||||
if ( undefined !== update[ row + '_right_center' ] && update[ row + '_right_center' ].length > 0 ) {
|
||||
update[ row + '_right_center' ].map( ( move ) => {
|
||||
updateState[ row ][ row + '_right' ].push( move );
|
||||
} )
|
||||
updateState[ row ][ row + '_right_center' ] = [];
|
||||
}
|
||||
}
|
||||
update[ zone ] = updateItems;
|
||||
updateState[ row ][ zone ] = updateItems;
|
||||
this.setState( { value: updateState } );
|
||||
this.updateValues( updateState );
|
||||
}
|
||||
}
|
||||
onAddItem( row, zone, items ) {
|
||||
this.onDragEnd( row, zone, items );
|
||||
let event = new CustomEvent(
|
||||
'kadenceRemovedBuilderItem', {
|
||||
'detail': this.controlParams.group
|
||||
} );
|
||||
document.dispatchEvent( event );
|
||||
}
|
||||
onFooterUpdate( row ) {
|
||||
let updateState = this.state.value;
|
||||
let update = updateState[ row ];
|
||||
let removeEvent = false;
|
||||
const columns = parseInt( this.props.customizer.control( 'footer_' + row + '_columns' ).setting.get(), 10 );
|
||||
if ( columns < 5 ) {
|
||||
if ( undefined !== update[ row + '_5' ] && update[ row + '_5' ].length > 0 ) {
|
||||
updateState[ row ][ row + '_5' ] = [];
|
||||
removeEvent = true;
|
||||
}
|
||||
}
|
||||
if ( columns < 4 ) {
|
||||
if ( undefined !== update[ row + '_4' ] && update[ row + '_4' ].length > 0 ) {
|
||||
updateState[ row ][ row + '_4' ] = [];
|
||||
removeEvent = true;
|
||||
}
|
||||
}
|
||||
if ( columns < 3 ) {
|
||||
if ( undefined !== update[ row + '_3' ] && update[ row + '_3' ].length > 0 ) {
|
||||
updateState[ row ][ row + '_3' ] = [];
|
||||
removeEvent = true;
|
||||
}
|
||||
}
|
||||
if ( columns < 2 ) {
|
||||
if ( undefined !== update[ row + '_2' ] && update[ row + '_2' ].length > 0 ) {
|
||||
updateState[ row ][ row + '_2' ] = [];
|
||||
removeEvent = true;
|
||||
}
|
||||
}
|
||||
this.setState( { value: updateState } );
|
||||
this.updateValues( updateState );
|
||||
if ( removeEvent ) {
|
||||
let event = new CustomEvent(
|
||||
'kadenceRemovedBuilderItem', {
|
||||
'detail': this.controlParams.group
|
||||
} );
|
||||
document.dispatchEvent( event );
|
||||
}
|
||||
}
|
||||
arraysEqual( a, b ) {
|
||||
if (a === b) return true;
|
||||
if (a == null || b == null) return false;
|
||||
if (a.length != b.length) return false;
|
||||
for (var i = 0; i < a.length; ++i) {
|
||||
if (a[i] !== b[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
focusPanel( item ) {
|
||||
if ( undefined !== this.props.customizer.section( 'kadence_customizer_' + item ) ) {
|
||||
this.props.customizer.section( 'kadence_customizer_' + item ).focus();
|
||||
}
|
||||
}
|
||||
focusItem( item ) {
|
||||
if ( undefined !== this.props.customizer.section( item ) ) {
|
||||
this.props.customizer.section( item ).focus();
|
||||
}
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div className={ `kadence-control-field kadence-builder-items${ ( this.controlParams.rows.includes( 'popup' ) ? ' kadence-builder-items-with-popup' : '' ) }` }>
|
||||
{ this.controlParams.rows.includes( 'popup' ) && (
|
||||
<RowComponent showDrop={ () => this.onDragStart() } focusPanel={ ( item ) => this.focusPanel( item ) } focusItem={ ( item ) => this.focusItem( item ) } removeItem={ ( remove, row, zone ) => this.removeItem( remove, row, zone ) } onAddItem={ ( updateRow, updateZone, updateItems ) => this.onAddItem( updateRow, updateZone, updateItems ) } hideDrop={ () => this.onDragStop() } onUpdate={ ( updateRow, updateZone, updateItems ) => this.onDragEnd( updateRow, updateZone, updateItems ) } key={ 'popup' } row={ 'popup' } controlParams={ this.controlParams } choices={ this.choices } items={ this.state.value[ 'popup' ] } settings={ this.state.value } />
|
||||
) }
|
||||
<div className="kadence-builder-row-items">
|
||||
{ this.controlParams.rows.map( ( row ) => {
|
||||
if ( 'popup' === row ) {
|
||||
return;
|
||||
}
|
||||
return <RowComponent showDrop={ () => this.onDragStart() } focusPanel={ ( item ) => this.focusPanel( item ) } focusItem={ ( item ) => this.focusItem( item ) } removeItem={ ( remove, row, zone ) => this.removeItem( remove, row, zone ) } hideDrop={ () => this.onDragStop() } onUpdate={ ( updateRow, updateZone, updateItems ) => this.onDragEnd( updateRow, updateZone, updateItems ) } onAddItem={ ( updateRow, updateZone, updateItems ) => this.onAddItem( updateRow, updateZone, updateItems ) } key={ row } row={ row } controlParams={ this.controlParams } choices={ this.choices } customizer={ this.props.customizer } items={ this.state.value[ row ] } settings={ this.state.value } />;
|
||||
} ) }
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
// linkFocusButtons() {
|
||||
// this.props.control.container.on( 'click', '.kadence-builder-areas .kadence-builder-item', function( e ) {
|
||||
// e.preventDefault();
|
||||
// var targetKey = e.target.getAttribute( 'data-section' );
|
||||
// var targetControl = wp.customize.section( targetKey );
|
||||
// if ( targetControl ) targetControl.focus();
|
||||
// } );
|
||||
// }
|
||||
updateValues( value ) {
|
||||
this.props.control.setting.set( {
|
||||
...this.props.control.setting.get(),
|
||||
...value,
|
||||
flag: !this.props.control.setting.get().flag
|
||||
} );
|
||||
}
|
||||
linkColumns() {
|
||||
let self = this;
|
||||
document.addEventListener( 'kadenceUpdateFooterColumns', function( e ) {
|
||||
if ( 'footer_items' === self.controlParams.group ) {
|
||||
self.onFooterUpdate( e.detail );
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
BuilderComponent.propTypes = {
|
||||
control: PropTypes.object.isRequired,
|
||||
customizer: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
export default BuilderComponent;
|
||||
@@ -0,0 +1,11 @@
|
||||
import { createRoot } from '@wordpress/element';
|
||||
import BuilderComponent from './builder-component.js';
|
||||
|
||||
export const BuilderControl = wp.customize.KadenceControl.extend( {
|
||||
renderContent: function renderContent() {
|
||||
let control = this;
|
||||
let root = createRoot( control.container[0] );
|
||||
root.render( <BuilderComponent control={ control } customizer={ wp.customize } /> );
|
||||
// ReactDOM.render( <BuilderComponent control={ control } customizer={ wp.customize } />, control.container[0] );
|
||||
}
|
||||
} );
|
||||
@@ -0,0 +1,79 @@
|
||||
/* jshint esversion: 6 */
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
import ResponsiveControl from '../common/responsive.js';
|
||||
import { ReactSortable } from "react-sortablejs";
|
||||
import Icons from '../common/icons.js';
|
||||
import ItemComponent from './item-component';
|
||||
import AddComponent from './add-component';
|
||||
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
const { ButtonGroup, Dashicon, Tooltip, Button } = wp.components;
|
||||
|
||||
const { Component, Fragment } = wp.element;
|
||||
class DropComponent extends Component {
|
||||
render() {
|
||||
const location = this.props.zone.replace( this.props.row + '_', '');
|
||||
const currentList = ( typeof this.props.items != "undefined" && this.props.items != null && this.props.items.length != null && this.props.items.length > 0 ? this.props.items : [] );
|
||||
let theItems = [];
|
||||
{ currentList.length > 0 && (
|
||||
currentList.map( ( item ) => {
|
||||
theItems.push(
|
||||
{
|
||||
id: item,
|
||||
}
|
||||
)
|
||||
} )
|
||||
) };
|
||||
const currentCenterList = ( typeof this.props.centerItems != "undefined" && this.props.centerItems != null && this.props.centerItems.length != null && this.props.centerItems.length > 0 ? this.props.centerItems : [] );
|
||||
let theCenterItems = [];
|
||||
{ currentCenterList.length > 0 && (
|
||||
currentCenterList.map( ( item ) => {
|
||||
theCenterItems.push(
|
||||
{
|
||||
id: item,
|
||||
}
|
||||
)
|
||||
} )
|
||||
) };
|
||||
return (
|
||||
<div className={ `kadence-builder-area kadence-builder-area-${ location }` } data-location={ this.props.zone }>
|
||||
<p className="kadence-small-label">{ this.props.controlParams.zones[this.props.row][this.props.zone] }</p>
|
||||
{ 'header_desktop_items' === this.props.controlParams.group && 'right' === location && (
|
||||
<Fragment>
|
||||
<ReactSortable animation={100} onStart={ () => this.props.showDrop() } onEnd={ () => this.props.hideDrop() } group={ this.props.controlParams.group } className={ `kadence-builder-drop kadence-builder-sortable-panel kadence-builder-drop-${ location }_center` } list={ theCenterItems } setList={ newState => this.props.onUpdate( this.props.row, this.props.zone + '_center', newState ) } >
|
||||
{ currentCenterList.length > 0 && (
|
||||
currentCenterList.map( ( item, index ) => {
|
||||
return <ItemComponent removeItem={ ( remove ) => this.props.removeItem( remove, this.props.row, this.props.zone + '_center' ) } focusItem={ ( focus ) => this.props.focusItem( focus ) } key={ item } index={ index } item={ item } controlParams={ this.props.controlParams } />;
|
||||
} )
|
||||
) }
|
||||
</ReactSortable>
|
||||
<AddComponent row={ this.props.row } list={ theCenterItems } settings={ this.props.settings } column={ this.props.zone + '_center' } setList={ newState => this.props.onAddItem( this.props.row, this.props.zone + '_center', newState ) } key={ location } location={ location + '_center' } id={ 'add-center-' + location } controlParams={ this.props.controlParams } choices={ this.props.choices } />
|
||||
</Fragment>
|
||||
) }
|
||||
<ReactSortable animation={100} onStart={ () => this.props.showDrop() } onEnd={ () => this.props.hideDrop() } group={ this.props.controlParams.group } className={ `kadence-builder-drop kadence-builder-sortable-panel kadence-builder-drop-${ location }` } list={ theItems } setList={ newState => this.props.onUpdate( this.props.row, this.props.zone, newState ) } >
|
||||
{ currentList.length > 0 && (
|
||||
currentList.map( ( item, index ) => {
|
||||
return <ItemComponent removeItem={ ( remove ) => this.props.removeItem( remove, this.props.row, this.props.zone ) } focusItem={ ( focus ) => this.props.focusItem( focus ) } key={ item } index={ index } item={ item } controlParams={ this.props.controlParams } />;
|
||||
} )
|
||||
) }
|
||||
</ReactSortable>
|
||||
<AddComponent row={ this.props.row } list={ theItems } settings={ this.props.settings } column={ this.props.zone } setList={ newState => this.props.onAddItem( this.props.row, this.props.zone, newState ) } key={ location } location={ location } id={ 'add-' + location } controlParams={ this.props.controlParams } choices={ this.props.choices } />
|
||||
{ 'header_desktop_items' === this.props.controlParams.group && 'left' === location && (
|
||||
<Fragment>
|
||||
<ReactSortable animation={100} onStart={ () => this.props.showDrop() } onEnd={ () => this.props.hideDrop() } group={ this.props.controlParams.group } className={ `kadence-builder-drop kadence-builder-sortable-panel kadence-builder-drop-${ location }_center` } list={ theCenterItems } setList={ newState => this.props.onUpdate( this.props.row, this.props.zone + '_center', newState ) } >
|
||||
{ currentCenterList.length > 0 && (
|
||||
currentCenterList.map( ( item, index ) => {
|
||||
return <ItemComponent removeItem={ ( remove ) => this.props.removeItem( remove, this.props.row, this.props.zone + '_center' ) } focusItem={ ( focus ) => this.props.focusItem( focus ) } key={ item } index={ index } item={ item } controlParams={ this.props.controlParams } />;
|
||||
} )
|
||||
) }
|
||||
</ReactSortable>
|
||||
<AddComponent row={ this.props.row } list={ theCenterItems } settings={ this.props.settings } column={ this.props.zone + '_center' } setList={ newState => this.props.onAddItem( this.props.row, this.props.zone + '_center', newState ) } key={ location } location={ location + '_center' } id={ 'add-center-' + location } controlParams={ this.props.controlParams } choices={ this.props.choices } />
|
||||
</Fragment>
|
||||
) }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
export default DropComponent;
|
||||
@@ -0,0 +1,74 @@
|
||||
/* jshint esversion: 6 */
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
import ResponsiveControl from '../common/responsive.js';
|
||||
import Icons from '../common/icons.js';
|
||||
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
const { ButtonGroup, Dashicon, Tooltip, Button } = wp.components;
|
||||
|
||||
const { Component, Fragment } = wp.element;
|
||||
class ItemComponent extends Component {
|
||||
constructor() {
|
||||
super( ...arguments );
|
||||
this.choices = ( kadenceCustomizerControlsData && kadenceCustomizerControlsData.choices && kadenceCustomizerControlsData.choices[ this.props.controlParams.group ] ? kadenceCustomizerControlsData.choices[ this.props.controlParams.group ] : [] );
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div className="kadence-builder-item" data-id={ this.props.item } data-section={ undefined !== this.choices[ this.props.item ] && undefined !== this.choices[ this.props.item ].section ? this.choices[ this.props.item ].section : '' } key={ this.props.item }>
|
||||
<span
|
||||
className="kadence-builder-item-icon kadence-move-icon"
|
||||
>
|
||||
{ Icons['drag'] }
|
||||
</span>
|
||||
<span
|
||||
className="kadence-builder-item-text"
|
||||
>
|
||||
{ ( undefined !== this.choices[ this.props.item ] && undefined !== this.choices[ this.props.item ].name ? this.choices[ this.props.item ].name : '' ) }
|
||||
</span>
|
||||
<Button
|
||||
className="kadence-builder-item-focus-icon kadence-builder-item-icon"
|
||||
aria-label={ __( 'Setting settings for', 'kadence' ) + ' ' + ( undefined !== this.choices[ this.props.item ] && undefined !== this.choices[ this.props.item ].name ? this.choices[ this.props.item ].name : '' ) }
|
||||
onClick={ () => {
|
||||
this.props.focusItem( undefined !== this.choices[ this.props.item ] && undefined !== this.choices[ this.props.item ].section ? this.choices[ this.props.item ].section : '' );
|
||||
} }
|
||||
>
|
||||
<Dashicon icon="admin-generic"/>
|
||||
</Button>
|
||||
{ kadenceCustomizerControlsData.blockWidgets && this.props.item.includes('widget') && 'toggle-widget' !== this.props.item && (
|
||||
<Button
|
||||
className="kadence-builder-item-focus-icon kadence-builder-item-icon"
|
||||
aria-label={ __( 'Setting settings for', 'kadence' ) + ' ' + ( undefined !== this.choices[ this.props.item ] && undefined !== this.choices[ this.props.item ].name ? this.choices[ this.props.item ].name : '' ) }
|
||||
onClick={ () => {
|
||||
this.props.focusItem( undefined !== this.choices[ this.props.item ] && undefined !== this.choices[ this.props.item ].section ? 'kadence_customizer_' + this.choices[ this.props.item ].section : '' );
|
||||
} }
|
||||
>
|
||||
<Dashicon icon="admin-settings"/>
|
||||
</Button>
|
||||
) }
|
||||
{ kadenceCustomizerControlsData.blockWidgets && 'toggle-widget' === this.props.item && (
|
||||
<Button
|
||||
className="kadence-builder-item-focus-icon kadence-builder-item-icon"
|
||||
aria-label={ __( 'Setting settings for', 'kadence' ) + ' ' + ( undefined !== this.choices[ this.props.item ] && undefined !== this.choices[ this.props.item ].name ? this.choices[ this.props.item ].name : '' ) }
|
||||
onClick={ () => {
|
||||
this.props.focusItem( 'kadence_customizer_sidebar-widgets-header2' );
|
||||
} }
|
||||
>
|
||||
<Dashicon icon="admin-settings"/>
|
||||
</Button>
|
||||
) }
|
||||
<Button
|
||||
className="kadence-builder-item-icon"
|
||||
aria-label={ __( 'Remove', 'kadence' ) + ' ' + ( undefined !== this.choices[ this.props.item ] && undefined !== this.choices[ this.props.item ].name ? this.choices[ this.props.item ].name : '' ) }
|
||||
onClick={ () => {
|
||||
this.props.removeItem( this.props.item );
|
||||
} }
|
||||
>
|
||||
<Dashicon icon="no-alt"/>
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
export default ItemComponent;
|
||||
@@ -0,0 +1,70 @@
|
||||
/* jshint esversion: 6 */
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
import ResponsiveControl from '../common/responsive.js';
|
||||
import Icons from '../common/icons.js';
|
||||
import DropComponent from './drop-component';
|
||||
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
const { ButtonGroup, Dashicon, Tooltip, Button } = wp.components;
|
||||
|
||||
const { Component, Fragment } = wp.element;
|
||||
class RowComponent extends Component {
|
||||
render() {
|
||||
let centerClass = 'no-center-items';
|
||||
if ( 'header_desktop_items' === this.props.controlParams.group && typeof this.props.items[this.props.row + '_center'] != "undefined" && this.props.items[this.props.row + '_center'] != null && this.props.items[this.props.row + '_center'].length != null && this.props.items[this.props.row + '_center'].length > 0 ){
|
||||
centerClass = 'has-center-items';
|
||||
}
|
||||
if ( 'popup' === this.props.row ) {
|
||||
centerClass = 'popup-vertical-group';
|
||||
}
|
||||
if ( 'footer_items' === this.props.controlParams.group ) {
|
||||
var columns = this.props.customizer.control( 'footer_' + this.props.row + '_columns' ).setting.get();
|
||||
var layout = this.props.customizer.control( 'footer_' + this.props.row + '_layout' ).setting.get();
|
||||
var direction = this.props.customizer.control( 'footer_' + this.props.row + '_direction' ).setting.get();
|
||||
centerClass = 'footer-column-row footer-row-columns-' + columns + ' footer-row-layout-' + layout.desktop + ' footer-row-direction-' + direction.desktop;
|
||||
}
|
||||
const mode = ( this.props.controlParams.group.indexOf( 'header' ) !== -1 ? 'header' : 'footer' );
|
||||
let besideItems = [];
|
||||
return (
|
||||
<div className={ `kadence-builder-areas ${ centerClass }` }>
|
||||
<Button
|
||||
className="kadence-row-left-actions"
|
||||
aria-label={ __( 'Edit Settings for', 'kadence' ) + ' ' + ( this.props.row === 'popup' ? __( 'Off Canvas', 'kadence' ) : this.props.row + ' ' + __( 'Row', 'kadence' ) ) }
|
||||
onClick={ () => this.props.focusPanel( mode + '_' + this.props.row ) }
|
||||
icon="admin-generic"
|
||||
>
|
||||
</Button>
|
||||
<Button
|
||||
className="kadence-row-actions"
|
||||
aria-label={ __( 'Edit Settings for', 'kadence' ) + ' ' + ( this.props.row === 'popup' ? __( 'Off Canvas', 'kadence' ) : this.props.row + ' ' + __( 'Row', 'kadence' ) ) }
|
||||
onClick={ () => this.props.focusPanel( mode + '_' + this.props.row ) }
|
||||
>
|
||||
{ ( this.props.row === 'popup' ? __( 'Off Canvas', 'kadence' ) : this.props.row + ' ' + __( 'Row', 'kadence' ) ) }
|
||||
<Dashicon icon="admin-generic" />
|
||||
</Button>
|
||||
<div className="kadence-builder-group kadence-builder-group-horizontal" data-setting={ this.props.row }>
|
||||
{ Object.keys( this.props.controlParams.zones[ this.props.row ] ).map( ( zone, index ) => {
|
||||
if ( this.props.row + '_left_center' === zone || this.props.row + '_right_center' === zone ) {
|
||||
return;
|
||||
}
|
||||
if ( 'footer_items' === this.props.controlParams.group ) {
|
||||
if ( columns < ( index + 1 ) ) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if ( 'header_desktop_items' === this.props.controlParams.group && this.props.row + '_left' === zone ) {
|
||||
besideItems = this.props.items[ this.props.row + '_left_center' ];
|
||||
}
|
||||
if ( 'header_desktop_items' === this.props.controlParams.group && this.props.row + '_right' === zone ) {
|
||||
besideItems = this.props.items[ this.props.row + '_right_center' ];
|
||||
}
|
||||
return <DropComponent removeItem={ ( remove, removeRow, removeZone ) => this.props.removeItem( remove, removeRow, removeZone ) } focusItem={ ( focus ) => this.props.focusItem( focus ) } hideDrop={ () => this.props.hideDrop() } showDrop={ () => this.props.showDrop() } onUpdate={ ( updateRow, updateZone, updateItems ) => this.props.onUpdate( updateRow, updateZone, updateItems ) } zone={ zone } row={ this.props.row } choices={ this.props.choices } key={ zone } items={ this.props.items[zone] } centerItems={ besideItems } controlParams={ this.props.controlParams } onAddItem={ ( updateRow, updateZone, updateItems ) => this.props.onAddItem( updateRow, updateZone, updateItems ) } settings={ this.props.settings } />;
|
||||
} ) }
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
export default RowComponent;
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createRoot } from '@wordpress/element';
|
||||
import MeasureComponent from './measure-component';
|
||||
|
||||
export const MeasureControl = wp.customize.KadenceControl.extend( {
|
||||
renderContent: function renderContent() {
|
||||
let control = this;
|
||||
let root = createRoot( control.container[0] );
|
||||
root.render( <MeasureComponent control={control}/> );
|
||||
// ReactDOM.render(
|
||||
// <MeasureComponent control={control}/>,
|
||||
// control.container[0]
|
||||
// );
|
||||
}
|
||||
} );
|
||||
@@ -0,0 +1,516 @@
|
||||
/* jshint esversion: 6 */
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
|
||||
import ResponsiveControl from '../common/responsive.js';
|
||||
import Icons from '../common/icons.js';
|
||||
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
const { RangeControl, Dashicon, Tooltip, Button, Toolbar, TextControl, ToolbarGroup } = wp.components;
|
||||
|
||||
const { Component, Fragment } = wp.element;
|
||||
class MeasureComponent extends Component {
|
||||
constructor() {
|
||||
super( ...arguments );
|
||||
this.updateValues = this.updateValues.bind( this );
|
||||
this.getUnitButtons = this.getUnitButtons.bind( this );
|
||||
this.createLevelControlToolbar = this.createLevelControlToolbar.bind( this );
|
||||
this.createResponsiveLevelControlToolbar = this.createResponsiveLevelControlToolbar.bind( this );
|
||||
this.getResponsiveUnitButtons = this.getResponsiveUnitButtons.bind( this );
|
||||
let value = this.props.control.setting.get();
|
||||
let baseDefault = {
|
||||
'unit': {
|
||||
'desktop': 'px'
|
||||
},
|
||||
'size': {
|
||||
'desktop': [ 0, 0, 0, 0 ]
|
||||
},
|
||||
'locked': {
|
||||
'desktop': true
|
||||
}
|
||||
};
|
||||
this.defaultValue = this.props.control.params.default ? {
|
||||
...baseDefault,
|
||||
...this.props.control.params.default
|
||||
} : baseDefault;
|
||||
value = value ? {
|
||||
...this.defaultValue,
|
||||
...value
|
||||
} : this.defaultValue;
|
||||
let defaultParams = {
|
||||
min: {
|
||||
px: '0',
|
||||
em: '0',
|
||||
rem: '0',
|
||||
},
|
||||
max: {
|
||||
px: '120',
|
||||
em: '12',
|
||||
rem: '12',
|
||||
},
|
||||
step: {
|
||||
px: '1',
|
||||
em: '0.01',
|
||||
rem: '0.01',
|
||||
},
|
||||
units: ['px', 'em', 'rem' ],
|
||||
responsive: true,
|
||||
};
|
||||
this.controlParams = this.props.control.params.input_attrs ? {
|
||||
...defaultParams,
|
||||
...this.props.control.params.input_attrs,
|
||||
} : defaultParams;
|
||||
this.state = {
|
||||
currentDevice: 'desktop',
|
||||
size: value.size,
|
||||
unit: value.unit,
|
||||
locked: value.locked
|
||||
};
|
||||
}
|
||||
render() {
|
||||
const responsiveControlLabel = (
|
||||
<Fragment>
|
||||
{ this.controlParams.responsive && (
|
||||
<Fragment>
|
||||
<Tooltip text={ __( 'Reset Device Values', 'kadence' ) }>
|
||||
<Button
|
||||
className="reset kadence-reset"
|
||||
disabled={ ( this.state.size[this.state.currentDevice] === this.defaultValue.size[this.state.currentDevice] ) && ( this.state.unit[this.state.currentDevice] === this.defaultValue.unit[this.state.currentDevice] ) }
|
||||
onClick={ () => {
|
||||
let value = this.state.size;
|
||||
value[this.state.currentDevice] = this.defaultValue.size[this.state.currentDevice];
|
||||
let svalue = this.state.unit;
|
||||
svalue[this.state.currentDevice] = this.defaultValue.unit[this.state.currentDevice];
|
||||
let lvalue = this.state.unit;
|
||||
lvalue[this.state.currentDevice] = this.defaultValue.locked[this.state.currentDevice];
|
||||
this.setState( { size: value, unit: svalue, locked: lvalue } );
|
||||
this.updateValues( { size: value, unit: svalue, locked: lvalue } );
|
||||
} }
|
||||
>
|
||||
<Dashicon icon='image-rotate' />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
{ this.props.control.params.label &&
|
||||
this.props.control.params.label
|
||||
}
|
||||
</Fragment>
|
||||
) }
|
||||
</Fragment>
|
||||
);
|
||||
const controlLabel = (
|
||||
<Fragment>
|
||||
<Tooltip text={ __( 'Reset Values', 'kadence' ) }>
|
||||
<Button
|
||||
className="reset kadence-reset"
|
||||
disabled={ ( this.state.size === this.defaultValue.size ) && ( this.state.unit === this.defaultValue.unit ) }
|
||||
onClick={ () => {
|
||||
let value = this.state.size;
|
||||
value = this.defaultValue.size;
|
||||
let svalue = this.state.unit;
|
||||
svalue = this.defaultValue.unit;
|
||||
let lvalue = this.state.locked;
|
||||
lvalue = this.defaultValue.locked;
|
||||
this.setState( { size: value, unit: svalue, locked: lvalue } );
|
||||
this.updateValues( { size: value, unit: svalue, locked: lvalue } );
|
||||
} }
|
||||
>
|
||||
<Dashicon icon='image-rotate' />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
{ this.props.control.params.label &&
|
||||
this.props.control.params.label
|
||||
}
|
||||
</Fragment>
|
||||
);
|
||||
return (
|
||||
<div className="kadence-control-field kadence-range-control">
|
||||
{ this.controlParams.responsive && (
|
||||
<ResponsiveControl
|
||||
onChange={ ( currentDevice) => this.setState( { currentDevice } ) }
|
||||
controlLabel={ responsiveControlLabel }
|
||||
>
|
||||
{ this.state.locked[this.state.currentDevice] && (
|
||||
<RangeControl
|
||||
initialPosition={ ( this.state.size[this.state.currentDevice] && this.state.size[this.state.currentDevice][0] ? this.state.size[this.state.currentDevice][0] : '' ) }
|
||||
value={ ( this.state.size[this.state.currentDevice] && this.state.size[this.state.currentDevice][0] ? this.state.size[this.state.currentDevice][0] : '' ) }
|
||||
onChange={ (val) => {
|
||||
let value = this.state.size;
|
||||
value[ this.state.currentDevice ] = [ val, val, val, val ];
|
||||
this.setState( { size: value } );
|
||||
this.updateValues( { size: value } );
|
||||
} }
|
||||
min={this.controlParams.min[this.state.unit[this.state.currentDevice]]}
|
||||
max={this.controlParams.max[this.state.unit[this.state.currentDevice]]}
|
||||
step={this.controlParams.step[this.state.unit[this.state.currentDevice]]}
|
||||
/>
|
||||
) }
|
||||
{ ! this.state.locked[this.state.currentDevice] && (
|
||||
<Fragment>
|
||||
<TextControl
|
||||
label={ __( 'Top', 'kadence' ) }
|
||||
hideLabelFromVision={ true }
|
||||
type="number"
|
||||
className="measure-inputs"
|
||||
value={( this.state.size[this.state.currentDevice] && this.state.size[this.state.currentDevice][0] ? this.state.size[this.state.currentDevice][0] : '' )}
|
||||
onChange={ (val) => {
|
||||
let value = this.state.size;
|
||||
if ( undefined === value[ this.state.currentDevice ] ) {
|
||||
value[ this.state.currentDevice ] = [ 0, 0, 0, 0 ];
|
||||
}
|
||||
value[ this.state.currentDevice ][0] = val;
|
||||
this.setState( { size: value } );
|
||||
this.updateValues( { size: value } );
|
||||
} }
|
||||
min={this.controlParams.min[this.state.unit[this.state.currentDevice]]}
|
||||
max={this.controlParams.max[this.state.unit[this.state.currentDevice]]}
|
||||
step={this.controlParams.step[this.state.unit[this.state.currentDevice]]}
|
||||
/>
|
||||
<TextControl
|
||||
label={ __( 'Right', 'kadence' ) }
|
||||
hideLabelFromVision={ true }
|
||||
type="number"
|
||||
className="measure-inputs"
|
||||
value={( this.state.size[this.state.currentDevice] && this.state.size[this.state.currentDevice][1] ? this.state.size[this.state.currentDevice][1] : '' )}
|
||||
onChange={ (val) => {
|
||||
let value = this.state.size;
|
||||
if ( undefined === value[ this.state.currentDevice ] ) {
|
||||
value[ this.state.currentDevice ] = [ 0, 0, 0, 0 ];
|
||||
}
|
||||
value[ this.state.currentDevice ][1] = val;
|
||||
this.setState( { size: value } );
|
||||
this.updateValues( { size: value } );
|
||||
} }
|
||||
min={this.controlParams.min[this.state.unit[this.state.currentDevice]]}
|
||||
max={this.controlParams.max[this.state.unit[this.state.currentDevice]]}
|
||||
step={this.controlParams.step[this.state.unit[this.state.currentDevice]]}
|
||||
/>
|
||||
<TextControl
|
||||
label={ __( 'Bottom', 'kadence' ) }
|
||||
hideLabelFromVision={ true }
|
||||
type="number"
|
||||
className="measure-inputs"
|
||||
value={( this.state.size[this.state.currentDevice] && this.state.size[this.state.currentDevice][2] ? this.state.size[this.state.currentDevice][2] : '' )}
|
||||
onChange={ (val) => {
|
||||
let value = this.state.size;
|
||||
if ( undefined === value[ this.state.currentDevice ] ) {
|
||||
value[ this.state.currentDevice ] = [ 0, 0, 0, 0 ];
|
||||
}
|
||||
value[ this.state.currentDevice ][2] = val;
|
||||
this.setState( { size: value } );
|
||||
this.updateValues( { size: value } );
|
||||
} }
|
||||
min={this.controlParams.min[this.state.unit[this.state.currentDevice]]}
|
||||
max={this.controlParams.max[this.state.unit[this.state.currentDevice]]}
|
||||
step={this.controlParams.step[this.state.unit[this.state.currentDevice]]}
|
||||
/>
|
||||
<TextControl
|
||||
label={ __( 'Left', 'kadence' ) }
|
||||
hideLabelFromVision={ true }
|
||||
type="number"
|
||||
className="measure-inputs"
|
||||
value={( this.state.size[this.state.currentDevice] && this.state.size[this.state.currentDevice][3] ? this.state.size[this.state.currentDevice][3] : '' )}
|
||||
onChange={ (val) => {
|
||||
let value = this.state.size;
|
||||
if ( undefined === value[ this.state.currentDevice ] ) {
|
||||
value[ this.state.currentDevice ] = [ 0, 0, 0, 0 ];
|
||||
}
|
||||
value[ this.state.currentDevice ][3] = val;
|
||||
this.setState( { size: value } );
|
||||
this.updateValues( { size: value } );
|
||||
} }
|
||||
min={this.controlParams.min[this.state.unit[this.state.currentDevice]]}
|
||||
max={this.controlParams.max[this.state.unit[this.state.currentDevice]]}
|
||||
step={this.controlParams.step[this.state.unit[this.state.currentDevice]]}
|
||||
/>
|
||||
</Fragment>
|
||||
) }
|
||||
<div className="kadence-units kadence-locked">
|
||||
{ this.getResponsiveLockedButtons() }
|
||||
</div>
|
||||
{ this.controlParams.units && (
|
||||
<div className="kadence-units">
|
||||
{ this.getResponsiveUnitButtons() }
|
||||
</div>
|
||||
) }
|
||||
</ResponsiveControl>
|
||||
) }
|
||||
{ ! this.controlParams.responsive && (
|
||||
<Fragment>
|
||||
<div className="kadence-responsive-control-bar">
|
||||
<span className="customize-control-title">{ controlLabel }</span>
|
||||
</div>
|
||||
<div className="kadence-responsive-controls-content">
|
||||
{ this.state.locked && (
|
||||
<RangeControl
|
||||
initialPosition={ this.state.size[0] }
|
||||
value={this.state.size[0]}
|
||||
onChange={ (val) => {
|
||||
let value = this.state.size;
|
||||
value = [ val, val, val, val ];
|
||||
this.setState( { size: value } );
|
||||
this.updateValues( { size: value } );
|
||||
} }
|
||||
min={this.controlParams.min[this.state.unit]}
|
||||
max={this.controlParams.max[this.state.unit]}
|
||||
step={this.controlParams.step[this.state.unit]}
|
||||
/>
|
||||
) }
|
||||
{ ! this.state.locked && (
|
||||
<Fragment>
|
||||
<div className="measure-input-wrap">
|
||||
<input
|
||||
value={this.state.size[0]}
|
||||
onChange={ ( event ) => {
|
||||
const val = ( '' !== event.target.value ? Number( event.target.value ) : '' );
|
||||
let value = this.state.size;
|
||||
value[0] = val;
|
||||
if ( val !== '' ) {
|
||||
if ( '' === value[1] ) {
|
||||
value[1] = 0;
|
||||
}
|
||||
if ( '' === value[2] ) {
|
||||
value[2] = 0;
|
||||
}
|
||||
if ( '' === value[3] ) {
|
||||
value[3] = 0;
|
||||
}
|
||||
}
|
||||
this.setState( { size: value } );
|
||||
this.updateValues( { size: value } );
|
||||
} }
|
||||
min={this.controlParams.min[this.state.unit]}
|
||||
max={this.controlParams.max[this.state.unit]}
|
||||
step={this.controlParams.step[this.state.unit]}
|
||||
type="number"
|
||||
className="measure-inputs"
|
||||
/>
|
||||
<small>{ __( 'Top', 'kadence' ) }</small>
|
||||
</div>
|
||||
<div className="measure-input-wrap">
|
||||
<input
|
||||
value={this.state.size[1]}
|
||||
onChange={ ( event ) => {
|
||||
const val = ( '' !== event.target.value ? Number( event.target.value ) : '' );
|
||||
let value = this.state.size;
|
||||
value[1] = val;
|
||||
if ( val !== '' ) {
|
||||
if ( '' === value[0] ) {
|
||||
value[0] = 0;
|
||||
}
|
||||
if ( '' === value[2] ) {
|
||||
value[2] = 0;
|
||||
}
|
||||
if ( '' === value[3] ) {
|
||||
value[3] = 0;
|
||||
}
|
||||
}
|
||||
this.setState( { size: value } );
|
||||
this.updateValues( { size: value } );
|
||||
} }
|
||||
min={this.controlParams.min[this.state.unit]}
|
||||
max={this.controlParams.max[this.state.unit]}
|
||||
step={this.controlParams.step[this.state.unit]}
|
||||
type="number"
|
||||
className="measure-inputs"
|
||||
/>
|
||||
<small>{ __( 'Right', 'kadence' ) }</small>
|
||||
</div>
|
||||
<div className="measure-input-wrap">
|
||||
<input
|
||||
value={this.state.size[2]}
|
||||
onChange={ ( event ) => {
|
||||
const val = ( '' !== event.target.value ? Number( event.target.value ) : '' );
|
||||
let value = this.state.size;
|
||||
value[2] = val;
|
||||
if ( val !== '' ) {
|
||||
if ( '' === value[0] ) {
|
||||
value[0] = 0;
|
||||
}
|
||||
if ( '' === value[1] ) {
|
||||
value[1] = 0;
|
||||
}
|
||||
if ( '' === value[3] ) {
|
||||
value[3] = 0;
|
||||
}
|
||||
}
|
||||
this.setState( { size: value } );
|
||||
this.updateValues( { size: value } );
|
||||
} }
|
||||
min={this.controlParams.min[this.state.unit]}
|
||||
max={this.controlParams.max[this.state.unit]}
|
||||
step={this.controlParams.step[this.state.unit]}
|
||||
type="number"
|
||||
className="measure-inputs"
|
||||
/>
|
||||
<small>{ __( 'Bottom', 'kadence' ) }</small>
|
||||
</div>
|
||||
<div className="measure-input-wrap">
|
||||
<input
|
||||
value={this.state.size[3]}
|
||||
onChange={ ( event ) => {
|
||||
const val = ( '' !== event.target.value ? Number( event.target.value ) : '' );
|
||||
let value = this.state.size;
|
||||
value[3] = val;
|
||||
if ( val !== '' ) {
|
||||
if ( '' === value[0] ) {
|
||||
value[0] = 0;
|
||||
}
|
||||
if ( '' === value[1] ) {
|
||||
value[1] = 0;
|
||||
}
|
||||
if ( '' === value[2] ) {
|
||||
value[2] = 0;
|
||||
}
|
||||
}
|
||||
this.setState( { size: value } );
|
||||
this.updateValues( { size: value } );
|
||||
} }
|
||||
min={this.controlParams.min[this.state.unit]}
|
||||
max={this.controlParams.max[this.state.unit]}
|
||||
step={this.controlParams.step[this.state.unit]}
|
||||
type="number"
|
||||
className="measure-inputs"
|
||||
/>
|
||||
<small>{ __( 'Left', 'kadence' ) }</small>
|
||||
</div>
|
||||
</Fragment>
|
||||
) }
|
||||
<div className="kadence-units kadence-locked">
|
||||
{ this.getLockedButtons() }
|
||||
</div>
|
||||
{ this.controlParams.units && (
|
||||
<div className="kadence-units">
|
||||
{ this.getUnitButtons() }
|
||||
</div>
|
||||
) }
|
||||
</div>
|
||||
</Fragment>
|
||||
) }
|
||||
{ this.props.control.renderNotice() }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
getLockedButtons() {
|
||||
const { locked } = this.state;
|
||||
if ( locked ) {
|
||||
return ( <Button
|
||||
className="is-single"
|
||||
onClick={ () => {
|
||||
let value = this.state.locked;
|
||||
value = false;
|
||||
this.setState( { locked: value } );
|
||||
this.updateValues( { locked: value } );
|
||||
} }
|
||||
isSmall
|
||||
>{ Icons['locked'] }</Button> );
|
||||
}
|
||||
return ( <Button
|
||||
className="is-single"
|
||||
isSmall
|
||||
onClick={ () => {
|
||||
let value = this.state.locked;
|
||||
value = true;
|
||||
this.setState( { locked: value } );
|
||||
this.updateValues( { locked: value } );
|
||||
} }
|
||||
>{ Icons['unlocked'] }</Button> );
|
||||
}
|
||||
getUnitButtons() {
|
||||
let self = this;
|
||||
const { units } = this.controlParams;
|
||||
if ( units.length === 1 ) {
|
||||
return ( <Button
|
||||
className="is-active is-single"
|
||||
isSmall
|
||||
disabled
|
||||
>{ ( '%' === self.state.unit ? Icons.percent : Icons[ self.state.unit ] ) }</Button> );
|
||||
}
|
||||
return <ToolbarGroup
|
||||
isCollapsed={ true }
|
||||
icon={ ( '%' === self.state.unit ? Icons.percent : Icons[ self.state.unit ] ) }
|
||||
label={ __( 'Unit', 'kadence' ) }
|
||||
controls={ units.map( (unit) => this.createLevelControlToolbar( unit ) ) }
|
||||
/>
|
||||
}
|
||||
createLevelControlToolbar( unit ) {
|
||||
return [ {
|
||||
icon: ( unit === '%' ? Icons.percent : Icons[ unit ] ),
|
||||
isActive: this.state.unit === unit,
|
||||
onClick: () => {
|
||||
let value = this.state.unit;
|
||||
value = unit;
|
||||
this.setState( { unit: value } );
|
||||
this.updateValues( { unit: value } );
|
||||
},
|
||||
} ];
|
||||
};
|
||||
createResponsiveLevelControlToolbar( unit ) {
|
||||
return [ {
|
||||
icon: ( unit === '%' ? Icons.percent : Icons[ unit ] ),
|
||||
isActive: this.state.unit[this.state.currentDevice] === unit,
|
||||
onClick: () => {
|
||||
let value = this.state.unit;
|
||||
value[ this.state.currentDevice ] = unit;
|
||||
this.setState( { unit: value } );
|
||||
this.updateValues( { unit: value } );
|
||||
},
|
||||
} ];
|
||||
};
|
||||
getResponsiveLockedButtons() {
|
||||
let self = this;
|
||||
const { locked } = this.state;
|
||||
if ( locked[ self.state.currentDevice ] ) {
|
||||
return ( <Button
|
||||
className="is-single"
|
||||
isSmall
|
||||
onClick={ () => {
|
||||
let value = this.state.locked;
|
||||
value[ this.state.currentDevice ] = false;
|
||||
this.setState( { locked: value } );
|
||||
this.updateValues( { locked: value } );
|
||||
} }
|
||||
>{ Icons['locked'] }</Button> );
|
||||
}
|
||||
return ( <Button
|
||||
className="is-single"
|
||||
isSmall
|
||||
onClick={ () => {
|
||||
let value = this.state.locked;
|
||||
value[ this.state.currentDevice ] = true;
|
||||
this.setState( { locked: value } );
|
||||
this.updateValues( { locked: value } );
|
||||
} }
|
||||
>{ Icons['unlocked'] }</Button> );
|
||||
}
|
||||
getResponsiveUnitButtons() {
|
||||
let self = this;
|
||||
const { units } = this.controlParams;
|
||||
if ( units.length === 1 ) {
|
||||
return ( <Button
|
||||
className="is-active is-single"
|
||||
isSmall
|
||||
disabled
|
||||
>{ ( '%' === self.state.unit[ self.state.currentDevice ] ? Icons.percent : Icons[ self.state.unit[ self.state.currentDevice ] ] ) }</Button> );
|
||||
}
|
||||
return <ToolbarGroup
|
||||
isCollapsed={ true }
|
||||
icon={ ( '%' === self.state.unit[ self.state.currentDevice ] ? Icons.percent : Icons[ self.state.unit[ self.state.currentDevice ] ] ) }
|
||||
label={ __( 'Unit', 'kadence' ) }
|
||||
controls={ units.map( (unit) => this.createResponsiveLevelControlToolbar( unit ) ) }
|
||||
/>
|
||||
}
|
||||
updateValues( value ) {
|
||||
this.props.control.setting.set( {
|
||||
...this.props.control.setting.get(),
|
||||
...value,
|
||||
flag: !this.props.control.setting.get().flag
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
MeasureComponent.propTypes = {
|
||||
control: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
export default MeasureComponent;
|
||||
@@ -0,0 +1,15 @@
|
||||
import { createRoot } from '@wordpress/element';
|
||||
|
||||
import MultiRadioIconComponent from './multi-radio-icon-component.js';
|
||||
|
||||
export const MultiRadioIconControl = wp.customize.KadenceControl.extend( {
|
||||
renderContent: function renderContent() {
|
||||
let control = this;
|
||||
let root = createRoot( control.container[0] );
|
||||
root.render( <MultiRadioIconComponent control={control}/> );
|
||||
// ReactDOM.render(
|
||||
// <MultiRadioIconComponent control={control}/>,
|
||||
// control.container[0]
|
||||
// );
|
||||
}
|
||||
} );
|
||||
@@ -0,0 +1,211 @@
|
||||
/* jshint esversion: 6 */
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
|
||||
import ResponsiveControl from '../common/responsive.js';
|
||||
import Icons from '../common/icons.js';
|
||||
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
const { ButtonGroup, Dashicon, Tooltip, Button } = wp.components;
|
||||
|
||||
const { Component, Fragment } = wp.element;
|
||||
class RadioIconComponent extends Component {
|
||||
constructor() {
|
||||
super( ...arguments );
|
||||
this.updateValues = this.updateValues.bind( this );
|
||||
let value = this.props.control.setting.get();
|
||||
let baseDefault = {
|
||||
'include': {
|
||||
'mobile': '',
|
||||
'tablet': '',
|
||||
'desktop': 'logo_title_tagline'
|
||||
},
|
||||
'layout': {
|
||||
'mobile': '',
|
||||
'tablet': '',
|
||||
'desktop': 'standard'
|
||||
}
|
||||
};
|
||||
this.defaultValue = this.props.control.params.default ? {
|
||||
...baseDefault,
|
||||
...this.props.control.params.default
|
||||
} : baseDefault;
|
||||
value = value ? {
|
||||
...this.defaultValue,
|
||||
...value
|
||||
} : this.defaultValue;
|
||||
let defaultParams = {
|
||||
include: {
|
||||
logo_only: {
|
||||
tooltip: __( 'Logo Only', 'kadence' ),
|
||||
name: __( 'Logo', 'kadence' ),
|
||||
},
|
||||
logo_title: {
|
||||
tooltip: __( 'Logo & Title', 'kadence' ),
|
||||
name: __( 'Logo & Title', 'kadence' ),
|
||||
},
|
||||
logo_title_tagline: {
|
||||
tooltip: __( 'Logo, Title & Tagline', 'kadence' ),
|
||||
name: __( 'Logo, Title & Tagline', 'kadence' ),
|
||||
},
|
||||
},
|
||||
layout: {
|
||||
logo_only: {
|
||||
standard: {
|
||||
tooltip: __( 'Logo Only', 'kadence' ),
|
||||
icon: Icons.logo
|
||||
},
|
||||
},
|
||||
logo_title: {
|
||||
standard: {
|
||||
tooltip: __( 'Logo - Title', 'kadence' ),
|
||||
icon: Icons.logoTitle
|
||||
},
|
||||
title_logo: {
|
||||
tooltip: __( 'Title - Logo', 'kadence' ),
|
||||
icon: Icons.titleLogo
|
||||
},
|
||||
top_logo_title: {
|
||||
tooltip: __( 'Top Logo - Title', 'kadence' ),
|
||||
icon: Icons.topLogoTitle
|
||||
},
|
||||
top_title_logo: {
|
||||
tooltip: __( 'Top Title - Logo', 'kadence' ),
|
||||
icon: Icons.topTitleLogo
|
||||
},
|
||||
},
|
||||
logo_title_tagline: {
|
||||
standard: {
|
||||
tooltip: __( 'Logo - Title - Tagline', 'kadence' ),
|
||||
icon: Icons.logoTitleTag
|
||||
},
|
||||
title_tag_logo: {
|
||||
tooltip: __( 'Title - Tagline - Logo', 'kadence' ),
|
||||
icon: Icons.titleTagLogo
|
||||
},
|
||||
top_logo_title_tag: {
|
||||
tooltip: __( 'Top Logo - Title - Tagline', 'kadence' ),
|
||||
icon: Icons.topLogoTitleTag
|
||||
},
|
||||
top_title_tag_logo: {
|
||||
tooltip: __( 'Top Title - Tagline - Logo', 'kadence' ),
|
||||
icon: Icons.topTitleTagLogo
|
||||
},
|
||||
top_title_logo_tag: {
|
||||
tooltip: __( 'Top Title - Logo - Tagline', 'kadence' ),
|
||||
icon: Icons.topTitleLogoTag
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
this.controlParams = this.props.control.params.input_attrs ? {
|
||||
...defaultParams,
|
||||
...this.props.control.params.input_attrs,
|
||||
} : defaultParams;
|
||||
this.state = {
|
||||
currentDevice: 'desktop',
|
||||
include: value.include,
|
||||
layout: value.layout,
|
||||
};
|
||||
}
|
||||
render() {
|
||||
const controlLabel = (
|
||||
<Fragment>
|
||||
{ this.state.currentDevice !== 'desktop' && (
|
||||
<Tooltip text={ __( 'Reset Device Values', 'kadence' ) }>
|
||||
<Button
|
||||
className="reset kadence-reset"
|
||||
disabled={ ( this.state.include[this.state.currentDevice] === this.defaultValue.include[this.state.currentDevice] ) && ( this.state.layout[this.state.currentDevice] === this.defaultValue.layout[this.state.currentDevice] ) }
|
||||
onClick={ () => {
|
||||
let value = this.state.include;
|
||||
value[this.state.currentDevice] = this.defaultValue.include[this.state.currentDevice];
|
||||
let svalue = this.state.layout;
|
||||
svalue[this.state.currentDevice] = this.defaultValue.layout[this.state.currentDevice];
|
||||
this.setState( { include: value, layout: svalue } );
|
||||
this.updateValues( { include: value, layout: svalue } );
|
||||
} }
|
||||
>
|
||||
<Dashicon icon='image-rotate' />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
) }
|
||||
{ this.props.control.params.label &&
|
||||
this.props.control.params.label
|
||||
}
|
||||
</Fragment>
|
||||
);
|
||||
return (
|
||||
<div className="kadence-control-field kadence-radio-icon-control">
|
||||
<ResponsiveControl
|
||||
onChange={ ( currentDevice) => this.setState( { currentDevice } ) }
|
||||
controlLabel={ controlLabel }
|
||||
>
|
||||
<ButtonGroup className="kadence-radio-container-control">
|
||||
{ Object.keys( this.controlParams.include ).map( ( item ) => {
|
||||
return (
|
||||
<Tooltip text={ this.controlParams.include[ item ].tooltip }>
|
||||
<Button
|
||||
isTertiary
|
||||
className={ ( item === this.state.include[this.state.currentDevice] ?
|
||||
'active-radio ' :
|
||||
'' ) + item }
|
||||
onClick={ () => {
|
||||
let value = this.state.include;
|
||||
value[ this.state.currentDevice ] = item;
|
||||
let svalue = this.state.layout;
|
||||
svalue[ this.state.currentDevice ] = 'standard';
|
||||
this.setState( { include: value, layout: svalue } );
|
||||
this.updateValues( { include: value, layout: svalue } );
|
||||
} }
|
||||
>
|
||||
{ this.controlParams.include[ item ].name }
|
||||
</Button>
|
||||
</Tooltip>
|
||||
);
|
||||
} )}
|
||||
</ButtonGroup>
|
||||
{ undefined !== this.state.include[this.state.currentDevice] && '' !== this.state.include[this.state.currentDevice] && 'logo_only' !== this.state.include[this.state.currentDevice] && (
|
||||
<ButtonGroup className="kadence-radio-container-control kadence-radio-icon-container-control">
|
||||
{ Object.keys( this.controlParams.layout[this.state.include[this.state.currentDevice] ] ).map( ( item ) => {
|
||||
return (
|
||||
<Tooltip text={ this.controlParams.layout[this.state.include[this.state.currentDevice] ][ item ].tooltip }>
|
||||
<Button
|
||||
isTertiary
|
||||
className={ ( item === this.state.layout[this.state.currentDevice] ?
|
||||
'active-radio ' :
|
||||
'' ) + item }
|
||||
onClick={ () => {
|
||||
let value = this.state.layout;
|
||||
value[ this.state.currentDevice ] = item;
|
||||
this.setState( { layout: value } );
|
||||
this.updateValues( { layout: value } );
|
||||
} }
|
||||
>
|
||||
{ this.controlParams.layout[this.state.include[this.state.currentDevice] ][ item ].icon }
|
||||
</Button>
|
||||
</Tooltip>
|
||||
);
|
||||
} )}
|
||||
</ButtonGroup>
|
||||
) }
|
||||
</ResponsiveControl>
|
||||
{ this.props.control.renderNotice() }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
updateValues( value ) {
|
||||
this.props.control.setting.set( {
|
||||
...this.props.control.setting.get(),
|
||||
...value,
|
||||
flag: !this.props.control.setting.get().flag
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
RadioIconComponent.propTypes = {
|
||||
control: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
export default RadioIconComponent;
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createRoot } from '@wordpress/element';
|
||||
import PaletteComponent from './palette-component.js';
|
||||
|
||||
export const PaletteControl = wp.customize.KadenceControl.extend( {
|
||||
renderContent: function renderContent() {
|
||||
let control = this;
|
||||
let root = createRoot( control.container[0] );
|
||||
root.render( <PaletteComponent control={control}/> );
|
||||
// ReactDOM.render(
|
||||
// <PaletteComponent control={control}/>,
|
||||
// control.container[0]
|
||||
// );
|
||||
}
|
||||
} );
|
||||
@@ -0,0 +1,748 @@
|
||||
import PropTypes from "prop-types";
|
||||
import { __ } from "@wordpress/i18n";
|
||||
/**
|
||||
* WordPress dependencies
|
||||
*/
|
||||
import { createRef, Component, Fragment } from "@wordpress/element";
|
||||
import map from "lodash/map";
|
||||
import ColorControl from "../common/color.js";
|
||||
const {
|
||||
ButtonGroup,
|
||||
Dashicon,
|
||||
Tooltip,
|
||||
Button,
|
||||
Popover,
|
||||
TabPanel,
|
||||
TextareaControl,
|
||||
} = wp.components;
|
||||
class ColorComponent extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.handleChangeComplete = this.handleChangeComplete.bind(this);
|
||||
this.handleChangePalette = this.handleChangePalette.bind(this);
|
||||
this.handleTextImport = this.handleTextImport.bind(this);
|
||||
this.handlePresetImport = this.handlePresetImport.bind(this);
|
||||
this.updateValues = this.updateValues.bind(this);
|
||||
let value = JSON.parse(this.props.control.setting.get());
|
||||
let baseDefault = kadenceCustomizerControlsData.palette
|
||||
? JSON.parse(kadenceCustomizerControlsData.palette)
|
||||
: { palette: [] };
|
||||
this.defaultValue = this.props.control.params.default
|
||||
? {
|
||||
...baseDefault,
|
||||
...this.props.control.params.default,
|
||||
}
|
||||
: baseDefault;
|
||||
value = value
|
||||
? {
|
||||
...this.defaultValue,
|
||||
...value,
|
||||
}
|
||||
: this.defaultValue;
|
||||
let defaultParams = {
|
||||
reset: '{"palette":[{"color":"#3182CE","slug":"palette1","name":"Palette Color 1"},{"color":"#2B6CB0","slug":"palette2","name":"Palette Color 2"},{"color":"#1A202C","slug":"palette3","name":"Palette Color 3"},{"color":"#2D3748","slug":"palette4","name":"Palette Color 4"},{"color":"#4A5568","slug":"palette5","name":"Palette Color 5"},{"color":"#718096","slug":"palette6","name":"Palette Color 6"},{"color":"#EDF2F7","slug":"palette7","name":"Palette Color 7"},{"color":"#F7FAFC","slug":"palette8","name":"Palette Color 8"},{"color":"#FFFFFF","slug":"palette9","name":"Palette Color 9"},{"color":"#FfFfFf","slug":"palette10","name":"Palette Color Complement"},{"color":"#13612e","slug":"palette11","name":"Palette Color Success"},{"color":"#1159af","slug":"palette12","name":"Palette Color Info"},{"color":"#b82105","slug":"palette13","name":"Palette Color Alert"},{"color":"#f7630c","slug":"palette14","name":"Palette Color Warning"},{"color":"#f5a524","slug":"palette15","name":"Palette Color Rating"}],"second-palette":[{"color":"#3182CE","slug":"palette1","name":"Palette Color 1"},{"color":"#2B6CB0","slug":"palette2","name":"Palette Color 2"},{"color":"#1A202C","slug":"palette3","name":"Palette Color 3"},{"color":"#2D3748","slug":"palette4","name":"Palette Color 4"},{"color":"#4A5568","slug":"palette5","name":"Palette Color 5"},{"color":"#718096","slug":"palette6","name":"Palette Color 6"},{"color":"#EDF2F7","slug":"palette7","name":"Palette Color 7"},{"color":"#F7FAFC","slug":"palette8","name":"Palette Color 8"},{"color":"#FFFFFF","slug":"palette9","name":"Palette Color 9"},{"color":"#FfFfFf","slug":"palette10","name":"Palette Color Complement"},{"color":"#13612e","slug":"palette11","name":"Palette Color Success"},{"color":"#1159af","slug":"palette12","name":"Palette Color Info"},{"color":"#b82105","slug":"palette13","name":"Palette Color Alert"},{"color":"#f7630c","slug":"palette14","name":"Palette Color Warning"},{"color":"#f5a524","slug":"palette15","name":"Palette Color Rating"}],"third-palette":[{"color":"#3182CE","slug":"palette1","name":"Palette Color 1"},{"color":"#2B6CB0","slug":"palette2","name":"Palette Color 2"},{"color":"#1A202C","slug":"palette3","name":"Palette Color 3"},{"color":"#2D3748","slug":"palette4","name":"Palette Color 4"},{"color":"#4A5568","slug":"palette5","name":"Palette Color 5"},{"color":"#718096","slug":"palette6","name":"Palette Color 6"},{"color":"#EDF2F7","slug":"palette7","name":"Palette Color 7"},{"color":"#F7FAFC","slug":"palette8","name":"Palette Color 8"},{"color":"#FFFFFF","slug":"palette9","name":"Palette Color 9"},{"color":"#FfFfFf","slug":"palette10","name":"Palette Color Complement"},{"color":"#13612e","slug":"palette11","name":"Palette Color Success"},{"color":"#1159af","slug":"palette12","name":"Palette Color Info"},{"color":"#b82105","slug":"palette13","name":"Palette Color Alert"},{"color":"#f7630c","slug":"palette14","name":"Palette Color Warning"},{"color":"#f5a524","slug":"palette15","name":"Palette Color Rating"}],"active":"palette"}',
|
||||
palettes: kadenceCustomizerControlsData.palettePresets
|
||||
? kadenceCustomizerControlsData.palettePresets
|
||||
: [],
|
||||
colors: {
|
||||
palette1: {
|
||||
tooltip: __("1 - Accent", "kadence"),
|
||||
palette: false,
|
||||
},
|
||||
palette2: {
|
||||
tooltip: __("2 - Accent - alt", "kadence"),
|
||||
palette: false,
|
||||
},
|
||||
palette3: {
|
||||
tooltip: __("3 - Strongest text", "kadence"),
|
||||
palette: false,
|
||||
},
|
||||
palette4: {
|
||||
tooltip: __("4 - Strong Text", "kadence"),
|
||||
palette: false,
|
||||
},
|
||||
palette5: {
|
||||
tooltip: __("5 - Medium text", "kadence"),
|
||||
palette: false,
|
||||
},
|
||||
palette6: {
|
||||
tooltip: __("6 - Subtle Text", "kadence"),
|
||||
palette: false,
|
||||
},
|
||||
palette7: {
|
||||
tooltip: __("7 - Subtle Background", "kadence"),
|
||||
palette: false,
|
||||
},
|
||||
palette8: {
|
||||
tooltip: __("8 - Lighter Background", "kadence"),
|
||||
palette: false,
|
||||
},
|
||||
palette9: {
|
||||
tooltip: __("9 - White or offwhite", "kadence"),
|
||||
palette: false,
|
||||
},
|
||||
palette10: {
|
||||
tooltip: __("10 - Accent - Complement", "kadence"),
|
||||
palette: false,
|
||||
},
|
||||
palette11: {
|
||||
tooltip: __("11 - Notices - Success", "kadence"),
|
||||
palette: false,
|
||||
},
|
||||
palette12: {
|
||||
tooltip: __("12 - Notices - Info", "kadence"),
|
||||
palette: false,
|
||||
},
|
||||
palette13: {
|
||||
tooltip: __("13 - Notices - Alert", "kadence"),
|
||||
palette: false,
|
||||
},
|
||||
palette14: {
|
||||
tooltip: __("14 - Notices - Warning", "kadence"),
|
||||
palette: false,
|
||||
},
|
||||
palette15: {
|
||||
tooltip: __("15 - Notices - Rating", "kadence"),
|
||||
palette: false,
|
||||
},
|
||||
},
|
||||
paletteMap: {
|
||||
palette: {
|
||||
tooltip: __("Palette 1", "kadence"),
|
||||
},
|
||||
"second-palette": {
|
||||
tooltip: __("Palette 2", "kadence"),
|
||||
},
|
||||
"third-palette": {
|
||||
tooltip: __("Palette 3", "kadence"),
|
||||
},
|
||||
},
|
||||
};
|
||||
this.controlParams = this.props.control.params.input_attrs
|
||||
? {
|
||||
...defaultParams,
|
||||
...this.props.control.params.input_attrs,
|
||||
}
|
||||
: defaultParams;
|
||||
this.state = {
|
||||
value: value,
|
||||
colorPalette: [],
|
||||
fresh: "start",
|
||||
isVisible: false,
|
||||
textImport: "",
|
||||
importError: false,
|
||||
};
|
||||
this.anchorNodeRef = createRef();
|
||||
}
|
||||
handleChangePalette(active) {
|
||||
let value = this.state.value;
|
||||
const newItems = this.state.value[active].map((item, index) => {
|
||||
const colorToUse =
|
||||
item.slug === "palette10" && item.color === "#FfFfFf"
|
||||
? "oklch(from var(--global-palette1) calc(l + 0.10 * (1 - l)) calc(c * 1.00) calc(h + 180) / 100%)"
|
||||
: item.color;
|
||||
document.documentElement.style.setProperty(
|
||||
"--global-" + item.slug,
|
||||
colorToUse
|
||||
);
|
||||
return item;
|
||||
});
|
||||
value.active = active;
|
||||
value[active] = newItems;
|
||||
this.setState({
|
||||
fresh: this.state.fresh !== "start" ? "start" : "second",
|
||||
});
|
||||
this.updateValues(value);
|
||||
}
|
||||
handlePresetImport(preset) {
|
||||
const presetPalettes = JSON.parse(this.controlParams.palettes);
|
||||
// Verify data.
|
||||
if (
|
||||
presetPalettes &&
|
||||
presetPalettes[preset] &&
|
||||
9 === presetPalettes[preset].length
|
||||
) {
|
||||
const newItems = presetPalettes[preset].map((item, index) => {
|
||||
if (item.color) {
|
||||
this.handleChangeComplete(
|
||||
{ hex: item.color },
|
||||
false,
|
||||
"",
|
||||
index
|
||||
);
|
||||
}
|
||||
});
|
||||
this.setState({
|
||||
fresh: this.state.fresh !== "start" ? "start" : "second",
|
||||
importError: false,
|
||||
});
|
||||
} else {
|
||||
this.setState({ importPresetError: true });
|
||||
}
|
||||
}
|
||||
handleTextImport() {
|
||||
const importText = this.state.textImport;
|
||||
if (!importText) {
|
||||
this.setState({ importError: true });
|
||||
return;
|
||||
}
|
||||
const textImportData = JSON.parse(importText);
|
||||
|
||||
// Get current palette
|
||||
const currentPalette = this.state.value[this.state.value.active];
|
||||
|
||||
// Get imported palette
|
||||
let sanitizedPalette = null;
|
||||
|
||||
// Check if imported palette is in named format (object with palette1, palette2, etc.)
|
||||
if (
|
||||
textImportData &&
|
||||
!Array.isArray(textImportData) &&
|
||||
typeof textImportData === "object"
|
||||
) {
|
||||
// Named format - loop through the palette colors
|
||||
sanitizedPalette = [];
|
||||
currentPalette.forEach((paletteItem) => {
|
||||
const paletteKey = paletteItem.slug;
|
||||
|
||||
// Find the corresponding named color in the import
|
||||
if (
|
||||
textImportData[paletteKey] &&
|
||||
textImportData[paletteKey].color
|
||||
) {
|
||||
// Start with a copy of current paletteItem, then merge in changes
|
||||
sanitizedPalette.push({
|
||||
...paletteItem,
|
||||
...textImportData[paletteKey],
|
||||
});
|
||||
} else {
|
||||
// Use current palette values for any that are missing
|
||||
sanitizedPalette.push(paletteItem);
|
||||
}
|
||||
});
|
||||
} else if (textImportData instanceof Array) {
|
||||
// Array format - continue with existing logic
|
||||
sanitizedPalette = textImportData;
|
||||
}
|
||||
|
||||
// Use the sanitized palette in the usual loop to complete the import
|
||||
// Verify data.
|
||||
if (
|
||||
sanitizedPalette &&
|
||||
sanitizedPalette instanceof Array &&
|
||||
sanitizedPalette[0] &&
|
||||
sanitizedPalette[0].color
|
||||
) {
|
||||
const newItems = sanitizedPalette.map((item, index) => {
|
||||
if (item.color) {
|
||||
this.handleChangeComplete(
|
||||
{ hex: item.color },
|
||||
false,
|
||||
"",
|
||||
index
|
||||
);
|
||||
}
|
||||
});
|
||||
this.setState({
|
||||
fresh: this.state.fresh !== "start" ? "start" : "second",
|
||||
textImport: "",
|
||||
isVisible: false,
|
||||
importError: false,
|
||||
});
|
||||
} else {
|
||||
this.setState({ importError: true });
|
||||
}
|
||||
}
|
||||
convertPaletteToNamedFormat(paletteArray) {
|
||||
const namedFormat = {};
|
||||
paletteArray.forEach((paletteItem) => {
|
||||
namedFormat[paletteItem.slug] = { color: paletteItem.color };
|
||||
});
|
||||
return namedFormat;
|
||||
}
|
||||
|
||||
handleChangeComplete(color, isPalette, item, index) {
|
||||
let newColor = {};
|
||||
if (
|
||||
undefined !== color.rgb &&
|
||||
undefined !== color.rgb.a &&
|
||||
1 !== color.rgb.a
|
||||
) {
|
||||
newColor.color =
|
||||
"rgba(" +
|
||||
color.rgb.r +
|
||||
"," +
|
||||
color.rgb.g +
|
||||
"," +
|
||||
color.rgb.b +
|
||||
"," +
|
||||
color.rgb.a +
|
||||
")";
|
||||
} else {
|
||||
newColor.color = color.hex;
|
||||
}
|
||||
let value = this.state.value;
|
||||
const newItems = this.state.value[this.state.value.active].map(
|
||||
(item, thisIndex) => {
|
||||
if (parseInt(index) === parseInt(thisIndex)) {
|
||||
item = { ...item, ...newColor };
|
||||
const colorToSet =
|
||||
this.state.value[this.state.value.active][index]
|
||||
.slug === "palette10" &&
|
||||
newColor.color === "#FfFfFf"
|
||||
? "oklch(from var(--global-palette1) calc(l + 0.10 * (1 - l)) calc(c * 1.00) calc(h + 180) / 100%)"
|
||||
: newColor.color;
|
||||
document.documentElement.style.setProperty(
|
||||
"--global-" +
|
||||
this.state.value[this.state.value.active][index]
|
||||
.slug,
|
||||
colorToSet
|
||||
);
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
);
|
||||
value[this.state.value.active] = newItems;
|
||||
this.updateValues(value);
|
||||
}
|
||||
|
||||
render() {
|
||||
const toggleVisible = () => {
|
||||
this.setState({ isVisible: true });
|
||||
};
|
||||
const toggleClose = () => {
|
||||
if (this.state.isVisible === true) {
|
||||
this.setState({ isVisible: false });
|
||||
}
|
||||
};
|
||||
const presetPalettes = JSON.parse(this.controlParams.palettes);
|
||||
const currentPaletteData = this.convertPaletteToNamedFormat(
|
||||
this.state.value[this.state.value.active]
|
||||
);
|
||||
const currentPaletteJson = JSON.stringify(currentPaletteData);
|
||||
|
||||
const paletteGroupData = {
|
||||
accent: {
|
||||
name: __("Accents", "kadence"),
|
||||
colors: ["palette1", "palette2", "palette10"],
|
||||
},
|
||||
contrast: {
|
||||
name: __("Contrast", "kadence"),
|
||||
colors: ["palette3", "palette4", "palette5", "palette6"],
|
||||
},
|
||||
base: {
|
||||
name: __("Base", "kadence"),
|
||||
colors: ["palette7", "palette8", "palette9"],
|
||||
},
|
||||
notice: {
|
||||
name: __("Notices", "kadence"),
|
||||
colors: [
|
||||
"palette11",
|
||||
"palette12",
|
||||
"palette13",
|
||||
"palette14",
|
||||
"palette15",
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="kadence-control-field kadence-palette-control kadence-color-control">
|
||||
<div className="kadence-palette-header">
|
||||
<Tooltip text={__("Reset Values", "kadence")}>
|
||||
<Button
|
||||
className="reset kadence-reset"
|
||||
onClick={() => {
|
||||
let value = this.state.value;
|
||||
const reset = JSON.parse(
|
||||
this.controlParams.reset
|
||||
);
|
||||
const newItems = this.state.value[
|
||||
this.state.value.active
|
||||
].map((item, thisIndex) => {
|
||||
item = {
|
||||
...item,
|
||||
...reset[this.state.value.active][
|
||||
thisIndex
|
||||
],
|
||||
};
|
||||
document.documentElement.style.setProperty(
|
||||
"--global-" +
|
||||
reset[this.state.value.active][
|
||||
thisIndex
|
||||
].slug,
|
||||
item.slug === "palette10" &&
|
||||
item.color === "#FfFfFf"
|
||||
? "oklch(from var(--global-palette1) calc(l + 0.10 * (1 - l)) calc(c * 1.00) calc(h + 180) / 100%)"
|
||||
: reset[this.state.value.active][
|
||||
thisIndex
|
||||
].color
|
||||
);
|
||||
return item;
|
||||
});
|
||||
value[this.state.value.active] = newItems;
|
||||
this.updateValues(value);
|
||||
}}
|
||||
>
|
||||
<Dashicon icon="image-rotate" />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
{this.props.control.params.label && (
|
||||
<span className="customize-control-title">
|
||||
{this.props.control.params.label}
|
||||
</span>
|
||||
)}
|
||||
{!this.props.hideResponsive && (
|
||||
<div className="floating-controls">
|
||||
<ButtonGroup>
|
||||
{Object.keys(this.controlParams.paletteMap).map(
|
||||
(palette) => {
|
||||
return (
|
||||
<Tooltip
|
||||
text={
|
||||
this.controlParams
|
||||
.paletteMap[palette]
|
||||
.tooltip
|
||||
}
|
||||
>
|
||||
<Button
|
||||
isTertiary
|
||||
className={
|
||||
(palette ===
|
||||
this.state.value.active
|
||||
? "active-palette "
|
||||
: "") + palette
|
||||
}
|
||||
onClick={() => {
|
||||
this.handleChangePalette(
|
||||
palette
|
||||
);
|
||||
}}
|
||||
>
|
||||
{
|
||||
this.controlParams
|
||||
.paletteMap[palette]
|
||||
.tooltip
|
||||
}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
)}
|
||||
</ButtonGroup>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div
|
||||
ref={this.anchorNodeRef}
|
||||
className="kadence-palette-colors"
|
||||
>
|
||||
{Object.keys(paletteGroupData).map((group, index) => {
|
||||
return (
|
||||
<div className="kadence-palette-group">
|
||||
<div className="kadence-palette-group-name">
|
||||
{paletteGroupData[group].name}
|
||||
</div>
|
||||
<div className="kadence-palette-group-colors">
|
||||
{paletteGroupData[group].colors.map(
|
||||
(item, colorIndex) => {
|
||||
const paletteIndex =
|
||||
item.match(/\d+$/)?.[0] - 1;
|
||||
return (
|
||||
<ColorControl
|
||||
key={
|
||||
item +
|
||||
this.state.value
|
||||
.active +
|
||||
this.state.fresh
|
||||
}
|
||||
presetColors={
|
||||
this.state.colorPalette
|
||||
}
|
||||
color={
|
||||
undefined !==
|
||||
this.state.value[
|
||||
this.state.value
|
||||
.active
|
||||
][paletteIndex] &&
|
||||
this.state.value[
|
||||
this.state.value
|
||||
.active
|
||||
][paletteIndex].color
|
||||
? this.state.value[
|
||||
this.state
|
||||
.value
|
||||
.active
|
||||
][paletteIndex]
|
||||
.color
|
||||
: ""
|
||||
}
|
||||
isPalette={""}
|
||||
usePalette={false}
|
||||
paletteName={item}
|
||||
className={"kt-" + item}
|
||||
tooltip={
|
||||
undefined !==
|
||||
this.controlParams
|
||||
.colors[item]
|
||||
.tooltip
|
||||
? this.controlParams
|
||||
.colors[
|
||||
item
|
||||
].tooltip
|
||||
: ""
|
||||
}
|
||||
onChangeComplete={(
|
||||
color,
|
||||
isPalette
|
||||
) =>
|
||||
this.handleChangeComplete(
|
||||
color,
|
||||
isPalette,
|
||||
item,
|
||||
paletteIndex
|
||||
)
|
||||
}
|
||||
controlRef={
|
||||
this.anchorNodeRef
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<div className={"kadence-palette-import-wrap"}>
|
||||
<Button
|
||||
className={"kadence-palette-import"}
|
||||
onClick={() => {
|
||||
this.state.isVisible
|
||||
? toggleClose()
|
||||
: toggleVisible();
|
||||
}}
|
||||
>
|
||||
<Dashicon icon="portfolio" />
|
||||
</Button>
|
||||
{this.state.isVisible && (
|
||||
<Popover
|
||||
position="bottom right"
|
||||
inline={true}
|
||||
className="kadence-palette-popover-copy-paste kadence-customizer-popover"
|
||||
onClose={toggleClose}
|
||||
>
|
||||
<TabPanel
|
||||
className="kadence-palette-popover-tabs"
|
||||
activeClass="active-tab"
|
||||
initialTabName={"import"}
|
||||
tabs={[
|
||||
{
|
||||
name: "import",
|
||||
title: __("Select Palette", "kadence"),
|
||||
className: "kadence-color-presets",
|
||||
},
|
||||
{
|
||||
name: "custom",
|
||||
title: __("Export/Import", "kadence"),
|
||||
className: "kadence-export-import",
|
||||
},
|
||||
]}
|
||||
>
|
||||
{(tab) => {
|
||||
let tabout;
|
||||
if (tab.name) {
|
||||
if ("import" === tab.name) {
|
||||
tabout = (
|
||||
<Fragment>
|
||||
{Object.keys(
|
||||
presetPalettes
|
||||
).map((item, index) => {
|
||||
return (
|
||||
<Button
|
||||
className={
|
||||
"kadence-palette-item"
|
||||
}
|
||||
style={{
|
||||
height: "100%",
|
||||
width: "100%",
|
||||
}}
|
||||
onClick={() =>
|
||||
this.handlePresetImport(
|
||||
item
|
||||
)
|
||||
}
|
||||
tabIndex={0}
|
||||
>
|
||||
{Object.keys(
|
||||
presetPalettes[
|
||||
item
|
||||
]
|
||||
).map(
|
||||
(
|
||||
color,
|
||||
subIndex
|
||||
) => {
|
||||
return (
|
||||
<div
|
||||
key={
|
||||
subIndex
|
||||
}
|
||||
style={{
|
||||
width: 26,
|
||||
height: 26,
|
||||
marginBottom: 0,
|
||||
transform:
|
||||
"scale(1)",
|
||||
transition:
|
||||
"100ms transform ease",
|
||||
}}
|
||||
className="kadence-swatche-item-wrap"
|
||||
>
|
||||
<span
|
||||
className={
|
||||
"kadence-swatch-item"
|
||||
}
|
||||
style={{
|
||||
height: "100%",
|
||||
display:
|
||||
"block",
|
||||
width: "100%",
|
||||
border: "1px solid rgb(218, 218, 218)",
|
||||
borderRadius:
|
||||
"50%",
|
||||
color: `${presetPalettes[item][color].color}`,
|
||||
boxShadow: `inset 0 0 0 ${
|
||||
30 /
|
||||
2
|
||||
}px`,
|
||||
transition:
|
||||
"100ms box-shadow ease",
|
||||
}}
|
||||
></span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
)}
|
||||
</Button>
|
||||
);
|
||||
})}
|
||||
</Fragment>
|
||||
);
|
||||
} else {
|
||||
tabout = (
|
||||
<Fragment>
|
||||
<h2>
|
||||
{__(
|
||||
"Export",
|
||||
"kadence"
|
||||
)}
|
||||
</h2>
|
||||
<TextareaControl
|
||||
label=""
|
||||
help={__(
|
||||
"Copy export data to use in another site.",
|
||||
"kadence"
|
||||
)}
|
||||
value={
|
||||
currentPaletteJson
|
||||
}
|
||||
onChange={false}
|
||||
/>
|
||||
<h2>
|
||||
{__(
|
||||
"Import",
|
||||
"kadence"
|
||||
)}
|
||||
</h2>
|
||||
<TextareaControl
|
||||
label={__(
|
||||
"Import color set from text data.",
|
||||
"kadence"
|
||||
)}
|
||||
help={__(
|
||||
"Follow format from export above.",
|
||||
"kadence"
|
||||
)}
|
||||
value={
|
||||
this.state
|
||||
.textImport
|
||||
}
|
||||
onChange={(text) =>
|
||||
this.setState({
|
||||
textImport:
|
||||
text,
|
||||
})
|
||||
}
|
||||
/>
|
||||
{this.state.importError && (
|
||||
<p
|
||||
style={{
|
||||
color: "red",
|
||||
}}
|
||||
>
|
||||
{__(
|
||||
"Error with Import data",
|
||||
"kadence"
|
||||
)}
|
||||
</p>
|
||||
)}
|
||||
<Button
|
||||
className={
|
||||
"kadence-import-button"
|
||||
}
|
||||
isPrimary
|
||||
disabled={
|
||||
this.state
|
||||
.textImport
|
||||
? false
|
||||
: true
|
||||
}
|
||||
onClick={() =>
|
||||
this.handleTextImport()
|
||||
}
|
||||
>
|
||||
{__(
|
||||
"Import",
|
||||
"kadence"
|
||||
)}
|
||||
</Button>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
return <div>{tabout}</div>;
|
||||
}}
|
||||
</TabPanel>
|
||||
</Popover>
|
||||
)}
|
||||
</div>
|
||||
{this.props.control.params.description && (
|
||||
<span className="customize-control-description">
|
||||
<a
|
||||
href="https://kadence-theme.com/docs/how-to-use-the-kadence-color-palette/"
|
||||
target="_blank"
|
||||
>
|
||||
{this.props.control.params.description}
|
||||
</a>
|
||||
</span>
|
||||
)}
|
||||
{ this.props.control.renderNotice() }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
updateValues(value) {
|
||||
this.setState({ value: value });
|
||||
this.props.control.setting.set(JSON.stringify(value));
|
||||
kadenceCustomizerControlsData.palette = JSON.stringify(value);
|
||||
}
|
||||
}
|
||||
|
||||
ColorComponent.propTypes = {
|
||||
control: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default ColorComponent;
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createRoot } from '@wordpress/element';
|
||||
import RadioIconComponent from './radio-icon-component.js';
|
||||
|
||||
export const RadioIconControl = wp.customize.KadenceControl.extend( {
|
||||
renderContent: function renderContent() {
|
||||
let control = this;
|
||||
let root = createRoot( control.container[0] );
|
||||
root.render( <RadioIconComponent control={control}/> );
|
||||
// ReactDOM.render(
|
||||
// <RadioIconComponent control={control}/>,
|
||||
// control.container[0]
|
||||
// );
|
||||
}
|
||||
} );
|
||||
@@ -0,0 +1,293 @@
|
||||
/* jshint esversion: 6 */
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
|
||||
import ResponsiveControl from '../common/responsive.js';
|
||||
import Icons from '../common/icons.js';
|
||||
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
const { ButtonGroup, Dashicon, Tooltip, Button } = wp.components;
|
||||
|
||||
const { Component, Fragment } = wp.element;
|
||||
class RadioIconComponent extends Component {
|
||||
constructor() {
|
||||
super( ...arguments );
|
||||
this.updateValues = this.updateValues.bind( this );
|
||||
let value = this.props.control.setting.get();
|
||||
let defaultParams = {
|
||||
layout: {
|
||||
standard: {
|
||||
tooltip: __( 'Background Fullwidth, Content Contained', 'kadence' ),
|
||||
name: __( 'Standard', 'kadence' ),
|
||||
icon: '',
|
||||
},
|
||||
fullwidth: {
|
||||
tooltip: __( 'Background & Content Fullwidth', 'kadence' ),
|
||||
name: __( 'Fullwidth', 'kadence' ),
|
||||
icon: '',
|
||||
},
|
||||
contained: {
|
||||
tooltip: __( 'Background & Content Contained', 'kadence' ),
|
||||
name: __( 'Contained', 'kadence' ),
|
||||
icon: '',
|
||||
},
|
||||
},
|
||||
responsive: true,
|
||||
};
|
||||
this.controlParams = this.props.control.params.input_attrs ? {
|
||||
...defaultParams,
|
||||
...this.props.control.params.input_attrs,
|
||||
} : defaultParams;
|
||||
let responsiveDefault = {
|
||||
'mobile': '',
|
||||
'tablet': '',
|
||||
'desktop': 'standard'
|
||||
};
|
||||
let nonResponsiveDefault = 'standard';
|
||||
let baseDefault;
|
||||
if ( this.controlParams.responsive ) {
|
||||
baseDefault = responsiveDefault;
|
||||
this.defaultValue = this.props.control.params.default ? {
|
||||
...baseDefault,
|
||||
...this.props.control.params.default
|
||||
} : baseDefault;
|
||||
} else {
|
||||
baseDefault = nonResponsiveDefault;
|
||||
this.defaultValue = this.props.control.params.default ? this.props.control.params.default : baseDefault;
|
||||
}
|
||||
if ( this.controlParams.responsive ) {
|
||||
value = value ? {
|
||||
...JSON.parse( JSON.stringify( this.defaultValue ) ),
|
||||
...value
|
||||
} : JSON.parse( JSON.stringify( this.defaultValue ) );
|
||||
} else {
|
||||
value = value ? value : this.defaultValue;
|
||||
}
|
||||
this.state = {
|
||||
currentDevice: 'desktop',
|
||||
value: value,
|
||||
};
|
||||
}
|
||||
render() {
|
||||
const responsiveControlLabel = (
|
||||
<Fragment>
|
||||
{ this.state.currentDevice !== 'desktop' && (
|
||||
<Tooltip text={ __( 'Reset Device Values', 'kadence' ) }>
|
||||
<Button
|
||||
className="reset kadence-reset"
|
||||
disabled={ ( this.state.value[this.state.currentDevice] === this.defaultValue[this.state.currentDevice] ) }
|
||||
onClick={ () => {
|
||||
let value = this.state.value;
|
||||
value[this.state.currentDevice] = this.defaultValue[this.state.currentDevice];
|
||||
this.setState( value );
|
||||
this.updateValues( value );
|
||||
} }
|
||||
>
|
||||
<Dashicon icon='image-rotate' />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
) }
|
||||
{ this.props.control.params.label &&
|
||||
this.props.control.params.label
|
||||
}
|
||||
</Fragment>
|
||||
);
|
||||
const controlLabel = (
|
||||
<Fragment>
|
||||
<Tooltip text={ __( 'Reset Values', 'kadence' ) }>
|
||||
<Button
|
||||
className="reset kadence-reset"
|
||||
disabled={ ( this.state.value === this.defaultValue ) }
|
||||
onClick={ () => {
|
||||
let value = this.defaultValue;
|
||||
this.setState( { value: this.defaultValue } );
|
||||
this.updateValues( value );
|
||||
} }
|
||||
>
|
||||
<Dashicon icon='image-rotate' />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
{ this.props.control.params.label &&
|
||||
this.props.control.params.label
|
||||
}
|
||||
</Fragment>
|
||||
);
|
||||
return (
|
||||
<div className={ `kadence-control-field kadence-radio-icon-control${ this.controlParams.class ? ' ' + this.controlParams.class : '' }` }>
|
||||
{ this.controlParams.responsive && (
|
||||
<ResponsiveControl
|
||||
onChange={ ( currentDevice) => this.setState( { currentDevice } ) }
|
||||
controlLabel={ responsiveControlLabel }
|
||||
>
|
||||
<ButtonGroup className="kadence-radio-container-control">
|
||||
{ Object.keys( this.controlParams.layout ).map( ( item ) => {
|
||||
return (
|
||||
<Fragment>
|
||||
{ this.controlParams.layout[ item ].tooltip && (
|
||||
<Tooltip text={ this.controlParams.layout[ item ].tooltip }>
|
||||
<Button
|
||||
isTertiary
|
||||
className={ ( item === this.state.value[this.state.currentDevice] ?
|
||||
'active-radio ' :
|
||||
'' ) + 'kt-ratio-' + item + ( this.controlParams.layout[ item ].icon && this.controlParams.layout[ item ].name ? ' btn-flex-col' : '' ) }
|
||||
onClick={ () => {
|
||||
let value = this.state.value;
|
||||
value[ this.state.currentDevice ] = item;
|
||||
this.setState( value );
|
||||
this.updateValues( value );
|
||||
} }
|
||||
>
|
||||
{ this.controlParams.layout[ item ].icon && (
|
||||
<span className="kadence-radio-icon">
|
||||
{ Icons[ this.controlParams.layout[ item ].icon ] }
|
||||
</span>
|
||||
) }
|
||||
{ this.controlParams.layout[ item ].dashicon && (
|
||||
<span className="kadence-radio-icon kadence-radio-dashicon">
|
||||
<Dashicon icon={ this.controlParams.layout[ item ].dashicon } />
|
||||
</span>
|
||||
) }
|
||||
{ this.controlParams.layout[ item ].name && (
|
||||
this.controlParams.layout[ item ].name
|
||||
) }
|
||||
</Button>
|
||||
</Tooltip>
|
||||
) }
|
||||
{ ! this.controlParams.layout[ item ].tooltip && (
|
||||
<Button
|
||||
isTertiary
|
||||
className={ ( item === this.state.value[this.state.currentDevice] ?
|
||||
'active-radio ' :
|
||||
'' ) + 'kt-radio-' + item + ( this.controlParams.layout[ item ].icon && this.controlParams.layout[ item ].name ? ' btn-flex-col' : '' ) }
|
||||
onClick={ () => {
|
||||
let value = this.state.value;
|
||||
value[ this.state.currentDevice ] = item;
|
||||
this.setState( value );
|
||||
this.updateValues( value );
|
||||
} }
|
||||
>
|
||||
{ this.controlParams.layout[ item ].icon && (
|
||||
<span className="kadence-radio-icon">
|
||||
{ Icons[ this.controlParams.layout[ item ].icon ] }
|
||||
</span>
|
||||
) }
|
||||
{ this.controlParams.layout[ item ].dashicon && (
|
||||
<span className="kadence-radio-icon kadence-radio-dashicon">
|
||||
<Dashicon icon={ this.controlParams.layout[ item ].dashicon } />
|
||||
</span>
|
||||
) }
|
||||
{ this.controlParams.layout[ item ].name && (
|
||||
this.controlParams.layout[ item ].name
|
||||
) }
|
||||
</Button>
|
||||
) }
|
||||
</Fragment>
|
||||
);
|
||||
} )}
|
||||
</ButtonGroup>
|
||||
</ResponsiveControl>
|
||||
) }
|
||||
{ ! this.controlParams.responsive && (
|
||||
<Fragment>
|
||||
<div className="kadence-responsive-control-bar">
|
||||
<span className="customize-control-title">{ controlLabel }</span>
|
||||
</div>
|
||||
<ButtonGroup className="kadence-radio-container-control">
|
||||
{ Object.keys( this.controlParams.layout ).map( ( item ) => {
|
||||
return (
|
||||
<Fragment>
|
||||
{ this.controlParams.layout[ item ].tooltip && (
|
||||
<Tooltip text={ this.controlParams.layout[ item ].tooltip }>
|
||||
<Button
|
||||
isTertiary
|
||||
className={ ( item === this.state.value ?
|
||||
'active-radio ' :
|
||||
'' ) + 'kt-radio-' + item + ( this.controlParams.layout[ item ].icon && this.controlParams.layout[ item ].name ? ' btn-flex-col' : '' ) }
|
||||
onClick={ () => {
|
||||
let value = this.state.value;
|
||||
value = item;
|
||||
this.setState( { value: item });
|
||||
this.updateValues( value );
|
||||
} }
|
||||
>
|
||||
{ this.controlParams.layout[ item ].icon && (
|
||||
<span className="kadence-radio-icon">
|
||||
{ Icons[ this.controlParams.layout[ item ].icon ] }
|
||||
</span>
|
||||
) }
|
||||
{ this.controlParams.layout[ item ].dashicon && (
|
||||
<span className="kadence-radio-icon kadence-radio-dashicon">
|
||||
<Dashicon icon={ this.controlParams.layout[ item ].dashicon } />
|
||||
</span>
|
||||
) }
|
||||
{ this.controlParams.layout[ item ].name && (
|
||||
this.controlParams.layout[ item ].name
|
||||
) }
|
||||
</Button>
|
||||
</Tooltip>
|
||||
) }
|
||||
{ ! this.controlParams.layout[ item ].tooltip && (
|
||||
<Button
|
||||
isTertiary
|
||||
className={ ( item === this.state.value ?
|
||||
'active-radio ' :
|
||||
'' ) + 'kt-radio-' + item + ( this.controlParams.layout[ item ].icon && this.controlParams.layout[ item ].name ? ' btn-flex-col' : '' ) }
|
||||
onClick={ () => {
|
||||
let value = this.state.value;
|
||||
value = item;
|
||||
this.setState( { value: item });
|
||||
this.updateValues( value );
|
||||
} }
|
||||
>
|
||||
{ this.controlParams.layout[ item ].icon && (
|
||||
<span className="kadence-radio-icon">
|
||||
{ Icons[ this.controlParams.layout[ item ].icon ] }
|
||||
</span>
|
||||
) }
|
||||
{ this.controlParams.layout[ item ].dashicon && (
|
||||
<span className="kadence-radio-icon kadence-radio-dashicon">
|
||||
<Dashicon icon={ this.controlParams.layout[ item ].dashicon } />
|
||||
</span>
|
||||
) }
|
||||
{ this.controlParams.layout[ item ].name && (
|
||||
this.controlParams.layout[ item ].name
|
||||
) }
|
||||
</Button>
|
||||
) }
|
||||
</Fragment>
|
||||
);
|
||||
} )}
|
||||
</ButtonGroup>
|
||||
</Fragment>
|
||||
) }
|
||||
{ this.props.control.renderNotice() }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
updateValues( value ) {
|
||||
if ( this.controlParams.footer ) {
|
||||
let event = new CustomEvent(
|
||||
'kadenceUpdateFooterColumns', {
|
||||
'detail': this.controlParams.footer,
|
||||
} );
|
||||
document.dispatchEvent( event );
|
||||
}
|
||||
if ( this.controlParams.responsive ) {
|
||||
this.props.control.setting.set( {
|
||||
...this.props.control.setting.get(),
|
||||
...value,
|
||||
flag: !this.props.control.setting.get().flag
|
||||
} );
|
||||
} else {
|
||||
this.props.control.setting.set( value );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RadioIconComponent.propTypes = {
|
||||
control: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
export default RadioIconComponent;
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createRoot } from '@wordpress/element';
|
||||
import RangeComponent from './range-component.js';
|
||||
|
||||
export const RangeControl = wp.customize.KadenceControl.extend( {
|
||||
renderContent: function renderContent() {
|
||||
let control = this;
|
||||
let root = createRoot( control.container[0] );
|
||||
root.render( <RangeComponent control={control}/> );
|
||||
// ReactDOM.render(
|
||||
// <RangeComponent control={control}/>,
|
||||
// control.container[0]
|
||||
// );
|
||||
}
|
||||
} );
|
||||
@@ -0,0 +1,307 @@
|
||||
/* jshint esversion: 6 */
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
|
||||
import ResponsiveControl from '../common/responsive.js';
|
||||
import KadenceRange from '../common/range.js';
|
||||
import Icons from '../common/icons.js';
|
||||
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
const { RangeControl, Dashicon, Tooltip, Button, ToolbarGroup } = wp.components;
|
||||
|
||||
const { Component, Fragment } = wp.element;
|
||||
class RangeComponent extends Component {
|
||||
constructor() {
|
||||
super( ...arguments );
|
||||
this.updateValues = this.updateValues.bind( this );
|
||||
this.getUnitButtons = this.getUnitButtons.bind( this );
|
||||
this.createLevelControlToolbar = this.createLevelControlToolbar.bind( this );
|
||||
this.createResponsiveLevelControlToolbar = this.createResponsiveLevelControlToolbar.bind( this );
|
||||
this.getResponsiveUnitButtons = this.getResponsiveUnitButtons.bind( this );
|
||||
let value = this.props.control.setting.get();
|
||||
let baseDefault = {
|
||||
'unit': {
|
||||
'mobile': 'px',
|
||||
'tablet': 'px',
|
||||
'desktop': 'px'
|
||||
},
|
||||
'size': {
|
||||
'mobile': 70,
|
||||
'tablet': 70,
|
||||
'desktop': 140
|
||||
}
|
||||
};
|
||||
this.defaultValue = this.props.control.params.default ? {
|
||||
...baseDefault,
|
||||
...this.props.control.params.default
|
||||
} : baseDefault;
|
||||
value = value ? {
|
||||
...this.defaultValue,
|
||||
...value
|
||||
} : this.defaultValue;
|
||||
let defaultParams = {
|
||||
min: {
|
||||
px: '0',
|
||||
em: '0',
|
||||
rem: '0',
|
||||
vh: '0'
|
||||
},
|
||||
max: {
|
||||
px: '300',
|
||||
em: '12',
|
||||
rem: '12',
|
||||
vh: '40'
|
||||
},
|
||||
step: {
|
||||
px: '1',
|
||||
em: '0.01',
|
||||
rem: '0.01',
|
||||
vh: '1'
|
||||
},
|
||||
units: ['px', 'em', 'rem', 'vh'],
|
||||
responsive: true,
|
||||
};
|
||||
this.controlParams = this.props.control.params.input_attrs ? {
|
||||
...defaultParams,
|
||||
...this.props.control.params.input_attrs,
|
||||
} : defaultParams;
|
||||
this.state = {
|
||||
currentDevice: 'desktop',
|
||||
size: value.size,
|
||||
unit: value.unit,
|
||||
};
|
||||
}
|
||||
render() {
|
||||
const responsiveControlLabel = (
|
||||
<Fragment>
|
||||
{ this.controlParams.responsive && (
|
||||
<Fragment>
|
||||
<Tooltip text={ __( 'Reset Device Values', 'kadence' ) }>
|
||||
<Button
|
||||
className="reset kadence-reset"
|
||||
disabled={ ( this.state.size[this.state.currentDevice] === this.defaultValue.size[this.state.currentDevice] ) && ( this.state.unit[this.state.currentDevice] === this.defaultValue.unit[this.state.currentDevice] ) }
|
||||
onClick={ () => {
|
||||
let value = this.state.size;
|
||||
let unit = this.state.unit;
|
||||
if ( typeof value !== 'object' ) {
|
||||
value = {
|
||||
'mobile': '',
|
||||
'tablet': '',
|
||||
'desktop': '',
|
||||
};
|
||||
this.setState( { size: value } );
|
||||
if ( typeof unit !== 'object' ) {
|
||||
unit = {
|
||||
'mobile': '',
|
||||
'tablet': '',
|
||||
'desktop': '',
|
||||
};
|
||||
this.setState( { unit: unit } );
|
||||
}
|
||||
}
|
||||
value[this.state.currentDevice] = this.defaultValue.size[this.state.currentDevice];
|
||||
unit[this.state.currentDevice] = this.defaultValue.unit[this.state.currentDevice];
|
||||
this.setState( { size: value, unit: unit } );
|
||||
this.updateValues( { size: value, unit: unit } );
|
||||
} }
|
||||
>
|
||||
<Dashicon icon='image-rotate' />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
{ this.props.control.params.label &&
|
||||
this.props.control.params.label
|
||||
}
|
||||
</Fragment>
|
||||
) }
|
||||
</Fragment>
|
||||
);
|
||||
const controlLabel = (
|
||||
<Fragment>
|
||||
<Tooltip text={ __( 'Reset Values', 'kadence' ) }>
|
||||
<Button
|
||||
className="reset kadence-reset"
|
||||
disabled={ ( this.state.size === this.defaultValue.size ) && ( this.state.unit === this.defaultValue.unit ) }
|
||||
onClick={ () => {
|
||||
let value = this.state.size;
|
||||
value = this.defaultValue.size;
|
||||
let svalue = this.state.unit;
|
||||
svalue = this.defaultValue.unit;
|
||||
this.setState( { size: value, unit: svalue } );
|
||||
this.updateValues( { size: value, unit: svalue } );
|
||||
} }
|
||||
>
|
||||
<Dashicon icon='image-rotate' />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
{ this.props.control.params.label &&
|
||||
this.props.control.params.label
|
||||
}
|
||||
</Fragment>
|
||||
);
|
||||
return (
|
||||
<div className="kadence-control-field kadence-range-control">
|
||||
{ this.controlParams.responsive && (
|
||||
<ResponsiveControl
|
||||
onChange={ ( currentDevice) => this.setState( { currentDevice } ) }
|
||||
controlLabel={ responsiveControlLabel }
|
||||
>
|
||||
<KadenceRange
|
||||
initialPosition={ ( ! this.state.size[this.state.currentDevice] ? this.defaultValue.size[this.state.currentDevice] : undefined ) }
|
||||
value={ ( undefined !== this.state.size[this.state.currentDevice] ? this.state.size[this.state.currentDevice] : undefined ) }
|
||||
onChange={ (val) => {
|
||||
let value = this.state.size;
|
||||
if ( typeof value !== 'object' ) {
|
||||
value = {
|
||||
'mobile': '',
|
||||
'tablet': '',
|
||||
'desktop': '',
|
||||
};
|
||||
this.setState( { size: value } );
|
||||
let unit = this.state.unit;
|
||||
if ( typeof unit !== 'object' ) {
|
||||
unit = {
|
||||
'mobile': '',
|
||||
'tablet': '',
|
||||
'desktop': '',
|
||||
};
|
||||
this.setState( { unit: unit } );
|
||||
}
|
||||
}
|
||||
value[ this.state.currentDevice ] = val;
|
||||
this.setState( { size: value } );
|
||||
this.updateValues( { size: value } );
|
||||
} }
|
||||
min={this.controlParams.min[this.state.unit[this.state.currentDevice]]}
|
||||
max={this.controlParams.max[this.state.unit[this.state.currentDevice]]}
|
||||
step={this.controlParams.step[this.state.unit[this.state.currentDevice]]}
|
||||
/>
|
||||
{ this.controlParams.units && (
|
||||
<div className="kadence-units">
|
||||
{ this.getResponsiveUnitButtons() }
|
||||
</div>
|
||||
) }
|
||||
</ResponsiveControl>
|
||||
) }
|
||||
{ ! this.controlParams.responsive && (
|
||||
<Fragment>
|
||||
<div className="kadence-responsive-control-bar">
|
||||
<span className="customize-control-title">{ controlLabel }</span>
|
||||
</div>
|
||||
<div className="kadence-responsive-controls-content">
|
||||
<KadenceRange
|
||||
initialPosition={ ( ! this.state.size ? this.defaultValue.size : undefined ) }
|
||||
value={this.state.size}
|
||||
onChange={ (val) => {
|
||||
let value = this.state.size;
|
||||
value = val;
|
||||
this.setState( { size: value } );
|
||||
this.updateValues( { size: value } );
|
||||
} }
|
||||
min={this.controlParams.min[this.state.unit]}
|
||||
max={this.controlParams.max[this.state.unit]}
|
||||
step={this.controlParams.step[this.state.unit]}
|
||||
/>
|
||||
{ this.controlParams.units && (
|
||||
<div className="kadence-units">
|
||||
{ this.getUnitButtons() }
|
||||
</div>
|
||||
) }
|
||||
</div>
|
||||
</Fragment>
|
||||
) }
|
||||
{ this.props.control.renderNotice() }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
getUnitButtons() {
|
||||
let self = this;
|
||||
const { units } = this.controlParams;
|
||||
if ( units.length === 1 ) {
|
||||
return ( <Button
|
||||
className="is-active is-single"
|
||||
isSmall
|
||||
disabled
|
||||
>{ ( '%' === self.state.unit ? Icons.percent : Icons[ self.state.unit ] ) }</Button> );
|
||||
}
|
||||
return <ToolbarGroup
|
||||
isCollapsed={ true }
|
||||
icon={ ( '%' === self.state.unit ? Icons.percent : Icons[ self.state.unit ] ) }
|
||||
label={ __( 'Unit', 'kadence' ) }
|
||||
controls={ units.map( (unit) => this.createLevelControlToolbar( unit ) ) }
|
||||
/>
|
||||
}
|
||||
createLevelControlToolbar( unit ) {
|
||||
return [ {
|
||||
icon: ( unit === '%' ? Icons.percent : Icons[ unit ] ),
|
||||
isActive: this.state.unit === unit,
|
||||
onClick: () => {
|
||||
let value = this.state.unit;
|
||||
value = unit;
|
||||
this.setState( { unit: value } );
|
||||
this.updateValues( { unit: value } );
|
||||
},
|
||||
} ];
|
||||
};
|
||||
createResponsiveLevelControlToolbar( unit ) {
|
||||
return [ {
|
||||
icon: ( unit === '%' ? Icons.percent : Icons[ unit ] ),
|
||||
isActive: this.state.unit[this.state.currentDevice] === unit,
|
||||
onClick: () => {
|
||||
let value = this.state.unit;
|
||||
if ( typeof value !== 'object' ) {
|
||||
value = {
|
||||
'mobile': '',
|
||||
'tablet': '',
|
||||
'desktop': '',
|
||||
};
|
||||
this.setState( { unit: value } );
|
||||
let size = this.state.size;
|
||||
if ( typeof size !== 'object' ) {
|
||||
size = {
|
||||
'mobile': '',
|
||||
'tablet': '',
|
||||
'desktop': '',
|
||||
};
|
||||
this.setState( { size: size } );
|
||||
}
|
||||
}
|
||||
value[ this.state.currentDevice ] = unit;
|
||||
this.setState( { unit: value } );
|
||||
this.updateValues( { unit: value } );
|
||||
},
|
||||
} ];
|
||||
};
|
||||
getResponsiveUnitButtons() {
|
||||
let self = this;
|
||||
const { units } = this.controlParams;
|
||||
if ( units.length === 1 ) {
|
||||
return ( <Button
|
||||
className="is-active is-single"
|
||||
isSmall
|
||||
disabled
|
||||
>{ ( '%' === self.state.unit[ self.state.currentDevice ] ? Icons.percent : Icons[ self.state.unit[ self.state.currentDevice ] ] ) }</Button> );
|
||||
}
|
||||
return <ToolbarGroup
|
||||
isCollapsed={ true }
|
||||
icon={ ( '%' === self.state.unit[ self.state.currentDevice ] ? Icons.percent : Icons[ self.state.unit[ self.state.currentDevice ] ] ) }
|
||||
label={ __( 'Unit', 'kadence' ) }
|
||||
controls={ units.map( (unit) => this.createResponsiveLevelControlToolbar( unit ) ) }
|
||||
/>
|
||||
}
|
||||
updateValues( value ) {
|
||||
if ( this.controlParams.responsive ) {
|
||||
value.flag = !this.props.control.setting.get().flag;
|
||||
}
|
||||
this.props.control.setting.set( {
|
||||
...this.props.control.setting.get(),
|
||||
...value,
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
RangeComponent.propTypes = {
|
||||
control: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
export default RangeComponent;
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createRoot } from '@wordpress/element';
|
||||
import RowLayoutComponent from './row-layout-component';
|
||||
|
||||
export const RowControl = wp.customize.KadenceControl.extend( {
|
||||
renderContent: function renderContent() {
|
||||
let control = this;
|
||||
let root = createRoot( control.container[0] );
|
||||
root.render( <RowLayoutComponent control={control} customizer={ wp.customize }/> );
|
||||
// ReactDOM.render(
|
||||
// <RowLayoutComponent control={control} customizer={ wp.customize }/>,
|
||||
// control.container[0]
|
||||
// );
|
||||
}
|
||||
} );
|
||||
@@ -0,0 +1,450 @@
|
||||
/* jshint esversion: 6 */
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
|
||||
import ResponsiveControl from '../common/responsive.js';
|
||||
import Icons from '../common/icons.js';
|
||||
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
const { ButtonGroup, Dashicon, Tooltip, Button } = wp.components;
|
||||
|
||||
const { Component, Fragment } = wp.element;
|
||||
class RowLayoutComponent extends Component {
|
||||
constructor() {
|
||||
super( ...arguments );
|
||||
this.updateValues = this.updateValues.bind( this );
|
||||
this.onFooterUpdate = this.onFooterUpdate.bind( this );
|
||||
this.linkColumns();
|
||||
let value = this.props.control.setting.get();
|
||||
let defaultParams = {
|
||||
desktop: {
|
||||
'column5': {
|
||||
'equal': {
|
||||
tooltip: __( 'Equal Width Columns', 'kadence' ),
|
||||
icon: 'fivecol',
|
||||
},
|
||||
},
|
||||
'column4': {
|
||||
'equal': {
|
||||
tooltip: __( 'Equal Width Columns', 'kadence' ),
|
||||
icon: 'fourcol',
|
||||
},
|
||||
'left-forty': {
|
||||
tooltip: __( 'Left Heavy 40/20/20/20', 'kadence' ),
|
||||
icon: 'lfourforty',
|
||||
},
|
||||
'right-forty': {
|
||||
tooltip: __( 'Right Heavy 20/20/20/40', 'kadence' ),
|
||||
icon: 'rfourforty',
|
||||
},
|
||||
},
|
||||
'column3': {
|
||||
'equal': {
|
||||
tooltip: __( 'Equal Width Columns', 'kadence' ),
|
||||
icon: 'threecol',
|
||||
},
|
||||
'left-half': {
|
||||
tooltip: __( 'Left Heavy 50/25/25', 'kadence' ),
|
||||
icon: 'lefthalf',
|
||||
},
|
||||
'right-half': {
|
||||
tooltip: __( 'Right Heavy 25/25/50', 'kadence' ),
|
||||
icon: 'righthalf',
|
||||
},
|
||||
'center-half': {
|
||||
tooltip: __( 'Center Heavy 25/50/25', 'kadence' ),
|
||||
icon: 'centerhalf',
|
||||
},
|
||||
'center-wide': {
|
||||
tooltip: __( 'Wide Center 20/60/20', 'kadence' ),
|
||||
icon: 'widecenter',
|
||||
},
|
||||
},
|
||||
'column2': {
|
||||
'equal': {
|
||||
tooltip: __( 'Equal Width Columns', 'kadence' ),
|
||||
icon: 'twocol',
|
||||
},
|
||||
'left-golden': {
|
||||
tooltip: __( 'Left Heavy 66/33', 'kadence' ),
|
||||
icon: 'twoleftgolden',
|
||||
},
|
||||
'right-golden': {
|
||||
tooltip: __( 'Right Heavy 33/66', 'kadence' ),
|
||||
icon: 'tworightgolden',
|
||||
},
|
||||
},
|
||||
'column1': {
|
||||
'row': {
|
||||
tooltip: __( 'Equal Width Columns', 'kadence' ),
|
||||
icon: 'row',
|
||||
},
|
||||
}
|
||||
},
|
||||
mobile: {
|
||||
'column5': {
|
||||
'equal': {
|
||||
tooltip: __( 'Equal Width Columns', 'kadence' ),
|
||||
icon: 'fivecol',
|
||||
},
|
||||
'row': {
|
||||
tooltip: __( 'Collapse to Rows', 'kadence' ),
|
||||
icon: 'collapserowfive',
|
||||
},
|
||||
},
|
||||
'column4': {
|
||||
'equal': {
|
||||
tooltip: __( 'Equal Width Columns', 'kadence' ),
|
||||
icon: 'fourcol',
|
||||
},
|
||||
'two-grid': {
|
||||
tooltip: __( 'Two Column Grid', 'kadence' ),
|
||||
icon: 'grid',
|
||||
},
|
||||
'row': {
|
||||
tooltip: __( 'Collapse to Rows', 'kadence' ),
|
||||
icon: 'collapserowfour',
|
||||
},
|
||||
},
|
||||
'column3': {
|
||||
'equal': {
|
||||
tooltip: __( 'Equal Width Columns', 'kadence' ),
|
||||
icon: 'threecol',
|
||||
},
|
||||
'left-half': {
|
||||
tooltip: __( 'Left Heavy 50/25/25', 'kadence' ),
|
||||
icon: 'lefthalf',
|
||||
},
|
||||
'right-half': {
|
||||
tooltip: __( 'Right Heavy 25/25/50', 'kadence' ),
|
||||
icon: 'righthalf',
|
||||
},
|
||||
'center-half': {
|
||||
tooltip: __( 'Center Heavy 25/50/25', 'kadence' ),
|
||||
icon: 'centerhalf',
|
||||
},
|
||||
'center-wide': {
|
||||
tooltip: __( 'Wide Center 20/60/20', 'kadence' ),
|
||||
icon: 'widecenter',
|
||||
},
|
||||
'first-row': {
|
||||
tooltip: __( 'First Row, Next Columns 100 - 50/50', 'kadence' ),
|
||||
icon: 'firstrow',
|
||||
},
|
||||
'last-row': {
|
||||
tooltip: __( 'Last Row, Previous Columns 50/50 - 100', 'kadence' ),
|
||||
icon: 'lastrow',
|
||||
},
|
||||
'row': {
|
||||
tooltip: __( 'Collapse to Rows', 'kadence' ),
|
||||
icon: 'collapserowthree',
|
||||
},
|
||||
},
|
||||
'column2': {
|
||||
'equal': {
|
||||
tooltip: __( 'Equal Width Columns', 'kadence' ),
|
||||
icon: 'twocol',
|
||||
},
|
||||
'left-golden': {
|
||||
tooltip: __( 'Left Heavy 66/33', 'kadence' ),
|
||||
icon: 'twoleftgolden',
|
||||
},
|
||||
'right-golden': {
|
||||
tooltip: __( 'Right Heavy 33/66', 'kadence' ),
|
||||
icon: 'tworightgolden',
|
||||
},
|
||||
'row': {
|
||||
tooltip: __( 'Collapse to Rows', 'kadence' ),
|
||||
icon: 'collapserow',
|
||||
},
|
||||
},
|
||||
'column1': {
|
||||
'row': {
|
||||
tooltip: __( 'Single Row', 'kadence' ),
|
||||
icon: 'row',
|
||||
},
|
||||
}
|
||||
},
|
||||
responsive: true,
|
||||
};
|
||||
this.controlParams = this.props.control.params.input_attrs ? {
|
||||
...defaultParams,
|
||||
...this.props.control.params.input_attrs,
|
||||
} : defaultParams;
|
||||
let responsiveDefault = {
|
||||
'mobile': 'row',
|
||||
'tablet': '',
|
||||
'desktop': 'equal'
|
||||
};
|
||||
let nonResponsiveDefault = 'equal';
|
||||
let baseDefault;
|
||||
if ( this.controlParams.responsive ) {
|
||||
baseDefault = responsiveDefault;
|
||||
this.defaultValue = this.props.control.params.default ? {
|
||||
...baseDefault,
|
||||
...this.props.control.params.default
|
||||
} : baseDefault;
|
||||
} else {
|
||||
baseDefault = nonResponsiveDefault;
|
||||
this.defaultValue = this.props.control.params.default ? this.props.control.params.default : baseDefault;
|
||||
}
|
||||
if ( this.controlParams.responsive ) {
|
||||
value = value ? {
|
||||
...JSON.parse( JSON.stringify( this.defaultValue ) ),
|
||||
...value
|
||||
} : JSON.parse( JSON.stringify( this.defaultValue ) );
|
||||
} else {
|
||||
value = value ? value : this.defaultValue;
|
||||
}
|
||||
let columns = 0;
|
||||
if ( this.controlParams.footer ) {
|
||||
columns = parseInt( this.props.customizer.control( 'footer_' + this.controlParams.footer + '_columns' ).setting.get(), 10 );
|
||||
}
|
||||
this.state = {
|
||||
currentDevice: 'desktop',
|
||||
columns: columns,
|
||||
value: value,
|
||||
};
|
||||
}
|
||||
render() {
|
||||
const responsiveControlLabel = (
|
||||
<Fragment>
|
||||
{ this.state.currentDevice !== 'desktop' && (
|
||||
<Tooltip text={ __( 'Reset Device Values', 'kadence' ) }>
|
||||
<Button
|
||||
className="reset kadence-reset"
|
||||
disabled={ ( this.state.value[this.state.currentDevice] === this.defaultValue[this.state.currentDevice] ) }
|
||||
onClick={ () => {
|
||||
let value = this.state.value;
|
||||
value[this.state.currentDevice] = this.defaultValue[this.state.currentDevice];
|
||||
this.setState( value );
|
||||
this.updateValues( value );
|
||||
} }
|
||||
>
|
||||
<Dashicon icon='image-rotate' />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
) }
|
||||
{ this.props.control.params.label &&
|
||||
this.props.control.params.label
|
||||
}
|
||||
</Fragment>
|
||||
);
|
||||
const controlLabel = (
|
||||
<Fragment>
|
||||
<Tooltip text={ __( 'Reset Values', 'kadence' ) }>
|
||||
<Button
|
||||
className="reset kadence-reset"
|
||||
disabled={ ( this.state.value === this.defaultValue ) }
|
||||
onClick={ () => {
|
||||
let value = this.defaultValue;
|
||||
this.setState( { value: this.defaultValue } );
|
||||
this.updateValues( value );
|
||||
} }
|
||||
>
|
||||
<Dashicon icon='image-rotate' />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
{ this.props.control.params.label &&
|
||||
this.props.control.params.label
|
||||
}
|
||||
</Fragment>
|
||||
);
|
||||
let controlMap = {}
|
||||
if ( this.state.currentDevice !== 'desktop' ) {
|
||||
controlMap = this.controlParams.mobile['column' + this.state.columns ];
|
||||
} else {
|
||||
controlMap = this.controlParams.desktop['column' + this.state.columns ];
|
||||
}
|
||||
return (
|
||||
<div className="kadence-control-field kadence-radio-icon-control kadence-row-layout-control">
|
||||
{ this.controlParams.responsive && (
|
||||
<ResponsiveControl
|
||||
onChange={ ( currentDevice) => this.setState( { currentDevice } ) }
|
||||
controlLabel={ responsiveControlLabel }
|
||||
>
|
||||
<ButtonGroup className="kadence-radio-container-control">
|
||||
{ Object.keys( controlMap ).map( ( item ) => {
|
||||
return (
|
||||
<Fragment>
|
||||
{ controlMap[ item ].tooltip && (
|
||||
<Tooltip text={ controlMap[ item ].tooltip }>
|
||||
<Button
|
||||
isTertiary
|
||||
className={ ( item === this.state.value[this.state.currentDevice] ?
|
||||
'active-radio ' :
|
||||
'' ) + 'kadence-btn-item-' + item }
|
||||
onClick={ () => {
|
||||
let value = this.state.value;
|
||||
value[ this.state.currentDevice ] = item;
|
||||
this.setState( value );
|
||||
this.updateValues( value );
|
||||
} }
|
||||
>
|
||||
{ controlMap[ item ].icon && (
|
||||
<span className="kadence-radio-icon">
|
||||
{ Icons[ controlMap[ item ].icon ] }
|
||||
</span>
|
||||
) }
|
||||
{ controlMap[ item ].dashicon && (
|
||||
<span className="kadence-radio-icon kadence-radio-dashicon">
|
||||
<Dashicon icon={ controlMap[ item ].dashicon } />
|
||||
</span>
|
||||
) }
|
||||
{ controlMap[ item ].name && (
|
||||
controlMap[ item ].name
|
||||
) }
|
||||
</Button>
|
||||
</Tooltip>
|
||||
) }
|
||||
{ ! controlMap[ item ].tooltip && (
|
||||
<Button
|
||||
isTertiary
|
||||
className={ ( item === this.state.value[this.state.currentDevice] ?
|
||||
'active-radio ' :
|
||||
'' ) + 'kadence-btn-item-' + item }
|
||||
onClick={ () => {
|
||||
let value = this.state.value;
|
||||
value[ this.state.currentDevice ] = item;
|
||||
this.setState( value );
|
||||
this.updateValues( value );
|
||||
} }
|
||||
>
|
||||
{ controlMap[ item ].icon && (
|
||||
<span className="kadence-radio-icon">
|
||||
{ Icons[ controlMap[ item ].icon ] }
|
||||
</span>
|
||||
) }
|
||||
{ controlMap[ item ].dashicon && (
|
||||
<span className="kadence-radio-icon kadence-radio-dashicon">
|
||||
<Dashicon icon={ controlMap[ item ].dashicon } />
|
||||
</span>
|
||||
) }
|
||||
{ controlMap[ item ].name && (
|
||||
controlMap[ item ].name
|
||||
) }
|
||||
</Button>
|
||||
) }
|
||||
</Fragment>
|
||||
);
|
||||
} )}
|
||||
</ButtonGroup>
|
||||
</ResponsiveControl>
|
||||
) }
|
||||
{ ! this.controlParams.responsive && (
|
||||
<Fragment>
|
||||
<div className="kadence-responsive-control-bar">
|
||||
<span className="customize-control-title">{ controlLabel }</span>
|
||||
</div>
|
||||
<ButtonGroup className="kadence-radio-container-control">
|
||||
{ Object.keys( controlMap ).map( ( item ) => {
|
||||
return (
|
||||
<Fragment>
|
||||
{ controlMap[ item ].tooltip && (
|
||||
<Tooltip text={ controlMap[ item ].tooltip }>
|
||||
<Button
|
||||
isTertiary
|
||||
className={ ( item === this.state.value ?
|
||||
'active-radio ' :
|
||||
'' ) + 'kadence-btn-item-' + item }
|
||||
onClick={ () => {
|
||||
let value = this.state.value;
|
||||
value = item;
|
||||
this.setState( { value: item });
|
||||
this.updateValues( value );
|
||||
} }
|
||||
>
|
||||
{ controlMap[ item ].icon && (
|
||||
<span className="kadence-radio-icon">
|
||||
{ Icons[ controlMap[ item ].icon ] }
|
||||
</span>
|
||||
) }
|
||||
{ controlMap[ item ].name && (
|
||||
controlMap[ item ].name
|
||||
) }
|
||||
</Button>
|
||||
</Tooltip>
|
||||
) }
|
||||
{ ! controlMap[ item ].tooltip && (
|
||||
<Button
|
||||
isTertiary
|
||||
className={ ( item === this.state.value ?
|
||||
'active-radio ' :
|
||||
'' ) + 'kadence-btn-item-' + item }
|
||||
onClick={ () => {
|
||||
let value = this.state.value;
|
||||
value = item;
|
||||
this.setState( { value: item });
|
||||
this.updateValues( value );
|
||||
} }
|
||||
>
|
||||
{ controlMap[ item ].icon && (
|
||||
<span className="kadence-radio-icon">
|
||||
{ Icons[ controlMap[ item ].icon ] }
|
||||
</span>
|
||||
) }
|
||||
{ controlMap[ item ].name && (
|
||||
controlMap[ item ].name
|
||||
) }
|
||||
</Button>
|
||||
) }
|
||||
</Fragment>
|
||||
);
|
||||
} )}
|
||||
</ButtonGroup>
|
||||
</Fragment>
|
||||
) }
|
||||
{ this.props.control.renderNotice() }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
onFooterUpdate() {
|
||||
const columns = parseInt( this.props.customizer.control( 'footer_' + this.controlParams.footer + '_columns' ).setting.get(), 10 );
|
||||
if ( this.state.columns !== columns ) {
|
||||
this.setState( { columns: columns } );
|
||||
let value = this.state.value;
|
||||
if ( columns === 1 ) {
|
||||
value.desktop = 'row';
|
||||
} else {
|
||||
value.desktop = 'equal';
|
||||
}
|
||||
value.tablet = '';
|
||||
value.mobile = 'row';
|
||||
this.setState( value );
|
||||
this.updateValues( value );
|
||||
}
|
||||
}
|
||||
linkColumns() {
|
||||
let self = this;
|
||||
document.addEventListener( 'kadenceUpdateFooterColumns', function( e ) {
|
||||
if ( e.detail === self.controlParams.footer ) {
|
||||
setTimeout(function(){ self.onFooterUpdate(); }, 200);
|
||||
}
|
||||
} );
|
||||
}
|
||||
updateValues( value ) {
|
||||
if ( undefined !== this.controlParams.footer && this.controlParams.footer ) {
|
||||
let event = new CustomEvent(
|
||||
'kadenceUpdateFooterColumns', {
|
||||
'detail': this.controlParams.footer,
|
||||
} );
|
||||
document.dispatchEvent( event );
|
||||
}
|
||||
if ( this.controlParams.responsive ) {
|
||||
this.props.control.setting.set( {
|
||||
...this.props.control.setting.get(),
|
||||
...value,
|
||||
flag: !this.props.control.setting.get().flag
|
||||
} );
|
||||
} else {
|
||||
this.props.control.setting.set( value );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RowLayoutComponent.propTypes = {
|
||||
control: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
export default RowLayoutComponent;
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createRoot } from '@wordpress/element';
|
||||
import SelectComponent from './select-component.js';
|
||||
|
||||
export const SelectControl = wp.customize.KadenceControl.extend( {
|
||||
renderContent: function renderContent() {
|
||||
let control = this;
|
||||
let root = createRoot( control.container[0] );
|
||||
root.render( <SelectComponent control={control}/> );
|
||||
// ReactDOM.render(
|
||||
// <SelectComponent control={control}/>,
|
||||
// control.container[0]
|
||||
// );
|
||||
}
|
||||
} );
|
||||
@@ -0,0 +1,89 @@
|
||||
/* jshint esversion: 6 */
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
const { SelectControl, Dashicon, Tooltip, Button } = wp.components;
|
||||
|
||||
const { Component, Fragment } = wp.element;
|
||||
class SelectComponent extends Component {
|
||||
constructor() {
|
||||
super( ...arguments );
|
||||
this.updateValues = this.updateValues.bind( this );
|
||||
let value = this.props.control.setting.get();
|
||||
let defaultParams = {
|
||||
options: {
|
||||
standard: {
|
||||
name: __( 'Standard', 'kadence' ),
|
||||
},
|
||||
fullwidth: {
|
||||
name: __( 'Fullwidth', 'kadence' ),
|
||||
},
|
||||
contained: {
|
||||
name: __( 'Contained', 'kadence' ),
|
||||
},
|
||||
},
|
||||
};
|
||||
this.controlParams = this.props.control.params.input_attrs ? {
|
||||
...defaultParams,
|
||||
...this.props.control.params.input_attrs,
|
||||
} : defaultParams;
|
||||
let baseDefault = 'standard';
|
||||
this.defaultValue = this.props.control.params.default ? this.props.control.params.default : baseDefault;
|
||||
value = value ? value : this.defaultValue;
|
||||
this.state = {
|
||||
value: value,
|
||||
};
|
||||
}
|
||||
render() {
|
||||
const controlLabel = (
|
||||
<Fragment>
|
||||
<Tooltip text={ __( 'Reset Value', 'kadence' ) }>
|
||||
<Button
|
||||
className="reset kadence-reset"
|
||||
disabled={ ( this.state.value === this.defaultValue ) }
|
||||
onClick={ () => {
|
||||
let value = this.defaultValue;
|
||||
this.updateValues( value );
|
||||
} }
|
||||
>
|
||||
<Dashicon icon='image-rotate' />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
{ this.props.control.params.label &&
|
||||
this.props.control.params.label
|
||||
}
|
||||
</Fragment>
|
||||
);
|
||||
const selectOptions = Object.keys( this.controlParams.options ).map( ( item ) => {
|
||||
return ( { label: this.controlParams.options[ item ].name, value: item } );
|
||||
} );
|
||||
return (
|
||||
<div className="kadence-control-field kadence-select-control">
|
||||
<div className="kadence-responsive-control-bar">
|
||||
<span className="customize-control-title">{ controlLabel }</span>
|
||||
</div>
|
||||
<SelectControl
|
||||
value={ this.state.value }
|
||||
options={ selectOptions }
|
||||
onChange={ ( val ) => {
|
||||
this.updateValues( val );
|
||||
} }
|
||||
/>
|
||||
{ this.props.control.renderNotice() }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
updateValues( value ) {
|
||||
this.setState( { value: value } );
|
||||
this.props.control.setting.set( value );
|
||||
}
|
||||
}
|
||||
|
||||
SelectComponent.propTypes = {
|
||||
control: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
export default SelectComponent;
|
||||
@@ -0,0 +1,11 @@
|
||||
import { createRoot } from '@wordpress/element';
|
||||
import SocialComponent from './social-component.js';
|
||||
|
||||
export const SocialControl = wp.customize.KadenceControl.extend( {
|
||||
renderContent: function renderContent() {
|
||||
let control = this;
|
||||
let root = createRoot( control.container[0] );
|
||||
root.render( <SocialComponent control={ control } /> );
|
||||
// ReactDOM.render( <SocialComponent control={ control } />, control.container[0] );
|
||||
}
|
||||
} );
|
||||
1155
wp-content/themes/kadence/inc/customizer/react/src/social/icons.js
Normal file
1155
wp-content/themes/kadence/inc/customizer/react/src/social/icons.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,234 @@
|
||||
/* jshint esversion: 6 */
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
import SocialIcons from './icons.js';
|
||||
import DOMPurify from 'dompurify';
|
||||
|
||||
import { __ } from '@wordpress/i18n';
|
||||
const { MediaUpload } = wp.blockEditor;
|
||||
const { ButtonGroup, Dashicon, Tooltip, TextControl, Button, TabPanel, RangeControl, Placeholder } = wp.components;
|
||||
|
||||
const { Component, Fragment } = wp.element;
|
||||
class ItemComponent extends Component {
|
||||
constructor() {
|
||||
super( ...arguments );
|
||||
this.state = {
|
||||
open: false,
|
||||
};
|
||||
}
|
||||
render() {
|
||||
const tabOptions = ( ( 'custom1' === this.props.item.id || 'custom2' === this.props.item.id || 'custom3' === this.props.item.id ) ? [
|
||||
{
|
||||
name: 'svg',
|
||||
title: __( 'SVG', 'kadence' ),
|
||||
},
|
||||
{
|
||||
name: 'image',
|
||||
title: __( 'Image', 'kadence' ),
|
||||
},
|
||||
] : [
|
||||
{
|
||||
name: 'icon',
|
||||
title: __( 'Icon', 'kadence' ),
|
||||
},
|
||||
{
|
||||
name: 'svg',
|
||||
title: __( 'SVG', 'kadence' ),
|
||||
},
|
||||
{
|
||||
name: 'image',
|
||||
title: __( 'Image', 'kadence' ),
|
||||
},
|
||||
] );
|
||||
const defaultTab = ( ( 'custom1' === this.props.item.id || 'custom2' === this.props.item.id || 'custom3' === this.props.item.id ) ? 'svg' : 'icon' );
|
||||
return (
|
||||
<div className="kadence-sorter-item" data-id={ this.props.item.id } key={ this.props.item.id }>
|
||||
<div className="kadence-sorter-item-panel-header">
|
||||
<Tooltip text={ __( 'Toggle Item Visibility', 'kadence' ) }>
|
||||
<Button
|
||||
className={ `kadence-sorter-visiblity ${ ( this.props.item.enabled ? 'item-is-visible' : 'item-is-hidden' ) }`}
|
||||
onClick={ () => {
|
||||
this.props.toggleEnabled( ( this.props.item.enabled ? false : true ), this.props.index );
|
||||
} }
|
||||
>
|
||||
{ SocialIcons[this.props.item.id] }
|
||||
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<span className="kadence-sorter-title">
|
||||
{ ( undefined !== this.props.item.label && '' !== this.props.item.label ? this.props.item.label : __( 'Social Item', 'kadence' ) ) }
|
||||
</span>
|
||||
<Tooltip text={ __( 'Expand Item Controls', 'kadence' ) }>
|
||||
<Button
|
||||
className="kadence-sorter-item-expand"
|
||||
onClick={ () => {
|
||||
this.setState( { open: ( this.state.open ? false : true ) } )
|
||||
} }
|
||||
>
|
||||
<Dashicon icon={ ( this.state.open ? 'arrow-up-alt2' : 'arrow-down-alt2' ) }/>
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
{ this.state.open && (
|
||||
<div className="kadence-sorter-item-panel-content">
|
||||
<TabPanel className="sortable-style-tabs kadence-social-type"
|
||||
activeClass="active-tab"
|
||||
initialTabName={ ( undefined !== this.props.item.source && '' !== this.props.item.source ? this.props.item.source : defaultTab ) }
|
||||
onSelect={ ( value ) => this.props.onChangeSource( value, this.props.index ) }
|
||||
tabs={ tabOptions }>
|
||||
{
|
||||
( tab ) => {
|
||||
let tabout;
|
||||
if ( tab.name ) {
|
||||
if ( 'image' === tab.name ) {
|
||||
tabout = (
|
||||
<Fragment>
|
||||
{ ! this.props.item.url && (
|
||||
<div className="attachment-media-view">
|
||||
<MediaUpload
|
||||
onSelect={ ( imageData ) => {
|
||||
this.props.onChangeURL( imageData.url, this.props.index );
|
||||
this.props.onChangeAttachment( imageData.id, this.props.index );
|
||||
} }
|
||||
allowedTypes={ ['image'] }
|
||||
render={ ( { open } ) => (
|
||||
<Button className="button-add-media" isSecondary onClick={ open }>
|
||||
{ __( 'Add Image', 'kadence' )}
|
||||
</Button>
|
||||
) }
|
||||
/>
|
||||
</div>
|
||||
) }
|
||||
{ this.props.item.url && (
|
||||
<div className="social-custom-image">
|
||||
<div className="kadence-social-image">
|
||||
<img className="kadence-social-image-preview" src={ this.props.item.url } />
|
||||
</div>
|
||||
<Button
|
||||
className='remove-image'
|
||||
isDestructive
|
||||
onClick={ () => {
|
||||
this.props.onChangeURL( '', this.props.index );
|
||||
this.props.onChangeAttachment( '', this.props.index );
|
||||
} }
|
||||
>
|
||||
{ __( 'Remove Image', 'kadence' ) }
|
||||
<Dashicon icon='no'/>
|
||||
</Button>
|
||||
</div>
|
||||
) }
|
||||
<RangeControl
|
||||
label={ __( 'Max Width (px)', 'kadence' ) }
|
||||
value={ ( undefined !== this.props.item.width ? this.props.item.width : 24 ) }
|
||||
onChange={ ( value ) => {
|
||||
this.props.onChangeWidth( value, this.props.index );
|
||||
} }
|
||||
step={ 1 }
|
||||
min={ 2 }
|
||||
max={ 100 }
|
||||
/>
|
||||
</Fragment>
|
||||
);
|
||||
} else if ( 'svg' === tab.name ) {
|
||||
tabout = (
|
||||
<Fragment>
|
||||
<TextControl
|
||||
label={ __( 'SVG HTML', 'kadence' ) }
|
||||
value={ this.props.item.svg ? this.props.item.svg : '' }
|
||||
onChange={ ( value ) => {
|
||||
const newvalue = DOMPurify.sanitize( value, { USE_PROFILES: { svg: true, svgFilters: true } } );
|
||||
this.props.onChangeSVG( newvalue, this.props.index );
|
||||
} }
|
||||
/>
|
||||
<RangeControl
|
||||
label={ __( 'Max Width (px)', 'kadence' ) }
|
||||
value={ ( undefined !== this.props.item.width ? this.props.item.width : 24 ) }
|
||||
onChange={ ( value ) => {
|
||||
this.props.onChangeWidth( value, this.props.index );
|
||||
} }
|
||||
step={ 1 }
|
||||
min={ 2 }
|
||||
max={ 100 }
|
||||
/>
|
||||
</Fragment>
|
||||
);
|
||||
} else {
|
||||
tabout = (
|
||||
<Fragment>
|
||||
<ButtonGroup className="kadence-radio-container-control">
|
||||
<Button
|
||||
isTertiary
|
||||
className={ ( this.props.item.id === ( undefined !== this.props.item.icon ? this.props.item.icon : this.props.item.id ) ?
|
||||
'active-radio ' :
|
||||
'' ) + 'svg-icon-' + this.props.item.id }
|
||||
onClick={ () => {
|
||||
this.props.onChangeIcon( this.props.item.id, this.props.index );
|
||||
} }
|
||||
>
|
||||
<span className="kadence-radio-icon">
|
||||
{ SocialIcons[this.props.item.id] }
|
||||
</span>
|
||||
</Button>
|
||||
{ SocialIcons[ this.props.item.id + 'Alt' ] && (
|
||||
<Button
|
||||
isTertiary
|
||||
className={ ( this.props.item.id + 'Alt' === ( undefined !== this.props.item.icon ? this.props.item.icon : this.props.item.id ) ?
|
||||
'active-radio ' :
|
||||
'' ) + 'svg-icon-' + this.props.item.id + 'Alt' }
|
||||
onClick={ () => {
|
||||
this.props.onChangeIcon( this.props.item.id + 'Alt', this.props.index );
|
||||
} }
|
||||
>
|
||||
<span className="kadence-radio-icon">
|
||||
{ SocialIcons[ this.props.item.id + 'Alt' ] }
|
||||
</span>
|
||||
</Button>
|
||||
) }
|
||||
{ SocialIcons[ this.props.item.id + 'Alt2' ] && (
|
||||
<Button
|
||||
isTertiary
|
||||
className={ ( this.props.item.id + 'Alt2' === ( undefined !== this.props.item.icon ? this.props.item.icon : this.props.item.id ) ?
|
||||
'active-radio ' :
|
||||
'' ) + 'svg-icon-' + this.props.item.id + 'Alt2' }
|
||||
onClick={ () => {
|
||||
this.props.onChangeIcon( this.props.item.id + 'Alt2', this.props.index );
|
||||
} }
|
||||
>
|
||||
<span className="kadence-radio-icon">
|
||||
{ SocialIcons[ this.props.item.id + 'Alt2' ] }
|
||||
</span>
|
||||
</Button>
|
||||
)}
|
||||
</ButtonGroup>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
return <div>{ tabout }</div>;
|
||||
}
|
||||
}
|
||||
</TabPanel>
|
||||
<TextControl
|
||||
label={ __( 'Item Label', 'kadence' ) }
|
||||
value={ this.props.item.label ? this.props.item.label : '' }
|
||||
onChange={ ( value ) => {
|
||||
this.props.onChangeLabel( value, this.props.index );
|
||||
} }
|
||||
/>
|
||||
<Button
|
||||
className="kadence-sorter-item-remove"
|
||||
isDestructive
|
||||
onClick={ () => {
|
||||
this.props.removeItem( this.props.index );
|
||||
} }
|
||||
>
|
||||
{ __( 'Remove Item', 'kadence' ) }
|
||||
<Dashicon icon="no-alt"/>
|
||||
</Button>
|
||||
</div>
|
||||
) }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
export default ItemComponent;
|
||||
@@ -0,0 +1,386 @@
|
||||
/* jshint esversion: 6 */
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
import ResponsiveControl from '../common/responsive.js';
|
||||
import Icons from '../common/icons.js';
|
||||
import { ReactSortable } from "react-sortablejs";
|
||||
import uniqueId from 'lodash/uniqueId';
|
||||
|
||||
import ItemComponent from './item-component';
|
||||
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
const { ButtonGroup, Dashicon, Tooltip, Popover, Button, SelectControl } = wp.components;
|
||||
|
||||
const { Component, Fragment } = wp.element;
|
||||
class SocialComponent extends Component {
|
||||
constructor() {
|
||||
super( ...arguments );
|
||||
this.updateValues = this.updateValues.bind( this );
|
||||
this.onDragEnd = this.onDragEnd.bind( this );
|
||||
this.onDragStart = this.onDragStart.bind( this );
|
||||
this.onDragStop = this.onDragStop.bind( this );
|
||||
this.removeItem = this.removeItem.bind( this );
|
||||
this.saveArrayUpdate = this.saveArrayUpdate.bind( this );
|
||||
this.toggleEnableItem = this.toggleEnableItem.bind( this );
|
||||
this.onChangeIcon = this.onChangeIcon.bind( this );
|
||||
this.onChangeLabel = this.onChangeLabel.bind( this );
|
||||
this.onChangeURL = this.onChangeURL.bind( this );
|
||||
this.onChangeAttachment = this.onChangeAttachment.bind( this );
|
||||
this.onChangeWidth = this.onChangeWidth.bind( this );
|
||||
this.onChangeSVG = this.onChangeSVG.bind( this );
|
||||
this.onChangeSource = this.onChangeSource.bind( this );
|
||||
this.addItem = this.addItem.bind( this );
|
||||
let value = this.props.control.setting.get();
|
||||
let baseDefault = {
|
||||
'items': [
|
||||
{
|
||||
'id': 'facebook',
|
||||
'enabled': true,
|
||||
'source': 'icon',
|
||||
'url': '',
|
||||
'imageid': '',
|
||||
'width': 24,
|
||||
'icon': 'facebook',
|
||||
'label': 'Facebook',
|
||||
'svg': '',
|
||||
},
|
||||
{
|
||||
'id': 'twitter',
|
||||
'enabled': true,
|
||||
'source': 'icon',
|
||||
'url': '',
|
||||
'imageid': '',
|
||||
'width': 24,
|
||||
'icon': 'twitterAlt2',
|
||||
'label': 'X',
|
||||
'svg': '',
|
||||
}
|
||||
],
|
||||
};
|
||||
this.defaultValue = this.props.control.params.default ? {
|
||||
...baseDefault,
|
||||
...this.props.control.params.default
|
||||
} : baseDefault;
|
||||
value = value ? {
|
||||
...this.defaultValue,
|
||||
...value
|
||||
} : this.defaultValue;
|
||||
let defaultParams = {
|
||||
'group' : 'social_item_group',
|
||||
'options': [
|
||||
{ value: '500px', label: __( '500PX', 'kadence' ) },
|
||||
{ value: 'amazon', label: __( 'Amazon', 'kadence' ) },
|
||||
{ value: 'anchor', label: __( 'Anchor', 'kadence' ) },
|
||||
{ value: 'apple_podcasts', label: __( 'Apple Podcast', 'kadence' ) },
|
||||
{ value: 'bandcamp', label: __( 'Bandcamp', 'kadence' ) },
|
||||
{ value: 'behance', label: __( 'Behance', 'kadence' ) },
|
||||
{ value: 'bluesky', label: __( 'Bluesky', 'kadence' ) },
|
||||
{ value: 'bookbub', label: __( 'Bookbub', 'kadence' ) },
|
||||
{ value: 'discord', label: __( 'Discord', 'kadence' ) },
|
||||
{ value: 'dribbble', label: __( 'Dribbble', 'kadence' ) },
|
||||
{ value: 'email', label: __( 'Email', 'kadence' ) },
|
||||
{ value: 'facebook', label: __( 'Facebook', 'kadence' ) },
|
||||
{ value: 'facebook_group', label: __( 'Facebook Group', 'kadence' ) },
|
||||
{ value: 'flickr', label: __( 'Flickr', 'kadence' ) },
|
||||
{ value: 'flipboard', label: __( 'Flipboard', 'kadence' ) },
|
||||
{ value: 'fstoppers', label: __( 'Fstoppers', 'kadence' ) },
|
||||
{ value: 'github', label: __( 'GitHub', 'kadence' ) },
|
||||
{ value: 'goodreads', label: __( 'Goodreads', 'kadence' ) },
|
||||
{ value: 'google_reviews', label: __( 'Google Reviews', 'kadence' ) },
|
||||
{ value: 'imgur', label: __( 'Imgur', 'kadence' ) },
|
||||
{ value: 'imdb', label: __( 'IMDB', 'kadence' ) },
|
||||
{ value: 'instagram', label: __( 'Instagram', 'kadence' ) },
|
||||
{ value: 'line', label: __( 'Line', 'kadence' ) },
|
||||
{ value: 'linkedin', label: __( 'Linkedin', 'kadence' ) },
|
||||
{ value: 'mastodon', label: __( 'Mastodon', 'kadence' ) },
|
||||
{ value: 'medium', label: __( 'Medium', 'kadence' ) },
|
||||
{ value: 'mewe', label: __( 'MeWe', 'kadence' ) },
|
||||
{ value: 'parler', label: __( 'Parler', 'kadence' ) },
|
||||
{ value: 'patreon', label: __( 'Patreon', 'kadence' ) },
|
||||
{ value: 'phone', label: __( 'Phone', 'kadence' ) },
|
||||
{ value: 'pinterest', label: __( 'Pinterest', 'kadence' ) },
|
||||
{ value: 'quora', label: __( 'Quora', 'kadence' ) },
|
||||
{ value: 'ravelry', label: __( 'Ravelry', 'kadence' ) },
|
||||
{ value: 'reddit', label: __( 'Reddit', 'kadence' ) },
|
||||
{ value: 'rumble', label: __( 'Rumble', 'kadence' ) },
|
||||
{ value: 'rss', label: __( 'RSS', 'kadence' ) },
|
||||
{ value: 'snapchat', label: __( 'Snapchat', 'kadence' ) },
|
||||
{ value: 'soundcloud', label: __( 'SoundCloud', 'kadence' ) },
|
||||
{ value: 'spotify', label: __( 'Spotify', 'kadence' ) },
|
||||
{ value: 'steam', label: __( 'Steam', 'kadence' ) },
|
||||
{ value: 'strava', label: __( 'Strava', 'kadence' ) },
|
||||
{ value: 'telegram', label: __( 'Telegram', 'kadence' ) },
|
||||
{ value: 'threads', label: __( 'Threads', 'kadence' ) },
|
||||
{ value: 'tiktok', label: __( 'TikTok', 'kadence' ) },
|
||||
{ value: 'trip_advisor', label: __( 'Trip Advisor', 'kadence' ) },
|
||||
{ value: 'tumblr', label: __( 'Tumblr', 'kadence' ) },
|
||||
{ value: 'twitch', label: __( 'Twitch', 'kadence' ) },
|
||||
{ value: 'twitter', label: __( 'X formerly Twitter', 'kadence' ) },
|
||||
{ value: 'vero', label: __( 'Vero', 'kadence' ) },
|
||||
{ value: 'vimeo', label: __( 'Vimeo', 'kadence' ) },
|
||||
{ value: 'vk', label: __( 'VK', 'kadence' ) },
|
||||
{ value: 'whatsapp', label: __( 'WhatsApp', 'kadence' ) },
|
||||
{ value: 'wordpress', label: __( 'WordPress', 'kadence' ) },
|
||||
{ value: 'xing', label: __( 'Xing', 'kadence' ) },
|
||||
{ value: 'yelp', label: __( 'Yelp', 'kadence' ) },
|
||||
{ value: 'youtube', label: __( 'YouTube', 'kadence' ) },
|
||||
{ value: 'custom1', label: __( 'Custom 1', 'kadence' ) },
|
||||
{ value: 'custom2', label: __( 'Custom 2', 'kadence' ) },
|
||||
{ value: 'custom3', label: __( 'Custom 3', 'kadence' ) },
|
||||
],
|
||||
};
|
||||
this.controlParams = this.props.control.params.input_attrs ? {
|
||||
...defaultParams,
|
||||
...this.props.control.params.input_attrs,
|
||||
} : defaultParams;
|
||||
let availableSocialOptions = [];
|
||||
this.controlParams.options.map( ( option ) => {
|
||||
if ( ! value.items.some( obj => obj.id === option.value ) ) {
|
||||
availableSocialOptions.push( option );
|
||||
}
|
||||
} );
|
||||
this.state = {
|
||||
value: value,
|
||||
isVisible: false,
|
||||
control: ( undefined !== availableSocialOptions[0] && undefined !== availableSocialOptions[0].value ? availableSocialOptions[0].value : '' ),
|
||||
};
|
||||
}
|
||||
onDragStart() {
|
||||
var dropzones = document.querySelectorAll( '.kadence-builder-area' );
|
||||
var i;
|
||||
for (i = 0; i < dropzones.length; ++i) {
|
||||
dropzones[i].classList.add( 'kadence-dragging-dropzones' );
|
||||
}
|
||||
}
|
||||
onDragStop() {
|
||||
var dropzones = document.querySelectorAll( '.kadence-builder-area' );
|
||||
var i;
|
||||
for (i = 0; i < dropzones.length; ++i) {
|
||||
dropzones[i].classList.remove( 'kadence-dragging-dropzones' );
|
||||
}
|
||||
}
|
||||
saveArrayUpdate( value, index ) {
|
||||
let updateState = this.state.value;
|
||||
let items = updateState.items;
|
||||
|
||||
const newItems = items.map( ( item, thisIndex ) => {
|
||||
if ( index === thisIndex ) {
|
||||
item = { ...item, ...value };
|
||||
}
|
||||
|
||||
return item;
|
||||
} );
|
||||
updateState.items = newItems;
|
||||
this.setState( { value: updateState } );
|
||||
this.updateValues( updateState );
|
||||
}
|
||||
toggleEnableItem( value, itemIndex ) {
|
||||
this.saveArrayUpdate( { enabled: value }, itemIndex );
|
||||
}
|
||||
onChangeLabel( value, itemIndex ) {
|
||||
this.saveArrayUpdate( { label: value }, itemIndex );
|
||||
}
|
||||
onChangeIcon( value, itemIndex ) {
|
||||
this.saveArrayUpdate( { icon: value }, itemIndex );
|
||||
}
|
||||
onChangeURL( value, itemIndex ) {
|
||||
this.saveArrayUpdate( { url: value }, itemIndex );
|
||||
}
|
||||
onChangeAttachment( value, itemIndex ) {
|
||||
this.saveArrayUpdate( { imageid: value }, itemIndex );
|
||||
}
|
||||
onChangeWidth( value, itemIndex ) {
|
||||
this.saveArrayUpdate( { width: value }, itemIndex );
|
||||
}
|
||||
onChangeSVG( value, itemIndex ) {
|
||||
this.saveArrayUpdate( { svg: value }, itemIndex );
|
||||
}
|
||||
onChangeSource( value, itemIndex ) {
|
||||
this.saveArrayUpdate( { source: value }, itemIndex );
|
||||
}
|
||||
removeItem( itemIndex ) {
|
||||
let updateState = this.state.value;
|
||||
let update = updateState.items;
|
||||
let updateItems = [];
|
||||
{ update.length > 0 && (
|
||||
update.map( ( old, index ) => {
|
||||
if ( itemIndex !== index ) {
|
||||
updateItems.push( old );
|
||||
}
|
||||
} )
|
||||
) };
|
||||
updateState.items = updateItems;
|
||||
this.setState( { value: updateState } );
|
||||
this.updateValues( updateState );
|
||||
}
|
||||
addItem() {
|
||||
const itemControl = this.state.control;
|
||||
this.setState( { isVisible: false } );
|
||||
if ( itemControl ) {
|
||||
let updateState = this.state.value;
|
||||
let update = updateState.items;
|
||||
const itemLabel = this.controlParams.options.filter(function(o){return o.value === itemControl;} );
|
||||
let newItem = {
|
||||
'id': itemControl,
|
||||
'enabled': true,
|
||||
'source': 'icon',
|
||||
'url': '',
|
||||
'imageid': '',
|
||||
'width': 24,
|
||||
'icon': itemControl,
|
||||
'label': itemLabel[0].label,
|
||||
'svg': '',
|
||||
};
|
||||
update.push( newItem );
|
||||
updateState.items = update;
|
||||
let availableSocialOptions = [];
|
||||
this.controlParams.options.map( ( option ) => {
|
||||
if ( ! update.some( obj => obj.id === option.value ) ) {
|
||||
availableSocialOptions.push( option );
|
||||
}
|
||||
} );
|
||||
this.setState( { control: ( undefined !== availableSocialOptions[0] && undefined !== availableSocialOptions[0].value ? availableSocialOptions[0].value : '' ) } );
|
||||
this.setState( { value: updateState } );
|
||||
this.updateValues( updateState );
|
||||
}
|
||||
}
|
||||
onDragEnd( items ) {
|
||||
let updateState = this.state.value;
|
||||
let update = updateState.items;
|
||||
let updateItems = [];
|
||||
{ items.length > 0 && (
|
||||
items.map( ( item ) => {
|
||||
update.filter( obj => {
|
||||
if ( obj.id === item.id ) {
|
||||
updateItems.push( obj );
|
||||
}
|
||||
} )
|
||||
} )
|
||||
) };
|
||||
if ( ! this.arraysEqual( update, updateItems ) ) {
|
||||
update.items = updateItems;
|
||||
updateState.items = updateItems;
|
||||
this.setState( { value: updateState } );
|
||||
this.updateValues( updateState );
|
||||
}
|
||||
}
|
||||
arraysEqual( a, b ) {
|
||||
if (a === b) return true;
|
||||
if (a == null || b == null) return false;
|
||||
if (a.length != b.length) return false;
|
||||
for (var i = 0; i < a.length; ++i) {
|
||||
if (a[i] !== b[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
render() {
|
||||
const currentList = ( typeof this.state.value != "undefined" && this.state.value.items != null && this.state.value.items.length != null && this.state.value.items.length > 0 ? this.state.value.items : [] );
|
||||
let theItems = [];
|
||||
{ currentList.length > 0 && (
|
||||
currentList.map( ( item ) => {
|
||||
theItems.push(
|
||||
{
|
||||
id: item.id,
|
||||
}
|
||||
)
|
||||
} )
|
||||
) };
|
||||
const availableSocialOptions = [];
|
||||
this.controlParams.options.map( ( option ) => {
|
||||
if ( ! theItems.some( obj => obj.id === option.value ) ) {
|
||||
availableSocialOptions.push( option );
|
||||
}
|
||||
} );
|
||||
const toggleClose = () => {
|
||||
if ( this.state.isVisible === true ) {
|
||||
this.setState( { isVisible: false } );
|
||||
}
|
||||
};
|
||||
return (
|
||||
<div className="kadence-control-field kadence-sorter-items">
|
||||
<div className="kadence-sorter-row">
|
||||
<ReactSortable animation={100} onStart={ () => this.onDragStop() } onEnd={ () => this.onDragStop() } group={ this.controlParams.group } className={ `kadence-sorter-drop kadence-sorter-sortable-panel kadence-sorter-drop-${ this.controlParams.group }` } handle={ '.kadence-sorter-item-panel-header' } list={ theItems } setList={ ( newState ) => this.onDragEnd( newState ) } >
|
||||
{ currentList.length > 0 && (
|
||||
currentList.map( ( item, index ) => {
|
||||
return <ItemComponent removeItem={ ( remove ) => this.removeItem( remove ) } toggleEnabled={ ( enable, itemIndex ) => this.toggleEnableItem( enable, itemIndex ) } onChangeLabel={ ( label, itemIndex ) => this.onChangeLabel( label, itemIndex ) } onChangeSource={ ( source, itemIndex ) => this.onChangeSource( source, itemIndex ) } onChangeWidth={ ( width, itemIndex ) => this.onChangeWidth( width, itemIndex ) } onChangeSVG={ ( svg, itemIndex ) => this.onChangeSVG( svg, itemIndex ) } onChangeURL={ ( url, itemIndex ) => this.onChangeURL( url, itemIndex ) } onChangeAttachment={ ( imageid, itemIndex ) => this.onChangeAttachment( imageid, itemIndex ) } onChangeIcon={ ( icon, itemIndex ) => this.onChangeIcon( icon, itemIndex ) } key={ item.id } index={ index } item={ item } controlParams={ this.controlParams } />;
|
||||
} )
|
||||
) }
|
||||
</ReactSortable>
|
||||
</div>
|
||||
{ undefined !== availableSocialOptions[0] && undefined !== availableSocialOptions[0].value && (
|
||||
<div className="kadence-social-add-area">
|
||||
{/* <SelectControl
|
||||
value={ this.state.control }
|
||||
options={ availableSocialOptions }
|
||||
onChange={ value => {
|
||||
this.setState( { control: value } );
|
||||
} }
|
||||
/> */}
|
||||
{ this.state.isVisible && (
|
||||
<Popover position="top right" inline={true} className="kadence-popover-color kadence-popover-social kadence-customizer-popover" onClose={ toggleClose }>
|
||||
<div className="kadence-popover-social-list">
|
||||
<ButtonGroup className="kadence-radio-container-control">
|
||||
{ availableSocialOptions.map( ( item, index ) => {
|
||||
return (
|
||||
<Fragment>
|
||||
<Button
|
||||
isTertiary
|
||||
className={ 'social-radio-btn' }
|
||||
onClick={ () => {
|
||||
this.setState( { control: availableSocialOptions[index].value } );
|
||||
this.state.control = availableSocialOptions[index].value;
|
||||
this.addItem();
|
||||
} }
|
||||
>
|
||||
{ availableSocialOptions[index].label && (
|
||||
availableSocialOptions[index].label
|
||||
) }
|
||||
</Button>
|
||||
</Fragment>
|
||||
);
|
||||
} ) }
|
||||
</ButtonGroup>
|
||||
</div>
|
||||
</Popover>
|
||||
) }
|
||||
<Button
|
||||
className="kadence-sorter-add-item"
|
||||
isPrimary
|
||||
onClick={ () => {
|
||||
this.setState( { isVisible: true } );
|
||||
} }
|
||||
>
|
||||
{ __( 'Add Social', 'kadence' ) }
|
||||
<Dashicon icon="plus"/>
|
||||
</Button>
|
||||
{/* <Button
|
||||
className="kadence-sorter-add-item"
|
||||
isPrimary
|
||||
onClick={ () => {
|
||||
this.addItem();
|
||||
} }
|
||||
>
|
||||
{ __( 'Add Item', 'kadence' ) }
|
||||
<Dashicon icon="plus"/>
|
||||
</Button> */}
|
||||
</div>
|
||||
) }
|
||||
{ this.props.control.renderNotice() }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
updateValues( value ) {
|
||||
this.props.control.setting.set( {
|
||||
...this.props.control.setting.get(),
|
||||
...value,
|
||||
flag: !this.props.control.setting.get().flag
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
SocialComponent.propTypes = {
|
||||
control: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default SocialComponent;
|
||||
@@ -0,0 +1,11 @@
|
||||
import { createRoot } from '@wordpress/element';
|
||||
import SorterComponent from './setting-sorter-component.js';
|
||||
|
||||
export const SorterControl = wp.customize.KadenceControl.extend( {
|
||||
renderContent: function renderContent() {
|
||||
let control = this;
|
||||
let root = createRoot( control.container[0] );
|
||||
root.render( <SorterComponent control={ control } customizer={ wp.customize } /> );
|
||||
// ReactDOM.render( <SorterComponent control={ control } customizer={ wp.customize } />, control.container[0] );
|
||||
}
|
||||
} );
|
||||
@@ -0,0 +1,264 @@
|
||||
/* jshint esversion: 6 */
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
import capitalizeFirstLetter from '../common/capitalize-first.js';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import Icons from '../common/icons.js';
|
||||
const { MediaUpload } = wp.blockEditor;
|
||||
const { ButtonGroup, Dashicon, Tooltip, TextControl, Button, TabPanel, ToggleControl, RangeControl, Placeholder } = wp.components;
|
||||
|
||||
const { Component, Fragment } = wp.element;
|
||||
class ItemComponent extends Component {
|
||||
constructor() {
|
||||
super( ...arguments );
|
||||
this.state = {
|
||||
open: false,
|
||||
};
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div className="kadence-sorter-item" data-id={ this.props.item.id } key={ this.props.item.id }>
|
||||
<div className={ `kadence-sorter-item-panel-header ${ ( this.props.item.enabled ? 'panel-item-is-visible' : 'panel-item-is-hidden' ) }` }>
|
||||
<Tooltip text={ __( 'Toggle Item Visibility', 'kadence' ) }>
|
||||
<Button
|
||||
className={ `kadence-sorter-visiblity ${ ( this.props.item.enabled ? 'item-is-visible' : 'item-is-hidden' ) }`}
|
||||
onClick={ () => {
|
||||
this.props.onItemChange( { enabled: ( this.props.item.enabled ? false : true ) }, this.props.index );
|
||||
} }
|
||||
>
|
||||
<Dashicon icon={ ( this.props.item.enabled ? 'visibility' : 'hidden' ) } />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<span className="kadence-sorter-title">
|
||||
{ capitalizeFirstLetter( this.props.item.id ) }
|
||||
</span>
|
||||
{ 'title' !== this.props.item.id && (
|
||||
<Tooltip text={ __( 'Expand Item Controls', 'kadence' ) }>
|
||||
<Button
|
||||
className="kadence-sorter-item-expand"
|
||||
onClick={ () => {
|
||||
this.setState( { open: ( this.state.open ? false : true ) } )
|
||||
} }
|
||||
>
|
||||
<Dashicon icon={ ( this.state.open ? 'arrow-up-alt2' : 'arrow-down-alt2' ) }/>
|
||||
</Button>
|
||||
</Tooltip>
|
||||
) }
|
||||
</div>
|
||||
{ this.state.open && (
|
||||
<div className="kadence-sorter-item-panel-content">
|
||||
{ undefined !== this.props.item.divider && (
|
||||
<div class="components-base-control">
|
||||
<span className="sorter-control-title">{ __( 'Choose a Divider', 'kadence' ) }</span>
|
||||
<ButtonGroup className="kadence-radio-container-control">
|
||||
{ Object.keys( this.props.controlParams.dividers ).map( ( item ) => {
|
||||
return (
|
||||
<Fragment>
|
||||
<Button
|
||||
isTertiary
|
||||
className={ ( item === this.props.item.divider ?
|
||||
'active-radio ' :
|
||||
'' ) + 'radio-btn-' + item }
|
||||
onClick={ () => {
|
||||
this.props.onItemChange( { divider: item }, this.props.index );
|
||||
} }
|
||||
>
|
||||
{ this.props.controlParams.dividers[ item ].icon && (
|
||||
<span className="kadence-radio-icon">
|
||||
{ Icons[ this.props.controlParams.dividers[ item ].icon ] }
|
||||
</span>
|
||||
) }
|
||||
{ this.props.controlParams.dividers[ item ].name && (
|
||||
this.props.controlParams.dividers[ item ].name
|
||||
) }
|
||||
</Button>
|
||||
</Fragment>
|
||||
);
|
||||
} ) }
|
||||
</ButtonGroup>
|
||||
</div>
|
||||
) }
|
||||
{ undefined !== this.props.item.author && (
|
||||
<div className="sorter-sub-option">
|
||||
<ToggleControl
|
||||
label={ __( 'Show Author?', 'kadence' ) }
|
||||
checked={ this.props.item.author ? this.props.item.author : this.props.item.author }
|
||||
onChange={ ( value ) => {
|
||||
this.props.onItemChange( { author: value }, this.props.index );
|
||||
} }
|
||||
/>
|
||||
{ this.props.item.author && (
|
||||
<Fragment>
|
||||
{ undefined !== this.props.item.authorImage && (
|
||||
<ToggleControl
|
||||
label={ __( 'Show Author Image?', 'kadence' ) }
|
||||
checked={ this.props.item.authorImage ? this.props.item.authorImage : this.props.item.authorImage }
|
||||
onChange={ ( value ) => {
|
||||
this.props.onItemChange( { authorImage: value }, this.props.index );
|
||||
} }
|
||||
/>
|
||||
) }
|
||||
{ undefined !== this.props.item.authorLabel && (
|
||||
<div className="meta-label-control">
|
||||
<span className="sorter-control-title">{ __( 'Author Label', 'kadence' ) }</span>
|
||||
<div className={ `meta-label-input-control ${ ( this.props.item.authorEnableLabel ? 'label-is-visible' : 'label-is-hidden' ) }` }>
|
||||
<Tooltip text={ __( 'Toggle Label Visibility', 'kadence' ) }>
|
||||
<Button
|
||||
className={ `kadence-label-visiblity ${ ( this.props.item.authorEnableLabel ? 'item-is-visible' : 'item-is-hidden' ) }`}
|
||||
onClick={ () => {
|
||||
this.props.onItemChange( { authorEnableLabel: ( this.props.item.authorEnableLabel ? false : true ) }, this.props.index );
|
||||
} }
|
||||
>
|
||||
<Dashicon icon={ ( this.props.item.authorEnableLabel ? 'visibility' : 'hidden' ) } />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<TextControl
|
||||
label=""
|
||||
placeholder={ __( 'By', 'kadence' ) }
|
||||
value={ this.props.item.authorLabel ? this.props.item.authorLabel : this.props.item.authorLabel }
|
||||
onChange={ ( value ) => {
|
||||
this.props.onItemChange( { authorLabel: value }, this.props.index );
|
||||
} }
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
) }
|
||||
</Fragment>
|
||||
) }
|
||||
</div>
|
||||
) }
|
||||
{ undefined !== this.props.item.date && (
|
||||
<div className="sorter-sub-option">
|
||||
<ToggleControl
|
||||
label={ __( 'Show Date?', 'kadence' ) }
|
||||
checked={ this.props.item.date ? this.props.item.date : this.props.item.date }
|
||||
onChange={ ( value ) => {
|
||||
this.props.onItemChange( { date: value }, this.props.index );
|
||||
} }
|
||||
/>
|
||||
{ this.props.item.date && (
|
||||
<ToggleControl
|
||||
label={ __( 'Show Time?', 'kadence' ) }
|
||||
checked={ this.props.item.dateTime ? this.props.item.dateTime : false }
|
||||
onChange={ ( value ) => {
|
||||
this.props.onItemChange( { dateTime: value }, this.props.index );
|
||||
} }
|
||||
/>
|
||||
) }
|
||||
{ undefined !== this.props.item.dateLabel && this.props.item.date && (
|
||||
<div className="meta-label-control">
|
||||
<span className="sorter-control-title">{ __( 'Date Label', 'kadence' ) }</span>
|
||||
<div className={ `meta-label-input-control ${ ( this.props.item.dateEnableLabel ? 'label-is-visible' : 'label-is-hidden' ) }` }>
|
||||
<Tooltip text={ __( 'Toggle Label Visibility', 'kadence' ) }>
|
||||
<Button
|
||||
className={ `kadence-label-visiblity ${ ( this.props.item.dateEnableLabel ? 'item-is-visible' : 'item-is-hidden' ) }`}
|
||||
onClick={ () => {
|
||||
this.props.onItemChange( { dateEnableLabel: ( this.props.item.dateEnableLabel ? false : true ) }, this.props.index );
|
||||
} }
|
||||
>
|
||||
<Dashicon icon={ ( this.props.item.dateEnableLabel ? 'visibility' : 'hidden' ) } />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<TextControl
|
||||
label=""
|
||||
placeholder={ __( 'Posted on', 'kadence' ) }
|
||||
value={ this.props.item.dateLabel ? this.props.item.dateLabel : this.props.item.dateLabel }
|
||||
onChange={ ( value ) => {
|
||||
this.props.onItemChange( { dateLabel: value }, this.props.index );
|
||||
} }
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
) }
|
||||
</div>
|
||||
) }
|
||||
{ undefined !== this.props.item.dateUpdated && (
|
||||
<div className="sorter-sub-option">
|
||||
<ToggleControl
|
||||
label={ __( 'Show Last Updated Date?', 'kadence' ) }
|
||||
checked={ this.props.item.dateUpdated ? this.props.item.dateUpdated : this.props.item.dateUpdated }
|
||||
onChange={ ( value ) => {
|
||||
this.props.onItemChange( { dateUpdated: value }, this.props.index );
|
||||
} }
|
||||
/>
|
||||
{ undefined !== this.props.item.dateUpdatedLabel && this.props.item.dateUpdated && (
|
||||
<div className="meta-label-control">
|
||||
<span className="sorter-control-title">{ __( 'Updated Date Label', 'kadence' ) }</span>
|
||||
<div className={ `meta-label-input-control ${ ( this.props.item.dateUpdatedEnableLabel ? 'label-is-visible' : 'label-is-hidden' ) }` }>
|
||||
<Tooltip text={ __( 'Toggle Label Visibility', 'kadence' ) }>
|
||||
<Button
|
||||
className={ `kadence-label-visiblity ${ ( this.props.item.dateUpdatedEnableLabel ? 'item-is-visible' : 'item-is-hidden' ) }`}
|
||||
onClick={ () => {
|
||||
this.props.onItemChange( { dateUpdatedEnableLabel: ( this.props.item.dateUpdatedEnableLabel ? false : true ) }, this.props.index );
|
||||
} }
|
||||
>
|
||||
<Dashicon icon={ ( this.props.item.dateUpdatedEnableLabel ? 'visibility' : 'hidden' ) } />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<TextControl
|
||||
label=""
|
||||
placeholder={ __( 'Updated on', 'kadence' ) }
|
||||
value={ this.props.item.dateUpdatedLabel ? this.props.item.dateUpdatedLabel : this.props.item.dateUpdatedLabel }
|
||||
onChange={ ( value ) => {
|
||||
this.props.onItemChange( { dateUpdatedLabel: value }, this.props.index );
|
||||
} }
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
) }
|
||||
</div>
|
||||
) }
|
||||
{ undefined !== this.props.item.categories && (
|
||||
<div className="sorter-sub-option">
|
||||
<ToggleControl
|
||||
label={ __( 'Show Categories?', 'kadence' ) }
|
||||
checked={ this.props.item.categories ? this.props.item.categories : this.props.item.categories }
|
||||
onChange={ ( value ) => {
|
||||
this.props.onItemChange( { categories: value }, this.props.index );
|
||||
} }
|
||||
/>
|
||||
{ undefined !== this.props.item.categoriesLabel && this.props.item.categories && this.props.item.metaLabel && (
|
||||
<div className="meta-label-control">
|
||||
<span className="sorter-control-title">{ __( 'Categories Label', 'kadence' ) }</span>
|
||||
<div className={ `meta-label-input-control ${ ( this.props.item.categoriesEnableLabel ? 'label-is-visible' : 'label-is-hidden' ) }` }>
|
||||
<Tooltip text={ __( 'Toggle Label Visibility', 'kadence' ) }>
|
||||
<Button
|
||||
className={ `kadence-label-visiblity ${ ( this.props.item.categoriesEnableLabel ? 'item-is-visible' : 'item-is-hidden' ) }`}
|
||||
onClick={ () => {
|
||||
this.props.onItemChange( { categoriesEnableLabel: ( this.props.item.categoriesEnableLabel ? false : true ) }, this.props.index );
|
||||
} }
|
||||
>
|
||||
<Dashicon icon={ ( this.props.item.categoriesEnableLabel ? 'visibility' : 'hidden' ) } />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<TextControl
|
||||
label=""
|
||||
placeholder={ __( 'Posted in', 'kadence' ) }
|
||||
value={ this.props.item.categoriesLabel ? this.props.item.categoriesLabel : this.props.item.categoriesLabel }
|
||||
onChange={ ( value ) => {
|
||||
this.props.onItemChange( { categoriesLabel: value }, this.props.index );
|
||||
} }
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
) }
|
||||
</div>
|
||||
) }
|
||||
{ undefined !== this.props.item.comments && (
|
||||
<div className="sorter-sub-option">
|
||||
<ToggleControl
|
||||
label={ __( 'Show Comments?', 'kadence' ) }
|
||||
checked={ this.props.item.comments ? this.props.item.comments : this.props.item.comments }
|
||||
onChange={ ( value ) => {
|
||||
this.props.onItemChange( { comments: value }, this.props.index );
|
||||
} }
|
||||
/>
|
||||
</div>
|
||||
) }
|
||||
</div>
|
||||
) }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
export default ItemComponent;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,224 @@
|
||||
/* jshint esversion: 6 */
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
import ResponsiveControl from '../common/responsive.js';
|
||||
import Icons from '../common/icons.js';
|
||||
import { ReactSortable } from "react-sortablejs";
|
||||
import isEqual from 'lodash/isEqual';
|
||||
import union from 'lodash/union';
|
||||
|
||||
import ItemComponent from './setting-item-component';
|
||||
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
const { ButtonGroup, Dashicon, Tooltip, Button } = wp.components;
|
||||
|
||||
const { Component, Fragment } = wp.element;
|
||||
class SorterComponent extends Component {
|
||||
constructor() {
|
||||
super( ...arguments );
|
||||
this.updateValues = this.updateValues.bind( this );
|
||||
this.onDragEnd = this.onDragEnd.bind( this );
|
||||
this.onDragStart = this.onDragStart.bind( this );
|
||||
this.onDragStop = this.onDragStop.bind( this );
|
||||
let value = this.props.control.settings['elements'].get();
|
||||
let baseDefault = [ 'title', 'breadcrumb', 'meta' ];
|
||||
this.defaultValue = this.props.control.params.default ? this.props.control.params.default : baseDefault;
|
||||
value = value ? union(
|
||||
value,
|
||||
this.defaultValue
|
||||
) : this.defaultValue;
|
||||
let defaultParams = {
|
||||
'group': 'title_item_group',
|
||||
'sortable': true,
|
||||
dividers: {
|
||||
dot: {
|
||||
icon: 'dot',
|
||||
},
|
||||
slash: {
|
||||
icon: 'slash',
|
||||
},
|
||||
dash: {
|
||||
icon: 'dash',
|
||||
},
|
||||
vline: {
|
||||
icon: 'vline',
|
||||
},
|
||||
},
|
||||
imageSizes: {
|
||||
thumbnail: {
|
||||
name: __( 'Thumbnail', 'kadence' ),
|
||||
},
|
||||
medium: {
|
||||
name: __( 'Medium', 'kadence' ),
|
||||
},
|
||||
medium_large: {
|
||||
name: __( 'Medium Large', 'kadence' ),
|
||||
},
|
||||
large: {
|
||||
name: __( 'Large', 'kadence' ),
|
||||
},
|
||||
full: {
|
||||
name: __( 'Full', 'kadence' ),
|
||||
},
|
||||
},
|
||||
ratios: {
|
||||
'inherit': {
|
||||
'name': __( 'Inherit', 'kadence' ),
|
||||
},
|
||||
'1-1': {
|
||||
'name': '1:1',
|
||||
},
|
||||
'3-4': {
|
||||
'name': '4:3',
|
||||
},
|
||||
'2-3': {
|
||||
'name': '3:2',
|
||||
},
|
||||
'9-16': {
|
||||
'name': '16:9',
|
||||
},
|
||||
'1-2': {
|
||||
'name': '2:1',
|
||||
},
|
||||
'5-4': {
|
||||
'name': '4:5',
|
||||
},
|
||||
'4-3': {
|
||||
'name': '3:4',
|
||||
},
|
||||
'3-2': {
|
||||
'name': '2:3',
|
||||
},
|
||||
}
|
||||
};
|
||||
this.controlParams = this.props.control.params.input_attrs ? {
|
||||
...defaultParams,
|
||||
...this.props.control.params.input_attrs,
|
||||
} : defaultParams;
|
||||
this.state = {
|
||||
value: value,
|
||||
};
|
||||
}
|
||||
onDragStart() {
|
||||
var dropzones = document.querySelectorAll( '.kadence-builder-area' );
|
||||
var i;
|
||||
for (i = 0; i < dropzones.length; ++i) {
|
||||
dropzones[i].classList.add( 'kadence-dragging-dropzones' );
|
||||
}
|
||||
}
|
||||
onDragStop() {
|
||||
var dropzones = document.querySelectorAll( '.kadence-builder-area' );
|
||||
var i;
|
||||
for (i = 0; i < dropzones.length; ++i) {
|
||||
dropzones[i].classList.remove( 'kadence-dragging-dropzones' );
|
||||
}
|
||||
}
|
||||
onDragEnd( items ) {
|
||||
let updateState = this.state.value;
|
||||
let update = updateState;
|
||||
let updateItems = [];
|
||||
{ items.length > 0 && (
|
||||
items.map( ( item ) => {
|
||||
updateItems.push( item.id );
|
||||
} )
|
||||
) };
|
||||
if ( JSON.stringify( update ) !== JSON.stringify( updateItems ) ) {
|
||||
update = updateItems;
|
||||
updateState = updateItems;
|
||||
this.setState( { value: updateState } );
|
||||
this.updateValues( updateState );
|
||||
}
|
||||
}
|
||||
arraysEqual( a, b ) {
|
||||
if (a === b) return true;
|
||||
if (a == null || b == null) return false;
|
||||
if (a.length != b.length) return false;
|
||||
for (var i = 0; i < a.length; ++i) {
|
||||
if (a[i] !== b[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
render() {
|
||||
const controlLabel = (
|
||||
<Fragment>
|
||||
{/* <Tooltip text={ __( 'Reset Value', 'kadence' ) }>
|
||||
<Button
|
||||
className="reset kadence-reset"
|
||||
disabled={ ( this.state.value === this.defaultValue ) }
|
||||
onClick={ () => {
|
||||
let value = this.defaultValue;
|
||||
this.setState( { value: value } );
|
||||
this.updateValues( value );
|
||||
} }
|
||||
>
|
||||
<Dashicon icon='image-rotate' />
|
||||
</Button>
|
||||
</Tooltip> */}
|
||||
{ this.props.control.params.label &&
|
||||
this.props.control.params.label
|
||||
}
|
||||
</Fragment>
|
||||
);
|
||||
const currentList = ( typeof this.state.value != "undefined" && undefined !== this.state.value ? this.state.value : [] );
|
||||
let theItems = [];
|
||||
{ currentList.map( ( item ) => {
|
||||
theItems.push(
|
||||
{
|
||||
id: item,
|
||||
}
|
||||
)
|
||||
} ) }
|
||||
return (
|
||||
<div className="kadence-control-field kadence-sorter-items kadence-post-title-sorter">
|
||||
<div className="kadence-responsive-control-bar">
|
||||
<span className="customize-control-title">{ controlLabel }</span>
|
||||
</div>
|
||||
<div className="kadence-sorter-row">
|
||||
{ this.controlParams.sortable && (
|
||||
<ReactSortable animation={100} onStart={ () => this.onDragStop() } onEnd={ () => this.onDragStop() } group={ this.controlParams.group } className={ `kadence-sorter-drop kadence-sorter-sortable-panel kadence-meta-sorter kadence-sorter-drop-${ this.controlParams.group }` } handle={ '.kadence-sorter-item-panel-header' } list={ theItems } setList={ ( newState ) => this.onDragEnd( newState ) } >
|
||||
{ currentList.map( ( item, index ) => {
|
||||
return <ItemComponent
|
||||
key={ item }
|
||||
item={ item }
|
||||
setting={ this.controlParams.group }
|
||||
index={ index }
|
||||
control={ this.props.control }
|
||||
moveable={ true }
|
||||
controlParams={ this.controlParams }
|
||||
customizer={ this.props.customizer }
|
||||
/>;
|
||||
} ) }
|
||||
</ReactSortable>
|
||||
) }
|
||||
{ ! this.controlParams.sortable && (
|
||||
<div className={ `kadence-sorter-drop kadence-sorter-sortable-panel kadence-sorter-no-sorting kadence-sorter-drop-${ this.controlParams.group }` } >
|
||||
{ currentList.map( ( item, index ) => {
|
||||
return <ItemComponent
|
||||
key={ item }
|
||||
item={ item }
|
||||
setting={ this.controlParams.group }
|
||||
index={ index }
|
||||
moveable={ false }
|
||||
control={ this.props.control }
|
||||
controlParams={ this.controlParams }
|
||||
customizer={ this.props.customizer }
|
||||
/>;
|
||||
} ) }
|
||||
</div>
|
||||
) }
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
updateValues( value ) {
|
||||
this.props.control.settings['elements'].set( value );
|
||||
}
|
||||
}
|
||||
|
||||
SorterComponent.propTypes = {
|
||||
control: PropTypes.object.isRequired,
|
||||
customizer: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
export default SorterComponent;
|
||||
@@ -0,0 +1,228 @@
|
||||
/* jshint esversion: 6 */
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
import ResponsiveControl from '../common/responsive.js';
|
||||
import Icons from '../common/icons.js';
|
||||
import { ReactSortable } from "react-sortablejs";
|
||||
import isEqual from 'lodash/isEqual';
|
||||
|
||||
import ItemComponent from './item-component';
|
||||
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
const { ButtonGroup, Dashicon, Tooltip, Button } = wp.components;
|
||||
|
||||
const { Component, Fragment } = wp.element;
|
||||
class SorterComponent extends Component {
|
||||
constructor() {
|
||||
super( ...arguments );
|
||||
this.updateValues = this.updateValues.bind( this );
|
||||
this.onDragEnd = this.onDragEnd.bind( this );
|
||||
this.onDragStart = this.onDragStart.bind( this );
|
||||
this.onDragStop = this.onDragStop.bind( this );
|
||||
this.saveObjectUpdate = this.saveObjectUpdate.bind( this );
|
||||
this.onItemChange = this.onItemChange.bind( this );;
|
||||
let value = this.props.control.setting.get();
|
||||
let baseDefault = {
|
||||
'items': {
|
||||
'title': {
|
||||
'id': 'title',
|
||||
'enabled': true,
|
||||
},
|
||||
'breadcrumb': {
|
||||
'id': 'breadcrumb',
|
||||
'enabled': true,
|
||||
'divider': 'dot',
|
||||
},
|
||||
'meta': {
|
||||
'id': 'meta',
|
||||
'enabled': true,
|
||||
'metaLabel': true,
|
||||
'divider': 'dot',
|
||||
'author': true,
|
||||
'authorImage': true,
|
||||
'authorLabel': '',
|
||||
'date': true,
|
||||
'dateTime': false,
|
||||
'dateLabel': '',
|
||||
'dateUpdated': true,
|
||||
'dateUpdatedTime': false,
|
||||
'dateUpdatedDifferent': false,
|
||||
'dateUpdatedLabel': '',
|
||||
'categories': true,
|
||||
'categoriesLabel': '',
|
||||
'comments': false,
|
||||
'commentsLabel': '',
|
||||
'commentsCondition': false,
|
||||
},
|
||||
'categories': {
|
||||
'id': 'categories',
|
||||
'enabled': true,
|
||||
'divider': 'dot',
|
||||
}
|
||||
}
|
||||
};
|
||||
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 ) );
|
||||
let defaultParams = {
|
||||
'group': 'title_item_group',
|
||||
dividers: {
|
||||
dot: {
|
||||
icon: 'dot',
|
||||
},
|
||||
slash: {
|
||||
name: '/',
|
||||
icon: '',
|
||||
},
|
||||
dash: {
|
||||
name: '-',
|
||||
icon: '',
|
||||
},
|
||||
arrow: {
|
||||
name: '>',
|
||||
icon: '',
|
||||
},
|
||||
doubleArrow: {
|
||||
name: '>>',
|
||||
icon: '',
|
||||
},
|
||||
},
|
||||
};
|
||||
this.controlParams = this.props.control.params.input_attrs ? {
|
||||
...defaultParams,
|
||||
...this.props.control.params.input_attrs,
|
||||
} : defaultParams;
|
||||
this.state = {
|
||||
value: value,
|
||||
};
|
||||
}
|
||||
onDragStart() {
|
||||
var dropzones = document.querySelectorAll( '.kadence-builder-area' );
|
||||
var i;
|
||||
for (i = 0; i < dropzones.length; ++i) {
|
||||
dropzones[i].classList.add( 'kadence-dragging-dropzones' );
|
||||
}
|
||||
}
|
||||
onDragStop() {
|
||||
var dropzones = document.querySelectorAll( '.kadence-builder-area' );
|
||||
var i;
|
||||
for (i = 0; i < dropzones.length; ++i) {
|
||||
dropzones[i].classList.remove( 'kadence-dragging-dropzones' );
|
||||
}
|
||||
}
|
||||
saveObjectUpdate( value, index ) {
|
||||
let updateState = this.state.value;
|
||||
let items = updateState.items;
|
||||
let newItems = updateState.items;
|
||||
Object.keys( items ).map( ( item, thisIndex ) => {
|
||||
if ( index === thisIndex ) {
|
||||
newItems[item] = { ...items[item], ...value };
|
||||
}
|
||||
} );
|
||||
updateState.items = newItems;
|
||||
this.setState( { value: updateState } );
|
||||
this.updateValues( updateState );
|
||||
}
|
||||
onItemChange( value, itemIndex ) {
|
||||
this.saveObjectUpdate( value, itemIndex );
|
||||
}
|
||||
onDragEnd( items ) {
|
||||
let updateState = this.state.value;
|
||||
let update = updateState.items;
|
||||
let updateItems = {};
|
||||
{ items.length > 0 && (
|
||||
items.map( ( item ) => {
|
||||
if ( update[item.id].id === item.id ) {
|
||||
updateItems[item.id] = update[item.id];
|
||||
}
|
||||
} )
|
||||
) };
|
||||
if ( JSON.stringify( update ) !== JSON.stringify( updateItems ) ) {
|
||||
update.items = updateItems;
|
||||
updateState.items = updateItems;
|
||||
this.setState( { value: updateState } );
|
||||
this.updateValues( updateState );
|
||||
}
|
||||
}
|
||||
arraysEqual( a, b ) {
|
||||
if (a === b) return true;
|
||||
if (a == null || b == null) return false;
|
||||
if (a.length != b.length) return false;
|
||||
for (var i = 0; i < a.length; ++i) {
|
||||
if (a[i] !== b[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
render() {
|
||||
const controlLabel = (
|
||||
<Fragment>
|
||||
<Tooltip text={ __( 'Reset Value', 'kadence' ) }>
|
||||
<Button
|
||||
className="reset kadence-reset"
|
||||
disabled={ ( this.state.value === this.defaultValue ) }
|
||||
onClick={ () => {
|
||||
let value = this.defaultValue;
|
||||
this.setState( { value: value } );
|
||||
this.updateValues( value );
|
||||
} }
|
||||
>
|
||||
<Dashicon icon='image-rotate' />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
{ this.props.control.params.label &&
|
||||
this.props.control.params.label
|
||||
}
|
||||
</Fragment>
|
||||
);
|
||||
const currentList = ( typeof this.state.value != "undefined" && undefined !== this.state.value.items ? this.state.value.items : {} );
|
||||
let theItems = [];
|
||||
{ Object.keys( currentList ).map( ( item ) => {
|
||||
theItems.push(
|
||||
{
|
||||
id: item,
|
||||
}
|
||||
)
|
||||
} ) }
|
||||
return (
|
||||
<div className="kadence-control-field kadence-sorter-items kadence-post-title-sorter">
|
||||
<div className="kadence-responsive-control-bar">
|
||||
<span className="customize-control-title">{ controlLabel }</span>
|
||||
</div>
|
||||
<div className="kadence-sorter-row">
|
||||
<ReactSortable animation={100} onStart={ () => this.onDragStop() } onEnd={ () => this.onDragStop() } group={ this.controlParams.group } className={ `kadence-sorter-drop kadence-sorter-sortable-panel kadence-meta-sorter kadence-sorter-drop-${ this.controlParams.group }` } handle={ '.kadence-sorter-item-panel-header' } list={ theItems } setList={ ( newState ) => this.onDragEnd( newState ) } >
|
||||
{ Object.keys( currentList ).map( ( item, index ) => {
|
||||
return <ItemComponent
|
||||
onItemChange={ ( value, itemIndex ) => this.onItemChange( value, itemIndex ) }
|
||||
key={ item }
|
||||
index={ index }
|
||||
item={ currentList[item] }
|
||||
controlParams={ this.controlParams }
|
||||
/>;
|
||||
} ) }
|
||||
</ReactSortable>
|
||||
</div>
|
||||
{ this.props.control.renderNotice() }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
updateValues( value ) {
|
||||
this.props.control.setting.set( {
|
||||
...this.props.control.setting.get(),
|
||||
...value,
|
||||
flag: !this.props.control.setting.get().flag
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
SorterComponent.propTypes = {
|
||||
control: PropTypes.object.isRequired,
|
||||
customizer: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
export default SorterComponent;
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createRoot } from '@wordpress/element';
|
||||
import SwitchComponent from './switch-component.js';
|
||||
|
||||
export const SwitchControl = wp.customize.KadenceControl.extend( {
|
||||
renderContent: function renderContent() {
|
||||
let control = this;
|
||||
let root = createRoot( control.container[0] );
|
||||
root.render( <SwitchComponent control={control}/> );
|
||||
// ReactDOM.render(
|
||||
// <SwitchComponent control={control}/>,
|
||||
// control.container[0]
|
||||
// );
|
||||
}
|
||||
} );
|
||||
@@ -0,0 +1,45 @@
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { __ } from '@wordpress/i18n';
|
||||
const { Component } = wp.element;
|
||||
const { ToggleControl } = wp.components;
|
||||
|
||||
class SwitchComponent extends Component {
|
||||
constructor(props) {
|
||||
super( props );
|
||||
let value = props.control.setting.get();
|
||||
this.state = {
|
||||
value
|
||||
};
|
||||
this.defaultValue = props.control.params.default || '';
|
||||
this.updateValues = this.updateValues.bind( this );
|
||||
}
|
||||
|
||||
render() {
|
||||
//console.log( this.props.control.params );
|
||||
return (
|
||||
<div className="kadence-control-field kadence-switch-control">
|
||||
<ToggleControl
|
||||
label={ this.props.control.params.label ? this.props.control.params.label : undefined }
|
||||
checked={ this.state.value }
|
||||
help={ this.props.control.params.input_attrs && this.props.control.params.input_attrs.help ? this.props.control.params.input_attrs.help : undefined }
|
||||
onChange={ (value) => {
|
||||
this.updateValues( value );
|
||||
} }
|
||||
/>
|
||||
{ this.props.control.renderNotice() }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
updateValues(value) {
|
||||
this.setState( { value: value } );
|
||||
this.props.control.setting.set( value );
|
||||
}
|
||||
}
|
||||
|
||||
SwitchComponent.propTypes = {
|
||||
control: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
export default SwitchComponent;
|
||||
@@ -0,0 +1,11 @@
|
||||
import { createRoot } from '@wordpress/element';
|
||||
import TabsComponent from './tabs-component';
|
||||
|
||||
export const TabsControl = wp.customize.KadenceControl.extend( {
|
||||
renderContent: function renderContent() {
|
||||
let control = this;
|
||||
let root = createRoot( control.container[0] );
|
||||
root.render( <TabsComponent control={ control } customizer={ wp.customize } /> );
|
||||
// ReactDOM.render( <TabsComponent control={ control } customizer={ wp.customize } />, control.container[0] );
|
||||
}
|
||||
} );
|
||||
@@ -0,0 +1,78 @@
|
||||
/* jshint esversion: 6 */
|
||||
import PropTypes from 'prop-types';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
const { ButtonGroup, Dashicon, Tooltip, Button } = wp.components;
|
||||
|
||||
const { Component, Fragment } = wp.element;
|
||||
class TabsComponent extends Component {
|
||||
constructor() {
|
||||
super( ...arguments );
|
||||
this.focusPanel = this.focusPanel.bind( this );
|
||||
let defaultParams = {
|
||||
'general': {
|
||||
'label': 'General',
|
||||
'target' : '',
|
||||
},
|
||||
'design': {
|
||||
'label': 'Design',
|
||||
'target' : 'design',
|
||||
},
|
||||
'active': 'general',
|
||||
};
|
||||
this.controlParams = this.props.control.params.input_attrs ? {
|
||||
...defaultParams,
|
||||
...this.props.control.params.input_attrs,
|
||||
} : defaultParams;
|
||||
}
|
||||
focusPanel( section ) {
|
||||
let self = this;
|
||||
let otherSection;
|
||||
let secton_id = ( 'woocommerce_product_catalog_design' === section || 'woocommerce_product_catalog' === section || 'woocommerce_store_notice' === section || 'woocommerce_store_notice_design' === section ? section : 'kadence_customizer_' + section )
|
||||
if ( section === self.controlParams.design.target ) {
|
||||
otherSection = ( 'woocommerce_product_catalog_design' === section || 'woocommerce_product_catalog' === section || 'woocommerce_store_notice' === section || 'woocommerce_store_notice_design' === section ? self.controlParams.general.target : 'kadence_customizer_' + self.controlParams.general.target );
|
||||
} else {
|
||||
otherSection = ( 'woocommerce_product_catalog_design' === section || 'woocommerce_product_catalog' === section || 'woocommerce_store_notice' === section || 'woocommerce_store_notice_design' === section ? self.controlParams.design.target : 'kadence_customizer_' + self.controlParams.design.target );
|
||||
}
|
||||
if ( undefined !== self.props.customizer.section( secton_id ) ) {
|
||||
const container = self.props.customizer.section( secton_id ).contentContainer[0];
|
||||
const otherContainer = self.props.customizer.section( otherSection ).contentContainer[0];
|
||||
container.classList.add( 'kadence-prevent-transition' );
|
||||
otherContainer.classList.add( 'kadence-prevent-transition' );
|
||||
setTimeout( function(){
|
||||
self.props.customizer.section( secton_id ).focus();
|
||||
}, 10);
|
||||
setTimeout( function(){
|
||||
container.classList.remove( 'kadence-prevent-transition' );
|
||||
container.classList.remove( 'busy' );
|
||||
container.style.top = null;
|
||||
otherContainer.classList.remove( 'kadence-prevent-transition' );
|
||||
otherContainer.classList.remove( 'busy' );
|
||||
}, 300);
|
||||
}
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div className="customize-control-kadence_blank_control">
|
||||
<div className="customize-control-description">
|
||||
<div class="kadence-nav-tabs kadence-compontent-tabs nav-tab-wrapper wp-clearfix">
|
||||
<Button className={ `nav-tab kadence-general-tab kadence-compontent-tabs-button kadence-nav-tabs-button${ 'general' === this.controlParams.active ? ' nav-tab-active' : '' }` } onClick={ () => this.focusPanel( this.controlParams.general.target ) }>
|
||||
<span>{ this.controlParams.general.label }</span>
|
||||
</Button>
|
||||
<Button className={ `nav-tab kadence-design-tab kadence-compontent-tabs-button kadence-nav-tabs-button${ 'design' === this.controlParams.active ? ' nav-tab-active' : '' }` } onClick={ () => this.focusPanel( this.controlParams.design.target ) }>
|
||||
<span>{ this.controlParams.design.label }</span>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
{ this.props.control.renderNotice() }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
TabsComponent.propTypes = {
|
||||
control: PropTypes.object.isRequired,
|
||||
customizer: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
export default TabsComponent;
|
||||
@@ -0,0 +1,11 @@
|
||||
import { createRoot } from '@wordpress/element';
|
||||
import TextComponent from './text-component.js';
|
||||
|
||||
export const TextControl = wp.customize.KadenceControl.extend( {
|
||||
renderContent: function renderContent() {
|
||||
let control = this;
|
||||
let root = createRoot( control.container[0] );
|
||||
root.render( <TextComponent control={ control } /> );
|
||||
// ReactDOM.render( <TextComponent control={ control } />, control.container[0] );
|
||||
}
|
||||
} );
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user