<?php
/**
* Homepage hero element
*
* @package Yuki
*/
use LottaFramework\Customizer\Controls\Background;
use LottaFramework\Customizer\Controls\Collapse;
use LottaFramework\Customizer\Controls\ColorPicker;
use LottaFramework\Customizer\Controls\Editor;
use LottaFramework\Customizer\Controls\ImageUploader;
use LottaFramework\Customizer\Controls\Radio;
use LottaFramework\Customizer\Controls\Section;
use LottaFramework\Customizer\Controls\Select;
use LottaFramework\Customizer\Controls\Separator;
use LottaFramework\Customizer\Controls\Slider;
use LottaFramework\Customizer\Controls\Spacing;
use LottaFramework\Customizer\Controls\Tabs;
use LottaFramework\Customizer\Controls\Text;
use LottaFramework\Customizer\Controls\Toggle;
use LottaFramework\Customizer\Controls\Typography;
use LottaFramework\Customizer\PageBuilder\Element;
use LottaFramework\Facades\Css;
use LottaFramework\Utils;
if ( !defined( 'ABSPATH' ) ) {
exit;
// Exit if accessed directly.
}
if ( !class_exists( 'Yuki_Hero_Element' ) ) {
class Yuki_Hero_Element extends Element {
use Yuki_Button_Controls;
/**
* @param null $id
* @param array $data
*/
public function after_register( $id = null, $data = [] ) {
}
/**
* {@inheritDoc}
*/
public function getControls() {
return [
( new Section() )->setLabel( __( 'Hero Content', 'yuki' ) )->setControls( $this->getContentControls() ),
( new Section() )->setLabel( __( 'Hero Layout', 'yuki' ) )->setControls( $this->getLayoutControls() ),
( new Section() )->setLabel( __( 'Hero Shape Divider', 'yuki' ) )->setControls( $this->getShapeDividerControls() ),
( new Section() )->setLabel( __( 'Hero Style', 'yuki' ) )->setControls( $this->getStyleControls() ),
( new Section($this->getSlug( 'overlay' )) )->setLabel( __( 'Hero Overlay', 'yuki' ) )->enableSwitch( false )->setControls( [( new Background($this->getSlug( 'overlay_background' )) )->setLabel( __( 'Overlay Color', 'yuki' ) )->setDefaultValue( [
'type' => 'color',
'color' => 'rgba(0,0,0,0.45)',
] ), ( new Slider($this->getSlug( 'overlay_opacity' )) )->setLabel( __( 'Overlay Opacity', 'yuki' ) )->setMin( 0 )->setMax( 1 )->setDecimals( 2 )->setDefaultUnit( false )->setDefaultValue( 1 )] )
];
}
/**
* @return array
*/
protected function getContentControls() {
return [( new Tabs() )->setActiveTab( 'content' )->addTab( 'content', __( 'Content', 'yuki' ), [
( new Text($this->getSlug( 'title' )) )->setLabel( __( 'Title', 'yuki' ) )->setDefaultValue( $this->getDefaultSetting( 'title', __( 'Build Your Awesome Business', 'yuki' ) ) ),
( new Select($this->getSlug( 'title_tag' )) )->setLabel( __( 'Title Tag', 'yuki' ) )->setDefaultValue( $this->getDefaultSetting( 'title-tag', 'h2' ) )->setChoices( [
'h1' => 'H1',
'h2' => 'H2',
'h3' => 'H3',
'h4' => 'H4',
'h5' => 'H5',
'h6' => 'H6',
'span' => 'Span',
] ),
( new Editor($this->getSlug( 'description' )) )->setLabel( __( 'Description', 'yuki' ) )->setDefaultValue( $this->getDefaultSetting( 'description', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua' ) ),
new Separator(),
( new Text($this->getSlug( 'button_text' )) )->setLabel( __( 'Button Text', 'yuki' ) )->setDefaultValue( $this->getDefaultSetting( 'button-text', __( 'Get Started', 'yuki' ) ) ),
( new Text($this->getSlug( 'button_url' )) )->setLabel( __( 'Button URL', 'yuki' ) )->setDefaultValue( $this->getDefaultSetting( 'button-url', '#' ) ),
( new Toggle($this->getSlug( 'button_open_new_tab' )) )->setLabel( __( 'Open In New Tab', 'yuki' ) )->setDefaultValue( $this->getDefaultSetting( 'button-open-new-tab', 'no' ) ),
( new Toggle($this->getSlug( 'button_no_follow' )) )->setLabel( __( 'No Follow', 'yuki' ) )->setDefaultValue( $this->getDefaultSetting( 'button-no-follow', 'no' ) ),
new Separator(),
( new Radio($this->getSlug( 'content_align' )) )->setLabel( __( 'Content Alignment', 'yuki' ) )->buttonsGroupView()->setDefaultValue( $this->getDefaultSetting( 'content-align', 'left' ) )->setChoices( [
'left' => __( 'Left', 'yuki' ),
'center' => __( 'Center', 'yuki' ),
'right' => __( 'Right', 'yuki' ),
] ),
( new Spacing($this->getSlug( 'content_spacing' )) )->enableResponsive()->setLabel( __( 'Content Spacing', 'yuki' ) )->setDefaultValue( [
'top' => '24px',
'right' => '24px',
'bottom' => '24px',
'left' => '24px',
'linked' => true,
] )
] )->addTab( 'media', __( 'Media', 'yuki' ), [( new ImageUploader($this->getSlug( 'media' )) )->setLabel( __( 'Media', 'yuki' ) )->setDefaultValue( $this->getDefaultSetting( 'media', [
'url' => yuki_image_url( 'hero-media.png' ),
] ) ), ( new Slider($this->getSlug( 'media_height' )) )->setLabel( __( 'Media Height', 'yuki' ) )->enableResponsive()->setMin( 200 )->setMax( 800 )->setDefaultUnit( 'px' )->setDefaultValue( $this->getDefaultSetting( 'media-height', '360px' ) ), ( new Radio($this->getSlug( 'media_align' )) )->setLabel( __( 'Media Alignment', 'yuki' ) )->buttonsGroupView()->setDefaultValue( $this->getDefaultSetting( 'media-align', 'center' ) )->setChoices( [
'left' => __( 'Left', 'yuki' ),
'center' => __( 'Center', 'yuki' ),
'right' => __( 'Right', 'yuki' ),
] )] )];
}
/**
* @return array
*/
protected function getLayoutControls() {
return [( new Slider($this->getSlug( 'min_height' )) )->setLabel( __( 'Min Height', 'yuki' ) )->enableResponsive()->setUnits( [[
'unit' => 'px',
'min' => 100,
'max' => 800,
], [
'unit' => 'vh',
'min' => 10,
'max' => 100,
]] )->setDefaultValue( $this->getDefaultSetting( 'min-height', '640px' ) ), ( new Select($this->getSlug( 'layout' )) )->setLabel( __( 'Layout', 'yuki' ) )->setDefaultValue( $this->getDefaultSetting( 'layout', 'content-media' ) )->setChoices( [
'content-media' => __( 'Content - Media', 'yuki' ),
'media-content' => __( 'Media - Content', 'yuki' ),
] )];
}
/**
* @return array
*/
protected function getShapeDividerControls() {
return [
( new Select($this->getSlug( 'shape_divider' )) )->setLabel( __( 'Shape Divider', 'yuki' ) )->setDefaultValue( 'tilt' )->setChoices( Utils::array_pluck( 'title', yuki_get_shapes() ) ),
( new Toggle($this->getSlug( 'shape_flip' )) )->setLabel( __( 'Flip', 'yuki' ) )->openByDefault(),
( new Toggle($this->getSlug( 'shape_invert' )) )->setLabel( __( 'Invert', 'yuki' ) )->closeByDefault(),
new Separator(),
( new Slider($this->getSlug( 'shape_width' )) )->setLabel( __( 'Shape Divider Width', 'yuki' ) )->setMin( 0 )->setMax( 100 )->setDefaultUnit( '%' )->setDefaultValue( '100%' ),
( new Slider($this->getSlug( 'shape_height' )) )->setLabel( __( 'Shape Divider Height', 'yuki' ) )->setMin( 0 )->setMax( 200 )->setDefaultUnit( 'px' )->setDefaultValue( $this->getDefaultSetting( 'shape-height', '50px' ) ),
new Separator(),
( new ColorPicker($this->getSlug( 'shape_color' )) )->setLabel( __( 'Shape Color', 'yuki' ) )->enableAlpha()->addColor( 'initial', __( 'Initial', 'yuki' ), $this->getDefaultSetting( 'title-initial', 'var(--yuki-base-100)' ) )
];
}
/**
* @return array
*/
protected function getStyleControls() {
return [( new Background($this->getSlug( 'background' )) )->setLabel( __( 'Background', 'yuki' ) )->enableResponsive()->setDefaultValue( $this->getDefaultSetting( 'background', [
'type' => 'color',
'color' => 'var(--yuki-accent-active)',
] ) ), ( new Collapse() )->setLabel( __( 'Title & Description Style', 'yuki' ) )->setControls( [
( new Typography($this->getSlug( 'title_typography' )) )->setLabel( __( 'Title Typography', 'yuki' ) )->setDefaultValue( [
'family' => 'inherit',
'fontSize' => '2.75rem',
'variant' => '700',
'lineHeight' => '1.25em',
] ),
( new ColorPicker($this->getSlug( 'title_color' )) )->setLabel( __( 'Title Color', 'yuki' ) )->enableAlpha()->addColor( 'initial', __( 'Initial', 'yuki' ), $this->getDefaultSetting( 'title-initial', 'var(--yuki-base-color)' ) ),
new Separator(),
( new Typography($this->getSlug( 'description_typography' )) )->setLabel( __( 'Description Typography', 'yuki' ) )->setDefaultValue( [
'family' => 'inherit',
'fontSize' => '1rem',
'variant' => '400',
'lineHeight' => '1.5',
] ),
( new ColorPicker($this->getSlug( 'description_color' )) )->setLabel( __( 'Description Color', 'yuki' ) )->enableAlpha()->addColor( 'initial', __( 'Initial', 'yuki' ), $this->getDefaultSetting( 'description-initial', 'var(--yuki-base-100)' ) )
] ), ( new Collapse() )->setLabel( __( 'Button Style', 'yuki' ) )->setControls( $this->getButtonStyleControls( $this->getSlug( 'button_' ), [
'min-height' => '48px',
'button-initial' => 'var(--yuki-transparent)',
'button-hover' => 'var(--yuki-primary-active)',
'border-initial' => 'var(--yuki-base-color)',
'border-hover' => 'var(--yuki-primary-active)',
'border-radius' => [
'left' => '4px',
'right' => '4px',
'top' => '4px',
'bottom' => '4px',
],
'padding' => [
'top' => '0.25em',
'right' => '1.5em',
'bottom' => '0.25em',
'left' => '1.5em',
],
] ) )];
}
/**
* {@inheritDoc}
*/
public function enqueue_frontend_scripts( $id = null, $data = [] ) {
if ( !$id ) {
return;
}
$settings = $data['settings'] ?? [];
add_filter( 'yuki_filter_dynamic_css', function ( $css ) use($id, $settings) {
$css[".yuki-hero.{$id}"] = array_merge(
[
'--media-max-height' => $this->get( $this->getSlug( 'media_height' ), $settings ),
'--yuki-hero-media-align' => $this->get( $this->getSlug( 'media_align' ), $settings ),
'--yuki-hero-content-align' => $this->get( $this->getSlug( 'content_align' ), $settings ),
'min-height' => $this->get( $this->getSlug( 'min_height' ), $settings ),
],
Css::dimensions( $this->get( $this->getSlug( 'content_spacing' ), $settings ), '--yuki-hero-content-padding' ),
Css::background( $this->get( $this->getSlug( 'background' ), $settings ) ),
Css::colors( $this->get( $this->getSlug( 'shape_color' ), $settings ), [
'initial' => '--yuki-hero-shape-fill',
] )
);
// overlay
$css[".yuki-hero.{$id} .hero-overlay"] = array_merge( Css::background( $this->get( $this->getSlug( 'overlay_background' ), $settings ) ), [
'opacity' => $this->get( $this->getSlug( 'overlay_opacity' ), $settings ),
] );
// shape divider
$shape_data = yuki_get_shapes( $this->get( $this->getSlug( 'shape_divider' ), $settings ) );
if ( $shape_data ) {
$flip = $this->checked( $this->getSlug( 'shape_flip' ), $settings ) && in_array( 'shape_flip', $shape_data['options'] );
$css[".yuki-hero.{$id} .hero-shape-divider svg"] = [
'width' => 'calc(' . $this->get( $this->getSlug( 'shape_width' ), $settings ) . ' + 1.3px)',
'height' => $this->get( $this->getSlug( 'shape_height' ), $settings ),
'transform' => ( $flip ? 'translateX(-50%) rotateY(180deg)' : 'translateX(-50%)' ),
];
}
// title
$css[".yuki-hero.{$id} .hero-title"] = array_merge( Css::typography( $this->get( $this->getSlug( 'title_typography' ), $settings ) ), Css::colors( $this->get( $this->getSlug( 'title_color' ), $settings ), [
'initial' => 'color',
] ) );
// description
$css[".yuki-hero.{$id} .hero-description"] = array_merge( Css::typography( $this->get( $this->getSlug( 'description_typography' ), $settings ) ), Css::colors( $this->get( $this->getSlug( 'description_color' ), $settings ), [
'initial' => 'color',
] ) );
// button
$css[".yuki-hero.{$id} .hero-button"] = array_merge(
[
'--yuki-button-height' => $this->get( $this->getSlug( 'button_min_height' ), $settings ),
],
Css::typography( $this->get( $this->getSlug( 'button_typography' ), $settings ) ),
Css::dimensions( $this->get( $this->getSlug( 'button_padding' ), $settings ), '--yuki-button-padding' ),
Css::dimensions( $this->get( $this->getSlug( 'button_radius' ), $settings ), '--yuki-button-radius' ),
Css::colors( $this->get( $this->getSlug( 'button_text_color' ), $settings ), [
'initial' => '--yuki-button-text-initial-color',
'hover' => '--yuki-button-text-hover-color',
] ),
Css::colors( $this->get( $this->getSlug( 'button_button_color' ), $settings ), [
'initial' => '--yuki-button-initial-color',
'hover' => '--yuki-button-hover-color',
] ),
Css::border( $this->get( $this->getSlug( 'button_border' ), $settings ), '--yuki-button-border' )
);
return $css;
} );
}
protected function get_shape_path( $shape, $is_negative = false ) {
$shape_data = yuki_get_shapes( $shape );
if ( !$shape_data ) {
return '';
}
if ( isset( $shape_data['path'] ) ) {
$path = $shape_data['path'];
return ( $is_negative ? str_replace( '.svg', '-negative.svg', $path ) : $path );
}
$folder = 'images/shapes/';
if ( isset( $shape_data['folder'] ) ) {
$folder = trailingslashit( $shape_data['folder'] );
}
$file_name = $shape;
if ( $is_negative ) {
$file_name .= '-negative';
}
return trailingslashit( get_template_directory() ) . 'dist/' . ($folder . $file_name . '.svg');
}
protected function shape_divider( $settings ) {
$shape = $this->get( $this->getSlug( 'shape_divider' ), $settings );
$shape_data = yuki_get_shapes( $shape );
if ( !$shape_data ) {
return;
}
if ( yuki_fs()->is_not_paying() && isset( $shape_data['folder'] ) ) {
return;
}
$negative = $this->checked( $this->getSlug( 'shape_invert' ), $settings ) && in_array( 'shape_invert', $shape_data['options'] );
$shape_path = $this->get_shape_path( $shape, $negative );
if ( !is_file( $shape_path ) || !is_readable( $shape_path ) ) {
return;
}
?>
<div class="hero-shape-divider" data-negative="<?php
// PHPCS - the variable $negative is getting a setting value with a strict structure.
echo var_export( $negative );
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
?>">
<?php
// PHPCS - The file content is being read from a strict file path structure.
echo file_get_contents( $shape_path );
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
?>
</div>
<?php
}
/**
* {@inheritDoc}
*/
public function render( $attrs = [] ) {
$id = $attrs['id'];
$settings = $attrs['settings'];
$this->add_render_attribute( $id, 'class', Utils::clsx( ['yuki-page-builder-element', 'yuki-hero relative', $id] ) );
if ( is_customize_preview() ) {
$this->add_render_attribute( $id, 'data-shortcut', 'drop' );
$this->add_render_attribute( $id, 'data-shortcut-location', $attrs['location'] );
}
$title = $this->get( $this->getSlug( 'title' ), $settings );
$tag = $this->get( $this->getSlug( 'title_tag' ), $settings );
$desc = $this->get( $this->getSlug( 'description' ), $settings );
$button_text = $this->get( $this->getSlug( 'button_text' ), $settings );
if ( $button_text != '' ) {
$this->add_render_attribute( $this->getSlug( 'button' ), 'href', esc_url( $this->get( 'button_url', $settings ) ) );
if ( $this->checked( $this->getSlug( 'button_open_new_tab' ), $settings ) ) {
$this->add_render_attribute( $this->getSlug( 'button' ), 'target', '_blank' );
}
if ( $this->checked( $this->getSlug( 'button_no_follow' ), $settings ) ) {
$this->add_render_attribute( $this->getSlug( 'button' ), 'rel', 'nofollow' );
}
}
$media = $this->get( $this->getSlug( 'media' ), $settings );
$media_attr = yuki_image_attr( $media );
?>
<div <?php
$this->print_attribute_string( $id );
?>>
<?php
if ( $this->checked( $this->getSlug( 'overlay' ), $settings ) ) {
?>
<div class="hero-overlay absolute w-full h-full left-0 top-0"></div>
<?php
}
?>
<div class="<?php
Utils::the_clsx( ['hero-container container mx-auto px-gutter relative z-[1]', 'flex-row-reverse' => $this->get( $this->getSlug( 'layout' ), $settings ) === 'media-content'] );
?>">
<div class="hero-content yuki-scroll-reveal">
<?php
if ( $title !== '' ) {
echo '<' . $tag . ' class="hero-title mb-gutter">';
echo esc_html( $title );
echo '</' . $tag . '>';
}
?>
<?php
if ( $desc !== '' ) {
?>
<div class="hero-description mb-gutter yuki-raw-html"><?php
echo do_shortcode( wp_kses_post( $desc ) );
?></div>
<?php
}
?>
<?php
if ( $button_text !== '' ) {
?>
<div class="mt-double-gutter">
<a class="hero-button yuki-button" <?php
$this->print_attribute_string( $this->getSlug( 'button' ) );
?>>
<?php
echo esc_html( $button_text );
?>
</a>
</div>
<?php
}
?>
</div>
<?php
if ( !empty( $media_attr ) ) {
?>
<div class="hero-media yuki-scroll-reveal p-gutter">
<img <?php
Utils::print_attribute_string( $media_attr );
?> />
</div>
<?php
}
?>
</div>
<?php
$this->shape_divider( $settings );
?>
</div>
<?php
}
}
} |