Skip to content
Snippets Groups Projects
Commit 95e9f765 authored by Tim Bozeman's avatar Tim Bozeman
Browse files

Add edit_plus_suite

parent c07721a3
Branches
Tags 2.0.2
No related merge requests found
Pipeline #449230 passed with warnings
Showing
with 754 additions and 0 deletions
.block__title {
&.text-jumbo1 {
font-size: 4.063rem;
line-height: 1.125;
letter-spacing: 0.003em;
}
&.text-jumbo2 {
font-size: 3.375rem;
line-height: 1.125;
letter-spacing: 0.006em;
}
&.text-jumbo3 {
font-size: 2.813rem;
line-height: 1.125;
letter-spacing: 0.009em;
}
&.text-jumbo4 {
font-size: 2.375rem;
line-height: 1.125;
letter-spacing: 0.011em;
}
&.text-large1 {
font-size: 2rem;
line-height: 1.200;
letter-spacing: 0.012em;
}
&.text-large2 {
font-size: 1.75rem;
line-height: 1.200;
letter-spacing: 0.013em;
}
&.text-large3 {
font-size: 1.5rem;
line-height: 1.200;
letter-spacing: 0.015em;
}
&.text-large4 {
font-size: 1.313rem;
line-height: 1.200;
letter-spacing: 0.017em;
}
&.text-large5 {
font-size: 1.125rem;
line-height: 1.200;
letter-spacing: -0.025em;
}
&.text-large6 {
font-size: 1rem;
line-height: 1.200;
letter-spacing: -0.020em;
}
}
name: 'Layout Builder + and + Suite'
type: module
description: 'Some example things for the + Suite recipe'
core_version_requirement: ^10 || ^11
package: 'Page Building'
dependencies:
- lb_plus:lb_plus
- lb_plus_edit_plus:lb_plus_edit_plus
- edit_plus_lb:edit_plus_lb
- field_sample_value:field_sample_value
- navigation_plus:navigation_plus
- edit_plus_lb:edit_plus_lb
- drupal:navigation
- drupal:navigation_top_bar
styles:
css:
theme:
css/edit-plus-sweet.css: {}
<?php
use Drupal\Component\Uuid\Uuid;
use Drupal\Core\Form\FormStateInterface;
use Drupal\edit_plus_sweet\Events\LayoutBuilderBlockFormAlterEvent;
/**
* Implements hook_form_alter().
*/
function edit_plus_sweet_form_alter(&$form, FormStateInterface $form_state, $form_id) {
if (!in_array($form_id, [
'layout_builder_update_block',
'layout_builder_add_block',
])) {
return;
}
/** @var \Drupal\layout_builder\SectionStorageInterface $storage */
[$storage, $delta, $region, $uuid, $nested_storage_path] = $form_state->getBuildInfo()['args'];
$configuration = [];
$current_section_storage = Drupal::service('lb_plus.section_storage_handler')->getCurrentSectionStorage($storage, $nested_storage_path);
if ($uuid && Uuid::isValid($uuid)) {
$component = $current_section_storage->getSection($delta)->getComponent($uuid);
$configuration = $component->getPlugin()->getConfiguration();
}
$blockEvent = new LayoutBuilderBlockFormAlterEvent($form, $form_state, $storage, $region, $configuration, $component ?? NULL);
Drupal::service('event_dispatcher')->dispatch($blockEvent);
$form = $blockEvent->getForm();
}
/**
* Implements hook_preprocess_HOOK().
*/
function edit_plus_sweet_preprocess_block__inline_block__heading(&$variables) {
$config = $variables['elements']['#configuration'];
$title_size = $config['title_size'] ?? '';
if ($title_size) {
$variables['title_attributes']['class'][] = $title_size;
}
$alignment = $config['alignment'] ?? '';
if ($alignment) {
$variables['title_attributes']['class'][] = $alignment;
}
$first_color = $config['first_color'] ?? '';
$second_color = $config['second_color'] ?? '';
$rotation = ($config['gradient_rotation'] ?? '90') . 'deg';
if ($first_color && $second_color) {
$variables['title_attributes']['style'] = "background:linear-gradient($rotation, $first_color, $second_color); -webkit-background-clip:text; color:transparent;";
}
$variables['#attached']['library'][] = 'edit_plus_sweet/styles';
}
services:
_defaults:
autoconfigure: true
autowire: true
edit_plus_sweet.heading:
class: Drupal\edit_plus_sweet\EventSubscriber\Heading
edit_plus_sweet.layout_builder_block_title:
class: Drupal\edit_plus_sweet\EventSubscriber\LayoutBuilderBlockForm\TitleCustomizations
edit_plus_sweet.heading_customizations:
class: Drupal\edit_plus_sweet\EventSubscriber\LayoutBuilderBlockForm\HeadingCustomizations
<?php
namespace Drupal\edit_plus_sweet\EventSubscriber;
use Drupal\lb_plus\Event\PlaceBlockEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class Heading implements EventSubscriberInterface {
public function onPostPlaceBlockFormBuild(PlaceBlockEvent $event) {
if ($event->getBlockPluginId() === 'inline_block' && $event->getBundle() === 'heading') {
$block_plugin = $event->getBlockPlugin();
$configuration = $block_plugin->getConfiguration();
$configuration['label_display'] = 'visible';
$configuration['label'] = $block_plugin->label();
$configuration['label_tag'] = 'h2';
$block_plugin->setConfiguration($configuration);
}
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
return [
PlaceBlockEvent::class => ['onPostPlaceBlockFormBuild'],
];
}
}
<?php
namespace Drupal\edit_plus_sweet\EventSubscriber\LayoutBuilderBlockForm;
use Drupal\Core\Block\BlockPluginInterface;
use Drupal\Core\Template\Attribute;
use Drupal\Core\Form\FormStateInterface;
use Drupal\layout_builder\LayoutBuilderEvents;
use Drupal\edit_plus_sweet\Events\LayoutBuilderBlockFormAlterEvent;
use Drupal\layout_builder\Event\SectionComponentBuildRenderArrayEvent;
/**
* Alters the block form to add some elements for styling of a heading/title.
*/
abstract class EnhancedTitleBase extends LayoutBuilderBlockFormBase {
/**
* List of title attributes that will be set in config on block form submit.
*
* @var array|string[]
*/
protected static array $configurableProperties = [
'first_color',
'second_color',
'gradient_rotation',
];
public static function getSubscribedEvents() {
$events = parent::getSubscribedEvents();
$events[LayoutBuilderEvents::SECTION_COMPONENT_BUILD_RENDER_ARRAY] = [
'onBuildRender',
90,
];
return $events;
}
/**
* {@inheritdoc}
*/
public function formAlter(LayoutBuilderBlockFormAlterEvent $event) {
$form = $event->getForm();
$config = $event->getConfiguration();
$actions = $form['actions'];
unset($form['actions']);
static::addTitleOptions($form['settings'], $config);
$form['actions'] = $actions;
$form['#submit'] = array_merge([[$this, 'formSubmit']], $form['#submit']);
$event->setForm($form);
}
/**
* Submit handler that saves title options like size and color into block.
*/
public function formSubmit(array &$form, FormStateInterface $form_state) {
static::setTitleOptions($form_state, 'block', $form_state->getValues()['settings']);
}
public function onBuildRender(SectionComponentBuildRenderArrayEvent $event) {
$block = $event->getPlugin();
if (!$block instanceof BlockPluginInterface) {
return;
}
$valid_block_ids = [$this->blockId, "inline_block:{$this->blockId}"];
if (!in_array($block->getPluginId(), $valid_block_ids)) {
return;
}
if (empty($block->getConfiguration()['title_size'])) {
return;
}
$config = $block->getConfiguration();
if (!empty($config['formatter']['type']) && $config['formatter']['type'] !== 'heading') {
return;
}
$build = $event->getBuild();
$title_attributes = NULL;
// Field blocks.
$content = !empty($build['content'][0]) ? $build['content'][0] : NULL;
if ($build['#base_plugin_id'] == 'field_block' && $content) {
/** @var \Drupal\Core\Template\Attribute $title_attributes */
if ($content[0]['#type'] === 'inline_template') {
$title_attributes = $content[0]['#context']['attributes'];
}
elseif (!empty($content[0]['#title']['#context']['attributes'])) {
$title_attributes = $content[0]['#title']['#context']['attributes'];
}
if ($content[0]['#type'] === 'link') {
$build['content'][0][0]['#attributes']['class'][] = 'no-underline';
}
}
elseif (!empty($build['content']['#block_content'])) {
$build['content']['#title_attributes'] = new Attribute();
$title_attributes = $build['content']['#title_attributes'];
}
if (!$title_attributes) {
$title_attributes = new Attribute();
}
if ($title_attributes) {
static::setTitleAttributes($title_attributes, $config);
}
$event->setBuild($build);
}
/**
* Adds fields for enhancement of a heading/title to a given form.
*
* @param array $form
* @param array $config
*
* @return void
*/
public static function addTitleOptions(array &$form, array $config) {
$form['title_size'] = [
'#type' => 'select',
'#title' => t('Select title size'),
'#options' => [
'text-jumbo1' => t('Jumbo 65px'),
'text-jumbo2' => t('Jumbo 54px'),
'text-jumbo3' => t('Jumbo 45px'),
'text-jumbo4' => t('Jumbo 38px'),
'text-large1' => t('Large 32px'),
'text-large2' => t('Large 28px'),
'text-large3' => t('Large 24px'),
'text-large4' => t('Large 21px'),
'text-large5' => t('Large 18px'),
'text-large6' => t('Large 16px'),
],
'#default_value' => $config['title_size'] ?? 'text-jumbo4',
];
$has_color_adjustment = (!empty($config['formatter']['type']) && $config['formatter']['type'] == 'heading' && !empty($config['first_color']))
|| empty($config['formatter']) && !empty($config['first_color']);
$form['title_color'] = [
'#type' => 'checkbox',
'#title' => t('Set custom title gradient'),
'#default_value' => $has_color_adjustment,
];
$form['first_color'] = [
'#type' => 'color',
'#title' => t('First color'),
'#default_value' => $config['first_color'] ?? '#000000',
'#states' => [
'visible' => [
'[name="settings[title_color]"]' => ['checked' => TRUE],
],
],
];
$form['second_color'] = [
'#type' => 'color',
'#title' => t('Second color'),
'#default_value' => $config['second_color'] ?? '#000000',
'#states' => [
'visible' => [
'[name="settings[title_color]"]' => ['checked' => TRUE],
],
],
];
$form['gradient_rotation'] = [
'#type' => 'number',
'#title' => t('Rotation'),
'#description' => t('Enter the rotation of the gradient in degrees between 0 and 360.'),
'#min' => 0,
'#max' => 360,
'#default_value' => $config['gradient_rotation'] ?? '90',
'#states' => [
'visible' => [
'[name="settings[title_color]"]' => ['checked' => TRUE],
],
],
];
}
/**
* Saves provided values into instance of configurable plugin.
*
* @param \Drupal\Core\Form\FormStateInterface $form_state
* @param string $property
* @param array $values
*
* @return void
* @throws \ReflectionException
*/
public static function setTitleOptions(FormStateInterface $form_state, string $property, array $values) {
$form_object = $form_state->getFormObject();
$p = new \ReflectionProperty($form_object, $property);
$p->setAccessible(TRUE);
/** @var \Drupal\Component\Plugin\ConfigurableInterface $component */
$component = $p->getValue($form_object);
$config = $component->getConfiguration();
$config['title_size'] = $values['title_size'];
foreach (static::$configurableProperties as $property) {
if (in_array($property, self::$configurableProperties)) {
if (!empty($values['title_color'])) {
$config[$property] = $values[$property];
}
else {
unset($config[$property]);
}
}
else {
$config[$property] = $values[$property];
}
}
$component->setConfiguration($config);
}
/**
* Sets attributes based on given config.
*
* @param \Drupal\Core\Template\Attribute $title_attributes
* @param array $config
*
* @return void
*/
public static function setTitleAttributes(Attribute $title_attributes, array $config) {
$title_size = $config['title_size'] ?? '';
if ($title_size) {
$title_attributes->addClass($title_size);
}
$first_color = $config['first_color'] ?? '';
$second_color = $config['second_color'] ?? '';
$rotation = ($config['gradient_rotation'] ?? '90') . 'deg';
if ($first_color && $second_color) {
$title_attributes->setAttribute('style', "background:linear-gradient($rotation, $first_color, $second_color); -webkit-background-clip:text; color:transparent;");
}
}
}
<?php
namespace Drupal\edit_plus_sweet\EventSubscriber\LayoutBuilderBlockForm;
use Drupal\edit_plus_sweet\Events\LayoutBuilderBlockFormAlterEvent;
use Drupal\Core\Template\Attribute;
/**
* Alters the block form of the 'heading' custom block bundle.
*/
class HeadingCustomizations extends EnhancedTitleBase {
/**
* {@inheritdoc}
*/
protected static array $configurableProperties = [
'first_color',
'second_color',
'gradient_rotation',
'alignment',
];
/**
* {@inheritdoc}
*/
public $blockId = 'heading';
/**
* {@inheritdoc}
*/
public function formAlter(LayoutBuilderBlockFormAlterEvent $event) {
parent::formAlter($event);
$form = $event->getForm();
// Callouts need the block's label, so we're going to remove the ability to
// disable it from the form.
$form['settings']['label']['#access'] = TRUE;
$form['settings']['label_display']['#value'] = TRUE;
$form['settings']['label_display']['#access'] = FALSE;
$form['settings']['label_display']['#default_value'] = TRUE;
$event->setForm($form);
}
/**
* {@inheritdoc}
*/
public static function addTitleOptions(array &$form, array $config) {
$form['alignment'] = [
'#title' => t('Heading Alignment'),
'#type' => 'select',
'#options' => [
'text-align-left' => t('Left'),
'text-align-center' => t('Center'),
'text-align-right' => t('Right'),
],
'#required' => TRUE,
'#default_value' => $config['alignment'] ?? 'text-align-left',
];
parent::addTitleOptions($form, $config);
}
/**
* {@inheritdoc}
*/
public static function setTitleAttributes(Attribute $title_attributes, array $config) {
parent::setTitleAttributes($title_attributes, $config);
$title_attributes->addClass('heading-formatter');
if (!empty($config['alignment'])) {
$title_attributes->addClass($config['alignment']);
}
}
}
<?php
namespace Drupal\edit_plus_sweet\EventSubscriber\LayoutBuilderBlockForm;
use Drupal\layout_builder\Form\AddBlockForm;
use Drupal\layout_builder\Form\UpdateBlockForm;
use Drupal\layout_builder\Plugin\Block\InlineBlock;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Drupal\edit_plus_sweet\Events\LayoutBuilderBlockFormAlterEvent;
abstract class LayoutBuilderBlockFormBase implements LayoutBuilderBlockFormInterface, EventSubscriberInterface {
/**
* Required Block ID to act on.
*
* @var string
*/
public $blockId;
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
$events = [];
$events[LayoutBuilderBlockFormAlterEvent::class][] = ['onBlockFormAlter', 10];
return $events;
}
/**
* Checks the Block ID and calls formAlter().
*
* @param \Drupal\edit_plus_sweet\Events\LayoutBuilderBlockFormAlterEvent $event
* The form alteration event.
*
* @throws \ReflectionException
*/
public function onBlockFormAlter(LayoutBuilderBlockFormAlterEvent $event) {
if (!$this->blockId) {
return;
}
$formObject = $event->getFormState()->getFormObject();
$block = FALSE;
if ($formObject instanceof AddBlockForm || $formObject instanceof UpdateBlockForm) {
$p = new \ReflectionProperty($formObject, 'block');
$p->setAccessible(TRUE);
/** @var $block InlineBlock **/
// This isn't actually an inline block all the time, but the interface is
// standard, and we only operate on inline call to action blocks.
$block = $p->getValue($formObject);
}
if (!$block || ($block->getPluginId() !== "inline_block:{$this->blockId}" && $block->getPluginId() !== $this->blockId)) {
return;
}
$event->setBlock($block);
$this->formAlter($event);
}
}
<?php
namespace Drupal\edit_plus_sweet\EventSubscriber\LayoutBuilderBlockForm;
use Drupal\edit_plus_sweet\Events\LayoutBuilderBlockFormAlterEvent;
/**
* Layout builder block form interface.
*/
interface LayoutBuilderBlockFormInterface {
/**
* Block form alter.
*
* @param \Drupal\edit_plus_sweet\Events\ $event
* The block form alter event.
*/
public function formAlter(LayoutBuilderBlockFormAlterEvent $event);
}
<?php
namespace Drupal\edit_plus_sweet\EventSubscriber\LayoutBuilderBlockForm;
use Drupal\edit_plus_sweet\Events\LayoutBuilderBlockFormAlterEvent;
use Drupal\layout_builder\LayoutBuilderEvents;
class TitleCustomizations extends EnhancedTitleBase {
public $blockId = 'field_block:node:landing_page:title';
public static function getSubscribedEvents() {
$events = parent::getSubscribedEvents();
$events[LayoutBuilderEvents::SECTION_COMPONENT_BUILD_RENDER_ARRAY] = ['onBuildRender', 90];
return $events;
}
public function formAlter(LayoutBuilderBlockFormAlterEvent $event) {
parent::formAlter($event);
$form = $event->getForm();
if ($form['settings']['label']['#default_value'] === "Title") {
$form['settings']['label']['#value'] = "Page Title";
}
$form['settings']['label']['#access'] = FALSE;
$form['settings']['label_display']['#value'] = FALSE;
$form['settings']['label_display']['#access'] = FALSE;
$form['settings']['formatter']['label']['#value'] = 'hidden';
$form['settings']['formatter']['label']['#access'] = FALSE;
$form['title_size']['#states'] = [
'visible' => [
':input[name="settings[formatter][type]"]' => ['value' => 'heading'],
],
];
$form['title_color']['#states'] = [
'visible' => [
':input[name="settings[formatter][type]"]' => ['value' => 'heading'],
],
];
$form['first_color']['#states']['visible'][] = [
':input[name="settings[formatter][type]"]' => ['value' => 'heading'],
];
$form['second_color']['#states']['visible'][] = [
':input[name="settings[formatter][type]"]' => ['value' => 'heading'],
];
$form['gradient_rotation']['#states']['visible'][] = [
':input[name="settings[formatter][type]"]' => ['value' => 'heading'],
];
$event->setForm($form);
}
}
<?php
namespace Drupal\edit_plus_sweet\Events;
use Drupal\Core\Block\BlockPluginInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\layout_builder\Plugin\Block\InlineBlock;
use Drupal\layout_builder\SectionComponent;
use Drupal\layout_builder\SectionStorageInterface;
use Symfony\Contracts\EventDispatcher\Event;
class LayoutBuilderBlockFormAlterEvent extends Event {
/**
* The form array being altered.
*
* @var array
*/
protected $form;
/**
* The formState object for the form being altered.
*
* @var FormStateInterface
*/
protected $formState;
/**
* The layout_builder instance storage the form appears within.
*
* @var SectionStorageInterface
*/
protected $storage;
/**
* The region in which the block does or will appear.
*
* @var string
*/
protected $region;
/**
* The block's configuration.
*
* This may be empty in the case that the block is being configured for the
* first time.
*
* @var array
*/
protected $configuration;
/**
* The section component if available.
*
* @var SectionComponent|null
*/
protected $component;
/**
* The inline block.
*
* @var
*/
protected $block;
/**
* LayoutBuilderBlockFormAlterEvent constructor.
* @param array $form
* @param FormStateInterface $formState
* @param SectionStorageInterface $storage
* @param string $region
* @param array $configuration
* @param SectionComponent|null $param
*/
public function __construct(array $form, FormStateInterface $formState, SectionStorageInterface $storage, string $region, array $configuration, SectionComponent $component = NULL) {
$this->form = $form;
$this->formState = $formState;
$this->storage = $storage;
$this->region = $region;
$this->configuration = $configuration;
$this->component = $component;
}
/**
* @return array
*/
public function getForm(): array {
return $this->form;
}
/**
* @param array $form
*/
public function setForm(array $form): void {
$this->form = $form;
}
/**
* @return FormStateInterface
*/
public function getFormState(): FormStateInterface {
return $this->formState;
}
/**
* @return SectionStorageInterface
*/
public function getStorage(): SectionStorageInterface {
return $this->storage;
}
/**
* @return string
*/
public function getRegion(): string {
return $this->region;
}
/**
* @return array
*/
public function getConfiguration(): array {
return $this->configuration;
}
/**
* @return SectionComponent|null
*/
public function getComponent() {
return $this->component;
}
/**
* @return \Drupal\Core\Block\BlockPluginInterface
*/
public function getBlock(): BlockPluginInterface {
return $this->block;
}
/**
* @param \Drupal\Core\Block\BlockPluginInterface $block
*/
public function setBlock(BlockPluginInterface $block): void {
$this->block = $block;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment