Update to Kirki 4.2.0

This commit is contained in:
AlxMedia 2023-08-04 15:41:48 +02:00
parent cbfd4f27e4
commit 77ecd4ca69
440 changed files with 6230 additions and 5211 deletions

View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 kirki-framework
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -0,0 +1,184 @@
<?php
/**
* Adds class aliases for backwards compatibility.
*
* @package Kirki
* @category Core
* @author Themeum
* @copyright Copyright (c) 2023, Themeum
* @license https://opensource.org/licenses/MIT
* @since 0.1
*/
namespace Kirki\Compatibility;
/**
* Adds class aliases for backwards compatibility.
*
* @since 0.1
*/
class Aliases {
/**
* An array of class aliases.
*
* @access private
* @since 0.1
* @var array
*/
private $aliases = [
'generic' => [
[ 'Kirki\Compatibility\Kirki', 'Kirki' ],
[ 'Kirki\Compatibility\Config', 'Kirki_Config' ],
[ 'Kirki\Compatibility\Control', 'Kirki_Control' ],
[ 'Kirki\Compatibility\Field', 'Kirki_Field' ],
[ 'Kirki\Util\Helper', 'Kirki_Helper' ],
[ 'Kirki\Compatibility\Init', 'Kirki_Init' ],
[ 'Kirki\L10n', 'Kirki_L10n' ],
[ 'Kirki\Compatibility\Modules', 'Kirki_Modules' ],
[ 'Kirki\Compatibility\Sanitize_Values', 'Kirki_Sanitize_Values' ],
[ 'Kirki\Compatibility\Section', 'Kirki_Section' ],
[ 'Kirki\Compatibility\Values', 'Kirki_Values' ],
[ 'Kirki\Util\Util', 'Kirki_Util' ],
[ 'Kirki\Compatibility\Framework', 'Kirki_Toolkit' ],
[ 'Kirki\Module\CSS', 'Kirki_Modules_CSS' ],
[ 'Kirki\Module\CSS\Output', 'Kirki_Output' ],
[ 'Kirki\Module\CSS\Generator', 'Kirki_Modules_CSS_Generator' ],
[ 'Kirki\Module\CSS\Property', 'Kirki_Output_Property' ],
[ 'Kirki\Module\CSS\Property\Font_Family', 'Kirki_Output_Property_Font_Family' ],
[ 'Kirki\Module\Preset', 'Kirki_Modules_Preset' ],
[ 'Kirki\Module\Tooltips', 'Kirki_Modules_Tooltips' ],
[ 'Kirki\Module\Webfonts', 'Kirki_Modules_Webfonts' ],
[ 'Kirki\Module\Webfonts\Google', 'Kirki_Fonts_Google' ],
[ 'Kirki\Module\Webfonts\Fonts', 'Kirki_Fonts' ],
[ 'Kirki\Module\Webfonts\Embed', 'Kirki_Modules_Webfonts_Embed' ],
[ 'Kirki\Module\Webfonts\Async', 'Kirki_Modules_Webfonts_Async' ],
[ 'Kirki\Module\Field_Dependencies', 'Kirki_Modules_Field_Dependencies' ],
[ 'Kirki\Module\Editor_Styles', 'Kirki_Modules_Gutenberg' ],
[ 'Kirki\Module\Selective_Refresh', 'Kirki_Modules_Selective_Refresh' ],
[ 'Kirki\Module\Postmessage', 'Kirki_Modules_Postmessage' ],
[ 'Kirki\Field\Background', 'Kirki_Field_Background' ],
[ 'Kirki\Field\CSS\Background', 'Kirki_Output_Field_Background' ],
[ 'Kirki\Field\Checkbox', 'Kirki_Field_Checkbox' ],
[ 'Kirki\Field\Checkbox_Switch', 'Kirki_Field_Switch' ],
[ 'Kirki\Field\Checkbox_Switch', 'Kirki\Field\Switch' ], // Preventing typo.
[ 'Kirki\Field\Checkbox_Toggle', 'Kirki_Field_Toggle' ],
[ 'Kirki\Field\Checkbox_Toggle', 'Kirki\Field\Toggle' ], // Preventing typo.
[ 'Kirki\Field\Code', 'Kirki_Field_Code' ],
[ 'Kirki\Field\Color', 'Kirki_Field_Color' ],
[ 'Kirki\Field\Color', 'Kirki_Field_Color_Alpha' ],
[ 'Kirki\Field\Color_Palette', 'Kirki_Field_Color_Palette' ],
[ 'Kirki\Field\Custom', 'Kirki_Field_Custom' ],
[ 'Kirki\Field\Dashicons', 'Kirki_Field_Dashicons' ],
[ 'Kirki\Field\Date', 'Kirki_Field_Date' ],
[ 'Kirki\Field\Dimension', 'Kirki_Field_Dimension' ],
[ 'Kirki\Field\Dimensions', 'Kirki_Field_Dimensions' ],
[ 'Kirki\Field\CSS\Dimensions', 'Kirki_Output_Field_Dimensions' ],
[ 'Kirki\Field\Dimensions', 'Kirki_Field_Spacing' ],
[ 'Kirki\Field\Dimensions', 'Kirki\Field\Spacing' ],
[ 'Kirki\Field\Editor', 'Kirki_Field_Editor' ],
[ 'Kirki\Field\FontAwesome', 'Kirki_Field_FontAwesome' ],
[ 'Kirki\Field\Generic', 'Kirki_Field_Kirki_Generic' ],
[ 'Kirki\Field\Generic', 'Kirki_Field_Generic' ],
[ 'Kirki\Field\Text', 'Kirki_Field_Text' ],
[ 'Kirki\Field\Textarea', 'Kirki_Field_Textarea' ],
[ 'Kirki\Field\URL', 'Kirki_Field_URL' ],
[ 'Kirki\Field\URL', 'Kirki_Field_Link' ],
[ 'Kirki\Field\URL', 'Kirki\Field\Link' ],
[ 'Kirki\Field\Image', 'Kirki_Field_Image' ],
[ 'Kirki\Field\CSS\Image', 'Kirki_Output_Field_Image' ],
[ 'Kirki\Field\Multicheck', 'Kirki_Field_Multicheck' ],
[ 'Kirki\Field\Multicolor', 'Kirki_Field_Multicolor' ],
[ 'Kirki\Field\CSS\Multicolor', 'Kirki_Output_Field_Multicolor' ],
[ 'Kirki\Field\Number', 'Kirki_Field_Number' ],
[ 'Kirki\Field\Palette', 'Kirki_Field_Palette' ],
[ 'Kirki\Field\Repeater', 'Kirki_Field_Repeater' ],
[ 'Kirki\Field\Dropdown_Pages', 'Kirki_Field_Dropdown_Pages' ],
[ 'Kirki\Field\Preset', 'Kirki_Field_Preset' ],
[ 'Kirki\Field\Select', 'Kirki_Field_Select' ],
[ 'Kirki\Field\Slider', 'Kirki_Field_Slider' ],
[ 'Kirki\Field\Sortable', 'Kirki_Field_Sortable' ],
[ 'Kirki\Field\Typography', 'Kirki_Field_Typography' ],
[ 'Kirki\Field\CSS\Typography', 'Kirki_Output_Field_Typography' ],
[ 'Kirki\Field\Upload', 'Kirki_Field_Upload' ],
],
'customizer' => [
[ 'Kirki\Control\Base', 'Kirki_Control_Base' ],
[ 'Kirki\Control\Base', 'Kirki_Customize_Control' ],
[ 'Kirki\Control\Checkbox', 'Kirki_Control_Checkbox' ],
[ 'Kirki\Control\Checkbox_Switch', 'Kirki_Control_Switch' ],
[ 'Kirki\Control\Checkbox_Toggle', 'Kirki_Control_Toggle' ],
[ 'WP_Customize_Code_Editor_Control', 'Kirki_Control_Code' ],
[ 'Kirki\Control\Color', 'Kirki_Control_Color' ],
[ 'Kirki\Control\Color_Palette', 'Kirki_Control_Color_Palette' ],
[ 'WP_Customize_Cropped_Image_Control', 'Kirki_Control_Cropped_Image' ],
[ 'Kirki\Control\Custom', 'Kirki_Control_Custom' ],
[ 'Kirki\Control\Dashicons', 'Kirki_Control_Dashicons' ],
[ 'Kirki\Control\Date', 'Kirki_Control_Date' ],
[ 'Kirki\Control\Dimension', 'Kirki_Control_Dimension' ],
[ 'Kirki\Control\Editor', 'Kirki_Control_Editor' ],
[ 'Kirki\Control\Generic', 'Kirki_Control_Generic' ],
[ 'Kirki\Control\Image', 'Kirki_Control_Image' ],
[ 'Kirki\Control\Multicheck', 'Kirki_Control_Multicheck' ],
[ 'Kirki\Control\Generic', 'Kirki_Control_Number' ],
[ 'Kirki\Control\Palette', 'Kirki_Control_Palette' ],
[ 'Kirki\Control\Radio', 'Kirki_Control_Radio' ],
[ 'Kirki\Control\Radio_Buttonset', 'Kirki_Control_Radio_Buttonset' ],
[ 'Kirki\Control\Radio_Image', 'Kirki_Control_Radio_Image' ],
[ 'Kirki\Control\Radio_Image', 'Kirki_Controls_Radio_Image_Control' ],
[ 'Kirki\Control\Repeater', 'Kirki_Control_Repeater' ],
[ 'Kirki\Control\Select', 'Kirki_Control_Select' ],
[ 'Kirki\Control\Slider', 'Kirki_Control_Slider' ],
[ 'Kirki\Control\Sortable', 'Kirki_Control_Sortable' ],
[ 'Kirki\Control\Upload', 'Kirki_Control_Upload' ],
[ 'Kirki\Settings\Repeater', 'Kirki\Settings\Repeater_Setting' ],
[ 'Kirki\Settings\Repeater', 'Kirki_Settings_Repeater_Setting' ],
[ 'WP_Customize_Section', 'Kirki_Sections_Default_Section' ],
[ 'Kirki\Section_Types\Expanded', 'Kirki_Sections_Expanded_Section' ],
[ 'Kirki\Section_Types\Nested', 'Kirki_Sections_Nested_Section' ],
[ 'Kirki\Section_Types\Link', 'Kirki_Sections_Link_Section' ],
[ 'Kirki\Panel_Types\Nested', 'Kirki_Panels_Nested_Panel' ],
],
];
/**
* Constructor.
*
* @access public
* @since 0.1
*/
public function __construct() {
$this->add_aliases();
add_action( 'customize_register', [ $this, 'add_customizer_aliases' ] );
}
/**
* Adds object aliases.
*
* @access public
* @since 0.1
* @return void
*/
public function add_aliases() {
foreach ( $this->aliases['generic'] as $item ) {
if ( class_exists( $item[0] ) ) {
class_alias( $item[0], $item[1] );
}
}
}
/**
* Adds object aliases for classes that get instantiated on customize_register.
*
* @access public
* @since 0.1
* @return void
*/
public function add_customizer_aliases() {
foreach ( $this->aliases['customizer'] as $item ) {
if ( class_exists( $item[0] ) ) {
class_alias( $item[0], $item[1] );
}
}
}
}

View file

@ -0,0 +1,179 @@
<?php
/**
* Processes configurations.
*
* @package Kirki
* @category Compatibility
* @author Themeum
* @copyright Copyright (c) 2023, Themeum
* @license https://opensource.org/licenses/MIT
*/
namespace Kirki\Compatibility;
/**
* The Config object
*/
final class Config {
/**
* Each instance is stored separately in this array.
*
* @static
* @access private
* @var array
*/
private static $instances = [];
/**
* The finalized configuration array.
*
* @access protected
* @var array
*/
protected $config_final = [];
/**
* The configuration ID.
*
* @access public
* @var string
*/
public $id = 'global';
/**
* Capability (fields will inherit this).
*
* @access protected
* @var string
*/
protected $capability = 'edit_theme_options';
/**
* The data-type we'll be using.
*
* @access protected
* @var string
*/
protected $option_type = 'theme_mod';
/**
* If we're using serialized options, then this is the global option name.
*
* @access protected
* @var string
*/
protected $option_name = '';
/**
* The compiler.
*
* @access protected
* @var array
*/
protected $compiler = [];
/**
* Set to true if you want to completely disable any Kirki-generated CSS.
*
* @access protected
* @var bool
*/
protected $disable_output = false;
/**
* The class constructor.
* Use the get_instance() static method to get the instance you need.
*
* @access private
* @param string $config_id @see Kirki\Compatibility\Config::get_instance().
* @param array $args @see Kirki\Compatibility\Config::get_instance().
*/
private function __construct( $config_id = 'global', $args = [] ) {
// Get defaults from the class.
$defaults = get_class_vars( __CLASS__ );
// Skip what we don't need in this context.
unset( $defaults['config_final'] );
unset( $defaults['instances'] );
// Apply any kirki_config global filters.
$defaults = apply_filters( 'kirki_config', $defaults );
// Merge our args with the defaults.
$args = wp_parse_args( $args, $defaults );
// Modify default values with the defined ones.
foreach ( $args as $key => $value ) {
// Is this property whitelisted?
if ( property_exists( $this, $key ) ) {
$args[ $key ] = $value;
}
}
$this->id = $config_id;
$this->config_final = wp_parse_args(
[
'id' => $config_id,
],
$args
);
}
/**
* Use this method to get an instance of your config.
* Each config has its own instance of this object.
*
* @static
* @access public
* @param string $id Config ID.
* @param array $args {
* Optional. Arguments to override config defaults.
*
* @type string $capability @see https://codex.wordpress.org/Roles_and_Capabilities
* @type string $option_type theme_mod or option.
* @type string $option_name If we want to used serialized options,
* this is where we'll be adding the option name.
* All fields using this config will be items in that array.
* @type array $compiler Not yet fully implemented
* @type bool $disable_output If set to true, no CSS will be generated
* from fields using this configuration.
* }
*
* @return Kirki\Compatibility\Config
*/
public static function get_instance( $id = 'global', $args = [] ) {
if ( empty( $id ) ) {
$id = 'global';
}
$id_md5 = md5( $id );
if ( ! isset( self::$instances[ $id_md5 ] ) ) {
self::$instances[ $id_md5 ] = new self( $id, $args );
}
return self::$instances[ $id_md5 ];
}
/**
* Get the IDs of all current configs.
*
* @static
* @access public
* @since 3.0.22
* @return array
*/
public static function get_config_ids() {
$configs = [];
foreach ( self::$instances as $instance ) {
$configs[] = $instance->id;
}
return array_unique( $configs );
}
/**
* Returns the $config_final property
*
* @access public
* @return array
*/
public function get_config() {
return $this->config_final;
}
}

View file

@ -0,0 +1,129 @@
<?php
/**
* Controls handler
*
* @package Kirki
* @category Core
* @author Themeum
* @copyright Copyright (c) 2023, Themeum
* @license https://opensource.org/licenses/MIT
*/
namespace Kirki\Compatibility;
/**
* Our main Kirki\Control object
*/
class Control {
/**
* The $wp_customize WordPress global.
*
* @access protected
* @var WP_Customize_Manager
*/
protected $wp_customize;
/**
* An array of all available control types.
*
* @access protected
* @var array
*/
protected static $control_types = [];
/**
* The class constructor.
* Creates the actual controls in the customizer.
*
* @access public
* @param array $args The field definition as sanitized in Kirki\Field.
*/
public function __construct( $args ) {
// Set the $wp_customize property.
global $wp_customize;
if ( ! $wp_customize ) {
return;
}
$this->wp_customize = $wp_customize;
// Set the control types.
$this->set_control_types();
// Add the control.
$this->add_control( $args );
}
/**
* Get the class name of the class needed to create tis control.
*
* @access private
* @param array $args The field definition as sanitized in Kirki\Field.
*
* @return string the name of the class that will be used to create this control.
*/
final function get_control_class_name( $args ) {
// Set a default class name.
$class_name = 'WP_Customize_Control';
// Get the classname from the array of control classnames.
if ( array_key_exists( $args['type'], self::$control_types ) ) {
$class_name = self::$control_types[ $args['type'] ];
}
return $class_name;
}
/**
* Adds the control.
*
* @access protected
* @param array $args The field definition as sanitized in Kirki\Field.
*/
final protected function add_control( $args ) {
// Get the name of the class we're going to use.
$class_name = $this->get_control_class_name( $args );
/**
* Allow filtering the arguments.
*
* @since 0.1
* @param array $args The arguments.
* @param WP_Customize_Manager $wp_customize The customizer instance.
* @return array Return the arguments.
*/
$args = apply_filters( 'kirki_field_add_control_args', $args, $this->wp_customize );
// Add the control.
$this->wp_customize->add_control( new $class_name( $this->wp_customize, $args['settings'], $args ) );
}
/**
* Sets the $control_types property.
* Makes sure the kirki_control_types filter is applied
* and that the defined classes actually exist.
* If a defined class does not exist, it is removed.
*
* @access private
*/
final function set_control_types() {
// Early exit if this has already run.
if ( ! empty( self::$control_types ) ) {
return;
}
self::$control_types = apply_filters( 'kirki_control_types', [] );
// Make sure the defined classes actually exist.
foreach ( self::$control_types as $key => $classname ) {
if ( ! class_exists( $classname ) ) {
unset( self::$control_types[ $key ] );
}
}
}
}

View file

@ -0,0 +1,32 @@
<?php
/**
* Backwards-compatibility for Kirki filters.
*
* @package Kirki
* @category Core
* @author Themeum
* @copyright Copyright (c) 2023, Themeum
* @license https://opensource.org/licenses/MIT
* @since 1.0
*/
namespace Kirki\Compatibility;
/**
* Please do not use this class directly.
* You should instead extend it per-field-type.
*/
class Deprecated {
/**
* Constructor.
*
* @access public
* @since 1.0
*/
public function __construct() {
require_once __DIR__ . '/deprecated/classes.php'; // phpcs:ignore WPThemeReview.CoreFunctionality.FileInclude
require_once __DIR__ . '/deprecated/functions.php'; // phpcs:ignore WPThemeReview.CoreFunctionality.FileInclude
require_once __DIR__ . '/deprecated/filters.php'; // phpcs:ignore WPThemeReview.CoreFunctionality.FileInclude
}
}

View file

@ -0,0 +1,683 @@
<?php
/**
* Creates and validates field parameters.
*
* @package Kirki
* @category Core
* @author Themeum
* @copyright Copyright (c) 2023, Themeum
* @license https://opensource.org/licenses/MIT
* @since 1.0
*/
namespace Kirki\Compatibility;
use Kirki\Compatibility\Kirki;
/**
* Please do not use this class directly.
* You should instead extend it per-field-type.
*/
class Field {
/**
* An array of the field arguments.
*
* @access protected
* @var array
*/
public $label;
public $row_label;
public $button_label;
public $description;
public $help;
protected $args = array();
/**
* The ID of the kirki_config we're using.
*
* @see Kirki\Compatibility\Config
* @access protected
* @var string
*/
protected $kirki_config = 'global';
/**
* The capability required so that users can edit this field.
*
* @access protected
* @var string
*/
protected $capability = 'edit_theme_options';
/**
* If we're using options instead of theme_mods
* and we want them serialized, this is the option that
* will saved in the db.
*
* @access protected
* @var string
*/
protected $option_name = '';
/**
* Custom input attributes (defined as an array).
*
* @access protected
* @var array
*/
protected $input_attrs = array();
/**
* Preset choices.
*
* @access protected
* @var array
*/
protected $preset = array();
/**
* CSS Variables.
*
* @access protected
* @var array
*/
protected $css_vars = array();
/**
* Use "theme_mod" or "option".
*
* @access protected
* @var string
*/
protected $option_type = 'theme_mod';
/**
* The name of this setting (id for the db).
*
* @access protected
* @var string|array
*/
protected $settings = '';
/**
* Set to true if you want to disable all CSS output for this field.
*
* @access protected
* @var bool
*/
protected $disable_output = false;
/**
* The field type.
*
* @access protected
* @var string
*/
protected $type = 'kirki-generic';
/**
* Some fields require options to be set.
* We're whitelisting the property here
* and suggest you validate this in a child class.
*
* @access protected
* @var array
*/
protected $choices = array();
/**
* Assign this field to a section.
* Fields not assigned to a section will not be displayed in the customizer.
*
* @access protected
* @var string
*/
protected $section = '';
/**
* The default value for this field.
*
* @access protected
* @var string|array|bool
*/
protected $default = '';
/**
* Priority determines the position of a control inside a section.
* Lower priority numbers move the control to the top.
*
* @access protected
* @var int
*/
protected $priority = 10;
/**
* Unique ID for this field.
* This is auto-calculated from the $settings argument.
*
* @access protected
* @var string
*/
protected $id = '';
/**
* Use if you want to automatically generate CSS from this field's value.
*
* @see https://kirki.org/docs/arguments/output
* @access protected
* @var array
*/
protected $output = array();
/**
* Use to automatically generate postMessage scripts.
* Not necessary to use if you use 'transport' => 'auto'
* and have already set an array for the 'output' argument.
*
* @see https://kirki.org/docs/arguments/js_vars
* @access protected
* @var array
*/
protected $js_vars = array();
/**
* If you want to use a CSS compiler, then use this to set the variable names.
*
* @see https://kirki.org/docs/arguments/variables
* @access protected
* @var array
*/
protected $variables = array();
/**
* Text that will be used in a tooltip to provide extra info for this field.
*
* @access protected
* @var string
*/
protected $tooltip = '';
/**
* A custom callback to determine if the field should be visible or not.
*
* @access protected
* @var string|array
*/
protected $active_callback = '__return_true';
/**
* A custom sanitize callback that will be used to properly save the values.
*
* @access protected
* @var string|array
*/
protected $sanitize_callback = '';
/**
* Use 'refresh', 'postMessage' or 'auto'.
* 'auto' will automatically geberate any 'js_vars' from the 'output' argument.
*
* @access protected
* @var string
*/
protected $transport = 'refresh';
/**
* Define dependencies to show/hide this field based on the values of other fields.
*
* @access protected
* @var array
*/
protected $required = array();
/**
* Partial Refreshes array.
*
* @access protected
* @var array
*/
protected $partial_refresh = array();
/**
* The class constructor.
* Parses and sanitizes all field arguments.
* Then it adds the field to Kirki::$fields.
*
* @access public
* @param string $config_id The ID of the config we want to use.
* Defaults to "global".
* Configs are handled by the Kirki\Compatibility\Config class.
* @param array $args The arguments of the field.
*/
public function __construct( $config_id = 'global', $args = array() ) {
/**
* In case the user only provides 1 argument,
* assume that the provided argument is $args and set $config_id = 'global'.
*/
if ( is_array( $config_id ) && empty( $args ) ) {
$args = $config_id;
$config_id = isset( $args['kirki_config'] ) ? $args['kirki_config'] : 'global';
}
if ( isset( $args['setting'] ) && ! empty( $args['setting'] ) && ( ! isset( $args['settings'] ) || empty( $args['settings'] ) ) ) {
/* translators: %s represents the field ID where the error occurs. */
_doing_it_wrong( __METHOD__, sprintf( esc_html__( 'Typo found in field %s - setting instead of settings.', 'kirki' ), esc_html( $args['settings'] ) ), '3.0.10' );
$args['settings'] = $args['setting'];
unset( $args['setting'] );
}
$args['kirki_config'] = $config_id;
$this->kirki_config = $config_id;
if ( '' === $config_id ) {
/* translators: %1$s represents the field ID where the error occurs. %2$s is the URL in the documentation site. */
_doing_it_wrong( __METHOD__, sprintf( esc_html__( 'Config not defined for field %1$s - See %2$s for details on how to properly add fields.', 'kirki' ), esc_html( $args['settings'] ), 'https://aristath.github.io/kirki/docs/getting-started/fields.html' ), '3.0.10' );
$this->kirki_config = 'global';
}
// Get defaults from the class.
$defaults = get_class_vars( __CLASS__ );
// Get the config arguments, and merge them with the defaults.
$config_defaults = ( isset( Kirki::$config['global'] ) ) ? Kirki::$config['global'] : array();
if ( 'global' !== $this->kirki_config && isset( Kirki::$config[ $this->kirki_config ] ) ) {
$config_defaults = Kirki::$config[ $this->kirki_config ];
}
$config_defaults = ( is_array( $config_defaults ) ) ? $config_defaults : array();
foreach ( $config_defaults as $key => $value ) {
if ( isset( $defaults[ $key ] ) && ! empty( $value ) && $value !== $defaults[ $key ] ) {
$defaults[ $key ] = $value;
}
}
// Merge our args with the defaults.
$args = wp_parse_args( $args, $defaults );
// Set the class properties using the parsed args.
foreach ( $args as $key => $value ) {
$this->$key = $value;
}
$this->args = $args;
$this->set_field();
// Instantiate the \Kirki\Field to apply hooks.
new \Kirki\Field\None( $this->args );
}
/**
* Processes the field arguments
*
* @access protected
*/
protected function set_field() {
$properties = get_class_vars( __CLASS__ );
// Some things must run before the others.
$this->set_option_type();
$this->set_settings();
// Sanitize the properties, skipping the ones that have already run above.
foreach ( array_keys( $properties ) as $property ) {
if ( in_array( $property, array( 'option_name', 'option_type', 'settings' ), true ) ) {
continue;
}
if ( method_exists( $this, 'set_' . $property ) ) {
$method_name = 'set_' . $property;
$this->$method_name();
}
}
// Get all arguments with their values.
$args = get_object_vars( $this );
foreach ( array_keys( $args ) as $key ) {
$args[ $key ] = $this->$key;
}
// Add the field to the static $fields variable properly indexed.
Kirki::$fields[ $this->settings ] = $args;
}
/**
* Escape the $section.
*
* @access protected
*/
protected function set_input_attrs() {
$this->input_attrs = (array) $this->input_attrs;
}
/**
* Make sure we're using the correct option_type
*
* @access protected
*/
protected function set_option_type() {
// Take care of common typos.
if ( 'options' === $this->option_type ) {
$this->option_type = 'option';
}
// Take care of common typos.
if ( 'theme_mods' === $this->option_type ) {
/* translators: %1$s represents the field ID where the error occurs. */
_doing_it_wrong( __METHOD__, sprintf( esc_html( 'Typo found in field %s - "theme_mods" vs "theme_mod"', 'kirki' ), esc_html( $this->settings ) ), '3.0.10' );
$this->option_type = 'theme_mod';
}
}
/**
* Modifications for partial refreshes.
*
* @access protected
*/
protected function set_partial_refresh() {
if ( ! is_array( $this->partial_refresh ) ) {
$this->partial_refresh = array();
}
foreach ( $this->partial_refresh as $id => $args ) {
if ( ! is_array( $args ) || ! isset( $args['selector'] ) || ! isset( $args['render_callback'] ) || ! is_callable( $args['render_callback'] ) ) {
/* translators: %1$s represents the field ID where the error occurs. */
_doing_it_wrong( __METHOD__, sprintf( esc_html__( '"partial_refresh" invalid entry in field %s', 'kirki' ), esc_html( $this->settings ) ), '3.0.10' );
unset( $this->partial_refresh[ $id ] );
continue;
}
}
if ( ! empty( $this->partial_refresh ) ) {
$this->transport = 'postMessage';
}
}
/**
* Sets the settings.
* If we're using serialized options it makes sure that settings are properly formatted.
* We'll also be escaping all setting names here for consistency.
*
* @access protected
*/
protected function set_settings() {
// If settings is not an array, temporarily convert it to an array.
// This is just to allow us to process everything the same way and avoid code duplication.
// if settings is not an array then it will not be set as an array in the end.
if ( ! is_array( $this->settings ) ) {
$this->settings = array(
'kirki_placeholder_setting' => $this->settings,
);
}
$settings = array();
foreach ( $this->settings as $setting_key => $setting_value ) {
$settings[ $setting_key ] = $setting_value;
// If we're using serialized options then we need to spice this up.
if ( 'option' === $this->option_type && '' !== $this->option_name && ( false === strpos( $setting_key, '[' ) ) ) {
$settings[ $setting_key ] = "{$this->option_name}[{$setting_value}]";
}
}
$this->settings = $settings;
if ( isset( $this->settings['kirki_placeholder_setting'] ) ) {
$this->settings = $this->settings['kirki_placeholder_setting'];
}
}
/**
* Sets the active_callback
* If we're using the $required argument,
* Then this is where the switch is made to our evaluation method.
*
* @access protected
*/
protected function set_active_callback() {
if ( is_array( $this->active_callback ) ) {
if ( ! is_callable( $this->active_callback ) ) {
// Bugfix for https://github.com/aristath/kirki/issues/1961.
foreach ( $this->active_callback as $key => $val ) {
if ( is_callable( $val ) ) {
unset( $this->active_callback[ $key ] );
}
}
if ( isset( $this->active_callback[0] ) ) {
$this->required = $this->active_callback;
}
}
}
if ( ! empty( $this->required ) ) {
$this->active_callback = '__return_true';
return;
}
// No need to proceed any further if we're using the default value.
if ( '__return_true' === $this->active_callback ) {
return;
}
// Make sure the function is callable, otherwise fallback to __return_true.
if ( ! is_callable( $this->active_callback ) ) {
$this->active_callback = '__return_true';
}
}
/**
* Sets the $id.
* Setting the ID should happen after the 'settings' sanitization.
* This way we can also properly handle cases where the option_type is set to 'option'
* and we're using an array instead of individual options.
*
* @access protected
*/
protected function set_id() {
$this->id = sanitize_key( str_replace( '[', '-', str_replace( ']', '', $this->settings ) ) );
}
/**
* Sets the $choices.
*
* @access protected
*/
protected function set_choices() {
if ( ! is_array( $this->choices ) ) {
$this->choices = array();
}
}
/**
* Escapes the $disable_output.
*
* @access protected
*/
protected function set_disable_output() {
$this->disable_output = (bool) $this->disable_output;
}
/**
* Sets the $sanitize_callback
*
* @access protected
*/
protected function set_output() {
if ( empty( $this->output ) ) {
return;
}
if ( ! is_array( $this->output ) ) {
/* translators: The field ID where the error occurs. */
_doing_it_wrong( __METHOD__, sprintf( esc_html__( '"output" invalid format in field %s. The "output" argument should be defined as an array of arrays.', 'kirki' ), esc_html( $this->settings ) ), '3.0.10' );
$this->output = array(
array(
'element' => $this->output,
),
);
}
// Convert to array of arrays if needed.
if ( isset( $this->output['element'] ) ) {
/* translators: The field ID where the error occurs. */
_doing_it_wrong( __METHOD__, sprintf( esc_html__( '"output" invalid format in field %s. The "output" argument should be defined as an array of arrays.', 'kirki' ), esc_html( $this->settings ) ), '3.0.10' );
$this->output = array( $this->output );
}
foreach ( $this->output as $key => $output ) {
if ( empty( $output ) || ! isset( $output['element'] ) ) {
unset( $this->output[ $key ] );
continue;
}
if ( ! isset( $output['sanitize_callback'] ) && isset( $output['callback'] ) ) {
$this->output[ $key ]['sanitize_callback'] = $output['callback'];
}
// Convert element arrays to strings.
if ( isset( $output['element'] ) && is_array( $output['element'] ) ) {
$this->output[ $key ]['element'] = array_unique( $this->output[ $key ]['element'] );
sort( $this->output[ $key ]['element'] );
// Trim each element in the array.
foreach ( $this->output[ $key ]['element'] as $index => $element ) {
$this->output[ $key ]['element'][ $index ] = trim( $element );
}
$this->output[ $key ]['element'] = implode( ',', $this->output[ $key ]['element'] );
}
// Fix for https://github.com/aristath/kirki/issues/1659#issuecomment-346229751.
$this->output[ $key ]['element'] = str_replace( array( "\t", "\n", "\r", "\0", "\x0B" ), ' ', $this->output[ $key ]['element'] );
$this->output[ $key ]['element'] = trim( preg_replace( '/\s+/', ' ', $this->output[ $key ]['element'] ) );
}
}
/**
* Sets the $js_vars
*
* @access protected
*/
protected function set_js_vars() {
if ( ! is_array( $this->js_vars ) ) {
$this->js_vars = array();
}
// Check if transport is set to auto.
// If not, then skip the auto-calculations and exit early.
if ( 'auto' !== $this->transport ) {
return;
}
// Set transport to refresh initially.
// Serves as a fallback in case we failt to auto-calculate js_vars.
$this->transport = 'refresh';
$js_vars = array();
// Try to auto-generate js_vars.
// First we need to check if js_vars are empty, and that output is not empty.
if ( empty( $this->js_vars ) && ! empty( $this->output ) ) {
// Start going through each item in the $output array.
foreach ( $this->output as $output ) {
$output['function'] = ( isset( $output['function'] ) ) ? $output['function'] : 'style';
// If 'element' is not defined, skip this.
if ( ! isset( $output['element'] ) ) {
continue;
}
if ( is_array( $output['element'] ) ) {
$output['element'] = implode( ',', $output['element'] );
}
// If there's a sanitize_callback defined skip this, unless we also have a js_callback defined.
if ( isset( $output['sanitize_callback'] ) && ! empty( $output['sanitize_callback'] ) && ! isset( $output['js_callback'] ) ) {
continue;
}
// If we got this far, it's safe to add this.
$js_vars[] = $output;
}
// Did we manage to get all the items from 'output'?
// If not, then we're missing something so don't add this.
if ( count( $js_vars ) !== count( $this->output ) ) {
return;
}
$this->js_vars = $js_vars;
$this->transport = 'postMessage';
}
}
/**
* Sets the $variables
*
* @access protected
*/
protected function set_variables() {
if ( ! is_array( $this->variables ) ) {
$variable = ( is_string( $this->variables ) && ! empty( $this->variables ) ) ? $this->variables : false;
$this->variables = array();
if ( $variable && empty( $this->variables ) ) {
$this->variables[0]['name'] = $variable;
}
}
}
/**
* Sets the $transport
*
* @access protected
*/
protected function set_transport() {
if ( 'postmessage' === trim( strtolower( $this->transport ) ) ) {
$this->transport = 'postMessage';
}
}
/**
* Sets the $required
*
* @access protected
*/
protected function set_required() {
if ( ! is_array( $this->required ) ) {
$this->required = array();
}
}
/**
* Sets the $priority
*
* @access protected
*/
protected function set_priority() {
$this->priority = absint( $this->priority );
}
/**
* Sets the $css_vars
*
* @access protected
*/
protected function set_css_vars() {
if ( is_string( $this->css_vars ) ) {
$this->css_vars = array( $this->css_vars );
}
if ( isset( $this->css_vars[0] ) && is_string( $this->css_vars[0] ) ) {
$this->css_vars = array( $this->css_vars );
}
foreach ( $this->css_vars as $key => $val ) {
if ( ! isset( $val[1] ) ) {
$this->css_vars[ $key ][1] = '$';
}
}
}
}

View file

@ -0,0 +1,47 @@
<?php
/**
* The main Kirki object
*
* @package Kirki
* @category Core
* @author Themeum
* @copyright Copyright (c) 2023, Themeum
* @license https://opensource.org/licenses/MIT
* @since 1.0
*/
namespace Kirki\Compatibility;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Singleton class
*/
final class Framework {
public $modules;
/**
* Holds the one, true instance of this object.
*
* @static
* @access protected
* @var object
*/
protected static $instance = null;
/**
* Access the single instance of this class.
*
* @static
* @access public
* @return Kirki\Compatibility\Framework
*/
public static function get_instance() {
if ( null === self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
}

View file

@ -0,0 +1,310 @@
<?php
/**
* Initializes Kirki
*
* @package Kirki
* @category Core
* @author Themeum
* @copyright Copyright (c) 2023, Themeum
* @license https://opensource.org/licenses/MIT
* @since 1.0
*/
namespace Kirki\Compatibility;
/**
* Initialize Kirki
*/
class Init {
/**
* Control types.
*
* @access private
* @since 3.0.0
* @var array
*/
private $control_types = [];
/**
* Should we show a nag for the deprecated fontawesome field?
*
* @static
* @access private
* @since 3.0.42
* @var bool
*/
private static $show_fa_nag = false;
/**
* The class constructor.
*/
public function __construct() {
add_action( 'wp_loaded', [ $this, 'add_to_customizer' ], 1 );
add_filter( 'kirki_control_types', [ $this, 'default_control_types' ] );
add_action( 'customize_register', [ $this, 'remove_controls' ], 99999 );
add_action( 'admin_notices', [ $this, 'admin_notices' ] );
add_action( 'admin_init', [ $this, 'dismiss_nag' ] );
// ? Bagus: is this necessary? The Values class doesn't have constructor, so this does nothing.
new Values();
}
/**
* Add the default Kirki control types.
*
* @access public
* @since 3.0.0
* @param array $control_types The control types array.
* @return array
*/
public function default_control_types( $control_types = [] ) {
$this->control_types = [
'kirki-composite' => '\Kirki\Control\Composite',
'checkbox' => '\Kirki\Control\Checkbox',
'kirki-color' => '\Kirki\Control\ReactColorful',
'kirki-color-palette' => '\Kirki\Control\Color_Palette',
'kirki-custom' => '\Kirki\Control\Custom',
'kirki-date' => '\Kirki\Control\Date',
'kirki-dashicons' => '\Kirki\Control\Dashicons',
'kirki-dimension' => '\Kirki\Control\Dimension',
'kirki-dimensions' => '\Kirki\Control\Dimensions',
'kirki-editor' => '\Kirki\Control\Editor',
'kirki-image' => '\Kirki\Control\Image',
'kirki-multicolor' => '\Kirki\Control\Multicolor',
'kirki-multicheck' => '\Kirki\Control\Multicheck',
'kirki-number' => '\Kirki\Control\Number',
'kirki-radio' => '\Kirki\Control\Radio',
'kirki-radio-buttonset' => '\Kirki\Control\Radio_Buttonset',
'kirki-radio-image' => '\Kirki\Control\Radio_Image',
'repeater' => '\Kirki\Control\Repeater',
'kirki-select' => '\Kirki\Control\Select',
'kirki-slider' => '\Kirki\Control\Slider',
'kirki-sortable' => '\Kirki\Control\Sortable',
'kirki-spacing' => '\Kirki\Control\Dimensions',
'kirki-switch' => '\Kirki\Control\Checkbox_Switch',
'kirki-generic' => '\Kirki\Control\Generic',
'kirki-toggle' => '\Kirki\Control\Checkbox_Toggle',
'image' => '\Kirki\Control\Image',
'cropped_image' => '\Kirki\Control\Cropped_Image',
'upload' => '\Kirki\Control\Upload',
];
return array_merge( $this->control_types, $control_types );
}
/**
* Helper function that adds the fields to the customizer.
*/
public function add_to_customizer() {
$this->fields_from_filters();
add_action( 'customize_register', [ $this, 'register_control_types' ] );
add_action( 'customize_register', [ $this, 'add_fields' ], 99 );
}
/**
* Register control types
*/
public function register_control_types() {
global $wp_customize;
$this->control_types = $this->default_control_types();
if ( ! class_exists( 'WP_Customize_Code_Editor_Control' ) ) {
unset( $this->control_types['code_editor'] );
}
foreach ( $this->control_types as $key => $classname ) {
if ( ! class_exists( $classname ) ) {
unset( $this->control_types[ $key ] );
}
}
$skip_control_types = apply_filters(
'kirki_control_types_exclude',
[
'\Kirki\Control\Repeater',
'\WP_Customize_Control',
]
);
foreach ( $this->control_types as $control_type ) {
if ( ! in_array( $control_type, $skip_control_types, true ) && class_exists( $control_type ) ) {
$wp_customize->register_control_type( $control_type );
}
}
}
/**
* Create the settings and controls from the $fields array and register them.
*
* @var object The WordPress Customizer object.
*/
public function add_fields() {
global $wp_customize;
foreach ( Kirki::$fields as $args ) {
// Create the settings.
new \Kirki\Compatibility\Settings( $args );
// Check if we're on the customizer.
// If we are, then we will create the controls, add the scripts needed for the customizer
// and any other tweaks that this field may require.
if ( $wp_customize ) {
// Create the control.
new Control( $args );
}
}
}
/**
* Process fields added using the 'kirki_fields' and 'kirki_controls' filter.
* These filters are no longer used, this is simply for backwards-compatibility.
*
* @access private
* @since 2.0.0
*/
private function fields_from_filters() {
$fields = apply_filters( 'kirki_controls', [] );
$fields = apply_filters( 'kirki_fields', $fields );
if ( ! empty( $fields ) ) {
foreach ( $fields as $field ) {
$field['kirki_config'] = 'global';
Kirki::add_field( 'global', $field );
}
}
}
/**
* Alias for the is_plugin static method in the Kirki\Util\Util class.
* This is here for backwards-compatibility purposes.
*
* @static
* @access public
* @since 3.0.0
* @return bool
*/
public static function is_plugin() {
return Util::is_plugin();
}
/**
* Alias for the get_variables static method in the Kirki\Util\Util class.
* This is here for backwards-compatibility purposes.
*
* @static
* @access public
* @since 2.0.0
* @return array Formatted as array( 'variable-name' => value ).
*/
public static function get_variables() {
// Log error for developers.
_doing_it_wrong( __METHOD__, esc_html__( 'We detected you\'re using Kirki\Compatibility\Init::get_variables(). Please use \Kirki\Util\Util::get_variables() instead.', 'kirki' ), '3.0.10' );
// ! This will be failed, because Util class is under Kirki\Util namespace.
return Util::get_variables();
}
/**
* Remove controls.
*
* @since 3.0.17
* @param object $wp_customize The customizer object.
* @return void
*/
public function remove_controls( $wp_customize ) {
foreach ( Kirki::$controls_to_remove as $control ) {
$wp_customize->remove_control( $control );
}
}
/**
* Shows an admin notice.
*
* @access public
* @since 3.0.42
* @return void
*/
public function admin_notices() {
// No need for a nag if we don't need to recommend installing the FA plugin.
if ( ! self::$show_fa_nag ) {
return;
}
// No need for a nag if FA plugin is already installed.
if ( defined( 'FONTAWESOME_DIR_PATH' ) ) {
return;
}
// No need for a nag if current user can't install plugins.
if ( ! current_user_can( 'install_plugins' ) ) {
return;
}
// No need for a nag if user has dismissed it.
$dismissed = get_user_meta( get_current_user_id(), 'kirki_fa_nag_dismissed', true );
if ( true === $dismissed || 1 === $dismissed || '1' === $dismissed ) {
return;
}
?>
<div class="notice notice-info is-dismissible">
<p>
<?php esc_html_e( 'Your theme uses a Font Awesome field for icons. To avoid issues with missing icons on your frontend we recommend you install the official Font Awesome plugin.', 'kirki' ); ?>
</p>
<p>
<a class="button button-primary" href="<?php echo esc_url( admin_url( 'plugin-install.php?tab=plugin-information&plugin=font-awesome&TB_iframe=true&width=600&height=550' ) ); ?>"><?php esc_html_e( 'Install Plugin', 'kirki' ); ?></a>
<a class="button button-secondary" href="<?php echo esc_url( wp_nonce_url( admin_url( '?dismiss-nag=font-awesome-kirki' ), 'kirki-dismiss-nag', 'nonce' ) ); ?>"><?php esc_html_e( 'Don\'t show this again', 'kirki' ); ?></a>
</p>
</div>
<?php
}
/**
* Dismisses the nag.
*
* @access public
* @since 3.0.42
* @return void
*/
public function dismiss_nag() {
if ( isset( $_GET['nonce'] ) && wp_verify_nonce( $_GET['nonce'], 'kirki-dismiss-nag' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
if ( get_current_user_id() && isset( $_GET['dismiss-nag'] ) && 'font-awesome-kirki' === $_GET['dismiss-nag'] ) {
update_user_meta( get_current_user_id(), 'kirki_fa_nag_dismissed', true );
}
}
}
/**
* Handles showing a nag if the theme is using the deprecated fontawesome field
*
* @static
* @access protected
* @since 3.0.42
* @param array $args The field arguments.
* @return void
*/
protected static function maybe_show_fontawesome_nag( $args ) {
// If we already know we want it, skip check.
if ( self::$show_fa_nag ) {
return;
}
// Check if the field is fontawesome.
if ( isset( $args['type'] ) && in_array( $args['type'], [ 'fontawesome', 'kirki-fontawesome' ], true ) ) {
// Skip check if theme has disabled FA enqueueing via a filter.
if ( ! apply_filters( 'kirki_load_fontawesome', true ) ) {
return;
}
// If we got this far, we need to show the nag.
self::$show_fa_nag = true;
}
}
}

View file

@ -0,0 +1,304 @@
<?php
/**
* The Kirki API class.
* Takes care of adding panels, sections & fields to the customizer.
* For documentation please see https://github.com/aristath/kirki/wiki
*
* @package Kirki
* @category Core
* @author Themeum
* @copyright Copyright (c) 2023, Themeum
* @license https://opensource.org/licenses/MIT
* @since 1.0
*/
namespace Kirki\Compatibility;
// ? Bagus: do we really need these? They are already under the same namespace as Kirki class (this file).
use Kirki\Compatibility\Config;
use Kirki\Compatibility\Field;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* This class acts as an interface.
* Developers may use this object to add configurations, fields, panels and sections.
* You can also access all available configurations, fields, panels and sections
* by accessing the object's static properties.
*/
class Kirki extends Init {
/**
* URL to the Kirki folder.
*
* @deprecated This is no longer used. Only kept here for backwards compatibility to avoid fatal errors.
* @static
* @access public
* @var string
*/
public static $url;
/**
* An array containing all configurations.
*
* @static
* @access public
* @var array
*/
public static $config = [];
/**
* An array containing all fields for compatibility purpose.
*
* @static
* @access public
* @var array
*/
public static $fields = [];
/**
* An array containing all fields.
*
* @static
* @access public
* @var array
*/
public static $all_fields = [];
/**
* An array containing all controls to be removed.
*
* @static
* @access public
* @since 3.0.17
* @var array
*/
public static $controls_to_remove = [];
/**
* Modules object.
*
* @access public
* @since 3.0.0
* @var object
*/
public $modules;
/**
* Get the value of an option from the db.
*
* @static
* @access public
* @param string $config_id The ID of the configuration corresponding to this field.
* @param string $field_id The field_id (defined as 'settings' in the field arguments).
* @return mixed The saved value of the field.
*/
public static function get_option( $config_id = '', $field_id = '' ) {
return Values::get_value( $config_id, $field_id );
}
/**
* Sets the configuration options.
*
* @static
* @access public
* @param string $config_id The configuration ID.
* @param array $args The configuration options.
*/
public static function add_config( $config_id, $args = [] ) {
$config = Config::get_instance( $config_id, $args );
$config_args = $config->get_config();
self::$config[ $config_args['id'] ] = $config_args;
}
/**
* Create a new panel.
*
* @static
* @access public
* @param string $id The ID for this panel.
* @param array $args The panel arguments.
*/
public static function add_panel( $id = '', $args = [] ) {
new \Kirki\Panel( $id, $args );
}
/**
* Remove a panel.
*
* @static
* @access public
* @since 3.0.17
* @param string $id The ID for this panel.
*/
public static function remove_panel( $id = '' ) {
$panel = new \Kirki\Panel( $id );
$panel->remove();
}
/**
* Create a new section.
*
* @static
* @access public
* @param string $id The ID for this section.
* @param array $args The section arguments.
*/
public static function add_section( $id, $args ) {
new \Kirki\Section( $id, $args );
}
/**
* Remove a section.
*
* @static
* @access public
* @since 3.0.17
* @param string $id The ID for this section.
*/
public static function remove_section( $id = '' ) {
$section = new \Kirki\Section( $id );
$section->remove();
}
/**
* Create a new field.
*
* @static
* @access public
* @param string $config_id The configuration ID for this field.
* @param array $args The field arguments.
*/
public static function add_field( $config_id, $args = [] ) {
if ( doing_action( 'customize_register' ) ) {
_doing_it_wrong( __METHOD__, esc_html__( 'Kirki fields should not be added on customize_register. Please add them directly, or on init.', 'kirki' ), '3.0.10' );
}
parent::maybe_show_fontawesome_nag( $args );
// Early exit if 'type' is not defined.
if ( ! isset( $args['type'] ) ) {
return;
}
$args = self::migrate_css_vars( $args );
$str = str_replace( [ '-', '_' ], ' ', $args['type'] );
$classname = '\Kirki\Field\\' . str_replace( ' ', '_', ucwords( $str ) );
$config = Config::get_instance( $config_id )->get_config();
$args['kirki_config'] = isset( $args['kirki_config'] ) ? $args['kirki_config'] : $config_id;
unset( $config['id'] );
$args = wp_parse_args( $args, $config );
if ( class_exists( $classname ) ) {
unset( $args['type'] );
new $classname( $args );
return;
}
new Field( $config_id, $args );
}
/**
* Remove a control.
*
* @static
* @access public
* @since 3.0.17
* @param string $id The field ID.
*/
public static function remove_control( $id ) {
if ( ! in_array( $id, self::$controls_to_remove, true ) ) {
self::$controls_to_remove[] = $id;
}
}
/**
* Gets a parameter for a config-id.
*
* @static
* @access public
* @since 3.0.10
* @param string $id The config-ID.
* @param string $param The parameter we want.
* @return string
*/
public static function get_config_param( $id, $param ) {
if ( ! isset( self::$config[ $id ] ) || ! isset( self::$config[ $id ][ $param ] ) ) {
return '';
}
return self::$config[ $id ][ $param ];
}
/**
* Migrate css-variables to output argument.
*
* This only exists for backwards-compatibility with the deprecated css-vars argument.
*
* @static
* @since 4.0
* @param array $args The field arguments.
* @return array
*/
private static function migrate_css_vars( $args ) {
// Convert css_vars to output args.
if ( isset( $args['css_vars'] ) ) {
if ( isset( $args['transport'] ) && 'postMessage' === $args['transport'] ) {
$args['transport'] = 'auto';
}
// Convert to properly-formatted arrays.
$args['css_vars'] = (array) $args['css_vars'];
if ( isset( $args['css_vars'][0] ) && is_string( $args['css_vars'][0] ) ) {
$args['css_vars'] = [ $args['css_vars'] ];
}
foreach ( $args['css_vars'] as $css_var ) {
$output = [
'element' => ':root',
'property' => $css_var[0],
];
if ( isset( $css_var[1] ) ) {
$output['value_pattern'] = $css_var[1];
}
if ( isset( $css_var[2] ) ) {
$output['choice'] = $css_var[2];
}
$args['output'][] = $output;
}
}
return $args;
}
}

View file

@ -0,0 +1,161 @@
<?php
/**
* Handles modules loading.
*
* @package Kirki
* @category Modules
* @author Themeum
* @copyright Copyright (c) 2023, Themeum
* @license https://opensource.org/licenses/MIT
* @since 3.0.0
*/
namespace Kirki\Compatibility;
/**
* The Modules class.
*/
class Modules {
/**
* An array of available modules.
*
* @static
* @access private
* @since 3.0.0
* @var array
*/
private static $modules = [];
/**
* An array of active modules (objects).
*
* @static
* @access private
* @since 3.0.0
* @var array
*/
private static $active_modules = [];
/**
* Constructor.
*
* @access public
* @since 3.0.0
*/
public function __construct() {
add_action( 'after_setup_theme', [ $this, 'setup_default_modules' ], 10 );
add_action( 'after_setup_theme', [ $this, 'init' ], 11 );
}
/**
* Set the default modules and apply the 'kirki_modules' filter.
* In v3.0.35 this method was renamed from default_modules to setup_default_modules,
* and its visibility changed from private to public to fix https://github.com/aristath/kirki/issues/2023
*
* @access public
* @since 3.0.0
*/
public function setup_default_modules() {
self::$modules = apply_filters(
'kirki_modules',
[
'css' => '\Kirki\Module\CSS',
'tooltips' => '\Kirki\Module\Tooltips',
'postMessage' => '\Kirki\Module\Postmessage',
'selective-refresh' => '\Kirki\Module\Selective_Refresh',
'field-dependencies' => '\Kirki\Module\Field_Dependencies',
'webfonts' => '\Kirki\Module\Webfonts',
'preset' => '\Kirki\Module\Preset',
'gutenberg' => '\Kirki\Module\Editor_Styles',
'section-icons' => '\Kirki\Module\Section_Icons',
]
);
}
/**
* Instantiates the modules.
* In v3.0.35 the visibility for this method was changed
* from private to public to fix https://github.com/aristath/kirki/issues/2023
*
* @access public
* @since 3.0.0
*/
public function init() {
foreach ( self::$modules as $module_class ) {
if ( class_exists( $module_class ) ) {
new $module_class();
}
}
}
/**
* Add a module.
*
* @static
* @access public
* @param string $module The classname of the module to add.
* @since 3.0.0
*/
public static function add_module( $module ) {
if ( ! in_array( $module, self::$modules, true ) ) {
self::$modules[] = $module;
}
}
/**
* Remove a module.
*
* @static
* @access public
* @param string $module The classname of the module to add.
* @since 3.0.0
*/
public static function remove_module( $module ) {
$key = array_search( $module, self::$modules, true );
if ( false !== $key ) {
unset( self::$modules[ $key ] );
}
}
/**
* Get the modules array.
*
* @static
* @access public
* @since 3.0.0
* @return array
*/
public static function get_modules() {
return self::$modules;
}
/**
* Get the array of active modules (objects).
*
* @static
* @access public
* @since 3.0.0
* @return array
*/
public static function get_active_modules() {
return self::$active_modules;
}
}

View file

@ -0,0 +1,209 @@
<?php
/**
* Additional sanitization methods for controls.
* These are used in the field's 'sanitize_callback' argument.
*
* @package Kirki
* @category Core
* @author Themeum
* @copyright Copyright (c) 2023, Themeum
* @license https://opensource.org/licenses/MIT
* @since 1.0
*/
namespace Kirki\Compatibility;
use Kirki\Field\Checkbox;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* A simple wrapper class for static methods.
*/
class Sanitize_Values {
/**
* Checkbox sanitization callback.
*
* Sanitization callback for 'checkbox' type controls.
* This callback sanitizes `$value` as a boolean value, either TRUE or FALSE.
*
* Deprecated. Use \Kirki\Field\Checkbox::sanitize() instead.
*
* @static
* @access public
* @see \Kirki\Field\Checkbox::sanitize()
* @param bool|string $value Whether the checkbox is checked.
* @return bool Whether the checkbox is checked.
*/
public static function checkbox( $value ) {
$obj = new Checkbox();
// ! This sanitize function doesn't exist. A method exists check should be used before actually calling it.
return (bool) $obj->sanitize( $value );
}
/**
* Sanitize number options.
*
* @static
* @access public
* @since 0.5
* @param int|float|double|string $value The value to be sanitized.
* @return integer|double|string
*/
public static function number( $value ) {
return ( is_numeric( $value ) ) ? $value : intval( $value );
}
/**
* Drop-down Pages sanitization callback.
*
* - Sanitization: dropdown-pages
* - Control: dropdown-pages
*
* Sanitization callback for 'dropdown-pages' type controls. This callback sanitizes `$page_id`
* as an absolute integer, and then validates that $input is the ID of a published page.
*
* @see absint() https://developer.wordpress.org/reference/functions/absint/
* @see get_post_status() https://developer.wordpress.org/reference/functions/get_post_status/
*
* @param int $page_id Page ID.
* @param WP_Customize_Setting $setting Setting instance.
* @return int|string Page ID if the page is published; otherwise, the setting default.
*/
public static function dropdown_pages( $page_id, $setting ) {
// Ensure $input is an absolute integer.
$page_id = absint( $page_id );
// If $page_id is an ID of a published page, return it; otherwise, return the default.
return ( 'publish' === get_post_status( $page_id ) ? $page_id : $setting->default );
}
/**
* Sanitizes css dimensions.
*
* @static
* @access public
* @since 2.2.0
* @param string $value The value to be sanitized.
* @return string
*/
public static function css_dimension( $value ) {
// Trim it.
$value = trim( $value );
// If the value is round, then return 50%.
if ( 'round' === $value ) {
$value = '50%';
}
// If the value is empty, return empty.
if ( '' === $value ) {
return '';
}
// If auto, inherit or initial, return the value.
if ( 'auto' === $value || 'initial' === $value || 'inherit' === $value || 'normal' === $value ) {
return $value;
}
// Return empty if there are no numbers in the value.
if ( ! preg_match( '#[0-9]#', $value ) ) {
return '';
}
// If we're using calc() then return the value.
if ( false !== strpos( $value, 'calc(' ) ) {
return $value;
}
// The raw value without the units.
$raw_value = self::filter_number( $value );
$unit_used = '';
// An array of all valid CSS units. Their order was carefully chosen for this evaluation, don't mix it up!!!
$units = [ 'fr', 'rem', 'em', 'ex', '%', 'px', 'cm', 'mm', 'in', 'pt', 'pc', 'ch', 'vh', 'vw', 'vmin', 'vmax' ];
foreach ( $units as $unit ) {
if ( false !== strpos( $value, $unit ) ) {
$unit_used = $unit;
}
}
// Hack for rem values.
if ( 'em' === $unit_used && false !== strpos( $value, 'rem' ) ) {
$unit_used = 'rem';
}
return $raw_value . $unit_used;
}
/**
* Filters numeric values.
*
* @static
* @access public
* @param string $value The value to be sanitized.
* @return int|float
*/
public static function filter_number( $value ) {
return filter_var( $value, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION );
}
/**
* Sanitize RGBA colors
*
* @static
* @since 0.8.5
* @param string $value The value to be sanitized.
* @return string
*/
public static function rgba( $value ) {
$color = \ariColor::newColor( $value );
return $color->toCSS( 'rgba' );
}
/**
* Sanitize colors.
*
* @static
* @since 0.8.5
* @param string $value The value to be sanitized.
* @return string
*/
public static function color( $value ) {
// If the value is empty, then return empty.
if ( '' === $value ) {
return '';
}
// If transparent, then return 'transparent'.
if ( is_string( $value ) && 'transparent' === trim( $value ) ) {
return 'transparent';
}
// Instantiate the object.
$color = \ariColor::newColor( $value );
// Return a CSS value, using the auto-detected mode.
return $color->toCSS( $color->mode );
}
/**
* DOES NOT SANITIZE ANYTHING.
*
* @static
* @since 0.5
* @param int|string|array $value The value to be sanitized.
* @return int|string|array
*/
public static function unfiltered( $value ) {
return $value;
}
}

View file

@ -0,0 +1,58 @@
<?php
/**
* Registers scripts for WordPress Compatibility with versions prior to WP5.0
*
* @package Kirki
* @category Core
* @author Themeum
* @copyright Copyright (c) 2023, Themeum
* @license https://opensource.org/licenses/MIT
* @since 0.1
*/
namespace Kirki\Compatibility;
use Kirki\URL;
/**
* Adds scripts for backwards-compatibility
*
* @since 0.1
*/
class Scripts {
/**
* Constructor.
*
* @access public
* @since 0.1
*/
public function __construct() {
global $wp_version;
/**
* Check if the WordPress version is lower than 5.0
* If lower then we need to enqueue the backported scripts.
*/
if ( version_compare( $GLOBALS['wp_version'], '5.0', '<' ) ) {
add_action( 'wp_enqueue_scripts', [ $this, 'register_scripts' ] );
add_action( 'admin_register_scripts', [ $this, 'register_scripts' ] );
add_action( 'customize_controls_enqueue_scripts', [ $this, 'register_scripts' ] );
}
}
/**
* Enqueue missing WP scripts.
*
* @access public
* @since 0.1
* @return void
*/
public function register_scripts() {
$folder_url = trailingslashit( URL::get_from_path( __DIR__ ) );
wp_register_script( 'wp-polyfill', $folder_url . 'scripts/wp-polyfill.js', [], '7.0.0', false );
wp_register_script( 'wp-hooks', $folder_url . 'scripts/hooks.js', [ 'wp-polyfill' ], '2.2.0', false );
wp_register_script( 'wp-i18n', $folder_url . 'scripts/i18n.js', [ 'wp-polyfill' ], '3.3.0', false );
}
}

View file

@ -0,0 +1,157 @@
<?php
/**
* Handles sections created via the Kirki API.
*
* @package Kirki
* @category Core
* @author Themeum
* @copyright Copyright (c) 2023, Themeum
* @license https://opensource.org/licenses/MIT
* @since 1.0
*/
namespace Kirki\Compatibility;
/**
* Each setting is a separate instance
*/
class Settings {
/**
* The global $wp_customize object.
*
* @access protected
* @var WP_Customize_Manager
*/
protected $wp_customize;
/**
* The setting-stypes we're using.
*
* @access protected
* @var array
*/
protected $setting_types = [];
/**
* Creates a new Settings object.
* Class constructor.
*
* @access public
* @param array $args The field definition as sanitized in Kirki\Compatibility\Field.
*/
public function __construct( $args = [] ) {
// Set the $wp_customize property.
global $wp_customize;
if ( ! $wp_customize ) {
return;
}
$this->wp_customize = $wp_customize;
// Set the setting_types.
$this->set_setting_types();
// Add the settings.
$this->add_settings( $args );
}
/**
* Adds the settings for this field.
* If settings are defined as an array, then it goes through them
* and calls the add_setting method.
* If not an array, then it just calls add_setting
*
* @access private
* @param array $args The field definition as sanitized in Kirki\Compatibility\Field.
*/
final function add_settings( $args = [] ) {
// Get the classname we'll be using to create our setting(s).
$classname = false;
if ( isset( $args['option_type'] ) && array_key_exists( $args['option_type'], $this->setting_types ) ) {
$classname = $this->setting_types[ $args['option_type'] ];
}
if ( ! isset( $args['type'] ) || ! array_key_exists( $args['type'], $this->setting_types ) ) {
$args['type'] = 'default';
}
$classname = ! $classname ? $this->setting_types[ $args['type'] ] : $classname;
// If settings are defined as an array, then we need to go through them
// and call add_setting for each one of them separately.
if ( isset( $args['settings'] ) && is_array( $args['settings'] ) ) {
// Make sure defaults have been defined.
if ( ! isset( $args['default'] ) || ! is_array( $args['default'] ) ) {
$args['default'] = [];
}
foreach ( $args['settings'] as $key => $value ) {
// ? Bagus: this $defaults var is not defined anywhere inside this function, so is this a mistake?
$default = ( isset( $defaults[ $key ] ) ) ? $defaults[ $key ] : '';
$this->add_setting( $classname, $value, $default, $args['option_type'], $args['capability'], $args['transport'], $args['sanitize_callback'] );
}
}
$this->add_setting( $classname, $args['settings'], $args['default'], $args['option_type'], $args['capability'], $args['transport'], $args['sanitize_callback'] );
}
/**
* This is where we're finally adding the setting to the Customizer.
*
* @access private
* @param string $classname The name of the class that will be used to create this setting.
* We're getting this from $this->setting_types.
* @param string $setting The setting-name.
* If settings is an array, then this method is called per-setting.
* @param string|array $default Default value for this setting.
* @param string $type The data type we're using. Valid options: theme_mod|option.
* @param string $capability @see https://codex.wordpress.org/Roles_and_Capabilities.
* @param string $transport Use refresh|postMessage.
* @param string|array $sanitize_callback A callable sanitization function or method.
*/
final function add_setting( $classname, $setting, $default, $type, $capability, $transport, $sanitize_callback ) {
$this->wp_customize->add_setting(
new $classname(
$this->wp_customize,
$setting,
[
'default' => $default,
'type' => $type,
'capability' => $capability,
'transport' => $transport,
'sanitize_callback' => $sanitize_callback,
]
)
);
}
/**
* Sets the $this->setting_types property.
* Makes sure the kirki_setting_types filter is applied
* and that the defined classes actually exist.
* If a defined class does not exist, it is removed.
*/
final function set_setting_types() {
// Apply the kirki_setting_types filter.
$this->setting_types = apply_filters(
'kirki_setting_types',
[
'default' => 'WP_Customize_Setting',
'repeater' => '\Kirki_Settings_Repeater_Setting',
'user_meta' => '\Kirki\Util\Setting\User_Meta',
'site_option' => '\Kirki\Util\Setting\Site_Option',
]
);
// Make sure the defined classes actually exist.
foreach ( $this->setting_types as $key => $classname ) {
if ( ! class_exists( $classname ) ) {
unset( $this->setting_types[ $key ] );
}
}
}
}

View file

@ -0,0 +1,124 @@
<?php
/**
* Helpers to get the values of a field.
*
* ! WARNING: PLEASE DO NOT USE THESE.
* we only have these for backwards-compatibility purposes.
* please use get_option() & get_theme_mod() instead.
*
* @package Kirki
* @category Core
* @author Themeum
* @copyright Copyright (c) 2023, Themeum
* @license https://opensource.org/licenses/MIT
* @since 1.0
*/
namespace Kirki\Compatibility;
/**
* Wrapper class for static methods.
*/
class Values {
/**
* Get the value of a field.
*
* @static
* @access public
* @param string $config_id The configuration ID. @see Kirki\Compatibility\Config.
* @param string $field_id The field ID.
* @return string|array
*/
public static function get_value( $config_id = '', $field_id = '' ) {
// Make sure value is defined.
$value = '';
// This allows us to skip the $config_id argument.
// If we skip adding a $config_id, use the 'global' configuration.
if ( ( '' === $field_id ) && '' !== $config_id ) {
$field_id = $config_id;
$config_id = 'global';
}
// If $config_id is empty, set it to 'global'.
$config_id = ( '' === $config_id ) ? 'global' : $config_id;
// Fallback to 'global' if $config_id is not found.
if ( ! isset( Kirki::$config[ $config_id ] ) ) {
$config_id = 'global';
}
if ( 'theme_mod' === Kirki::$config[ $config_id ]['option_type'] ) {
// We're using theme_mods so just get the value using get_theme_mod.
$default_value = null;
if ( isset( Kirki::$all_fields[ $field_id ] ) && isset( Kirki::$all_fields[ $field_id ]['default'] ) ) {
$default_value = Kirki::$all_fields[ $field_id ]['default'];
}
$value = get_theme_mod( $field_id, $default_value );
return apply_filters( 'kirki_values_get_value', $value, $field_id );
}
if ( 'option' === Kirki::$config[ $config_id ]['option_type'] ) {
// We're using options.
if ( '' !== Kirki::$config[ $config_id ]['option_name'] ) {
// Options are serialized as a single option in the db.
// We'll have to get the option and then get the item from the array.
$options = get_option( Kirki::$config[ $config_id ]['option_name'] );
if ( ! isset( Kirki::$all_fields[ $field_id ] ) && isset( Kirki::$all_fields[ Kirki::$config[ $config_id ]['option_name'] . '[' . $field_id . ']' ] ) ) {
$field_id = Kirki::$config[ $config_id ]['option_name'] . '[' . $field_id . ']';
}
$setting_modified = str_replace( ']', '', str_replace( Kirki::$config[ $config_id ]['option_name'] . '[', '', $field_id ) );
$default_value = ( isset( Kirki::$all_fields[ $field_id ] ) && isset( Kirki::$all_fields[ $field_id ]['default'] ) ) ? Kirki::$all_fields[ $field_id ]['default'] : '';
$value = ( isset( $options[ $setting_modified ] ) ) ? $options[ $setting_modified ] : $default_value;
$value = maybe_unserialize( $value );
return apply_filters( 'kirki_values_get_value', $value, $field_id );
}
// Each option separately saved in the db.
$value = get_option( $field_id, Kirki::$all_fields[ $field_id ]['default'] );
return apply_filters( 'kirki_values_get_value', $value, $field_id );
}
return apply_filters( 'kirki_values_get_value', $value, $field_id );
}
/**
* Gets the value or fallsback to default.
*
* @static
* @access public
* @param array $field The field aruments.
* @return string|array
*/
public static function get_sanitized_field_value( $field ) {
$value = $field['default'];
if ( ! isset( $field['option_type'] ) || 'theme_mod' === $field['option_type'] ) {
$value = get_theme_mod( $field['settings'], $field['default'] );
} elseif ( isset( $field['option_type'] ) && 'option' === $field['option_type'] ) {
if ( isset( $field['option_name'] ) && '' !== $field['option_name'] ) {
$all_values = get_option( $field['option_name'], [] );
$sub_setting_id = str_replace( [ ']', $field['option_name'] . '[' ], '', $field['settings'] );
if ( isset( $all_values[ $sub_setting_id ] ) ) {
$value = $all_values[ $sub_setting_id ];
}
} else {
$value = get_option( $field['settings'], $field['default'] );
}
}
return $value;
}
}

View file

@ -0,0 +1,35 @@
<?php
// phpcs:ignoreFile
if ( ! class_exists( 'Kirki_Active_Callback' ) ) {
// Removed in https://github.com/aristath/kirki/pull/1682/files
class Kirki_Active_Callback {
public static function evaluate() {
_deprecated_function( __METHOD__, '3.0.17', null );
return true;
}
private static function evaluate_requirement() {
_deprecated_function( __METHOD__, '3.0.17', null );
return true;
}
public static function compare( $value1, $value2, $operator ) {
_deprecated_function( __METHOD__, '3.0.17', 'Kirki_Helper::compare_values' );
return Kirki_Helper::compare_values( $value1, $value2, $operator );
}
}
}
/**
* Deprecated in v3.0.36
*
* Keeping it here in case a theme or plugin was using one of its public methods.
* This is just to avoid fatal errors, it does not do anything.
*/
if ( ! class_exists( 'Kirki_CSS_To_File' ) ) {
class Kirki_CSS_To_File {
public function __construct() {}
public function get_url() {}
public function get_timestamp() {}
public function write_file() {}
}
}

View file

@ -0,0 +1,112 @@
<?php
// phpcs:ignoreFile
add_filter( 'kirki_config', function( $args ) {
return apply_filters( 'kirki/config', $args );
}, 99 );
add_filter( 'kirki_control_types', function( $args ) {
return apply_filters( 'kirki/control_types', $args );
}, 99 );
add_filter( 'kirki_section_types', function( $args ) {
return apply_filters( 'kirki/section_types', $args );
}, 99 );
add_filter( 'kirki_section_types_exclude', function( $args ) {
return apply_filters( 'kirki/section_types/exclude', $args );
}, 99 );
add_filter( 'kirki_control_types_exclude', function( $args ) {
return apply_filters( 'kirki/control_types/exclude', $args );
}, 99 );
add_filter( 'kirki_controls', function( $args ) {
return apply_filters( 'kirki/controls', $args );
}, 99 );
add_filter( 'kirki_fields', function( $args ) {
return apply_filters( 'kirki/fields', $args );
}, 99 );
add_filter( 'kirki_modules', function( $args ) {
return apply_filters( 'kirki/modules', $args );
}, 99 );
add_filter( 'kirki_panel_types', function( $args ) {
return apply_filters( 'kirki/panel_types', $args );
}, 99 );
add_filter( 'kirki_setting_types', function( $args ) {
return apply_filters( 'kirki/setting_types', $args );
}, 99 );
add_filter( 'kirki_variable', function( $args ) {
return apply_filters( 'kirki/variable', $args );
}, 99 );
add_filter( 'kirki_values_get_value', function( $arg1, $arg2 ) {
return apply_filters( 'kirki/values/get_value', $arg1, $arg2 );
}, 99, 2 );
add_action( 'init', function() {
$config_ids = \Kirki\Compatibility\Config::get_config_ids();
global $kirki_deprecated_filters_iteration;
foreach ( $config_ids as $config_id ) {
foreach( array(
'/dynamic_css',
'/output/control-classnames',
'/css/skip_hidden',
'/styles',
'/output/property-classnames',
'/webfonts/skip_hidden',
) as $filter_suffix ) {
$kirki_deprecated_filters_iteration = array( $config_id, $filter_suffix );
add_filter( "kirki_{$config_id}_{$filter_suffix}", function( $args ) {
global $kirki_deprecated_filters_iteration;
$kirki_deprecated_filters_iteration[1] = str_replace( '-', '_', $kirki_deprecated_filters_iteration[1] );
return apply_filters( "kirki/{$kirki_deprecated_filters_iteration[0]}/{$kirki_deprecated_filters_iteration[1]}", $args );
}, 99 );
if ( false !== strpos( $kirki_deprecated_filters_iteration[1], '-' ) ) {
$kirki_deprecated_filters_iteration[1] = str_replace( '-', '_', $kirki_deprecated_filters_iteration[1] );
add_filter( "kirki_{$config_id}_{$filter_suffix}", function( $args ) {
global $kirki_deprecated_filters_iteration;
$kirki_deprecated_filters_iteration[1] = str_replace( '-', '_', $kirki_deprecated_filters_iteration[1] );
return apply_filters( "kirki/{$kirki_deprecated_filters_iteration[0]}/{$kirki_deprecated_filters_iteration[1]}", $args );
}, 99 );
}
}
}
}, 99 );
add_filter( 'kirki_enqueue_google_fonts', function( $args ) {
return apply_filters( 'kirki/enqueue_google_fonts', $args );
}, 99 );
add_filter( 'kirki_styles_array', function( $args ) {
return apply_filters( 'kirki/styles_array', $args );
}, 99 );
add_filter( 'kirki_dynamic_css_method', function( $args ) {
return apply_filters( 'kirki/dynamic_css/method', $args );
}, 99 );
add_filter( 'kirki_postmessage_script', function( $args ) {
return apply_filters( 'kirki/postmessage/script', $args );
}, 99 );
add_filter( 'kirki_fonts_all', function( $args ) {
return apply_filters( 'kirki/fonts/all', $args );
}, 99 );
add_filter( 'kirki_fonts_standard_fonts', function( $args ) {
return apply_filters( 'kirki/fonts/standard_fonts', $args );
}, 99 );
add_filter( 'kirki_fonts_google_fonts', function( $args ) {
return apply_filters( 'kirki/fonts/google_fonts', $args );
}, 99 );
add_filter( 'kirki_googlefonts_load_method', function( $args ) {
return apply_filters( 'kirki/googlefonts_load_method', $args );
}, 99 );

View file

@ -0,0 +1,57 @@
<?php
// phpcs:ignoreFile
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! function_exists( 'kirki_get_option' ) ) {
/**
* Get the value of a field.
* This is a deprecated function that we used when there was no API.
* Please use get_theme_mod() or get_option() instead.
* @see https://developer.wordpress.org/reference/functions/get_theme_mod/
* @see https://developer.wordpress.org/reference/functions/get_option/
*
* @return mixed
*/
function kirki_get_option( $option = '' ) {
_deprecated_function( __FUNCTION__, '1.0.0', sprintf( esc_html__( '%1$s or %2$s', 'kirki' ), 'get_theme_mod', 'get_option' ) );
return Kirki::get_option( '', $option );
}
}
if ( ! function_exists( 'kirki_sanitize_hex' ) ) {
function kirki_sanitize_hex( $color ) {
_deprecated_function( __FUNCTION__, '1.0.0', 'ariColor::newColor( $color )->toCSS( \'hex\' )' );
return Kirki_Color::sanitize_hex( $color );
}
}
if ( ! function_exists( 'kirki_get_rgb' ) ) {
function kirki_get_rgb( $hex, $implode = false ) {
_deprecated_function( __FUNCTION__, '1.0.0', 'ariColor::newColor( $color )->toCSS( \'rgb\' )' );
return Kirki_Color::get_rgb( $hex, $implode );
}
}
if ( ! function_exists( 'kirki_get_rgba' ) ) {
function kirki_get_rgba( $hex = '#fff', $opacity = 100 ) {
_deprecated_function( __FUNCTION__, '1.0.0', 'ariColor::newColor( $color )->toCSS( \'rgba\' )' );
return Kirki_Color::get_rgba( $hex, $opacity );
}
}
if ( ! function_exists( 'kirki_get_brightness' ) ) {
function kirki_get_brightness( $hex ) {
_deprecated_function( __FUNCTION__, '1.0.0', 'ariColor::newColor( $color )->lightness' );
return Kirki_Color::get_brightness( $hex );
}
}
if ( ! function_exists( 'Kirki' ) ) {
function Kirki() {
return \Kirki\Compatibility\Framework::get_instance();
}
}

View file

@ -0,0 +1,623 @@
this["wp"] = this["wp"] || {}; this["wp"]["hooks"] =
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ }
/******/ };
/******/
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/
/******/ // create a fake namespace object
/******/ // mode & 1: value is a module id, require it
/******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like require
/******/ __webpack_require__.t = function(value, mode) {
/******/ if(mode & 1) value = __webpack_require__(value);
/******/ if(mode & 8) return value;
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ var ns = Object.create(null);
/******/ __webpack_require__.r(ns);
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/ return ns;
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 366);
/******/ })
/************************************************************************/
/******/ ({
/***/ 366:
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
// CONCATENATED MODULE: ./node_modules/@wordpress/hooks/build-module/validateNamespace.js
/**
* Validate a namespace string.
*
* @param {string} namespace The namespace to validate - should take the form
* `vendor/plugin/function`.
*
* @return {boolean} Whether the namespace is valid.
*/
function validateNamespace(namespace) {
if ('string' !== typeof namespace || '' === namespace) {
// eslint-disable-next-line no-console
console.error('The namespace must be a non-empty string.');
return false;
}
if (!/^[a-zA-Z][a-zA-Z0-9_.\-\/]*$/.test(namespace)) {
// eslint-disable-next-line no-console
console.error('The namespace can only contain numbers, letters, dashes, periods, underscores and slashes.');
return false;
}
return true;
}
/* harmony default export */ var build_module_validateNamespace = (validateNamespace);
// CONCATENATED MODULE: ./node_modules/@wordpress/hooks/build-module/validateHookName.js
/**
* Validate a hookName string.
*
* @param {string} hookName The hook name to validate. Should be a non empty string containing
* only numbers, letters, dashes, periods and underscores. Also,
* the hook name cannot begin with `__`.
*
* @return {boolean} Whether the hook name is valid.
*/
function validateHookName(hookName) {
if ('string' !== typeof hookName || '' === hookName) {
// eslint-disable-next-line no-console
console.error('The hook name must be a non-empty string.');
return false;
}
if (/^__/.test(hookName)) {
// eslint-disable-next-line no-console
console.error('The hook name cannot begin with `__`.');
return false;
}
if (!/^[a-zA-Z][a-zA-Z0-9_.-]*$/.test(hookName)) {
// eslint-disable-next-line no-console
console.error('The hook name can only contain numbers, letters, dashes, periods and underscores.');
return false;
}
return true;
}
/* harmony default export */ var build_module_validateHookName = (validateHookName);
// CONCATENATED MODULE: ./node_modules/@wordpress/hooks/build-module/createAddHook.js
/**
* Internal dependencies
*/
/**
* Returns a function which, when invoked, will add a hook.
*
* @param {Object} hooks Stored hooks, keyed by hook name.
*
* @return {Function} Function that adds a new hook.
*/
function createAddHook(hooks) {
/**
* Adds the hook to the appropriate hooks container.
*
* @param {string} hookName Name of hook to add
* @param {string} namespace The unique namespace identifying the callback in the form `vendor/plugin/function`.
* @param {Function} callback Function to call when the hook is run
* @param {?number} priority Priority of this hook (default=10)
*/
return function addHook(hookName, namespace, callback) {
var priority = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 10;
if (!build_module_validateHookName(hookName)) {
return;
}
if (!build_module_validateNamespace(namespace)) {
return;
}
if ('function' !== typeof callback) {
// eslint-disable-next-line no-console
console.error('The hook callback must be a function.');
return;
} // Validate numeric priority
if ('number' !== typeof priority) {
// eslint-disable-next-line no-console
console.error('If specified, the hook priority must be a number.');
return;
}
var handler = {
callback: callback,
priority: priority,
namespace: namespace
};
if (hooks[hookName]) {
// Find the correct insert index of the new hook.
var handlers = hooks[hookName].handlers;
var i;
for (i = handlers.length; i > 0; i--) {
if (priority >= handlers[i - 1].priority) {
break;
}
}
if (i === handlers.length) {
// If append, operate via direct assignment.
handlers[i] = handler;
} else {
// Otherwise, insert before index via splice.
handlers.splice(i, 0, handler);
} // We may also be currently executing this hook. If the callback
// we're adding would come after the current callback, there's no
// problem; otherwise we need to increase the execution index of
// any other runs by 1 to account for the added element.
(hooks.__current || []).forEach(function (hookInfo) {
if (hookInfo.name === hookName && hookInfo.currentIndex >= i) {
hookInfo.currentIndex++;
}
});
} else {
// This is the first hook of its type.
hooks[hookName] = {
handlers: [handler],
runs: 0
};
}
if (hookName !== 'hookAdded') {
doAction('hookAdded', hookName, namespace, callback, priority);
}
};
}
/* harmony default export */ var build_module_createAddHook = (createAddHook);
// CONCATENATED MODULE: ./node_modules/@wordpress/hooks/build-module/createRemoveHook.js
/**
* Internal dependencies
*/
/**
* Returns a function which, when invoked, will remove a specified hook or all
* hooks by the given name.
*
* @param {Object} hooks Stored hooks, keyed by hook name.
* @param {boolean} removeAll Whether to remove all callbacks for a hookName, without regard to namespace. Used to create `removeAll*` functions.
*
* @return {Function} Function that removes hooks.
*/
function createRemoveHook(hooks, removeAll) {
/**
* Removes the specified callback (or all callbacks) from the hook with a
* given hookName and namespace.
*
* @param {string} hookName The name of the hook to modify.
* @param {string} namespace The unique namespace identifying the callback in the form `vendor/plugin/function`.
*
* @return {number} The number of callbacks removed.
*/
return function removeHook(hookName, namespace) {
if (!build_module_validateHookName(hookName)) {
return;
}
if (!removeAll && !build_module_validateNamespace(namespace)) {
return;
} // Bail if no hooks exist by this name
if (!hooks[hookName]) {
return 0;
}
var handlersRemoved = 0;
if (removeAll) {
handlersRemoved = hooks[hookName].handlers.length;
hooks[hookName] = {
runs: hooks[hookName].runs,
handlers: []
};
} else {
// Try to find the specified callback to remove.
var handlers = hooks[hookName].handlers;
var _loop = function _loop(i) {
if (handlers[i].namespace === namespace) {
handlers.splice(i, 1);
handlersRemoved++; // This callback may also be part of a hook that is
// currently executing. If the callback we're removing
// comes after the current callback, there's no problem;
// otherwise we need to decrease the execution index of any
// other runs by 1 to account for the removed element.
(hooks.__current || []).forEach(function (hookInfo) {
if (hookInfo.name === hookName && hookInfo.currentIndex >= i) {
hookInfo.currentIndex--;
}
});
}
};
for (var i = handlers.length - 1; i >= 0; i--) {
_loop(i);
}
}
if (hookName !== 'hookRemoved') {
doAction('hookRemoved', hookName, namespace);
}
return handlersRemoved;
};
}
/* harmony default export */ var build_module_createRemoveHook = (createRemoveHook);
// CONCATENATED MODULE: ./node_modules/@wordpress/hooks/build-module/createHasHook.js
/**
* Returns a function which, when invoked, will return whether any handlers are
* attached to a particular hook.
*
* @param {Object} hooks Stored hooks, keyed by hook name.
*
* @return {Function} Function that returns whether any handlers are
* attached to a particular hook.
*/
function createHasHook(hooks) {
/**
* Returns how many handlers are attached for the given hook.
*
* @param {string} hookName The name of the hook to check for.
*
* @return {boolean} Whether there are handlers that are attached to the given hook.
*/
return function hasHook(hookName) {
return hookName in hooks;
};
}
/* harmony default export */ var build_module_createHasHook = (createHasHook);
// CONCATENATED MODULE: ./node_modules/@wordpress/hooks/build-module/createRunHook.js
/**
* Returns a function which, when invoked, will execute all callbacks
* registered to a hook of the specified type, optionally returning the final
* value of the call chain.
*
* @param {Object} hooks Stored hooks, keyed by hook name.
* @param {?boolean} returnFirstArg Whether each hook callback is expected to
* return its first argument.
*
* @return {Function} Function that runs hook callbacks.
*/
function createRunHook(hooks, returnFirstArg) {
/**
* Runs all callbacks for the specified hook.
*
* @param {string} hookName The name of the hook to run.
* @param {...*} args Arguments to pass to the hook callbacks.
*
* @return {*} Return value of runner, if applicable.
*/
return function runHooks(hookName) {
if (!hooks[hookName]) {
hooks[hookName] = {
handlers: [],
runs: 0
};
}
hooks[hookName].runs++;
var handlers = hooks[hookName].handlers;
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = arguments[_key];
}
if (!handlers || !handlers.length) {
return returnFirstArg ? args[0] : undefined;
}
var hookInfo = {
name: hookName,
currentIndex: 0
};
hooks.__current.push(hookInfo);
while (hookInfo.currentIndex < handlers.length) {
var handler = handlers[hookInfo.currentIndex];
var result = handler.callback.apply(null, args);
if (returnFirstArg) {
args[0] = result;
}
hookInfo.currentIndex++;
}
hooks.__current.pop();
if (returnFirstArg) {
return args[0];
}
};
}
/* harmony default export */ var build_module_createRunHook = (createRunHook);
// CONCATENATED MODULE: ./node_modules/@wordpress/hooks/build-module/createCurrentHook.js
/**
* Returns a function which, when invoked, will return the name of the
* currently running hook, or `null` if no hook of the given type is currently
* running.
*
* @param {Object} hooks Stored hooks, keyed by hook name.
*
* @return {Function} Function that returns the current hook.
*/
function createCurrentHook(hooks) {
/**
* Returns the name of the currently running hook, or `null` if no hook of
* the given type is currently running.
*
* @return {?string} The name of the currently running hook, or
* `null` if no hook is currently running.
*/
return function currentHook() {
if (!hooks.__current || !hooks.__current.length) {
return null;
}
return hooks.__current[hooks.__current.length - 1].name;
};
}
/* harmony default export */ var build_module_createCurrentHook = (createCurrentHook);
// CONCATENATED MODULE: ./node_modules/@wordpress/hooks/build-module/createDoingHook.js
/**
* Returns a function which, when invoked, will return whether a hook is
* currently being executed.
*
* @param {Object} hooks Stored hooks, keyed by hook name.
*
* @return {Function} Function that returns whether a hook is currently
* being executed.
*/
function createDoingHook(hooks) {
/**
* Returns whether a hook is currently being executed.
*
* @param {?string} hookName The name of the hook to check for. If
* omitted, will check for any hook being executed.
*
* @return {boolean} Whether the hook is being executed.
*/
return function doingHook(hookName) {
// If the hookName was not passed, check for any current hook.
if ('undefined' === typeof hookName) {
return 'undefined' !== typeof hooks.__current[0];
} // Return the __current hook.
return hooks.__current[0] ? hookName === hooks.__current[0].name : false;
};
}
/* harmony default export */ var build_module_createDoingHook = (createDoingHook);
// CONCATENATED MODULE: ./node_modules/@wordpress/hooks/build-module/createDidHook.js
/**
* Internal dependencies
*/
/**
* Returns a function which, when invoked, will return the number of times a
* hook has been called.
*
* @param {Object} hooks Stored hooks, keyed by hook name.
*
* @return {Function} Function that returns a hook's call count.
*/
function createDidHook(hooks) {
/**
* Returns the number of times an action has been fired.
*
* @param {string} hookName The hook name to check.
*
* @return {number} The number of times the hook has run.
*/
return function didHook(hookName) {
if (!build_module_validateHookName(hookName)) {
return;
}
return hooks[hookName] && hooks[hookName].runs ? hooks[hookName].runs : 0;
};
}
/* harmony default export */ var build_module_createDidHook = (createDidHook);
// CONCATENATED MODULE: ./node_modules/@wordpress/hooks/build-module/createHooks.js
/**
* Internal dependencies
*/
/**
* Returns an instance of the hooks object.
*
* @return {Object} Object that contains all hooks.
*/
function createHooks() {
var actions = Object.create(null);
var filters = Object.create(null);
actions.__current = [];
filters.__current = [];
return {
addAction: build_module_createAddHook(actions),
addFilter: build_module_createAddHook(filters),
removeAction: build_module_createRemoveHook(actions),
removeFilter: build_module_createRemoveHook(filters),
hasAction: build_module_createHasHook(actions),
hasFilter: build_module_createHasHook(filters),
removeAllActions: build_module_createRemoveHook(actions, true),
removeAllFilters: build_module_createRemoveHook(filters, true),
doAction: build_module_createRunHook(actions),
applyFilters: build_module_createRunHook(filters, true),
currentAction: build_module_createCurrentHook(actions),
currentFilter: build_module_createCurrentHook(filters),
doingAction: build_module_createDoingHook(actions),
doingFilter: build_module_createDoingHook(filters),
didAction: build_module_createDidHook(actions),
didFilter: build_module_createDidHook(filters),
actions: actions,
filters: filters
};
}
/* harmony default export */ var build_module_createHooks = (createHooks);
// CONCATENATED MODULE: ./node_modules/@wordpress/hooks/build-module/index.js
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "addAction", function() { return addAction; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "addFilter", function() { return addFilter; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "removeAction", function() { return removeAction; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "removeFilter", function() { return removeFilter; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "hasAction", function() { return hasAction; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "hasFilter", function() { return hasFilter; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "removeAllActions", function() { return removeAllActions; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "removeAllFilters", function() { return removeAllFilters; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "doAction", function() { return doAction; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "applyFilters", function() { return applyFilters; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "currentAction", function() { return currentAction; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "currentFilter", function() { return currentFilter; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "doingAction", function() { return doingAction; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "doingFilter", function() { return doingFilter; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "didAction", function() { return didAction; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "didFilter", function() { return didFilter; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "actions", function() { return build_module_actions; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "filters", function() { return build_module_filters; });
/* concated harmony reexport createHooks */__webpack_require__.d(__webpack_exports__, "createHooks", function() { return build_module_createHooks; });
/**
* Internal dependencies
*/
var _createHooks = build_module_createHooks(),
addAction = _createHooks.addAction,
addFilter = _createHooks.addFilter,
removeAction = _createHooks.removeAction,
removeFilter = _createHooks.removeFilter,
hasAction = _createHooks.hasAction,
hasFilter = _createHooks.hasFilter,
removeAllActions = _createHooks.removeAllActions,
removeAllFilters = _createHooks.removeAllFilters,
doAction = _createHooks.doAction,
applyFilters = _createHooks.applyFilters,
currentAction = _createHooks.currentAction,
currentFilter = _createHooks.currentFilter,
doingAction = _createHooks.doingAction,
doingFilter = _createHooks.doingFilter,
didAction = _createHooks.didAction,
didFilter = _createHooks.didFilter,
build_module_actions = _createHooks.actions,
build_module_filters = _createHooks.filters;
/***/ })
/******/ });

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 kirki-framework
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -0,0 +1,2 @@
@media screen and (min-width:1667px){.rtl .wp-full-overlay.expanded{margin-left:0;margin-right:300px}.wp-full-overlay.expanded{margin-left:300px}}#customize-theme-controls .customize-pane-child.open{overflow:visible}.wp-full-overlay-sidebar{width:300px}.expanded .wp-full-overlay-footer{max-width:299px}.kirki-w100{width:100%}.kirki-w50{width:50%}.kirki-w45{width:45%}.kirki-w40{width:40%}.kirki-w33{width:33.3333%}.kirki-w30{width:30%}.kirki-w25{width:25%}.kirki-w20{width:20%}.kirki-w15{width:15%}.kirki-w10{width:10%}.kirki-w5{width:5%}.control-section-kirki-default,.control-section-kirki-outer{min-height:100%}.customize-control-has-small-gap{margin-bottom:9px}.customize-control-is-gapless{margin-bottom:0}.customize-control-kirki-hidden-field{height:0;margin-bottom:0}.customize-control-kirki,.customize-control-kirki *{box-sizing:border-box}.customize-control-kirki.kirki-group-item{clear:none}.kirki-group-item{clear:none;float:left;padding-left:3px;padding-right:3px}.kirki-group-item.kirki-group-start{padding-left:0;padding-right:3px}.kirki-group-item.kirki-group-break,.kirki-group-item.kirki-group-end{padding-left:3px;padding-right:0}.kirki-group-item.kirki-group-end:after{clear:both;content:"";display:block;height:0;width:100%}.customize-control-kirki{position:relative}.customize-control-kirki .kirki-control-label,.customize-control-kirki label.customize-control-title{display:block}.customize-control-kirki .kirki-control-form{position:relative}.customize-control-kirki .kirki-control-form textarea{display:block;width:100%}
/*# sourceMappingURL=control.css.map */

View file

@ -0,0 +1 @@
{"mappings":"AACE,qCACE,+BAEE,aAAA,CADA,kBCCJ,CCDA,0BACE,iBDMF,CALF,CCGA,qDACE,gBDKF,CCFA,yBACE,WDKF,CCFA,kCACE,eDKF,CCFA,YACE,UDKF,CCFA,WACE,SDKF,CCFA,WACE,SDKF,CCFA,WACE,SDKF,CCFA,WACE,cDKF,CCFA,WACE,SDKF,CCFA,WACE,SDKF,CCFA,WACE,SDKF,CCFA,WACE,SDKF,CCFA,WACE,SDKF,CCFA,UACE,QDKF,CCFA,4DAEE,eDKF,CCFA,iCACE,iBDKF,CCFA,8BACE,eDKF,CCFA,sCAEE,QAAA,CADA,eDMF,CCFA,oDAEE,qBDKF,CCFA,0CACE,UDKF,CCFA,kBAEE,UAAA,CADA,UAAA,CAEA,gBAAA,CACA,iBDKF,CCHE,oCACE,cAAA,CACA,iBDKJ,CCFE,sEAEE,gBAAA,CACA,eDGJ,CCCI,wCAKE,UAAA,CAJA,UAAA,CACA,aAAA,CAEA,QAAA,CADA,UDGN,CCIA,yBACE,iBDDF,CCGE,qGAEE,aDDJ,CCIE,6CACE,iBDFJ,CCII,sDACE,aAAA,CACA,UDFN","sources":["src/rtl.scss","%3Cinput%20css%20N7IR_2%3E","src/control.scss"],"sourcesContent":[".rtl {\n @media screen and (min-width: 1667px) {\n .wp-full-overlay.expanded {\n margin-right: 300px;\n margin-left: 0;\n }\n }\n}\n","@media screen and (min-width: 1667px) {\n .rtl .wp-full-overlay.expanded {\n margin-right: 300px;\n margin-left: 0;\n }\n}\n\n@media screen and (min-width: 1667px) {\n .wp-full-overlay.expanded {\n margin-left: 300px;\n }\n}\n#customize-theme-controls .customize-pane-child.open {\n overflow: visible;\n}\n\n.wp-full-overlay-sidebar {\n width: 300px;\n}\n\n.expanded .wp-full-overlay-footer {\n max-width: 299px;\n}\n\n.kirki-w100 {\n width: 100%;\n}\n\n.kirki-w50 {\n width: 50%;\n}\n\n.kirki-w45 {\n width: 45%;\n}\n\n.kirki-w40 {\n width: 40%;\n}\n\n.kirki-w33 {\n width: 33.3333%;\n}\n\n.kirki-w30 {\n width: 30%;\n}\n\n.kirki-w25 {\n width: 25%;\n}\n\n.kirki-w20 {\n width: 20%;\n}\n\n.kirki-w15 {\n width: 15%;\n}\n\n.kirki-w10 {\n width: 10%;\n}\n\n.kirki-w5 {\n width: 5%;\n}\n\n.control-section-kirki-default,\n.control-section-kirki-outer {\n min-height: 100%;\n}\n\n.customize-control-has-small-gap {\n margin-bottom: 9px;\n}\n\n.customize-control-is-gapless {\n margin-bottom: 0;\n}\n\n.customize-control-kirki-hidden-field {\n margin-bottom: 0;\n height: 0;\n}\n\n.customize-control-kirki,\n.customize-control-kirki * {\n box-sizing: border-box;\n}\n\n.customize-control-kirki.kirki-group-item {\n clear: none;\n}\n\n.kirki-group-item {\n float: left;\n clear: none;\n padding-left: 3px;\n padding-right: 3px;\n}\n.kirki-group-item.kirki-group-start {\n padding-left: 0;\n padding-right: 3px;\n}\n.kirki-group-item.kirki-group-break, .kirki-group-item.kirki-group-end {\n padding-left: 3px;\n padding-right: 0;\n}\n.kirki-group-item.kirki-group-end::after {\n content: \"\";\n display: block;\n width: 100%;\n height: 0;\n clear: both;\n}\n\n.customize-control-kirki {\n position: relative;\n}\n.customize-control-kirki .kirki-control-label,\n.customize-control-kirki label.customize-control-title {\n display: block;\n}\n.customize-control-kirki .kirki-control-form {\n position: relative;\n}\n.customize-control-kirki .kirki-control-form textarea {\n display: block;\n width: 100%;\n}\n/*# sourceMappingURL=control.css.map */\n","@import \"rtl.scss\";\n\n@media screen and (min-width: 1667px) {\n .wp-full-overlay.expanded {\n margin-left: 300px;\n }\n}\n\n#customize-theme-controls .customize-pane-child.open {\n overflow: visible;\n}\n\n.wp-full-overlay-sidebar {\n width: 300px;\n}\n\n.expanded .wp-full-overlay-footer {\n max-width: 299px;\n}\n\n.kirki-w100 {\n width: 100%;\n}\n\n.kirki-w50 {\n width: 50%;\n}\n\n.kirki-w45 {\n width: 45%;\n}\n\n.kirki-w40 {\n width: 40%;\n}\n\n.kirki-w33 {\n width: 33.3333%;\n}\n\n.kirki-w30 {\n width: 30%;\n}\n\n.kirki-w25 {\n width: 25%;\n}\n\n.kirki-w20 {\n width: 20%;\n}\n\n.kirki-w15 {\n width: 15%;\n}\n\n.kirki-w10 {\n width: 10%;\n}\n\n.kirki-w5 {\n width: 5%;\n}\n\n.control-section-kirki-default,\n.control-section-kirki-outer {\n min-height: 100%;\n}\n\n.customize-control-has-small-gap {\n margin-bottom: 9px;\n}\n\n.customize-control-is-gapless {\n margin-bottom: 0;\n}\n\n.customize-control-kirki-hidden-field {\n margin-bottom: 0;\n height: 0;\n}\n\n.customize-control-kirki,\n.customize-control-kirki * {\n box-sizing: border-box;\n}\n\n.customize-control-kirki.kirki-group-item {\n clear: none; // Override WordPress.\n}\n\n.kirki-group-item {\n float: left;\n clear: none;\n padding-left: 3px;\n padding-right: 3px;\n\n &.kirki-group-start {\n padding-left: 0;\n padding-right: 3px;\n }\n\n &.kirki-group-break,\n &.kirki-group-end {\n padding-left: 3px;\n padding-right: 0;\n }\n\n &.kirki-group-end {\n &::after {\n content: \"\";\n display: block;\n width: 100%;\n height: 0;\n clear: both;\n }\n }\n}\n\n.customize-control-kirki {\n position: relative;\n\n .kirki-control-label,\n label.customize-control-title {\n display: block;\n }\n\n .kirki-control-form {\n position: relative;\n\n textarea {\n display: block;\n width: 100%;\n }\n }\n}\n"],"names":[],"version":3,"file":"control.css.map"}

View file

@ -0,0 +1,2 @@
!function(){var t;wp.customize.kirkiDynamicControl=wp.customize.Control.extend({initialize:function(t,e){var i,n=this,o=e||{};if(o.params=o.params||{},o.params.type||(o.params.type="kirki-generic"),o.content){var r=o.content.split('class="');r=r[1].split('"'),i=r[0]}else i="customize-control customize-control-"+o.params.type;!o.params.wrapper_attrs&&o.params.wrapper_atts&&(o.params.wrapper_attrs=o.params.wrapper_atts),o.params.content=jQuery("<li></li>"),o.params.content.attr("id","customize-control-"+t.replace(/]/g,"").replace(/\[/g,"-")),o.params.content.attr("class",i),_.each(o.params.wrapper_attrs,(function(t,e){"class"===e&&(t=t.replace("{default_class}",i)),o.params.content.attr(e,t)})),n.propertyElements=[],wp.customize.Control.prototype.initialize.call(n,t,o),wp.hooks.doAction("kirki.dynamicControl.init.after",t,n,o)},_setUpSettingRootLinks:function(){var t=this;t.container.find("[data-customize-setting-link]").each((function(){var e=jQuery(this);wp.customize(e.data("customizeSettingLink"),(function(i){var n=new wp.customize.Element(e);t.elements.push(n),n.sync(i),n.set(i())}))}))},_setUpSettingPropertyLinks:function(){var t=this;t.setting&&t.container.find("[data-customize-setting-property-link]").each((function(){var e,i=jQuery(this),n=i.data("customizeSettingPropertyLink");e=new wp.customize.Element(i),t.propertyElements.push(e),e.set(t.setting()[n]),e.bind((function(e){var i=t.setting();e!==i[n]&&((i=_.clone(i))[n]=e,t.setting.set(i))})),t.setting.bind((function(t){t[n]!==e.get()&&e.set(t[n])}))}))},ready:function(){var t=this;t._setUpSettingRootLinks(),t._setUpSettingPropertyLinks(),wp.customize.Control.prototype.ready.call(t),t.deferred.embedded.done((function(){t.initKirkiControl(),wp.hooks.doAction("kirki.dynamicControl.ready.deferred.embedded.done",t)})),wp.hooks.doAction("kirki.dynamicControl.ready.after",t)},embed:function(){var t=this,e=t.section();e&&(wp.customize.section(e,(function(e){"kirki-expanded"===e.params.type||e.expanded()||wp.customize.settings.autofocus.control===t.id?t.actuallyEmbed():e.expanded.bind((function(e){e&&t.actuallyEmbed()}))})),wp.hooks.doAction("kirki.dynamicControl.embed.after",t))},actuallyEmbed:function(){var t=this;"resolved"!==t.deferred.embedded.state()&&(t.renderContent(),t.deferred.embedded.resolve(),wp.hooks.doAction("kirki.dynamicControl.actuallyEmbed.after",t))},focus:function(t){var e=this;e.actuallyEmbed(),wp.customize.Control.prototype.focus.call(e,t),wp.hooks.doAction("kirki.dynamicControl.focus.after",e)},initKirkiControl:function(t){t=t||this,wp.hooks.doAction("kirki.dynamicControl.initKirkiControl",this),t.container.on("change keyup paste click","input",(function(){t.setting.set(jQuery(this).val())}))}}),(t=wp.customize).Value.prototype.set=function(e){var i,n,o=this._value;return e=this._setter.apply(this,arguments),null===(e=this.validate(e))||_.isEqual(o,e)||(this.id&&t.control(this.id)&&t.control(this.id).params&&t.control(this.id).params.parent_setting&&(i=t.control(this.id).params.parent_setting,(n={})[this.id.replace(i+"[","").replace("]","")]=e,t.control(i).setting.set(jQuery.extend({},t.control(i).setting._value,n))),this._value=e,this._dirty=!0,this.callbacks.fireWith(this,[e,o])),this},t.Value.prototype.get=function(){var e;return this.id&&t.control(this.id)&&t.control(this.id).params&&t.control(this.id).params.parent_setting?(e=t.control(this.id).params.parent_setting,t.control(e).setting.get()[this.id.replace(e+"[","").replace("]","")]):this._value}}();
//# sourceMappingURL=control.js.map

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,347 @@
<?php
/**
* Customizer Controls Base.
*
* Extend this in other controls.
*
* @package kirki-framework/control-base
* @copyright Copyright (c) 2023, Themeum
* @license https://opensource.org/licenses/MIT
* @since 1.0
*/
namespace Kirki\Control;
use Kirki\URL;
/**
* A base for controls.
*
* @since 1.0
*/
class Base extends \WP_Customize_Control {
/**
* Used to automatically generate all CSS output.
*
* Whitelisting property for use in Kirki modules.
*
* @access public
* @since 1.0
* @var array
*/
public $output = [];
/**
* Data type
*
* @access public
* @since 1.0
* @var string
*/
public $option_type = 'theme_mod';
/**
* Option name (if using options).
*
* Whitelisting property for use in Kirki modules.
*
* @access public
* @since 1.0
* @var string
*/
public $option_name = false;
/**
* The kirki_config we're using for this control
*
* Whitelisting property for use in Kirki modules.
*
* @access public
* @since 1.0
* @var string
*/
public $kirki_config = 'global';
/**
* Whitelisting the "preset" argument for use in Kirki modules.
*
* @access public
* @since 1.0
* @var array
*/
public $preset = [];
/**
* Whitelisting the "css_vars" argument for use in Kirki modules.
*
* @access public
* @since 1.0
* @var string
*/
public $css_vars = '';
/**
* The version. Used in scripts & styles for cache-busting.
*
* @static
* @access public
* @since 1.0
* @var string
*/
public static $control_ver = '1.0.4';
/**
* Parent setting.
*
* Used for composite controls to denote the setting that should be saved.
*
* @access public
* @since 1.1
* @var string
*/
public $parent_setting;
/**
* Wrapper attributes.
*
* The value of this property will be rendered to the wrapper element.
* Can be 'class', 'id', 'data-*', and other attributes.
*
* @access public
* @since 1.1
* @var array
*/
public $wrapper_attrs = [];
/**
* Backwards compatibility support for `$wrapper_attrs`.
*
* Kirki v3 already has this `$wrapper_atts` property.
* It was not published in the documentation, and more for internal use.
*
* The `WP_Customize_Control` is using `input_attrs` not `input_atts` (see, attrs vs atts).
* So Kirki uses `$wrapper_attrs` for consistency and keep the old `$wrapper_atts` backwards compatibility.
*
* This property could be removed in the future.
* Please use `$wrapper_attrs` instead.
*
* @since 1.1
* @deprecated 1.0.1 This variable could be removed in the future. Please use `$wrapper_attrs` instead.
* @var array
*/
public $wrapper_atts = [];
/**
* Wrapper options.
*
* This won't be rendered automatically to the wrapper element.
* The purpose is to allow us to have custom options so we can manage it when needed.
*
* @access public
* @since 1.1
* @var array
*/
public $wrapper_opts = [];
/**
* Extra script dependencies.
*
* @access public
* @since 1.0
* @return array
*/
public function kirki_script_dependencies() {
return [];
}
/**
* Enqueue control related scripts/styles.
*
* @access public
* @since 1.0
* @return void
*/
public function enqueue() {
// Enqueue the styles.
wp_enqueue_style( 'kirki-control-base', URL::get_from_path( dirname( dirname( __DIR__ ) ) . '/dist/control.css' ), [], self::$control_ver );
// Enqueue the scripts.
wp_enqueue_script( 'kirki-control-base', URL::get_from_path( dirname( dirname( __DIR__ ) ) . '/dist/control.js' ), [ 'customize-controls' ], self::$control_ver, false );
}
/**
* Renders the control wrapper and calls $this->render_content() for the internals.
*
* @since 1.0
*/
protected function render() {
$id = 'customize-control-' . str_replace( [ '[', ']' ], [ '-', '' ], $this->id );
$class = 'customize-control customize-control-kirki customize-control-' . $this->type;
$gap = isset( $this->wrapper_opts['gap'] ) ? $this->wrapper_opts['gap'] : 'default';
$tag = isset( $this->wrapper_opts['tag'] ) ? $this->wrapper_opts['tag'] : 'li';
switch ( $gap ) {
case 'small':
$class .= ' customize-control-has-small-gap';
break;
case 'none':
$class .= ' customize-control-is-gapless';
break;
default:
break;
}
if ( empty( $this->wrapper_attrs ) && ! empty( $this->wrapper_atts ) ) {
$this->wrapper_attrs = $this->wrapper_atts;
}
if ( isset( $this->wrapper_attrs['id'] ) ) {
$id = $this->wrapper_attrs['id'];
}
if ( ! isset( $this->wrapper_attrs['data-kirki-setting'] ) ) {
$this->wrapper_attrs['data-kirki-setting'] = $this->id;
}
if ( ! isset( $this->wrapper_attrs['data-kirki-setting-link'] ) ) {
if ( isset( $this->settings['default'] ) ) {
$this->wrapper_attrs['data-kirki-setting-link'] = $this->settings['default']->id;
}
}
$data_attrs = '';
foreach ( $this->wrapper_attrs as $attr_key => $attr_value ) {
if ( 0 === strpos( $attr_key, 'data-' ) ) {
$data_attrs .= ' ' . esc_attr( $attr_key ) . '="' . esc_attr( $attr_value ) . '"';
}
}
if ( isset( $this->wrapper_attrs['class'] ) ) {
$class = str_ireplace( '{default_class}', $class, $this->wrapper_attrs['class'] );
}
// ! Consider to esc $data_attrs.
// ? What function we can use to escape string like data-xx="yy"?
printf( '<' . esc_attr( $tag ) . ' id="%s" class="%s"%s>', esc_attr( $id ), esc_attr( $class ), $data_attrs );
$this->render_content();
echo '</' . esc_attr( $tag ) . '>';
}
/**
* Refresh the parameters passed to the JavaScript via JSON.
*
* @access public
* @since 1.0
* @see WP_Customize_Control::to_json()
* @return void
*/
public function to_json() {
// Get the basics from the parent class.
parent::to_json();
// Default value.
$this->json['default'] = $this->setting->default;
if ( isset( $this->default ) ) {
$this->json['default'] = $this->default;
}
// Output.
$this->json['output'] = $this->output;
// Value.
$this->json['value'] = $this->value();
// Choices.
$this->json['choices'] = $this->choices;
// The link.
$this->json['link'] = $this->get_link();
// The ID.
$this->json['id'] = $this->id;
// Translation strings.
$this->json['l10n'] = $this->l10n();
// The ajaxurl in case we need it.
$this->json['ajaxurl'] = admin_url( 'admin-ajax.php' );
// Input attributes.
$this->json['inputAttrs'] = '';
if ( is_array( $this->input_attrs ) ) {
foreach ( $this->input_attrs as $attr => $value ) {
$this->json['inputAttrs'] .= $attr . '="' . esc_attr( $value ) . '" ';
}
}
// The kirki-config.
$this->json['kirkiConfig'] = $this->kirki_config;
// The option-type.
$this->json['kirkiOptionType'] = $this->option_type;
// The option-name.
$this->json['kirkiOptionName'] = $this->option_name;
// The preset.
$this->json['preset'] = $this->preset;
// The CSS-Variables.
$this->json['css-var'] = $this->css_vars;
// Parent setting.
$this->json['parent_setting'] = $this->parent_setting;
// Wrapper Attributes.
$this->json['wrapper_attrs'] = $this->wrapper_attrs;
$this->json['wrapper_atts'] = $this->wrapper_attrs; // For backward compatibility - Could be removed in the future.
}
/**
* Render the control's content.
*
* Allows the content to be overridden without having to rewrite the wrapper in `$this::render()`.
* Control content can alternately be rendered in JS. See WP_Customize_Control::print_template().
*
* @access protected
* @since 1.0
* @return void
*/
protected function render_content() {}
/**
* An Underscore (JS) template for this control's content (but not its container).
*
* Class variables for this control class are available in the `data` JS object;
* export custom variables by overriding {@see WP_Customize_Control::to_json()}.
*
* @access protected
* @since 1.0
* @see WP_Customize_Control::print_template()
* @return void
*/
protected function content_template() {}
/**
* Returns an array of translation strings.
*
* @access protected
* @since 3.0.0
* @return array
*/
protected function l10n() {
return [];
}
}

View file

@ -0,0 +1,2 @@
import "./control.scss";
import "./dynamic-control";

View file

@ -0,0 +1,136 @@
@import "rtl.scss";
@media screen and (min-width: 1667px) {
.wp-full-overlay.expanded {
margin-left: 300px;
}
}
#customize-theme-controls .customize-pane-child.open {
overflow: visible;
}
.wp-full-overlay-sidebar {
width: 300px;
}
.expanded .wp-full-overlay-footer {
max-width: 299px;
}
.kirki-w100 {
width: 100%;
}
.kirki-w50 {
width: 50%;
}
.kirki-w45 {
width: 45%;
}
.kirki-w40 {
width: 40%;
}
.kirki-w33 {
width: 33.3333%;
}
.kirki-w30 {
width: 30%;
}
.kirki-w25 {
width: 25%;
}
.kirki-w20 {
width: 20%;
}
.kirki-w15 {
width: 15%;
}
.kirki-w10 {
width: 10%;
}
.kirki-w5 {
width: 5%;
}
.control-section-kirki-default,
.control-section-kirki-outer {
min-height: 100%;
}
.customize-control-has-small-gap {
margin-bottom: 9px;
}
.customize-control-is-gapless {
margin-bottom: 0;
}
.customize-control-kirki-hidden-field {
margin-bottom: 0;
height: 0;
}
.customize-control-kirki,
.customize-control-kirki * {
box-sizing: border-box;
}
.customize-control-kirki.kirki-group-item {
clear: none; // Override WordPress.
}
.kirki-group-item {
float: left;
clear: none;
padding-left: 3px;
padding-right: 3px;
&.kirki-group-start {
padding-left: 0;
padding-right: 3px;
}
&.kirki-group-break,
&.kirki-group-end {
padding-left: 3px;
padding-right: 0;
}
&.kirki-group-end {
&::after {
content: "";
display: block;
width: 100%;
height: 0;
clear: both;
}
}
}
.customize-control-kirki {
position: relative;
.kirki-control-label,
label.customize-control-title {
display: block;
}
.kirki-control-form {
position: relative;
textarea {
display: block;
width: 100%;
}
}
}

View file

@ -0,0 +1,289 @@
/**
* The majority of the code in this file
* is derived from the wp-customize-posts plugin
* and the work of @westonruter to whom I am very grateful.
*
* @see https://github.com/xwp/wp-customize-posts
*/
(function () {
'use strict';
/**
* A dynamic color-alpha control.
*
* @class
* @augments wp.customize.Control
* @augments wp.customize.Class
*/
wp.customize.kirkiDynamicControl = wp.customize.Control.extend({
initialize: function (id, options) {
let control = this;
let args = options || {};
args.params = args.params || {};
if (!args.params.type) {
args.params.type = 'kirki-generic';
}
let className;
if (args.content) {
let splits = args.content.split('class="');
splits = splits[1].split('"');
className = splits[0];
} else {
className = 'customize-control customize-control-' + args.params.type;
}
if (!args.params.wrapper_attrs && args.params.wrapper_atts) {
args.params.wrapper_attrs = args.params.wrapper_atts;
}
// Hijack the container to add wrapper_attrs.
args.params.content = jQuery("<li></li>");
args.params.content.attr('id', 'customize-control-' + id.replace(/]/g, '').replace(/\[/g, '-'));
args.params.content.attr('class', className);
_.each(args.params.wrapper_attrs, function (val, key) {
if ('class' === key) {
val = val.replace('{default_class}', className);
}
args.params.content.attr(key, val);
});
control.propertyElements = [];
wp.customize.Control.prototype.initialize.call(control, id, args);
wp.hooks.doAction('kirki.dynamicControl.init.after', id, control, 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 {void}
*/
_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 {void}
*/
_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 () {
control.initKirkiControl();
wp.hooks.doAction('kirki.dynamicControl.ready.deferred.embedded.done', control);
});
wp.hooks.doAction('kirki.dynamicControl.ready.after', control);
},
/**
* 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 {void}
*/
embed: function () {
var control = this,
sectionId = control.section();
if (!sectionId) {
return;
}
wp.customize.section(sectionId, function (section) {
if ('kirki-expanded' === section.params.type || section.expanded() || wp.customize.settings.autofocus.control === control.id) {
control.actuallyEmbed();
} else {
section.expanded.bind(function (expanded) {
if (expanded) {
control.actuallyEmbed();
}
});
}
});
wp.hooks.doAction('kirki.dynamicControl.embed.after', control);
},
/**
* 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 {void}
*/
actuallyEmbed: function () {
var control = this;
if ('resolved' === control.deferred.embedded.state()) {
return;
}
control.renderContent();
control.deferred.embedded.resolve(); // This triggers control.ready().
wp.hooks.doAction('kirki.dynamicControl.actuallyEmbed.after', control);
},
/**
* This is not working with autofocus.
*
* @param {object} [args] Args.
* @returns {void}
*/
focus: function (args) {
var control = this;
control.actuallyEmbed();
wp.customize.Control.prototype.focus.call(control, args);
wp.hooks.doAction('kirki.dynamicControl.focus.after', control);
},
/**
* Additional actions that run on ready.
*
* @param {object} control - The control object. If undefined fallsback to the this.
* @returns {void}
*/
initKirkiControl: function (control) {
control = control || this;
wp.hooks.doAction('kirki.dynamicControl.initKirkiControl', this);
// Save the value
control.container.on('change keyup paste click', 'input', function () {
control.setting.set(jQuery(this).val());
});
}
});
}());
(function (api) {
/**
* Set the value and trigger all bound callbacks.
*
* @since 1.0
* @param {object} to - New value.
* @returns {Object} - this
*/
api.Value.prototype.set = function (to) {
var from = this._value,
parentSetting,
newVal;
to = this._setter.apply(this, arguments);
to = this.validate(to);
// Bail if the sanitized value is null or unchanged.
if (null === to || _.isEqual(from, to)) {
return this;
}
/**
* Start Kirki mod.
*/
if (this.id && api.control(this.id) && api.control(this.id).params && api.control(this.id).params.parent_setting) {
parentSetting = api.control(this.id).params.parent_setting;
newVal = {};
newVal[this.id.replace(parentSetting + '[', '').replace(']', '')] = to;
api.control(parentSetting).setting.set(jQuery.extend({}, api.control(parentSetting).setting._value, newVal));
}
/**
* End Kirki mod.
*/
this._value = to;
this._dirty = true;
this.callbacks.fireWith(this, [to, from]);
return this;
};
/**
* Get the value.
*
* @returns {mixed} - Returns the value.
*/
api.Value.prototype.get = function () {
// Start Kirki mod.
var parentSetting;
if (this.id && api.control(this.id) && api.control(this.id).params && api.control(this.id).params.parent_setting) {
parentSetting = api.control(this.id).params.parent_setting;
return api.control(parentSetting).setting.get()[this.id.replace(parentSetting + '[', '').replace(']', '')];
}
// End Kirki mod.
return this._value;
};
}(wp.customize));

View file

@ -0,0 +1,8 @@
.rtl {
@media screen and (min-width: 1667px) {
.wp-full-overlay.expanded {
margin-right: 300px;
margin-left: 0;
}
}
}

View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 kirki-framework
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -0,0 +1,2 @@
.customize-control-kirki-toggle .kirki-toggle{align-items:flex-start;display:flex;justify-content:space-between}.customize-control-kirki-toggle .kirki-toggle .kirki-control-label{width:80%}.customize-control-kirki-toggle .kirki-toggle .kirki-control-form{text-align:right;width:20%}.customize-control-kirki-toggle .kirki-toggle .kirki-toggle-switch-label{width:100%}.customize-control-kirki-toggle .kirki-toggle .kirki-toggle-switch-label:before{right:0}.customize-control-kirki-toggle .kirki-toggle .kirki-toggle-switch-label:after{right:18px}.customize-control-kirki-switch .kirki-switch .kirki-toggle-switch-label{padding:10px 0 12px 44px;text-align:left}.customize-control-kirki-switch .kirki-switch .kirki-toggle-switch-label:after,.customize-control-kirki-switch .kirki-switch .kirki-toggle-switch-label:before{left:0}.customize-control-kirki-switch .kirki-switch .toggle-off,.customize-control-kirki-switch .kirki-switch .toggle-on{bottom:-2px;padding-left:5px;position:relative}.customize-control-kirki-switch .kirki-switch .toggle-on{color:#0073aa;display:none}.customize-control-kirki-switch .kirki-switch .toggle-off{color:#82878c;display:inline-block}.kirki-toggle-switch-label{cursor:pointer;display:inline-block;position:relative}.kirki-toggle-switch-label:after,.kirki-toggle-switch-label:before{box-sizing:border-box;content:"";margin:0;outline:0;position:absolute;top:50%;transform:translate3d(0,-50%,0);transition:all .35s cubic-bezier(0,.95,.38,.98),background-color .15s ease}.kirki-toggle-switch-label:before{background-color:#b4b9be;border:1px solid #b4b9be;border-radius:8px;height:14px;width:37px}.kirki-toggle-switch-label:after{background-color:#999;border:1px solid rgba(0,0,0,.1);border-radius:50%;height:22px;width:22px}.kirki-toggle-switch-input{opacity:0}.kirki-toggle-switch-input:checked+.kirki-toggle-switch-label:after{background-color:#0073aa;transform:translate3d(100%,-50%,0)}.kirki-toggle-switch-input:checked+.kirki-toggle-switch-label .toggle-on{display:inline-block}.kirki-toggle-switch-input:checked+.kirki-toggle-switch-label .toggle-off{display:none}
/*# sourceMappingURL=control.css.map */

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,2 @@
!function(){var i={initKirkiControl:function(i){(i=i||this).container.on("change","input",(function(){i.setting.set(jQuery(this).is(":checked"))}))}};wp.customize.controlConstructor["kirki-checkbox"]=wp.customize.kirkiDynamicControl.extend(i),wp.customize.controlConstructor["kirki-switch"]=wp.customize.kirkiDynamicControl.extend(i),wp.customize.controlConstructor["kirki-toggle"]=wp.customize.kirkiDynamicControl.extend(i)}();
//# sourceMappingURL=control.js.map

View file

@ -0,0 +1 @@
{"mappings":"YAEA,IAAIA,EAAsB,CAEzBC,iBAAkB,SAAUC,IAC3BA,EAAUA,GAAWC,MACbC,UAAUC,GAAI,SAAU,SAAS,WACxCH,EAAQI,QAAQC,IAAKC,OAAQL,MAAOM,GAAI,kBAK3CC,GAAGC,UAAUC,mBAAmB,kBAAoBF,GAAGC,UAAUE,oBAAoBC,OAAQd,GAC7FU,GAAGC,UAAUC,mBAAmB,gBAAoBF,GAAGC,UAAUE,oBAAoBC,OAAQd,GAC7FU,GAAGC,UAAUC,mBAAmB,gBAAoBF,GAAGC,UAAUE,oBAAoBC,OAAQd","sources":["src/control.js"],"sourcesContent":["import \"./control.scss\";\n\nvar kirkiCheckboxScript = {\n\n\tinitKirkiControl: function( control ) {\n\t\tcontrol = control || this;\n\t\tcontrol.container.on( 'change', 'input', function() {\n\t\t\tcontrol.setting.set( jQuery( this ).is( ':checked' ) );\n\t\t} );\n\t}\n};\n\nwp.customize.controlConstructor['kirki-checkbox'] = wp.customize.kirkiDynamicControl.extend( kirkiCheckboxScript );\nwp.customize.controlConstructor['kirki-switch'] = wp.customize.kirkiDynamicControl.extend( kirkiCheckboxScript );\nwp.customize.controlConstructor['kirki-toggle'] = wp.customize.kirkiDynamicControl.extend( kirkiCheckboxScript );\n"],"names":["$1abc80d3e2df1201$var$kirkiCheckboxScript","initKirkiControl","control","this","container","on","setting","set","jQuery","is","wp","customize","controlConstructor","kirkiDynamicControl","extend"],"version":3,"file":"control.js.map"}

View file

@ -0,0 +1,90 @@
<?php
/**
* Customizer Control: checkbox.
*
* Creates a new custom control.
* Custom controls contains all background-related options.
*
* @package kirki-framework/control-checkbox
* @copyright Copyright (c) 2023, Themeum
* @license https://opensource.org/licenses/MIT
* @since 1.0
*/
namespace Kirki\Control;
use Kirki\Control\Base;
use Kirki\URL;
/**
* Adds a checkbox control.
*
* @since 1.0
*/
class Checkbox extends Base {
/**
* The control type.
*
* @access public
* @since 1.0
* @var string
*/
public $type = 'kirki-checkbox';
/**
* The control version.
*
* @static
* @access public
* @since 1.0
* @var string
*/
public static $control_ver = '1.0.3';
/**
* Enqueue control related scripts/styles.
*
* @access public
* @since 1.0
* @return void
*/
public function enqueue() {
parent::enqueue();
// Enqueue the script.
wp_enqueue_script( 'kirki-control-checkbox', URL::get_from_path( dirname( dirname( __DIR__ ) ) . '/dist/control.js' ), [ 'jquery', 'customize-base', 'kirki-control-base' ], self::$control_ver, false );
// Enqueue the style.
wp_enqueue_style( 'kirki-control-checkbox-style', URL::get_from_path( dirname( dirname( __DIR__ ) ) . '/dist/control.css' ), [], self::$control_ver );
}
/**
* An Underscore (JS) template for this control's content (but not its container).
*
* Class variables for this control class are available in the `data` JS object;
* export custom variables by overriding {@see WP_Customize_Control::to_json()}.
*
* @see WP_Customize_Control::print_template()
*
* @access protected
* @since 1.0
* @return void
*/
protected function content_template() {
?>
<input
id="_customize-input-{{ data.id }}"
type="checkbox"
value="{{ data.value }}"
{{{ data.link }}}
<# if ( data.description ) { #>aria-describedby="_customize-description-{{ data.id }}"<# } #>
<# if ( data.value ) { #>checked="checked"<# } #>
/>
<label for="_customize-input-{{ data.id }}">{{{ data.label }}}</label>
<# if ( data.description ) { #>
<span id="_customize-description-{{ data.id }}" class="description customize-control-description">{{{ data.description }}}</span>
<# } #>
<?php
}
}

View file

@ -0,0 +1,134 @@
<?php
/**
* Customizer Control: switch.
*
* @package kirki-framework/checkbox
* @copyright Copyright (c) 2023, Themeum
* @license https://opensource.org/licenses/MIT
* @since 1.0
*/
namespace Kirki\Control;
use Kirki\Control\Base;
use Kirki\URL;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Switch control (modified checkbox).
*
* @since 1.0
*/
class Checkbox_Switch extends Base {
/**
* The control type.
*
* @access public
* @since 1.0
* @var string
*/
public $type = 'kirki-switch';
/**
* The control version.
*
* @static
* @access public
* @since 1.0
* @var string
*/
public static $control_ver = '1.0.3';
/**
* Enqueue control related scripts/styles.
*
* @access public
* @since 1.0
* @return void
*/
public function enqueue() {
parent::enqueue();
// Enqueue the script.
wp_enqueue_script( 'kirki-control-checkbox', URL::get_from_path( dirname( dirname( __DIR__ ) ) . '/dist/control.js' ), [ 'jquery', 'customize-base', 'kirki-control-base' ], self::$control_ver, false );
// Enqueue the style.
wp_enqueue_style( 'kirki-control-checkbox-style', URL::get_from_path( dirname( dirname( __DIR__ ) ) . '/dist/control.css' ), [], self::$control_ver );
}
/**
* Refresh the parameters passed to the JavaScript via JSON.
*
* @since 3.4.0
*/
public function to_json() {
// Get the basics from the parent class.
parent::to_json();
$this->json['checkboxType'] = str_ireplace( 'kirki-', '', $this->type );
$this->json['defaultChoices'] = [
'on' => __( 'On', 'kirki' ),
'off' => __( 'Off', 'kirki' ),
];
}
/**
* An Underscore (JS) template for this control's content (but not its container).
*
* Class variables for this control class are available in the `data` JS object;
* export custom variables by overriding {@see WP_Customize_Control::to_json()}.
*
* @see WP_Customize_Control::print_template()
*
* @access protected
* @since 1.0
* @return void
*/
protected function content_template() {
?>
<div class="kirki-{{ data.checkboxType }}-control kirki-{{ data.checkboxType }}">
<# if ( data.label || data.description ) { #>
<div class="kirki-control-label">
<# if ( data.label ) { #>
<label class="customize-control-title" for="kirki_{{ data.checkboxType }}_{{ data.id }}">
{{{ data.label }}}
</label>
<# } #>
<# if ( data.description ) { #>
<span class="description customize-control-description">{{{ data.description }}}</span>
<# } #>
</div>
<# } #>
<div class="kirki-control-form">
<input class="screen-reader-text kirki-toggle-switch-input" {{{ data.inputAttrs }}} name="kirki_{{ data.checkboxType }}_{{ data.id }}" id="kirki_{{ data.checkboxType }}_{{ data.id }}" type="checkbox" value="{{ data.value }}" {{{ data.link }}}<# if ( '1' == data.value ) { #> checked<# } #> />
<label class="kirki-toggle-switch-label" for="kirki_{{ data.checkboxType }}_{{ data.id }}">
<# if ('switch' === data.checkboxType) { #>
<span class="toggle-on">
<# data.choices.on = data.choices.on || data.defaultChoices.on #>
{{ data.choices.on }}
</span>
<span class="toggle-off">
<# data.choices.off = data.choices.off || data.defaultChoices.off #>
{{ data.choices.off }}
</span>
<# } #>
</label>
</div>
</div>
<?php
}
}

View file

@ -0,0 +1,34 @@
<?php
/**
* Customizer Control: toggle.
*
* @package kirki-framework/checkbox
* @copyright Copyright (c) 2023, Themeum
* @license https://opensource.org/licenses/MIT
* @since 1.0
*/
namespace Kirki\Control;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Switch control (modified checkbox).
*
* @since 1.0
*/
class Checkbox_Toggle extends Checkbox_Switch {
/**
* The control type.
*
* @access public
* @since 1.0
* @var string
*/
public $type = 'kirki-toggle';
}

View file

@ -0,0 +1,99 @@
<?php
/**
* Override field methods
*
* @package kirki-framework/checkbox
* @copyright Copyright (c) 2023, Themeum
* @license https://opensource.org/licenses/MIT
* @since 1.0
*/
namespace Kirki\Field;
use Kirki\Field;
/**
* Field overrides.
*
* @since 1.0
*/
class Checkbox extends Field {
/**
* The field type.
*
* @access public
* @since 1.0
* @var string
*/
public $type = 'kirki-checkbox';
/**
* The control class-name.
*
* @access protected
* @since 0.1
* @var string
*/
protected $control_class = '\Kirki\Control\Checkbox';
/**
* Whether we should register the control class for JS-templating or not.
*
* @access protected
* @since 0.1
* @var bool
*/
protected $control_has_js_template = true;
/**
* Filter arguments before creating the setting.
*
* @access public
* @since 0.1
* @param array $args The field arguments.
* @param WP_Customize_Manager $wp_customize The customizer instance.
* @return array
*/
public function filter_setting_args( $args, $wp_customize ) {
if ( $args['settings'] === $this->args['settings'] ) {
$args = parent::filter_setting_args( $args, $wp_customize );
// Set the sanitize-callback if none is defined.
if ( ! isset( $args['sanitize_callback'] ) || ! $args['sanitize_callback'] ) {
$args['sanitize_callback'] = function( $value ) {
return ( '0' === $value || 'false' === $value ) ? false : (bool) $value;
};
}
$args['default'] = isset( $args['default'] ) ? $args['default'] : false;
// Make sure the default is formatted as boolean.
$args['default'] = (bool) ( 1 === $args['default'] || '1' === $args['default'] || true === $args['default'] || 'true' === $args['default'] || 'on' === $args['default'] );
}
return $args;
}
/**
* Filter arguments before creating the control.
*
* @access public
* @since 0.1
* @param array $args The field arguments.
* @param WP_Customize_Manager $wp_customize The customizer instance.
* @return array
*/
public function filter_control_args( $args, $wp_customize ) {
if ( $args['settings'] === $this->args['settings'] ) {
$args = parent::filter_control_args( $args, $wp_customize );
$args['type'] = 'kirki-checkbox';
}
return $args;
}
}

View file

@ -0,0 +1,57 @@
<?php
/**
* Override field methods
*
* @package kirki-framework/checkbox
* @copyright Copyright (c) 2023, Themeum
* @license https://opensource.org/licenses/MIT
* @since 1.0
*/
namespace Kirki\Field;
/**
* Field overrides.
*
* @since 1.0
*/
class Checkbox_Switch extends Checkbox {
/**
* The field type.
*
* @access public
* @since 1.0
* @var string
*/
public $type = 'kirki-switch';
/**
* The control class-name.
*
* @access protected
* @since 0.1
* @var string
*/
protected $control_class = '\Kirki\Control\Checkbox_Switch';
/**
* Filter arguments before creating the control.
*
* @access public
* @since 0.1
* @param array $args The field arguments.
* @param WP_Customize_Manager $wp_customize The customizer instance.
* @return array
*/
public function filter_control_args( $args, $wp_customize ) {
if ( $args['settings'] === $this->args['settings'] ) {
$args = parent::filter_control_args( $args, $wp_customize );
$args['type'] = 'kirki-switch';
}
return $args;
}
}

View file

@ -0,0 +1,55 @@
<?php
/**
* Override field methods
*
* @package kirki-framework/checkbox
* @since 1.0
*/
namespace Kirki\Field;
/**
* Field overrides.
*
* @since 1.0
*/
class Checkbox_Toggle extends Checkbox {
/**
* The field type.
*
* @access public
* @since 1.0
* @var string
*/
public $type = 'kirki-toggle';
/**
* The control class-name.
*
* @access protected
* @since 0.1
* @var string
*/
protected $control_class = '\Kirki\Control\Checkbox_Toggle';
/**
* Filter arguments before creating the control.
*
* @access public
* @since 0.1
* @param array $args The field arguments.
* @param WP_Customize_Manager $wp_customize The customizer instance.
* @return array
*/
public function filter_control_args( $args, $wp_customize ) {
if ( $args['settings'] === $this->args['settings'] ) {
$args = parent::filter_control_args( $args, $wp_customize );
$args['type'] = 'kirki-toggle';
}
return $args;
}
}

View file

@ -0,0 +1,15 @@
import "./control.scss";
var kirkiCheckboxScript = {
initKirkiControl: function( control ) {
control = control || this;
control.container.on( 'change', 'input', function() {
control.setting.set( jQuery( this ).is( ':checked' ) );
} );
}
};
wp.customize.controlConstructor['kirki-checkbox'] = wp.customize.kirkiDynamicControl.extend( kirkiCheckboxScript );
wp.customize.controlConstructor['kirki-switch'] = wp.customize.kirkiDynamicControl.extend( kirkiCheckboxScript );
wp.customize.controlConstructor['kirki-toggle'] = wp.customize.kirkiDynamicControl.extend( kirkiCheckboxScript );

View file

@ -0,0 +1,126 @@
@import "scss/vars";
.customize-control-kirki-toggle {
.kirki-toggle {
display: flex;
align-items: flex-start;
justify-content: space-between;
.kirki-control-label {
width: 80%;
}
.kirki-control-form {
text-align: right;
width: 20%;
}
.kirki-toggle-switch-label {
width: 100%;
&::before {
right: 0;
}
&::after {
right: 18px;
}
}
}
}
.customize-control-kirki-switch {
.kirki-switch {
.kirki-toggle-switch-label {
padding: 10px 0 12px 44px;
text-align: left;
&::before {
left: 0;
}
&::after {
left: 0;
}
}
.toggle-on,
.toggle-off {
position: relative;
bottom: -2px;
padding-left: 5px;
}
.toggle-on {
display: none;
color: $color-wp-blue;
}
.toggle-off {
display: inline-block;
color: $color-dark-silver-gray;
}
}
}
.kirki-toggle-switch-label {
position: relative;
display: inline-block;
cursor: pointer;
&::before,
&::after {
box-sizing: border-box;
content: "";
position: absolute;
margin: 0;
outline: 0;
top: 50%;
transform: translate3d(0, -50%, 0);
transition: all 350ms cubic-bezier(0, 0.95, 0.38, 0.98),
background-color 150ms ease;
}
&::before {
width: 37px;
height: 14px;
// background-color: $color-silver-gray;
background-color: $color-light-silver-gray;
border: 1px solid $color-light-silver-gray;
border-radius: 8px;
}
&::after {
width: 22px;
height: 22px;
background-color: $color-medium-gray;
border-radius: 50%;
// box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.14), 0 2px 2px 0 rgba(0, 0, 0, 0.098), 0 1px 5px 0 rgba(0, 0, 0, 0.084);
border: 1px solid rgba(0, 0, 0, 0.1);
}
}
.kirki-toggle-switch-input {
opacity: 0;
&:checked {
+ .kirki-toggle-switch-label {
&::before {
// background-color: desaturate(lighten($color-wp-blue, 40%), 40%);
}
&::after {
background-color: $color-wp-blue;
transform: translate3d(100%, -50%, 0);
}
.toggle-on {
display: inline-block;
}
.toggle-off {
display: none;
}
}
}
}

View file

@ -0,0 +1,100 @@
// See https://make.wordpress.org/design/handbook/design-guide/foundations/colors/
// Colors copied from https://codepen.io/hugobaeta/pen/RNOzoV
$color-wp-blue: #0073aa;
$color-medium-blue: #00a0d2;
$color-light-blue: #00b9eb;
$color-ultra-dark-gray: #191e23;
$color-dark-gray: #23282d;
$color-base-gray: #32373c;
$color-dark-medium-gray: lighten($color-base-gray,15%);
$color-dark-silver-gray: #82878c;
$color-silver-gray: #a0a5aa;
$color-light-silver-gray: #b4b9be;
// $color-medium-gray: mix($color-base-gray,$color-dark-silver-gray,20%);
$color-medium-gray: #999;
$color-gray-900: $color-ultra-dark-gray;
$color-gray-800: $color-dark-gray;
$color-gray-700: $color-base-gray;
$color-gray-600: lighten($color-base-gray,6%);
$color-gray-500: lighten($color-base-gray,15%);
$color-gray-400: lighten($color-base-gray,20%);
$color-gray-300: lighten($color-base-gray,25%);
$color-gray-200: lighten($color-base-gray,32%);
$color-gray-100: lighten($color-base-gray,38%);
$color--gray-light-900: lighten($color-base-gray,45%);
$color--gray-light-800: lighten($color-base-gray,52%);
$color--gray-light-700: lighten($color-base-gray,60%);
$color--gray-light-600: lighten($color-base-gray,64%);
$color--gray-light-500: lighten($color-base-gray,68%);
$color--gray-light-400: lighten($color-base-gray,70%);
$color--gray-light-300: lighten($color-base-gray,72%);
$color--gray-light-200: lighten($color-base-gray,74%);
$color--gray-light-100: lighten($color-base-gray,77%);
$color-accent-red: #dc3232;
$color-accent-fire-orange: #d54e21;
$color-accent-orange: #f56e28;
$color-accent-yellow: #ffb900;
$color-accent-green: #46b450; //old #64b450;
$color-accent-blue: $color-medium-blue;
$color-accent-purple: #826eb4;
//Tints and Tones and Shades - Oh My!
$color-accent-red-shade30: shade($color-accent-red,30%);
$color-accent-red-shade20: shade($color-accent-red,20%);
$color-accent-red-shade10: shade($color-accent-red,10%);
$color-accent-red-tint20: tint($color-accent-red,20%);
$color-accent-red-tint40: tint($color-accent-red,40%);
$color-accent-red-tint60: tint($color-accent-red,60%);
$color-accent-red-tint90: tint($color-accent-red,90%);
$color-accent-fire-orange-shade10: shade($color-accent-fire-orange,10%);
$color-accent-fire-orange-shade5: shade($color-accent-fire-orange,5%);
$color-accent-orange-tint20: tint($color-accent-orange,20%);
$color-accent-orange-tint40: tint($color-accent-orange,40%);
$color-accent-orange-tint60: tint($color-accent-orange,60%);
$color-accent-orange-tint90: tint($color-accent-orange,90%);
$color-accent-yellow-tonefire40: mix($color-accent-fire-orange,$color-accent-yellow,40%);
$color-accent-yellow-tonefire20: mix($color-accent-fire-orange,$color-accent-yellow,20%);
$color-accent-yellow-tint20: tint($color-accent-yellow,20%);
$color-accent-yellow-tint40: tint($color-accent-yellow,40%);
$color-accent-yellow-tint60: tint($color-accent-yellow,60%);
$color-accent-yellow-tint90: tint($color-accent-yellow,90%);
$color-accent-green-toneblue5shade25: shade(mix($color-wp-blue, $color-accent-green,5%),25%);
$color-accent-green-toneblue5shade15: shade(mix($color-wp-blue, $color-accent-green,5%),15%);
$color-accent-green-tint20: tint($color-accent-green,20%);
$color-accent-green-tint40: tint($color-accent-green,40%);
$color-accent-green-tint60: tint($color-accent-green,60%);
$color-accent-green-tint70: tint($color-accent-green,70%);
$color-accent-green-tint90: tint($color-accent-green,90%);
$color-accent-wp-blue-shade10: shade($color-wp-blue,10%);
$color-accent-blue-toneblue80: mix($color-wp-blue,$color-accent-blue,80%);
$color-accent-blue-toneblue60: mix($color-wp-blue,$color-accent-blue,60%);
$color-accent-blue-toneblue40: mix($color-wp-blue,$color-accent-blue,40%);
$color-accent-blue-tint20: tint($color-accent-blue,20%);
$color-accent-blue-tint40: tint($color-accent-blue,40%);
$color-accent-blue-tint60: tint($color-accent-blue,60%);
$color-accent-blue-tint75: tint($color-accent-blue,75%);
$color-accent-blue-tint90: tint($color-accent-blue,90%);
$color-accent-purple-shade40: shade($color-accent-purple,40%);
$color-accent-purple-shade20: shade($color-accent-purple,20%);
$color-accent-purple-tint20: tint($color-accent-purple,20%);
$color-accent-purple-tint40: tint($color-accent-purple,40%);
$color-accent-purple-tint60: tint($color-accent-purple,60%);
$color-accent-purple-tint90: tint($color-accent-purple,90%);
//Text Colors
$textcolor-dark: rgba($color-base-gray,.8);
$textcolor-dark-mid: rgba($color-base-gray,.5);
$textcolor-light: rgba(#fff,.8);
$textcolor-light-mid: rgba(#fff,.5);

View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 kirki-framework
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -0,0 +1,125 @@
<?php
/**
* The code editor control.
*
* Creates a code editor control.
*
* @package kirki-framework/control-code
* @license MIT (https://oss.ninja/mit?organization=Kirki%20Framework)
* @since 1.0.2
*/
namespace Kirki\Control;
use Kirki\Control\Base;
/**
* Slider control.
*
* @since 1.0.2
*/
class Code extends Base {
/**
* The control version.
*
* @since 1.0.2
* @access public
* @var string
*/
public static $control_ver = '1.0.2';
/**
* Customize control type.
*
* @since 1.0.2
* @var string
*/
public $type = 'code_editor';
/**
* Type of code that is being edited.
*
* @since 1.0.2
* @var string
*/
public $code_type = '';
/**
* Code editor settings.
*
* @see wp_enqueue_code_editor()
* @since 1.0.2
* @var array|false
*/
public $editor_settings = array();
/**
* Enqueue control related scripts/styles.
*
* @since 1.0.2
*/
public function enqueue() {
$this->editor_settings = wp_enqueue_code_editor(
array_merge(
array(
'type' => $this->code_type,
'codemirror' => array(
'indentUnit' => 2,
'tabSize' => 2,
),
),
$this->editor_settings
)
);
}
/**
* Refresh the parameters passed to the JavaScript via JSON.
*
* @since 1.0.2
*
* @see WP_Customize_Control::json()
*
* @return array Array of parameters passed to the JavaScript.
*/
public function json() {
$json = parent::json();
$json['editor_settings'] = $this->editor_settings;
$json['input_attrs'] = $this->input_attrs;
return $json;
}
/**
* Don't render the control content from PHP, as it's rendered via JS on load.
*
* @since 1.0.2
*/
public function render_content() {}
/**
* Render a JS template for control display.
*
* @since 1.0.2
*/
public function content_template() {
?>
<# var elementIdPrefix = 'el' + String( Math.random() ); #>
<# if ( data.label ) { #>
<label for="{{ elementIdPrefix }}_editor" class="customize-control-title">
{{ data.label }}
</label>
<# } #>
<# if ( data.description ) { #>
<span class="description customize-control-description">{{{ data.description }}}</span>
<# } #>
<div class="customize-control-notifications-container"></div>
<textarea id="{{ elementIdPrefix }}_editor"
<# _.each( _.extend( { 'class': 'code' }, data.input_attrs ), function( value, key ) { #>
{{{ key }}}="{{ value }}"
<# }); #>
></textarea>
<?php
}
}

View file

@ -0,0 +1,140 @@
<?php
/**
* Override field methods
*
* @package kirki-framework/control-code
* @copyright Copyright (c) 2023, Themeum
* @license https://opensource.org/licenses/MIT
* @since 1.0
*/
namespace Kirki\Field;
use Kirki\Field;
/**
* Field overrides.
*/
class Code extends Field {
/**
* The field type.
*
* @access public
* @since 1.0
* @var string
*/
public $type = 'kirki-code';
/**
* The control class-name.
*
* @access protected
* @since 0.1
* @var string
*/
protected $control_class = '\Kirki\Control\Code';
/**
* Filter arguments before creating the setting.
*
* @access public
* @since 0.1
* @param array $args The field arguments.
* @param WP_Customize_Manager $wp_customize The customizer instance.
* @return array
*/
public function filter_setting_args( $args, $wp_customize ) {
if ( $args['settings'] === $this->args['settings'] ) {
$args = parent::filter_setting_args( $args, $wp_customize );
// Set the sanitize-callback if none is defined.
if ( ! isset( $args['sanitize_callback'] ) || ! $args['sanitize_callback'] ) {
$args['sanitize_callback'] = function( $value ) {
/**
* Code fields should not be filtered by default.
* Their values usually contain CSS/JS and it it the responsibility
* of the theme/plugin that registers this field
* to properly apply any necessary sanitization.
*/
return $value;
};
}
}
return $args;
}
/**
* Filter arguments before creating the control.
*
* @access public
* @since 0.1
* @param array $args The field arguments.
* @param WP_Customize_Manager $wp_customize The customizer instance.
* @return array
*/
public function filter_control_args( $args, $wp_customize ) {
if ( $args['settings'] === $this->args['settings'] ) {
$args = parent::filter_control_args( $args, $wp_customize );
$args['type'] = 'code_editor';
$args['input_attrs'] = [
'aria-describedby' => 'kirki-code editor-keyboard-trap-help-1 editor-keyboard-trap-help-2 editor-keyboard-trap-help-3 editor-keyboard-trap-help-4',
];
if ( ! isset( $args['choices']['language'] ) ) {
return;
}
$language = $args['choices']['language'];
switch ( $language ) {
case 'json':
case 'xml':
$language = 'application/' . $language;
break;
case 'http':
$language = 'message/' . $language;
break;
case 'js':
case 'javascript':
$language = 'text/javascript';
break;
case 'txt':
$language = 'text/plain';
break;
case 'css':
case 'jsx':
case 'html':
$language = 'text/' . $language;
break;
default:
$language = ( 'js' === $language ) ? 'javascript' : $language;
$language = ( 'htm' === $language ) ? 'html' : $language;
$language = ( 'yml' === $language ) ? 'yaml' : $language;
$language = 'text/x-' . $language;
break;
}
if ( ! isset( $args['editor_settings'] ) ) {
$args['editor_settings'] = [];
}
if ( ! isset( $args['editor_settings']['codemirror'] ) ) {
$args['editor_settings']['codemirror'] = [];
}
if ( ! isset( $args['editor_settings']['codemirror']['mode'] ) ) {
$args['editor_settings']['codemirror']['mode'] = $language;
}
if ( 'text/x-scss' === $args['editor_settings']['codemirror']['mode'] ) {
$args['editor_settings']['codemirror'] = array_merge(
$args['editor_settings']['codemirror'],
[
'lint' => false,
'autoCloseBrackets' => true,
'matchBrackets' => true,
]
);
}
}
return $args;
}
}

View file

@ -0,0 +1,2 @@
.customize-control-kirki-color-palette,.customize-control-kirki-color-palette *{box-sizing:border-box}.customize-control-kirki-color-palette .kirki-control-label{display:block;position:relative}.customize-control-kirki-color-palette .kirki-control-form{margin-bottom:6px;position:relative}.customize-control-kirki-color-palette .kirki-control-form:hover .kirki-control-reset{opacity:1}.customize-control-kirki-color-palette .kirki-control-reset{align-items:center;background-color:transparent;border-radius:50%;border-width:0;color:#50575e;cursor:pointer;display:flex;height:20px;justify-content:center;opacity:0;padding:0;position:absolute;right:0;top:0;transition:all .3s;width:20px;z-index:3}.customize-control-kirki-color-palette .kirki-control-reset:focus{opacity:1}.customize-control-kirki-color-palette .kirki-control-reset:hover i{color:red;transform:rotate(-45deg)}.customize-control-kirki-color-palette .kirki-control-reset i{font-size:12px;height:auto;transform:rotate(45deg);transition:transform .3s;width:auto}.customize-control-kirki-color-palette .kirki-colors{align-items:center;display:flex;flex-wrap:wrap;list-style:none;margin:0;padding:0;width:100%}.customize-control-kirki-color-palette .kirki-colors.kirki-round-colors .kirki-color div{border-radius:50%}.customize-control-kirki-color-palette .kirki-color{display:block;margin:0 11px 11px 0;padding:0;position:relative}.customize-control-kirki-color-palette .kirki-color:last-child{padding-right:0}.customize-control-kirki-color-palette .kirki-color>div{align-items:center;border:1px solid #dedede;border-radius:4px;cursor:pointer;display:flex;height:100%;justify-content:center;position:absolute;transform:scale(1);transition:transform .2s;width:100%}.customize-control-kirki-color-palette .kirki-color>div:hover{transform:scale(1.2)}.customize-control-kirki-color-palette .kirki-color.is-selected>div{border-color:#2271b1;border-width:4px}
/*# sourceMappingURL=control.css.map */

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,2 @@
(()=>{var t={};t=React;var e=e=>{const{control:o,customizerSetting:n,choices:i}=e,[a,c]=t.useState(e.value);o.updateComponentState=t=>{c(t)};const r=t=>{n.set(t.target.title)},s=i.size+2;return React.createElement("div",{className:"kirki-control-form",tabIndex:"1"},React.createElement("label",{className:"kirki-control-label"},React.createElement("span",{className:"customize-control-title"},e.label),React.createElement("span",{className:"customize-control-description description",dangerouslySetInnerHTML:{__html:e.description}})),React.createElement("div",{className:"customize-control-notifications-container",ref:e.setNotificationContainer}),React.createElement("button",{type:"button",className:"kirki-control-reset",onClick:()=>{""!==e.default&&void 0!==e.default?n.set(e.default):n.set(e.value)}},React.createElement("i",{className:"dashicons dashicons-image-rotate"})),React.createElement("ul",{className:"kirki-colors kirki-"+i.shape+"-colors"},i.colors.map(((t,e)=>{const o=t===a?"kirki-color is-selected":"kirki-color";return React.createElement("li",{key:e.toString(),className:o,style:{width:s+"px",height:s+"px"}},React.createElement("div",{title:t,style:{backgroundColor:t},onClick:r}))}))))};function o(){return o=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var o=arguments[e];for(var n in o)Object.prototype.hasOwnProperty.call(o,n)&&(t[n]=o[n])}return t},o.apply(this,arguments)}var n=wp.customize.Control.extend({initialize:function(t,e){const o=this;o.setNotificationContainer=o.setNotificationContainer.bind(o),wp.customize.Control.prototype.initialize.call(o,t,e),wp.customize.control.bind("removed",(function t(e){o===e&&(o.destroy(),o.container.remove(),wp.customize.control.unbind("removed",t))}))},setNotificationContainer:function(t){this.notifications.container=jQuery(t),this.notifications.render()},renderContent:function(){const t=this;ReactDOM.render(React.createElement(e,o({},t.params,{control:t,customizerSetting:t.setting,setNotificationContainer:t.setNotificationCotainer,value:t.params.value})),t.container[0]),!1!==t.params.choices.allowCollapse&&t.container.addClass("allowCollapse")},ready:function(){const t=this;t.setting.bind((e=>{t.updateComponentState(e)}))},updateComponentState:t=>{},destroy:function(){ReactDOM.unmountComponentAtNode(this.container[0]),wp.customize.Control.prototype.destroy&&wp.customize.Control.prototype.destroy.call(this)}});wp.customize.controlConstructor["kirki-color-palette"]=n})();
//# sourceMappingURL=control.js.map

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,123 @@
<?php
/**
* The slider control.
*
* Creates a slider control.
*
* @package kirki-framework/control-slider
* @license MIT (https://oss.ninja/mit?organization=Kirki%20Framework)
* @since 1.0
*/
namespace Kirki\Control;
use Kirki\Control\Base;
use Kirki\URL;
/**
* Color Palette control.
*
* @since 1.0
*/
class Color_Palette extends Base {
/**
* The control type.
*
* @since 1.0
* @access public
* @var string
*/
public $type = 'kirki-color-palette';
/**
* The control version.
*
* @since 1.0
* @access public
* @var string
*/
public static $control_ver = '1.0';
/**
* Enqueue control related styles/scripts.
*
* @since 1.0
* @access public
*/
public function enqueue() {
parent::enqueue();
// Enqueue the style.
wp_enqueue_style( 'kirki-color-palette-control', URL::get_from_path( dirname( dirname( __DIR__ ) ) . '/dist/control.css' ), [], self::$control_ver );
// Enqueue the script.
wp_enqueue_script( 'kirki-color-palette-control', URL::get_from_path( dirname( dirname( __DIR__ ) ) . '/dist/control.js' ), [ 'jquery', 'customize-controls', 'customize-base', 'react-dom' ], self::$control_ver, false );
}
/**
* Refresh the parameters passed to the JavaScript via JSON.
*
* @see WP_Customize_Control::to_json()
*
* @since 1.0
* @access public
*/
public function to_json() {
parent::to_json();
if ( isset( $this->json['label'] ) ) {
$this->json['label'] = html_entity_decode( $this->json['label'] );
}
if ( isset( $this->json['description'] ) ) {
$this->json['description'] = html_entity_decode( $this->json['description'] );
}
$this->json['value'] = strtolower( $this->json['value'] );
$choices = $this->json['choices'];
$this->json['choices'] = wp_parse_args(
$choices,
[
'shape' => 'square',
'size' => 28,
'colors' => [],
]
);
$this->json['choices']['colors'] = array_map( 'strtolower', $this->json['choices']['colors'] );
if ( isset( $choices['style'] ) && ! empty( $choices['style'] ) ) {
if ( ! isset( $choices['shape'] ) || empty( $choices['shape'] ) ) {
$this->json['choices']['shape'] = $choices['style'];
}
unset( $this->json['choices']['style'] );
}
if ( ! is_numeric( $this->json['choices']['size'] ) ) {
$this->json['choices']['size'] = 28;
}
$this->json['choices']['shape'] = 'circle' === $this->json['choices']['shape'] ? 'round' : $this->json['choices']['shape'];
}
/**
* An Underscore (JS) template for this control's content (but not its container).
*
* Class variables for this control class are available in the `data` JS object;
* export custom variables by overriding WP_Customize_Control::to_json().
*
* @see WP_Customize_Control::print_template()
*
* @since 1.0
*/
protected function content_template() {}
}

View file

@ -0,0 +1,147 @@
<?php
/**
* Override field methods.
*
* @package kirki-framework/control-slider
* @license MIT (https://oss.ninja/mit?organization=Kirki%20Framework)
* @since 1.0
*/
namespace Kirki\Field;
use Kirki\Field;
/**
* Field overrides.
*
* @since 1.0
*/
class Color_Palette extends Field {
/**
* The field type.
*
* @since 1.0
* @access public
* @var string
*/
public $type = 'kirki-color-palette';
/**
* The control class-name.
*
* @since 1.0
* @access protected
* @var string
*/
protected $control_class = '\Kirki\Control\Color_Palette';
/**
* Whether we should register the control class for JS-templating or not.
*
* @since 1.0
* @access protected
* @var bool
*/
protected $control_has_js_template = true;
/**
* Filter arguments before creating the setting.
*
* @param array $args The field arguments.
* @param \WP_Customize_Manager $wp_customize The customizer instance.
*
* @return array $args The maybe-filtered arguments.
*/
public function filter_setting_args( $args, $wp_customize ) {
if ( $args['settings'] === $this->args['settings'] ) {
$args = parent::filter_setting_args( $args, $wp_customize );
// Set the sanitize_callback if none is defined.
if ( ! isset( $args['sanitize_callback'] ) || ! $args['sanitize_callback'] ) {
$args['sanitize_callback'] = [ __CLASS__, 'sanitize' ];
}
}
return $args;
}
/**
* Filter arguments before creating the control.
*
* @param array $args The field arguments.
* @param \WP_Customize_Manager $wp_customize The customizer instance.
*
* @return array $args The maybe-filtered arguments.
*/
public function filter_control_args( $args, $wp_customize ) {
if ( $args['settings'] === $this->args['settings'] ) {
$args = parent::filter_control_args( $args, $wp_customize );
$args['type'] = 'kirki-color-palette';
}
return $args;
}
/**
* Sanitize colors.
*
* @static
* @access public
* @since 1.0.2
* @param string $value The color.
* @return string
*/
public static function sanitize( $value ) {
/**
* This pattern will check and match 3/6/8-character hex, rgb, rgba, hsl, hsla, hsv, and hsva colors.
*
* RGB regex:
* @link https://stackoverflow.com/questions/9585973/javascript-regular-expression-for-rgb-values#answer-9586045
*
* For testing it, you can use these links:
*
* @link https://regex101.com/
* @link https://regexr.com/
* @link https://www.regextester.com/
*
* How to test it?
*
* Paste the following code to the test field (of course without the asterisks and spaces in front of them):
* rgba(255, 255, 0, 0.9)
* rgb(255, 255, 0)
* #ff0
* #ffff00
* hsl(150, 25%, 25%)
* hsla(250, 25%, 25%, 0.7)
* hsv(125, 15%, 30%)
* hsva(125, 15%, 30%, 0.5)
*
* And then paste the regex `$pattern` below (without the single quote's start and end) to the regular expression box.
* Set the flag to use "global" and "multiline".
*/
$pattern = '/^(\#[\da-f]{3}|\#[\da-f]{6}|\#[\da-f]{8}|rgba\(((\d{1,2}|1\d\d|2([0-4]\d|5[0-5]))\s*,\s*){2}((\d{1,2}|1\d\d|2([0-4]\d|5[0-5]))\s*)(,\s*(0\.\d+|1))\)|rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)|hsla\(\s*((\d{1,2}|[1-2]\d{2}|3([0-5]\d|60)))\s*,\s*((\d{1,2}|100)\s*%)\s*,\s*((\d{1,2}|100)\s*%)(,\s*(0\.\d+|1))\)|hsl\(\s*((\d{1,2}|[1-2]\d{2}|3([0-5]\d|60)))\s*,\s*((\d{1,2}|100)\s*%)\s*,\s*((\d{1,2}|100)\s*%)\)|hsva\(\s*((\d{1,2}|[1-2]\d{2}|3([0-5]\d|60)))\s*,\s*((\d{1,2}|100)\s*%)\s*,\s*((\d{1,2}|100)\s*%)(,\s*(0\.\d+|1))\)|hsv\(\s*((\d{1,2}|[1-2]\d{2}|3([0-5]\d|60)))\s*,\s*((\d{1,2}|100)\s*%)\s*,\s*((\d{1,2}|100)\s*%)\))$/';
\preg_match( $pattern, $value, $matches );
// Return the 1st match found.
if ( isset( $matches[0] ) ) {
if ( is_string( $matches[0] ) ) {
return $matches[0];
}
if ( is_array( $matches[0] ) && isset( $matches[0][0] ) ) {
return $matches[0][0];
}
}
// If no match was found, return an empty string.
return '';
}
}

View file

@ -0,0 +1,128 @@
import KirkiColorPaletteForm from './KirkiColorPaletteForm';
/**
* KirkiColorPaletteControl.
*
* Global objects brought:
* - wp
* - jQuery
* - React
* - ReactDOM
*
* @class
* @augments wp.customize.Control
* @augments wp.customize.Class
*/
const KirkiColorPaletteControl = wp.customize.Control.extend({
/**
* Initialize.
*
* @param {string} id - Control ID.
* @param {object} params - Control params.
*/
initialize: function (id, params) {
const control = this;
// Bind functions to this control context for passing as React props.
control.setNotificationContainer = control.setNotificationContainer.bind(control);
wp.customize.Control.prototype.initialize.call(control, id, params);
// The following should be eliminated with <https://core.trac.wordpress.org/ticket/31334>.
function onRemoved(removedControl) {
if (control === removedControl) {
control.destroy();
control.container.remove();
wp.customize.control.unbind('removed', onRemoved);
}
}
wp.customize.control.bind('removed', onRemoved);
},
/**
* Set notification container and render.
*
* This is called when the React component is mounted.
*
* @param {Element} element - Notification container.
* @returns {void}
*/
setNotificationContainer: function setNotificationContainer(element) {
const control = this;
control.notifications.container = jQuery(element);
control.notifications.render();
},
/**
* Render the control into the DOM.
*
* This is called from the Control#embed() method in the parent class.
*
* @returns {void}
*/
renderContent: function renderContent() {
const control = this;
ReactDOM.render(
<KirkiColorPaletteForm
{...control.params}
control={control}
customizerSetting={control.setting}
setNotificationContainer={control.setNotificationCotainer}
value={control.params.value}
/>,
control.container[0]
);
if (false !== control.params.choices.allowCollapse) {
control.container.addClass('allowCollapse');
}
},
/**
* After control has been first rendered, start re-rendering when setting changes.
*
* React is able to be used here instead of the wp.customize.Element abstraction.
*
* @returns {void}
*/
ready: function ready() {
const control = this;
/**
* Update component value's state when customizer setting's value is changed.
*/
control.setting.bind((val) => {
control.updateComponentState(val);
});
},
/**
* This method will be overriden by the rendered component.
*/
updateComponentState: (val) => { },
/**
* Handle removal/de-registration of the control.
*
* This is essentially the inverse of the Control#embed() method.
*
* @link https://core.trac.wordpress.org/ticket/31334
* @returns {void}
*/
destroy: function destroy() {
const control = this;
// Garbage collection: undo mounting that was done in the embed/renderContent method.
ReactDOM.unmountComponentAtNode(control.container[0]);
// Call destroy method in parent if it exists (as of #31334).
if (wp.customize.Control.prototype.destroy) {
wp.customize.Control.prototype.destroy.call(control);
}
}
});
export default KirkiColorPaletteControl;

View file

@ -0,0 +1,78 @@
import { useState } from "react";
const KirkiColorPaletteForm = (props) => {
const { control, customizerSetting, choices } = props;
const [selectedItem, setSelectedItem] = useState(props.value);
control.updateComponentState = (val) => {
setSelectedItem(val);
};
const handleSelect = (e) => {
customizerSetting.set(e.target.title);
};
const handleReset = () => {
if ("" !== props.default && "undefined" !== typeof props.default) {
customizerSetting.set(props.default);
} else {
customizerSetting.set(props.value);
}
};
const size = choices.size + 2; // 2 here is 1px border on each side.
return (
<div className="kirki-control-form" tabIndex="1">
<label className="kirki-control-label">
<span className="customize-control-title">{props.label}</span>
<span
className="customize-control-description description"
dangerouslySetInnerHTML={{ __html: props.description }}
/>
</label>
<div
className="customize-control-notifications-container"
ref={props.setNotificationContainer}
></div>
<button
type="button"
className="kirki-control-reset"
onClick={handleReset}
>
<i className="dashicons dashicons-image-rotate"></i>
</button>
<ul className={"kirki-colors kirki-" + choices.shape + "-colors"}>
{choices.colors.map((color, index) => {
const itemClassName =
color === selectedItem ? "kirki-color is-selected" : "kirki-color";
return (
<li
key={index.toString()}
className={itemClassName}
style={{
width: size + "px",
height: size + "px",
}}
>
<div
title={color}
style={{
backgroundColor: color,
}}
onClick={handleSelect}
></div>
</li>
);
})}
</ul>
</div>
);
};
export default KirkiColorPaletteForm;

View file

@ -0,0 +1,6 @@
import "./control.scss";
import KirkiColorPaletteControl from './KirkiColorPaletteControl';
// Register control type with Customizer.
wp.customize.controlConstructor['kirki-color-palette'] = KirkiColorPaletteControl;

View file

@ -0,0 +1,115 @@
// Color palette control.
.customize-control-kirki-color-palette,
.customize-control-kirki-color-palette * {
box-sizing: border-box;
}
.customize-control-kirki-color-palette {
.kirki-control-label {
position: relative;
display: block;
}
.kirki-control-form {
position: relative;
margin-bottom: 6px;
&:hover {
.kirki-control-reset {
opacity: 1;
}
}
}
.kirki-control-reset {
display: flex;
align-items: center;
justify-content: center;
right: 0;
top: 0;
position: absolute;
padding: 0;
width: 20px;
height: 20px;
color: #50575e;
background-color: transparent;
border-radius: 50%;
border-width: 0;
opacity: 0;
cursor: pointer;
transition: all 0.3s;
z-index: 3;
// a11y: support tab focus.
&:focus {
opacity: 1;
}
}
.kirki-control-reset:hover i {
color: #f00;
transform: rotate(-45deg);
}
.kirki-control-reset i {
font-size: 12px;
width: auto;
height: auto;
transform: rotate(45deg);
transition: transform 0.3s;
}
.kirki-colors {
display: flex;
align-items: center;
flex-wrap: wrap;
width: 100%;
margin: 0;
padding: 0;
list-style: none;
&.kirki-round-colors {
.kirki-color {
div {
border-radius: 50%;
}
}
}
}
.kirki-color {
position: relative;
display: block;
margin: 0 11px 11px 0;
padding: 0;
&:last-child {
padding-right: 0;
}
> div {
display: flex;
align-items: center;
justify-content: center;
position: absolute;
width: 100%;
height: 100%;
border-radius: 4px;
border: 1px solid #dedede;
transform: scale(1);
cursor: pointer;
transition: transform 0.2s;
&:hover {
transform: scale(1.2);
}
}
&.is-selected {
> div {
border-color: #2271b1;
border-width: 4px;
}
}
}
}

View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 kirki-framework
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -0,0 +1,23 @@
<?php
/**
* Object used by the Kirki framework to instantiate the control.
*
* This is a man-in-the-middle class, nothing but a proxy to set sanitization
* callbacks and any usother properties we may need.
*
* @package kirki-framework/control-color
* @copyright Copyright (c) 2023, Themeum
* @license https://opensource.org/licenses/MIT
* @since 1.0
*/
namespace Kirki\Field;
use Kirki\Field;
/**
* Field overrides.
*
* @since 1.0
*/
class Color extends ReactColorful {}

View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 kirki-framework
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -0,0 +1,28 @@
<?php
/**
* Customizer Control: cropped-image.
*
* @package kirki-framework/control-cropped-image
* @copyright Copyright (c) 2023, Themeum
* @license https://opensource.org/licenses/MIT
* @since 1.0
*/
namespace Kirki\Control;
/**
* Adds the image control.
*
* @since 1.0
*/
class Cropped_Image extends \WP_Customize_Cropped_Image_Control {
/**
* The field type.
*
* @access public
* @since 1.0
* @var string
*/
public $type = 'kirki-cropped-image';
}

View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 kirki-framework
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -0,0 +1,64 @@
<?php
/**
* Customizer Control: custom.
*
* Creates a new custom control.
* Custom controls accept raw HTML/JS.
*
* @package kirki-framework/control-custom
* @copyright Copyright (c) 2023, Themeum
* @license https://opensource.org/licenses/MIT
* @since 1.0
*/
namespace Kirki\Control;
use Kirki\Control\Base;
/**
* The "custom" control allows you to add any raw HTML.
*
* @since 1.0
*/
class Custom extends Base {
/**
* The control type.
*
* @access public
* @since 1.0
* @var string
*/
public $type = 'kirki-custom';
/**
* An Underscore (JS) template for this control's content (but not its container).
*
* Class variables for this control class are available in the `data` JS object;
* export custom variables by overriding {@see WP_Customize_Control::to_json()}.
*
* @see WP_Customize_Control::print_template()
*
* @access protected
* @since 1.0
* @return void
*/
protected function content_template() {
?>
<label>
<# if ( data.label ) { #><span class="customize-control-title">{{{ data.label }}}</span><# } #>
<# if ( data.description ) { #><span class="description customize-control-description">{{{ data.description }}}</span><# } #>
<?php
/**
* The value is defined by the developer in the field configuration as 'default'.
* There is no user input on this field, it's a raw HTML/JS field and we do not sanitize it.
* Do not be alarmed, this is not a security issue.
* In order for someone to be able to change this they would have to have access to your filesystem.
* If that happens, they can change whatever they want anyways. This field is not a concern.
*/
?>
{{{ data.value }}}
</label>
<?php
}
}

View file

@ -0,0 +1,84 @@
<?php
/**
* Override field methods when used with the Kirki API.
*
* @package kirki-framework/control-custom
* @copyright Copyright (c) 2023, Themeum
* @license https://opensource.org/licenses/MIT
* @since 1.0
*/
namespace Kirki\Field;
use Kirki\Field;
/**
* Field overrides.
*
* @since 1.0
*/
class Custom extends Field {
/**
* The field type.
*
* @access public
* @since 1.0
* @var string
*/
public $type = 'kirki-custom';
/**
* The control class-name.
*
* @access protected
* @since 0.1
* @var string
*/
protected $control_class = '\Kirki\Control\Custom';
/**
* Whether we should register the control class for JS-templating or not.
*
* @access protected
* @since 0.1
* @var bool
*/
protected $control_has_js_template = true;
/**
* Filter arguments before creating the setting.
*
* @access public
* @since 0.1
* @param array $args The field arguments.
* @param WP_Customize_Manager $wp_customize The customizer instance.
* @return array
*/
public function filter_setting_args( $args, $wp_customize ) {
if ( $args['settings'] === $this->args['settings'] ) {
$args = parent::filter_setting_args( $args, $wp_customize );
if ( ! isset( $args['sanitize_callback'] ) || ! $args['sanitize_callback'] ) {
$args['sanitize_callback'] = '__return_null';
}
}
return $args;
}
/**
* Filter arguments before creating the control.
*
* @access public
* @since 0.1
* @param array $args The field arguments.
* @param WP_Customize_Manager $wp_customize The customizer instance.
* @return array
*/
public function filter_control_args( $args, $wp_customize ) {
if ( $args['settings'] === $this->args['settings'] ) {
$args = parent::filter_control_args( $args, $wp_customize );
$args['type'] = 'kirki-custom';
}
return $args;
}
}

View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 kirki-framework
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -0,0 +1,2 @@
.customize-control-kirki-dashicons{position:relative}.customize-control-kirki-dashicons label{display:inline-block;position:relative}.customize-control-kirki-dashicons .icons-wrapper{max-height:300px;overflow-y:scroll}.customize-control-kirki-dashicons .icons-wrapper h4{font-weight:300;margin:.7em 0}.customize-control-kirki-dashicons .icons-wrapper .dashicons{border:1px solid transparent;font-size:25px;height:25px;padding:3px;width:25px}.customize-control-kirki-dashicons .icons-wrapper input{display:none}.customize-control-kirki-dashicons .icons-wrapper input:checked+label .dashicons{border:1px solid #3498db;color:#000}
/*# sourceMappingURL=control.css.map */

View file

@ -0,0 +1 @@
{"mappings":"AAAA,mCACE,iBCCF,CDCE,yCAEE,oBAAA,CADA,iBCEJ,CDEE,kDACE,gBAAA,CACA,iBCAJ,CDEI,qDACE,eAAA,CACA,aCAN,CDGI,6DAKE,4BAAA,CAHA,cAAA,CAEA,WAAA,CAHA,WAAA,CAEA,UCCN,CDII,wDACE,YCFN,CDMU,iFACE,wBAAA,CACA,UCJZ","sources":["src/control.scss","%3Cinput%20css%20xiOUbS%3E"],"sourcesContent":[".customize-control-kirki-dashicons {\r\n position: relative;\r\n\r\n label {\r\n position: relative;\r\n display: inline-block;\r\n }\r\n\r\n .icons-wrapper {\r\n max-height: 300px;\r\n overflow-y: scroll;\r\n\r\n h4 {\r\n font-weight: 300;\r\n margin: 0.7em 0;\r\n }\r\n\r\n .dashicons {\r\n padding: 3px;\r\n font-size: 25px;\r\n width: 25px;\r\n height: 25px;\r\n border: 1px solid transparent;\r\n }\r\n\r\n input {\r\n display: none;\r\n\r\n &:checked {\r\n + label {\r\n .dashicons {\r\n border: 1px solid #3498DB;\r\n color: #000;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n}\r\n",".customize-control-kirki-dashicons {\n position: relative;\n}\n.customize-control-kirki-dashicons label {\n position: relative;\n display: inline-block;\n}\n.customize-control-kirki-dashicons .icons-wrapper {\n max-height: 300px;\n overflow-y: scroll;\n}\n.customize-control-kirki-dashicons .icons-wrapper h4 {\n font-weight: 300;\n margin: 0.7em 0;\n}\n.customize-control-kirki-dashicons .icons-wrapper .dashicons {\n padding: 3px;\n font-size: 25px;\n width: 25px;\n height: 25px;\n border: 1px solid transparent;\n}\n.customize-control-kirki-dashicons .icons-wrapper input {\n display: none;\n}\n.customize-control-kirki-dashicons .icons-wrapper input:checked + label .dashicons {\n border: 1px solid #3498DB;\n color: #000;\n}\n/*# sourceMappingURL=control.css.map */\n"],"names":[],"version":3,"file":"control.css.map"}

View file

@ -0,0 +1,2 @@
wp.customize.controlConstructor["kirki-dashicons"]=wp.customize.kirkiDynamicControl.extend({});
//# sourceMappingURL=control.js.map

View file

@ -0,0 +1 @@
{"mappings":"AAEAA,GAAGC,UAAUC,mBAAkB,mBAAsBF,GAAGC,UAAUE,oBAAoBC,OAAM","sources":["src/control.js"],"sourcesContent":["import \"./control.scss\";\n\nwp.customize.controlConstructor['kirki-dashicons'] = wp.customize.kirkiDynamicControl.extend( {} );\n"],"names":["wp","customize","controlConstructor","kirkiDynamicControl","extend"],"version":3,"file":"control.js.map"}

View file

@ -0,0 +1,140 @@
<?php
/**
* Customizer Control: dashicons.
*
* @package kirki-framework/control-dashicons
* @copyright Copyright (c) 2023, Themeum
* @license https://opensource.org/licenses/MIT
* @since 1.0
*/
namespace Kirki\Control;
use Kirki\URL;
use Kirki\Control\Base;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Dashicons control (modified radio).
*
* @since 1.0
*/
class Dashicons extends Base {
/**
* The control type.
*
* @access public
* @since 1.0
* @var string
*/
public $type = 'kirki-dashicons';
/**
* The version. Used in scripts & styles for cache-busting.
*
* @static
* @access public
* @since 1.0.2
* @var string
*/
public static $control_ver = '1.0';
/**
* Enqueue control related scripts/styles.
*
* @access public
* @since 1.0
* @return void
*/
public function enqueue() {
parent::enqueue();
// Enqueue the script.
wp_enqueue_script( 'kirki-control-dashicons', URL::get_from_path( dirname(dirname( __DIR__ )) . '/dist/control.js' ), [ 'jquery', 'customize-base', 'kirki-control-base' ], self::$control_ver, false );
// Enqueue the style.
wp_enqueue_style( 'kirki-control-dashicons-style', URL::get_from_path( dirname(dirname( __DIR__ )) . '/dist/control.css' ), [ 'dashicons' ], self::$control_ver );
}
/**
* Refresh the parameters passed to the JavaScript via JSON.
*
* @access public
* @since 1.0
* @return void
*/
public function to_json() {
parent::to_json();
$this->json['icons'] = \Kirki\Util\Dashicons::get_icons();
}
/**
* An Underscore (JS) template for this control's content (but not its container).
*
* Class variables for this control class are available in the `data` JS object;
* export custom variables by overriding {@see WP_Customize_Control::to_json()}.
*
* @see WP_Customize_Control::print_template()
*
* @access protected
* @since 1.0
* @return void
*/
protected function content_template() {
?>
<# if ( data.label ) { #><span class="customize-control-title">{{{ data.label }}}</span><# } #>
<# if ( data.description ) { #><span class="description customize-control-description">{{{ data.description }}}</span><# } #>
<div class="icons-wrapper">
<# if ( ! _.isUndefined( data.choices ) && 1 < _.size( data.choices ) ) { #>
<# for ( key in data.choices ) { #>
<input {{{ data.inputAttrs }}} class="dashicons-select" type="radio" value="{{ key }}" name="_customize-dashicons-radio-{{ data.id }}" id="{{ data.id }}{{ key }}" {{{ data.link }}}<# if ( data.value === key ) { #> checked="checked"<# } #>>
<label for="{{ data.id }}{{ key }}"><span class="dashicons dashicons-{{ data.choices[ key ] }}"></span></label>
</input>
<# } #>
<# } else { #>
<#
var dashiconSections = {
'admin-menu': '<?php esc_html_e( 'Admin Menu', 'kirki' ); ?>',
'welcome-screen': '<?php esc_html_e( 'Welcome Screen', 'kirki' ); ?>',
'post-formats': '<?php esc_html_e( 'Post Formats', 'kirki' ); ?>',
'media': '<?php esc_html_e( 'Media', 'kirki' ); ?>',
'image-editing': '<?php esc_html_e( 'Image Editing', 'kirki' ); ?>',
'tinymce': 'TinyMCE',
'posts': '<?php esc_html_e( 'Posts', 'kirki' ); ?>',
'sorting': '<?php esc_html_e( 'Sorting', 'kirki' ); ?>',
'social': '<?php esc_html_e( 'Social', 'kirki' ); ?>',
'wordpress_org': 'WordPress',
'products': '<?php esc_html_e( 'Products', 'kirki' ); ?>',
'taxonomies': '<?php esc_html_e( 'Taxonomies', 'kirki' ); ?>',
'widgets': '<?php esc_html_e( 'Widgets', 'kirki' ); ?>',
'notifications': '<?php esc_html_e( 'Notifications', 'kirki' ); ?>',
'misc': '<?php esc_html_e( 'Miscelaneous', 'kirki' ); ?>'
};
#>
<# _.each( dashiconSections, function( sectionLabel, sectionKey ) { #>
<h4>{{ sectionLabel }}</h4>
<# for ( key in data.icons[ sectionKey ] ) { #>
<input {{{ data.inputAttrs }}}
class="dashicons-select"
type="radio"
value="{{ data.icons[ sectionKey ][ key ] }}"
name="_customize-dashicons-radio-{{ data.id }}"
id="{{ data.id }}{{ data.icons[ sectionKey ][ key ] }}"
{{{ data.link }}}
<# if ( data.value === data.icons[ sectionKey ][ key ] ) { #> checked="checked"<# } #>>
<label for="{{ data.id }}{{ data.icons[ sectionKey ][ key ] }}">
<span class="dashicons dashicons-{{ data.icons[ sectionKey ][ key ] }}"></span>
</label>
</input>
<# } #>
<# }); #>
<# } #>
</div>
<?php
}
}

View file

@ -0,0 +1,84 @@
<?php
/**
* Override field methods
*
* @package kirki-framework/control-dashicons
* @copyright Copyright (c) 2023, Themeum
* @license https://opensource.org/licenses/MIT
* @since 1.0
*/
namespace Kirki\Field;
use Kirki\Field;
/**
* Field overrides.
*/
class Dashicons extends Field {
/**
* The field type.
*
* @access public
* @since 1.0
* @var string
*/
public $type = 'kirki-dashicons';
/**
* The control class-name.
*
* @access protected
* @since 0.1
* @var string
*/
protected $control_class = '\Kirki\Control\Dashicons';
/**
* Whether we should register the control class for JS-templating or not.
*
* @access protected
* @since 0.1
* @var bool
*/
protected $control_has_js_template = true;
/**
* Filter arguments before creating the setting.
*
* @access public
* @since 0.1
* @param array $args The field arguments.
* @param WP_Customize_Manager $wp_customize The customizer instance.
* @return array
*/
public function filter_setting_args( $args, $wp_customize ) {
if ( $args['settings'] === $this->args['settings'] ) {
$args = parent::filter_setting_args( $args, $wp_customize );
// Set the sanitize-callback if none is defined.
if ( ! isset( $args['sanitize_callback'] ) || ! $args['sanitize_callback'] ) {
$args['sanitize_callback'] = 'sanitize_text_field';
}
}
return $args;
}
/**
* Filter arguments before creating the control.
*
* @access public
* @since 0.1
* @param array $args The field arguments.
* @param WP_Customize_Manager $wp_customize The customizer instance.
* @return array
*/
public function filter_control_args( $args, $wp_customize ) {
if ( $args['settings'] === $this->args['settings'] ) {
$args = parent::filter_control_args( $args, $wp_customize );
$args['type'] = 'kirki-dashicons';
}
return $args;
}
}

View file

@ -0,0 +1,47 @@
<?php
/**
* Helper methods for dashicons.
*
* @package kirki-framework/control-dashicons
* @category Core
* @author Themeum
* @copyright Copyright (c) 2023, Themeum
* @license https://opensource.org/licenses/MIT
* @since 1.0
*/
namespace Kirki\Util;
/**
* A simple object containing static methods.
*/
class Dashicons {
/**
* Get an array of all available dashicons.
*
* @static
* @access public
* @since 1.0
* @return array
*/
public static function get_icons() {
return [
'admin-menu' => [ 'menu', 'menu-alt', 'menu-alt2', 'menu-alt3', 'admin-site', 'admin-site-alt', 'admin-site-alt2', 'admin-site-alt3', 'dashboard', 'admin-post', 'admin-media', 'admin-links', 'admin-page', 'admin-comments', 'admin-appearance', 'admin-plugins', 'plugins-checked', 'admin-users', 'admin-tools', 'admin-settings', 'admin-network', 'admin-home', 'admin-generic', 'admin-collapse', 'filter', 'admin-customizer', 'admin-multisite' ],
'welcome-screen' => [ 'welcome-write-blog', 'welcome-add-page', 'welcome-view-site', 'welcome-widgets-menus', 'welcome-comments', 'welcome-learn-more' ],
'post-formats' => [ 'format-aside', 'format-image', 'format-gallery', 'format-video', 'format-status', 'format-quote', 'format-chat', 'format-audio', 'camera', 'camera-alt', 'images-alt', 'images-alt2', 'video-alt', 'video-alt2', 'video-alt3' ],
'media' => [ 'media-archive', 'media-audio', 'media-code', 'media-default', 'media-document', 'media-interactive', 'media-spreadsheet', 'media-text', 'media-video', 'playlist-audio', 'playlist-video', 'controls-play', 'controls-pause', 'controls-forward', 'controls-skipforward', 'controls-back', 'controls-skipback', 'controls-repeat', 'controls-volumeon', 'controls-volumeoff' ],
'image-editing' => [ 'image-crop', 'image-rotate', 'image-rotate-left', 'image-rotate-right', 'image-flip-vertical', 'image-flip-horizontal', 'image-filter', 'undo', 'redo' ],
'tinymce' => [ 'editor-bold', 'editor-italic', 'editor-ul', 'editor-ol', 'editor-ol-rtl', 'editor-quote', 'editor-alignleft', 'editor-aligncenter', 'editor-alignright', 'editor-insertmore', 'editor-spellcheck', 'editor-expand', 'editor-contract', 'editor-kitchensink', 'editor-underline', 'editor-justify', 'editor-textcolor', 'editor-paste-word', 'editor-paste-text', 'editor-removeformatting', 'editor-video', 'editor-customchar', 'editor-outdent', 'editor-indent', 'editor-help', 'editor-strikethrough', 'editor-unlink', 'editor-rtl', 'editor-ltr', 'editor-break', 'editor-code', 'editor-paragraph', 'editor-table' ],
'posts' => [ 'align-left', 'align-right', 'align-center', 'align-none', 'lock', 'unlock', 'calendar', 'calendar-alt', 'visibility', 'hidden', 'post-status', 'edit', 'trash', 'sticky' ],
'sorting' => [ 'external', 'arrow-up', 'arrow-down', 'arrow-right', 'arrow-left', 'arrow-up-alt', 'arrow-down-alt', 'arrow-right-alt', 'arrow-left-alt', 'arrow-up-alt2', 'arrow-down-alt2', 'arrow-right-alt2', 'arrow-left-alt2', 'sort', 'leftright', 'randomize', 'list-view', 'exerpt-view', 'grid-view', 'move' ],
'social' => [ 'share', 'share-alt', 'share-alt2', 'twitter', 'rss', 'email', 'email-alt', 'email-alt2', 'facebook', 'facebook-alt', 'googleplus', 'networking', 'instagram' ],
'wordpress_org' => [ 'hammer', 'art', 'migrate', 'performance', 'universal-access', 'universal-access-alt', 'tickets', 'nametag', 'clipboard', 'heart', 'megaphone', 'schedule', 'tide', 'rest-api', 'code-standards' ],
'products' => [ 'wordpress', 'wordpress-alt', 'pressthis', 'update', 'update-alt', 'screenoptions', 'info', 'cart', 'feedback', 'cloud', 'translation' ],
'taxonomies' => [ 'tag', 'category' ],
'widgets' => [ 'archive', 'tagcloud', 'text' ],
'notifications' => [ 'yes', 'yes-alt', 'no', 'no-alt', 'plus', 'plus-alt', 'minus', 'dismiss', 'marker', 'star-filled', 'star-half', 'star-empty', 'flag', 'warning' ],
'misc' => [ 'location', 'location-alt', 'vault', 'shield', 'shield-alt', 'sos', 'search', 'slides', 'text-page', 'analytics', 'chart-pie', 'chart-bar', 'chart-line', 'chart-area', 'groups', 'businessman', 'businesswoman', 'businessperson', 'id', 'id-alt', 'products', 'awards', 'forms', 'testimonial', 'portfolio', 'book', 'book-alt', 'download', 'upload', 'backup', 'clock', 'lightbulb', 'microphone', 'desktop', 'tablet', 'smartphone', 'phone', 'index-card', 'carrot', 'building', 'store', 'album', 'palmtree', 'tickets-alt', 'money', 'smiley', 'thumbs-up', 'thumbs-down', 'layout', 'paperclip' ],
];
}
}

View file

@ -0,0 +1,3 @@
import "./control.scss";
wp.customize.controlConstructor['kirki-dashicons'] = wp.customize.kirkiDynamicControl.extend( {} );

View file

@ -0,0 +1,39 @@
.customize-control-kirki-dashicons {
position: relative;
label {
position: relative;
display: inline-block;
}
.icons-wrapper {
max-height: 300px;
overflow-y: scroll;
h4 {
font-weight: 300;
margin: 0.7em 0;
}
.dashicons {
padding: 3px;
font-size: 25px;
width: 25px;
height: 25px;
border: 1px solid transparent;
}
input {
display: none;
&:checked {
+ label {
.dashicons {
border: 1px solid #3498DB;
color: #000;
}
}
}
}
}
}

View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 kirki-framework
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -0,0 +1,2 @@
.kirki-datepicker-popup{background-color:#fff;border:1px solid #ddd;border-radius:6px;box-shadow:0 12px 15px 0 rgba(0,0,0,.09);margin-top:15px;max-width:275px;overflow:hidden;padding-bottom:10px;z-index:500001!important}.kirki-datepicker-popup .ui-datepicker-header{background-color:#eee;padding:10px}.kirki-datepicker-popup .ui-datepicker-header .ui-datepicker-next,.kirki-datepicker-popup .ui-datepicker-header .ui-datepicker-prev{align-items:center;border-radius:50%;cursor:pointer;display:flex;height:30px;justify-content:center;overflow:hidden;position:absolute;transition:all .2s;width:30px}.kirki-datepicker-popup .ui-datepicker-header .ui-datepicker-next:active,.kirki-datepicker-popup .ui-datepicker-header .ui-datepicker-next:focus,.kirki-datepicker-popup .ui-datepicker-header .ui-datepicker-next:hover,.kirki-datepicker-popup .ui-datepicker-header .ui-datepicker-prev:active,.kirki-datepicker-popup .ui-datepicker-header .ui-datepicker-prev:focus,.kirki-datepicker-popup .ui-datepicker-header .ui-datepicker-prev:hover{background-color:#2271b1;color:#fff}.kirki-datepicker-popup .ui-datepicker-header .ui-datepicker-next:after,.kirki-datepicker-popup .ui-datepicker-header .ui-datepicker-next:before,.kirki-datepicker-popup .ui-datepicker-header .ui-datepicker-prev:after,.kirki-datepicker-popup .ui-datepicker-header .ui-datepicker-prev:before{font-family:dashicons}.kirki-datepicker-popup .ui-datepicker-header .ui-datepicker-next .ui-icon,.kirki-datepicker-popup .ui-datepicker-header .ui-datepicker-prev .ui-icon{display:none}.kirki-datepicker-popup .ui-datepicker-header .ui-datepicker-prev{left:10px}.kirki-datepicker-popup .ui-datepicker-header .ui-datepicker-prev:before{content:"\f341"}.kirki-datepicker-popup .ui-datepicker-header .ui-datepicker-next{right:10px}.kirki-datepicker-popup .ui-datepicker-header .ui-datepicker-next:after{content:"\f345"}.kirki-datepicker-popup .ui-datepicker-header .ui-datepicker-title{align-items:center;display:flex;font-size:16px;height:30px;justify-content:center;text-align:center;width:100%}.kirki-datepicker-popup .ui-datepicker-calendar{border-collapse:collapse;padding-bottom:20px;width:100%}.kirki-datepicker-popup .ui-datepicker-calendar thead{background-color:#ddd;padding-left:5px;padding-right:5px}.kirki-datepicker-popup .ui-datepicker-calendar thead th{font-size:13px;font-weight:600;padding-bottom:5px;padding-top:5px;text-align:center}.kirki-datepicker-popup .ui-datepicker-calendar tbody{padding:5px}.kirki-datepicker-popup .ui-datepicker-calendar tbody td{padding:2px;text-align:center}.kirki-datepicker-popup .ui-datepicker-calendar tbody a{color:#333;text-decoration:none}.kirki-datepicker-popup .ui-datepicker-calendar tbody .ui-datepicker-today .ui-state-default{background-color:#eee}.kirki-datepicker-popup .ui-datepicker-calendar tbody .ui-datepicker-today .ui-state-active,.kirki-datepicker-popup .ui-datepicker-calendar tbody .ui-datepicker-today .ui-state-active:active,.kirki-datepicker-popup .ui-datepicker-calendar tbody .ui-datepicker-today .ui-state-active:focus,.kirki-datepicker-popup .ui-datepicker-calendar tbody .ui-datepicker-today .ui-state-active:hover{background-color:#2271b1}.kirki-datepicker-popup .ui-datepicker-calendar tbody .ui-state-default{align-items:center;border-radius:50%;display:inline-flex;height:30px;justify-content:center;width:30px}.kirki-datepicker-popup .ui-datepicker-calendar tbody .ui-state-default:active,.kirki-datepicker-popup .ui-datepicker-calendar tbody .ui-state-default:hover{background-color:#eee}.kirki-datepicker-popup .ui-datepicker-calendar tbody .ui-state-active,.kirki-datepicker-popup .ui-datepicker-calendar tbody .ui-state-default:focus{background-color:#2271b1;color:#fff}.kirki-datepicker-popup .ui-datepicker-calendar tbody .ui-state-active:active,.kirki-datepicker-popup .ui-datepicker-calendar tbody .ui-state-active:focus,.kirki-datepicker-popup .ui-datepicker-calendar tbody .ui-state-active:hover{background-color:#2271b1}
/*# sourceMappingURL=control.css.map */

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,2 @@
wp.customize.controlConstructor["kirki-date"]=wp.customize.kirkiDynamicControl.extend({handleWidth:function(e){document.querySelector("#kirki-style-datepicker").innerHTML=".kirki-datepicker-popup {width: "+e.clientWidth.toString()+"px;}"},initKirkiControl:function(e){var t;t=(e=e||this).selector+" input.datepicker";var i=document.querySelector("#kirki-style-datepicker");i||((i=document.createElement("style")).id="kirki-style-datepicker",document.head.appendChild(i)),jQuery(t).datepicker({dateFormat:"yy-mm-dd",duration:200,beforeShow:function(t,i){i.dpDiv[0].classList.add("kirki-datepicker-popup"),e.handleWidth(t)}}),this.container.on("change keyup paste","input.datepicker",(function(){e.setting.set(jQuery(this).val())}))}});
//# sourceMappingURL=control.js.map

View file

@ -0,0 +1 @@
{"mappings":"AAEAA,GAAGC,UAAUC,mBAAkB,cAAiBF,GAAGC,UAAUE,oBAAoBC,OAAM,CAEtFC,YAAW,SAAGC,GACEC,SAASC,cAAa,2BAC5BC,UAAS,mCAAwCH,EAAMI,YAAYC,WAAQ,QAGrFC,iBAAgB,SAAYC,GAC3B,IAAIC,EAGJA,GADAD,EAAUA,GAAOE,MACED,SAAQ,oBAE3B,IAAIE,EAAWT,SAASC,cAAa,2BAEhCQ,KACJA,EAAWT,SAASU,cAAa,UACxBC,GAAE,yBACXX,SAASY,KAAKC,YAAYJ,IAI3BK,OAAOP,GAAUQ,WAAU,CAC1BC,WAAU,WACVC,SAAU,IACVC,WAAU,SAAYnB,EAAOoB,GAC5BA,EAAKC,MAAM,GAAGC,UAAUC,IAAG,0BAC3BhB,EAAQR,YAAYC,WAKjBwB,UAAUC,GAAE,qBAAqB,oBAAoB,WACzDlB,EAAQmB,QAAQC,IAAIZ,OAAMN,MAAOmB","sources":["src/control.js"],"sourcesContent":["import \"./control.scss\";\n\nwp.customize.controlConstructor['kirki-date'] = wp.customize.kirkiDynamicControl.extend({\n\n\thandleWidth: (input) => {\n\t\tvar styleTag = document.querySelector('#kirki-style-datepicker');\n\t\tstyleTag.innerHTML = '.kirki-datepicker-popup {width: ' + input.clientWidth.toString() + 'px;}';\n\t},\n\n\tinitKirkiControl: function (control) {\n\t\tvar selector;\n\n\t\tcontrol = control || this;\n\t\tselector = control.selector + ' input.datepicker';\n\n\t\tvar styleTag = document.querySelector('#kirki-style-datepicker');\n\n\t\tif (!styleTag) {\n\t\t\tstyleTag = document.createElement('style');\n\t\t\tstyleTag.id = 'kirki-style-datepicker';\n\t\t\tdocument.head.appendChild(styleTag);\n\t\t}\n\n\t\t// Init the datepicker.\n\t\tjQuery(selector).datepicker({\n\t\t\tdateFormat: 'yy-mm-dd',\n\t\t\tduration: 200,\n\t\t\tbeforeShow: function (input, inst) {\n\t\t\t\tinst.dpDiv[0].classList.add('kirki-datepicker-popup');\n\t\t\t\tcontrol.handleWidth(input);\n\t\t\t}\n\t\t});\n\n\t\t// Save the changes\n\t\tthis.container.on('change keyup paste', 'input.datepicker', function () {\n\t\t\tcontrol.setting.set(jQuery(this).val());\n\t\t});\n\t}\n});\n"],"names":["wp","customize","controlConstructor","kirkiDynamicControl","extend","handleWidth","input","document","querySelector","innerHTML","clientWidth","toString","initKirkiControl","control","selector","this","styleTag","createElement","id","head","appendChild","jQuery","datepicker","dateFormat","duration","beforeShow","inst","dpDiv","classList","add","container","on","setting","set","val"],"version":3,"file":"control.js.map"}

View file

@ -0,0 +1,82 @@
<?php
/**
* Customizer Control: kirki-date.
*
* @package kirki-framework/control-date
* @copyright Copyright (c) 2023, Themeum
* @license https://opensource.org/licenses/MIT
* @since 1.0
*/
namespace Kirki\Control;
use Kirki\URL;
use Kirki\Control\Base;
/**
* A simple date control, using jQuery UI.
*
* @since 1.0
*/
class Date extends Base {
/**
* The control type.
*
* @access public
* @since 1.0
* @var string
*/
public $type = 'kirki-date';
/**
* The version. Used in scripts & styles for cache-busting.
*
* @static
* @access public
* @since 1.0
* @var string
*/
public static $control_ver = '1.0';
/**
* Enqueue control related scripts/styles.
*
* @access public
* @since 1.0
* @return void
*/
public function enqueue() {
parent::enqueue();
// Enqueue the script.
wp_enqueue_script( 'kirki-control-date', URL::get_from_path( dirname( dirname( __DIR__ ) ) . '/dist/control.js' ), [ 'jquery', 'customize-base', 'kirki-control-base', 'jquery-ui-datepicker' ], self::$control_ver, false );
// Enqueue the style.
wp_enqueue_style( 'kirki-control-date-style', URL::get_from_path( dirname( dirname( __DIR__ ) ) . '/dist/control.css' ), [], self::$control_ver );
}
/**
* An Underscore (JS) template for this control's content (but not its container).
*
* Class variables for this control class are available in the `data` JS object;
* export custom variables by overriding {@see WP_Customize_Control::to_json()}.
*
* @see WP_Customize_Control::print_template()
*
* @access protected
* @since 1.0
* @return void
*/
protected function content_template() {
?>
<label>
<# if ( data.label ) { #><span class="customize-control-title">{{{ data.label }}}</span><# } #>
<# if ( data.description ) { #><span class="description customize-control-description">{{{ data.description }}}</span><# } #>
<div class="customize-control-content">
<input {{{ data.inputAttrs }}} class="datepicker" type="text" id="{{ data.id }}" value="{{ data.value }}" {{{ data.link }}} />
</div>
</label>
<?php
}
}

View file

@ -0,0 +1,86 @@
<?php
/**
* Override field methods
*
* @package kirki-framework/control-date
* @copyright Copyright (c) 2023, Themeum
* @license https://opensource.org/licenses/MIT
* @since 1.0
*/
namespace Kirki\Field;
use Kirki\Field;
/**
* Field overrides.
*
* @since 1.0
*/
class Date extends Field {
/**
* The field type.
*
* @access public
* @since 1.0
* @var string
*/
public $type = 'kirki-date';
/**
* The control class-name.
*
* @access protected
* @since 0.1
* @var string
*/
protected $control_class = '\Kirki\Control\Date';
/**
* Whether we should register the control class for JS-templating or not.
*
* @access protected
* @since 0.1
* @var bool
*/
protected $control_has_js_template = true;
/**
* Filter arguments before creating the setting.
*
* @access public
* @since 0.1
* @param array $args The field arguments.
* @param WP_Customize_Manager $wp_customize The customizer instance.
* @return array
*/
public function filter_setting_args( $args, $wp_customize ) {
if ( $args['settings'] === $this->args['settings'] ) {
$args = parent::filter_setting_args( $args, $wp_customize );
// Set the sanitize-callback if none is defined.
if ( ! isset( $args['sanitize_callback'] ) || ! $args['sanitize_callback'] ) {
$args['sanitize_callback'] = 'sanitize_text_field';
}
}
return $args;
}
/**
* Filter arguments before creating the control.
*
* @access public
* @since 0.1
* @param array $args The field arguments.
* @param WP_Customize_Manager $wp_customize The customizer instance.
* @return array
*/
public function filter_control_args( $args, $wp_customize ) {
if ( $args['settings'] === $this->args['settings'] ) {
$args = parent::filter_control_args( $args, $wp_customize );
$args['type'] = 'kirki-date';
}
return $args;
}
}

View file

@ -0,0 +1,39 @@
import "./control.scss";
wp.customize.controlConstructor['kirki-date'] = wp.customize.kirkiDynamicControl.extend({
handleWidth: (input) => {
var styleTag = document.querySelector('#kirki-style-datepicker');
styleTag.innerHTML = '.kirki-datepicker-popup {width: ' + input.clientWidth.toString() + 'px;}';
},
initKirkiControl: function (control) {
var selector;
control = control || this;
selector = control.selector + ' input.datepicker';
var styleTag = document.querySelector('#kirki-style-datepicker');
if (!styleTag) {
styleTag = document.createElement('style');
styleTag.id = 'kirki-style-datepicker';
document.head.appendChild(styleTag);
}
// Init the datepicker.
jQuery(selector).datepicker({
dateFormat: 'yy-mm-dd',
duration: 200,
beforeShow: function (input, inst) {
inst.dpDiv[0].classList.add('kirki-datepicker-popup');
control.handleWidth(input);
}
});
// Save the changes
this.container.on('change keyup paste', 'input.datepicker', function () {
control.setting.set(jQuery(this).val());
});
}
});

View file

@ -0,0 +1,153 @@
$date-hover-color: #eee;
$date-active-color: #2271b1;
.kirki-datepicker-popup {
padding-bottom: 10px;
background-color: #fff;
border: 1px solid #ddd;
box-shadow: rgba(0, 0, 0, 0.09) 0 12px 15px 0;
border-radius: 6px;
z-index: 500001 !important;
margin-top: 15px;
overflow: hidden;
max-width: 275px;
.ui-datepicker-header {
padding: 10px;
background-color: $date-hover-color;
.ui-datepicker-next,
.ui-datepicker-prev {
display: flex;
align-items: center;
justify-content: center;
position: absolute;
width: 30px;
height: 30px;
border-radius: 50%;
cursor: pointer;
overflow: hidden;
transition: all .2s;
&:hover, &:active, &:focus {
color: #fff;
background-color: $date-active-color;
}
&:after,
&:before {
font-family: dashicons;
}
.ui-icon {
display: none;
}
}
.ui-datepicker-prev {
left: 10px;
&:before {
content: "\f341";
}
}
.ui-datepicker-next {
right: 10px;
&:after {
content: "\f345";
}
}
.ui-datepicker-title {
display: flex;
width: 100%;
align-items: center;
justify-content: center;
height: 30px;
font-size: 16px;
text-align: center;
}
}
.ui-datepicker-calendar {
border-collapse: collapse;
padding-bottom: 20px;
width: 100%;
thead {
background-color: #ddd;
padding-left: 5px;
padding-right: 5px;
th {
padding-top: 5px;
padding-bottom: 5px;
text-align: center;
font-weight: 600;
font-size: 13px;
}
}
tbody {
padding: 5px;
td {
padding: 2px;
text-align: center;
}
a {
text-decoration: none;
color: #333;
}
.ui-datepicker-today {
.ui-state-default {
background-color: $date-hover-color;
}
.ui-state-active {
background-color: $date-active-color;
&:hover,
&:active,
&:focus {
background-color: $date-active-color;
}
}
}
.ui-state-default {
display: inline-flex;
align-items: center;
justify-content: center;
width: 30px;
height: 30px;
border-radius: 50%;
&:hover,
&:active {
background-color: $date-hover-color;
}
&:focus {
color: #fff;
background-color: $date-active-color;
}
}
.ui-state-active {
background-color: $date-active-color;
color: #fff;
&:hover,
&:active,
&:focus {
background-color: $date-active-color;
}
}
}
}
}

View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 kirki-framework
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -0,0 +1,2 @@
.customize-control-kirki-dimension .has-label-bottom .kirki-control-label{color:#333;font-size:11px;font-weight:500;margin-top:3px;text-align:center}.customize-control-kirki-dimension .has-label-bottom .kirki-control-input{background-color:#f7f7f7}.customize-control-kirki-dimension .has-label-bottom .kirki-control-input:focus{background-color:#fff}
/*# sourceMappingURL=control.css.map */

View file

@ -0,0 +1 @@
{"mappings":"AAEI,0EAIE,UAAA,CADA,cAAA,CAEA,eAAA,CAJA,cAAA,CACA,iBCEN,CDII,0EACE,wBCFN,CDIM,gFACE,qBCFR","sources":["src/control.scss","%3Cinput%20css%20bqm70f%3E"],"sourcesContent":[".customize-control-kirki-dimension {\r\n .has-label-bottom {\r\n .kirki-control-label {\r\n margin-top: 3px;\r\n text-align: center;\r\n font-size: 11px;\r\n color: #333;\r\n font-weight: 500;\r\n }\r\n\r\n .kirki-control-input {\r\n background-color: #f7f7f7;\r\n\r\n &:focus {\r\n background-color: #fff;\r\n }\r\n }\r\n }\r\n}\r\n",".customize-control-kirki-dimension .has-label-bottom .kirki-control-label {\n margin-top: 3px;\n text-align: center;\n font-size: 11px;\n color: #333;\n font-weight: 500;\n}\n.customize-control-kirki-dimension .has-label-bottom .kirki-control-input {\n background-color: #f7f7f7;\n}\n.customize-control-kirki-dimension .has-label-bottom .kirki-control-input:focus {\n background-color: #fff;\n}\n/*# sourceMappingURL=control.css.map */\n"],"names":[],"version":3,"file":"control.css.map"}

View file

@ -0,0 +1,2 @@
wp.customize.controlConstructor["kirki-dimension"]=wp.customize.kirkiDynamicControl.extend({initKirkiControl:function(i){var n;(i=i||this).kirkiNotifications(),i.container.on("change keyup paste","input",(function(){n=jQuery(this).val(),i.setting.set(n)}))},kirkiNotifications:function(){var i=this,n=void 0!==i.params.choices&&void 0!==i.params.choices.accept_unitless&&!0===i.params.choices.accept_unitless;wp.customize(i.id,(function(t){t.bind((function(e){var a="long_title";!1!==i.validateCssValue(e)||n&&!isNaN(e)?t.notifications.remove(a):t.notifications.add(a,new wp.customize.Notification(a,{type:"warning",message:dimensionkirkiL10n["invalid-value"]}))}))}))},validateCssValue:function(i){var n,t,e,a=this,o=!0;return!i||""===i||0===i||"0"===i||"auto"===i||"inherit"===i||"initial"===i||0<=i.indexOf("calc(")&&0<=i.indexOf(")")||(n=parseFloat(i),!(t=i.replace(n,""))||(2<=(e=i.split(" ")).length?(e.forEach((function(i){i&&!a.validateCssValue(i)&&(o=!1)})),o):!isNaN(n)&&-1!==["fr","rem","em","ex","%","px","cm","mm","in","pt","pc","ch","vh","vw","vmin","vmax"].indexOf(t)))}});
//# sourceMappingURL=control.js.map

View file

@ -0,0 +1 @@
{"mappings":"AAGAA,GAAGC,UAAUC,mBAAmB,mBAAqBF,GAAGC,UAAUE,oBAAoBC,OAAQ,CAE7FC,iBAAkB,SAAUC,GAC3B,IAAIC,GACJD,EAAUA,GAAWE,MAGbC,qBAGRH,EAAQI,UAAUC,GAAI,qBAAsB,SAAS,WACpDJ,EAAQK,OAAQJ,MAAOK,MACvBP,EAAQQ,QAAQC,IAAKR,0BAgBZ,iBAEHC,KAAKQ,OAAa,IAAiCV,EAAAW,OAAcC,cAAW,IACxEZ,EAAiBW,OAAQC,QAAOC,kBAAU,IAAoBb,EAACW,OAAAC,QAAAC,6BACtEb,EAAec,IAAA,SAAAN,KACfO,MAAA,SAASd,GACV,IAACe,EAAA,kBAEOhB,EAAAiB,iBAA0BhB,IAAAS,IAAAQ,MAAAjB,GAMtBO,EAAEW,cAAlBC,OAA4BJ,GANUR,EAAAW,cAAAE,IAAAL,EAAA,IAAAtB,GAAAC,UAAA2B,aAAAN,EAAA,CAEnCO,KAAA,UACDC,QAAAC,mBAAA,4CAMgC,SAAAxB,OAY/ByB,EAAcC,EAASC,EAZU5B,EAAIE,KAYP2B,GAAiB,EAKjD,OAAA5B,GAAY,KAAGA,GAAY,IAAKA,GAAA,MAAAA,GAAA,SAAAA,GAAA,YAAAA,GAAA,YAAAA,GAG5B,GAAGA,EAAM6B,QAAS,UAAc,GAAE7B,EAAA6B,QAAA,OAGtCJ,EACCK,WAAW9B,KAIZ0B,EAAA1B,EAAY+B,QAAMN,EAAU,OAQ3B,MAFCzB,EAAAgC,MAAA,MAEMC,QACPN,EAAAO,SAAA,SAAAC,GAEoDA,IAAApC,EAAAiB,iBAAAmB,KAAAP,GAAA,MAErDA,mBAzCuC,CAAE,KAAK,MAAM,KAAM,KAAM,IAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAQ,KAC3G,KAKmB,KAClB,OAIyB","sources":["src/control.js"],"sourcesContent":["import \"./control.scss\";\r\n\r\n/* global dimensionkirkiL10n */\r\nwp.customize.controlConstructor['kirki-dimension'] = wp.customize.kirkiDynamicControl.extend( {\r\n\r\n\tinitKirkiControl: function( control ) {\r\n\t\tvar value;\r\n\t\tcontrol = control || this;\r\n\r\n\t\t// Notifications.\r\n\t\tcontrol.kirkiNotifications();\r\n\r\n\t\t// Save the value\r\n\t\tcontrol.container.on( 'change keyup paste', 'input', function() {\r\n\t\t\tvalue = jQuery( this ).val();\r\n\t\t\tcontrol.setting.set( value );\r\n\t\t} );\r\n\t},\r\n\r\n\t/**\r\n\t * Handles notifications.\r\n\t *\r\n\t * @returns {void}\r\n\t */\r\n\tkirkiNotifications: function() {\r\n\r\n\t\tvar control = this,\r\n\t\t\tacceptUnitless = ( 'undefined' !== typeof control.params.choices && 'undefined' !== typeof control.params.choices.accept_unitless && true === control.params.choices.accept_unitless );\r\n\r\n\t\twp.customize( control.id, function( setting ) {\r\n\t\t\tsetting.bind( function( value ) {\r\n\t\t\t\tvar code = 'long_title';\r\n\r\n\t\t\t\tif ( false === control.validateCssValue( value ) && ( ! acceptUnitless || isNaN( value ) ) ) {\r\n\t\t\t\t\tsetting.notifications.add( code, new wp.customize.Notification( code, {\r\n\t\t\t\t\t\ttype: 'warning',\r\n\t\t\t\t\t\tmessage: dimensionkirkiL10n['invalid-value']\r\n\t\t\t\t\t} ) );\r\n\t\t\t\t} else {\r\n\t\t\t\t\tsetting.notifications.remove( code );\r\n\t\t\t\t}\r\n\t\t\t} );\r\n\t\t} );\r\n\t},\r\n\r\n\tvalidateCssValue: function( value ) {\r\n\r\n\t\tvar control = this,\r\n\t\t\tvalidUnits = [ 'fr', 'rem', 'em', 'ex', '%', 'px', 'cm', 'mm', 'in', 'pt', 'pc', 'ch', 'vh', 'vw', 'vmin', 'vmax' ],\r\n\t\t\tnumericValue,\r\n\t\t\tunit,\r\n\t\t\tmultiples,\r\n\t\t\tmultiplesValid = true;\r\n\r\n\t\t// Whitelist values.\r\n\t\tif ( ! value || '' === value || 0 === value || '0' === value || 'auto' === value || 'inherit' === value || 'initial' === value ) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n\t\t// Skip checking if calc().\r\n\t\tif ( 0 <= value.indexOf( 'calc(' ) && 0 <= value.indexOf( ')' ) ) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n\t\t// Get the numeric value.\r\n\t\tnumericValue = parseFloat( value );\r\n\r\n\t\t// Get the unit\r\n\t\tunit = value.replace( numericValue, '' );\r\n\r\n\t\t// Allow unitless.\r\n\t\tif ( ! unit ) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n\t\t// Check for multiple values.\r\n\t\tmultiples = value.split( ' ' );\r\n\t\tif ( 2 <= multiples.length ) {\r\n\t\t\tmultiples.forEach( function( item ) {\r\n\t\t\t\tif ( item && ! control.validateCssValue( item ) ) {\r\n\t\t\t\t\tmultiplesValid = false;\r\n\t\t\t\t}\r\n\t\t\t});\r\n\r\n\t\t\treturn multiplesValid;\r\n\t\t}\r\n\r\n\t\t// Check the validity of the numeric value and units.\r\n\t\treturn ( ! isNaN( numericValue ) && -1 !== validUnits.indexOf( unit ) );\r\n\t}\r\n} );\r\n"],"names":["wp","customize","controlConstructor","kirkiDynamicControl","extend","initKirkiControl","control","value","this","kirkiNotifications","container","on","jQuery","val","setting","set","acceptUnitless","params","choices","accept_unitless","id","bind","code","validateCssValue","isNaN","notifications","remove","add","Notification","type","message","dimensionkirkiL10n","numericValue","unit","multiples","multiplesValid","indexOf","parseFloat","replace","split","length","forEach","item"],"version":3,"file":"control.js.map"}

View file

@ -0,0 +1,159 @@
<?php
/**
* Customizer Control: dimension
*
* @package kirki-framework/control-dimension
* @copyright Copyright (c) 2023, Themeum
* @license https://opensource.org/licenses/MIT
* @since 1.0
*/
namespace Kirki\Control;
use Kirki\Control\Base;
use Kirki\URL;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* A text control with validation for CSS units.
*
* @since 1.0
*/
class Dimension extends Base {
/**
* The control type.
*
* @access public
* @since 1.0
* @var string
*/
public $type = 'kirki-dimension';
/**
* The version. Used in scripts & styles for cache-busting.
*
* @static
* @access public
* @since 1.0
* @var string
*/
public static $control_ver = '1.0';
/**
* Enqueue control related scripts/styles.
*
* @access public
* @since 1.0
* @return void
*/
public function enqueue() {
parent::enqueue();
// Enqueue the script.
wp_enqueue_script( 'kirki-control-dimension', URL::get_from_path( dirname( dirname( __DIR__ ) ) . '/dist/control.js' ), [ 'jquery', 'customize-base', 'kirki-control-base' ], self::$control_ver, false );
// Enqueue the style.
wp_enqueue_style( 'kirki-control-dimension-style', URL::get_from_path( dirname( dirname( __DIR__ ) ) . '/dist/control.css' ), [], self::$control_ver );
wp_localize_script(
'kirki-control-dimension',
'dimensionkirkiL10n',
[
'invalid-value' => esc_html__( 'Invalid Value', 'kirki' ),
]
);
}
/**
* Get the URL for the control folder.
*
* This is a static method because there are more controls in the Kirki framework
* that use colorpickers, and they all need to enqueue the same assets.
*
* @static
* @access public
* @since 1.0
* @return string
*/
public static function get_control_path_url() {
return URL::get_from_path( dirname( __DIR__ ) );
}
/**
* Refresh the parameters passed to the JavaScript via JSON.
*
* @access public
* @since 1.0
* @see WP_Customize_Control::to_json()
* @return void
*/
public function to_json() {
$input_class = 'kirki-control-input';
if ( isset( $this->input_attrs['class'] ) ) {
$input_class .= ' ' . $this->input_attrs['class'];
unset( $this->input_attrs['class'] );
}
// Get the basics from the parent class.
parent::to_json();
// Input class name.
$this->json['inputClass'] = $input_class;
// Label position.
$this->json['labelPosition'] = 'top';
if ( isset( $this->choices['label_position'] ) && 'bottom' === $this->choices['label_position'] ) {
$this->json['labelPosition'] = 'bottom';
}
// Input id.
$this->json['inputId'] = '_customize-input-' . $this->id;
}
/**
* An Underscore (JS) template for this control's content (but not its container).
*
* Class variables for this control class are available in the `data` JS object;
* export custom variables by overriding {@see WP_Customize_Control::to_json()}.
*
* @see WP_Customize_Control::print_template()
*
* @access protected
* @since 1.0
* @return void
*/
protected function content_template() {
?>
<div class="kirki-control-form <# if ('bottom' === data.labelPosition) { #>has-label-bottom<# } #>">
<# if ( 'top' === data.labelPosition ) { #>
<label class="kirki-control-label" for="{{ data.inputId }}">
<# if ( data.label ) { #><span class="customize-control-title">{{{ data.label }}}</span><# } #>
<# if ( data.description ) { #><span class="description customize-control-description">{{{ data.description }}}</span><# } #>
</label>
<# } #>
<div class="kirki-input-control">
<# var val = ( data.value && _.isString( data.value ) ) ? data.value.replace( '%%', '%' ) : ''; #>
<input id="{{ data.inputId }}" {{{ data.inputAttrs }}} type="text" value="{{ val }}" class="{{ data.inputClass }}" />
</div>
<# if ( 'bottom' === data.labelPosition ) { #>
<label class="kirki-control-label" for="{{ data.inputId }}">
<# if ( data.label ) { #>{{{ data.label }}} <# } #>
</label>
<# } #>
</div>
<?php
}
}

View file

@ -0,0 +1,84 @@
<?php
/**
* Override field methods
*
* @package Kirki
* @copyright Copyright (c) 2023, Themeum
* @license https://opensource.org/licenses/MIT
* @since 1.0
*/
namespace Kirki\Field;
use Kirki\Field;
/**
* Field overrides.
*/
class Dimension extends Field {
/**
* The field type.
*
* @access public
* @since 1.0
* @var string
*/
public $type = 'kirki-dimension';
/**
* The control class-name.
*
* @access protected
* @since 0.1
* @var string
*/
protected $control_class = '\Kirki\Control\Dimension';
/**
* Whether we should register the control class for JS-templating or not.
*
* @access protected
* @since 0.1
* @var bool
*/
protected $control_has_js_template = true;
/**
* Filter arguments before creating the setting.
*
* @access public
* @since 0.1
* @param array $args The field arguments.
* @param WP_Customize_Manager $wp_customize The customizer instance.
* @return array
*/
public function filter_setting_args( $args, $wp_customize ) {
if ( $args['settings'] === $this->args['settings'] ) {
$args = parent::filter_setting_args( $args, $wp_customize );
// Set the sanitize-callback if none is defined.
if ( ! isset( $args['sanitize_callback'] ) || ! $args['sanitize_callback'] ) {
$args['sanitize_callback'] = 'sanitize_text_field';
}
}
return $args;
}
/**
* Filter arguments before creating the control.
*
* @access public
* @since 0.1
* @param array $args The field arguments.
* @param WP_Customize_Manager $wp_customize The customizer instance.
* @return array
*/
public function filter_control_args( $args, $wp_customize ) {
if ( $args['settings'] === $this->args['settings'] ) {
$args = parent::filter_control_args( $args, $wp_customize );
$args['type'] = 'kirki-dimension';
}
return $args;
}
}

View file

@ -0,0 +1,91 @@
import "./control.scss";
/* global dimensionkirkiL10n */
wp.customize.controlConstructor['kirki-dimension'] = wp.customize.kirkiDynamicControl.extend( {
initKirkiControl: function( control ) {
var value;
control = control || this;
// Notifications.
control.kirkiNotifications();
// Save the value
control.container.on( 'change keyup paste', 'input', function() {
value = jQuery( this ).val();
control.setting.set( value );
} );
},
/**
* Handles notifications.
*
* @returns {void}
*/
kirkiNotifications: function() {
var control = this,
acceptUnitless = ( 'undefined' !== typeof control.params.choices && 'undefined' !== typeof control.params.choices.accept_unitless && true === control.params.choices.accept_unitless );
wp.customize( control.id, function( setting ) {
setting.bind( function( value ) {
var code = 'long_title';
if ( false === control.validateCssValue( value ) && ( ! acceptUnitless || isNaN( value ) ) ) {
setting.notifications.add( code, new wp.customize.Notification( code, {
type: 'warning',
message: dimensionkirkiL10n['invalid-value']
} ) );
} else {
setting.notifications.remove( code );
}
} );
} );
},
validateCssValue: function( value ) {
var control = this,
validUnits = [ 'fr', 'rem', 'em', 'ex', '%', 'px', 'cm', 'mm', 'in', 'pt', 'pc', 'ch', 'vh', 'vw', 'vmin', 'vmax' ],
numericValue,
unit,
multiples,
multiplesValid = true;
// Whitelist values.
if ( ! value || '' === value || 0 === value || '0' === value || 'auto' === value || 'inherit' === value || 'initial' === value ) {
return true;
}
// Skip checking if calc().
if ( 0 <= value.indexOf( 'calc(' ) && 0 <= value.indexOf( ')' ) ) {
return true;
}
// Get the numeric value.
numericValue = parseFloat( value );
// Get the unit
unit = value.replace( numericValue, '' );
// Allow unitless.
if ( ! unit ) {
return true;
}
// Check for multiple values.
multiples = value.split( ' ' );
if ( 2 <= multiples.length ) {
multiples.forEach( function( item ) {
if ( item && ! control.validateCssValue( item ) ) {
multiplesValid = false;
}
});
return multiplesValid;
}
// Check the validity of the numeric value and units.
return ( ! isNaN( numericValue ) && -1 !== validUnits.indexOf( unit ) );
}
} );

View file

@ -0,0 +1,19 @@
.customize-control-kirki-dimension {
.has-label-bottom {
.kirki-control-label {
margin-top: 3px;
text-align: center;
font-size: 11px;
color: #333;
font-weight: 500;
}
.kirki-control-input {
background-color: #f7f7f7;
&:focus {
background-color: #fff;
}
}
}
}

View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 kirki-framework
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -0,0 +1,2 @@
.customize-control-kirki-editor textarea{width:100%}
/*# sourceMappingURL=control.css.map */

View file

@ -0,0 +1 @@
{"mappings":"AACE,yCACE,UCAJ","sources":["src/control.scss","%3Cinput%20css%20nydtJI%3E"],"sourcesContent":[".customize-control-kirki-editor {\n textarea {\n width: 100%;\n }\n}\n",".customize-control-kirki-editor textarea {\n width: 100%;\n}\n/*# sourceMappingURL=control.css.map */\n"],"names":[],"version":3,"file":"control.css.map"}

View file

@ -0,0 +1,2 @@
wp.customize.controlConstructor["kirki-editor"]=wp.customize.kirkiDynamicControl.extend({initKirkiControl:function(i){var t,e,n,o;t=(i=i||this).container.find("textarea"),n="kirki-editor-"+i.id.replace("[","").replace("]",""),o={tinymce:{wpautop:!0},quicktags:!0,mediaButtons:!0},wp.editor&&wp.editor.initialize&&wp.editor.initialize(n,jQuery.extend({},o,i.params.choices)),(e=tinyMCE.get(n))&&e.onChange.add((function(n){var o;n.save(),o=e.getContent(),t.val(o).trigger("change"),wp.customize.instance(i.id).set(o)}))}});
//# sourceMappingURL=control.js.map

View file

@ -0,0 +1 @@
{"mappings":"AAGAA,GAAGC,UAAUC,mBAAkB,gBAAqBF,GAAGC,UAAUE,oBAAoBC,OAAM,CAC1FC,iBAAgB,SAAYC,GAC3B,IAAIC,EAASC,EAAQC,EAAIC,EAEzBH,GADAD,EAAUA,GAAOK,MACCC,UAAUC,KAAI,YAChCJ,EAAE,gBAA0BH,EAAQG,GAAGK,QAAO,IAAK,IAAOA,QAAO,IAAK,IAEtEJ,EAAa,CACZK,QAAO,CACNC,SAAS,GAEVC,WAAW,EACXC,cAAc,GAIVlB,GAAGQ,QAAUR,GAAGQ,OAAOW,YAC3BnB,GAAGQ,OAAOW,WAAYV,EAAIW,OAAOhB,OAAM,GAAMM,EAAeJ,EAAQe,OAAOC,WAG5Ed,EAASe,QAAQC,IAAKf,KAGrBD,EAAOiB,SAASC,KAAG,SAAYC,GAC9B,IAAIC,EAEJD,EAAGE,OACHD,EAAUpB,EAAOsB,aACjBvB,EAAQwB,IAAKH,GAAUI,QAAO,UAC9BhC,GAAGC,UAAUgC,SAAU3B,EAAQG,IAAKyB,IAAKN","sources":["src/control.js"],"sourcesContent":["import \"./control.scss\";\n\n/* global tinyMCE */\nwp.customize.controlConstructor[ 'kirki-editor' ] = wp.customize.kirkiDynamicControl.extend( {\n\tinitKirkiControl: function( control ) {\n\t\tvar element, editor, id, defaultParams;\n\t\tcontrol = control || this;\n\t\telement = control.container.find( 'textarea' );\n\t\tid = 'kirki-editor-' + control.id.replace( '[', '' ).replace( ']', '' );\n\n\t\tdefaultParams = {\n\t\t\ttinymce: {\n\t\t\t\twpautop: true\n\t\t\t},\n\t\t\tquicktags: true,\n\t\t\tmediaButtons: true\n\t\t};\n\n\t\t// Overwrite the default paramaters if choices is defined.\n\t\tif ( wp.editor && wp.editor.initialize ) {\n\t\t\twp.editor.initialize( id, jQuery.extend( {}, defaultParams, control.params.choices ) );\n\t\t}\n\n\t\teditor = tinyMCE.get( id );\n\n\t\tif ( editor ) {\n\t\t\teditor.onChange.add( function( ed ) {\n\t\t\t\tvar content;\n\n\t\t\t\ted.save();\n\t\t\t\tcontent = editor.getContent();\n\t\t\t\telement.val( content ).trigger( 'change' );\n\t\t\t\twp.customize.instance( control.id ).set( content );\n\t\t\t} );\n\t\t}\n\t}\n} );\n"],"names":["wp","customize","controlConstructor","kirkiDynamicControl","extend","initKirkiControl","control","element","editor","id","defaultParams","this","container","find","replace","tinymce","wpautop","quicktags","mediaButtons","initialize","jQuery","params","choices","tinyMCE","get","onChange","add","ed","content","save","getContent","val","trigger","instance","set"],"version":3,"file":"control.js.map"}

View file

@ -0,0 +1,107 @@
<?php
/**
* Customizer Control: editor.
*
* Creates a TinyMCE textarea.
*
* @package kirki-framework/control-editor
* @copyright Copyright (c) 2023, Themeum
* @license https://opensource.org/licenses/MIT
* @since 1.0
*/
namespace Kirki\Control;
use Kirki\Control\Base;
use Kirki\URL;
/**
* A TinyMCE control.
*
* @since 1.0
*/
class Editor extends Base {
/**
* The control type.
*
* @access public
* @since 1.0
* @var string
*/
public $type = 'kirki-editor';
/**
* The version. Used in scripts & styles for cache-busting.
*
* @static
* @access public
* @since 1.0
* @var string
*/
public static $control_ver = '1.0';
/**
* Args to pass to TinyMCE.
*
* @access public
* @since 1.0
* @var bool
*/
public $choices = [];
/**
* Enqueue control related scripts/styles.
*
* @access public
* @since 1.0
* @return void
*/
public function enqueue() {
parent::enqueue();
// Enqueue the script.
wp_enqueue_script( 'kirki-control-editor', URL::get_from_path( dirname( dirname( __DIR__ ) ) . '/dist/control.js' ), [ 'jquery', 'customize-base', 'kirki-control-base' ], self::$control_ver, false );
// Enqueue the style.
wp_enqueue_style( 'kirki-control-editor-style', URL::get_from_path( dirname( dirname( __DIR__ ) ) . '/dist/control.css' ), [], self::$control_ver );
}
/**
* Refresh the parameters passed to the JavaScript via JSON.
*
* @access public
* @since 1.0
* @return void
*/
public function to_json() {
parent::to_json();
$this->json['choices'] = $this->choices;
}
/**
* An Underscore (JS) template for this control's content (but not its container).
*
* Class variables for this control class are available in the `data` JS object;
* export custom variables by overriding {@see WP_Customize_Control::to_json()}.
*
* The actual editor is added from the \Kirki\Field\Editor class.
* All this template contains is a button that triggers the global editor on/off
* and a hidden textarea element that is used to mirror save the options.
*
* @see WP_Customize_Control::print_template()
*
* @access protected
* @since 1.0
* @return void
*/
protected function content_template() {
?>
<label>
<# if ( data.label ) { #><span class="customize-control-title">{{{ data.label }}}</span><# } #>
<# if ( data.description ) { #><span class="description customize-control-description">{{{ data.description }}}</span><# } #>
</label>
<textarea id="kirki-editor-{{{ data.id.replace( '[', '' ).replace( ']', '' ) }}}" {{{ data.inputAttrs }}} {{{ data.link }}}>{{ data.value }}</textarea>
<?php
}
}

View file

@ -0,0 +1,84 @@
<?php
/**
* Override field methods
*
* @package kirki-framework/control-editor
* @copyright Copyright (c) 2023, Themeum
* @license https://opensource.org/licenses/MIT
* @since 1.0
*/
namespace Kirki\Field;
use Kirki\Field;
/**
* Field overrides.
*/
class Editor extends Field {
/**
* The field type.
*
* @access public
* @since 1.0
* @var string
*/
public $type = 'kirki-editor';
/**
* The control class-name.
*
* @access protected
* @since 0.1
* @var string
*/
protected $control_class = '\Kirki\Control\Editor';
/**
* Whether we should register the control class for JS-templating or not.
*
* @access protected
* @since 0.1
* @var bool
*/
protected $control_has_js_template = true;
/**
* Filter arguments before creating the setting.
*
* @access public
* @since 0.1
* @param array $args The field arguments.
* @param WP_Customize_Manager $wp_customize The customizer instance.
* @return array
*/
public function filter_setting_args( $args, $wp_customize ) {
if ( $args['settings'] === $this->args['settings'] ) {
$args = parent::filter_setting_args( $args, $wp_customize );
// Set the sanitize-callback if none is defined.
if ( ! isset( $args['sanitize_callback'] ) || ! $args['sanitize_callback'] ) {
$args['sanitize_callback'] = 'wp_kses_post';
}
}
return $args;
}
/**
* Filter arguments before creating the control.
*
* @access public
* @since 0.1
* @param array $args The field arguments.
* @param WP_Customize_Manager $wp_customize The customizer instance.
* @return array
*/
public function filter_control_args( $args, $wp_customize ) {
if ( $args['settings'] === $this->args['settings'] ) {
$args = parent::filter_control_args( $args, $wp_customize );
$args['type'] = 'kirki-editor';
}
return $args;
}
}

View file

@ -0,0 +1,37 @@
import "./control.scss";
/* global tinyMCE */
wp.customize.controlConstructor[ 'kirki-editor' ] = wp.customize.kirkiDynamicControl.extend( {
initKirkiControl: function( control ) {
var element, editor, id, defaultParams;
control = control || this;
element = control.container.find( 'textarea' );
id = 'kirki-editor-' + control.id.replace( '[', '' ).replace( ']', '' );
defaultParams = {
tinymce: {
wpautop: true
},
quicktags: true,
mediaButtons: true
};
// Overwrite the default paramaters if choices is defined.
if ( wp.editor && wp.editor.initialize ) {
wp.editor.initialize( id, jQuery.extend( {}, defaultParams, control.params.choices ) );
}
editor = tinyMCE.get( id );
if ( editor ) {
editor.onChange.add( function( ed ) {
var content;
ed.save();
content = editor.getContent();
element.val( content ).trigger( 'change' );
wp.customize.instance( control.id ).set( content );
} );
}
}
} );

Some files were not shown because too many files have changed in this diff Show more