Skip to content
Snippets Groups Projects
Commit 3cb40a47 authored by Nick Dickinson-Wilde's avatar Nick Dickinson-Wilde
Browse files

Issue #2932106 by attisan, NickDickinsonWilde: CSS Declaration Formatter (Custom CSS Declaration)

parent 44d9c006
No related branches found
No related tags found
No related merge requests found
......@@ -5,6 +5,8 @@
* A color field with a custom color picker using the Field Types API.
*/
use Drupal\Core\Render\BubbleableMetadata;
use Drupal\color_field\ColorHex;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Url;
......@@ -71,3 +73,119 @@ function color_field_theme() {
return $theme;
}
/**
* Implements hook_token_info().
*/
function color_field_token_info() {
$tokens = [];
$tokens['color_field']['hex'] = [
'name' => t('HEX'),
'description' => t("Hex style color values."),
'type' => 'hex',
];
$tokens['hex']['with_opacity'] = [
'name' => t('With Opacity'),
'description' => t('HEX style color with opacity'),
];
$tokens['color_field']['rgb'] = [
'name' => t('RGB'),
'description' => t("RGB style color values."),
'type' => 'rgb',
];
$tokens['rgb']['rgba'] = [
'name' => t('RGBA'),
'description' => t("Color value expressed as rgba(xx,xx,xx,x.x)."),
];
$tokens['rgb']['red'] = [
'name' => t('Red'),
'description' => t("RGB Color value for red only expressed as an int."),
];
$tokens['rgb']['blue'] = [
'name' => t('Blue'),
'description' => t("RGB Color value for blue only expressed as an int."),
];
$tokens['rgb']['green'] = [
'name' => t('Green'),
'description' => t("RGB Color value for green only expressed as an int."),
];
$tokens['rgb']['opacity'] = [
'name' => t('Opacity'),
'description' => t("RGB Color value for opacity only expressed as a float."),
];
return [
'types' => [
'color_field' => [
'name' => t('Color Field'),
'description' => t('Values from a specific color field item.'),
'needs-data' => 'color_field',
],
'rgb' => [
'name' => t('RGB'),
'description' => t('RGB Values from a specific color field item.'),
'needs-data' => 'color_field',
],
'hex' => [
'name' => t('HEX'),
'description' => t('HEX values from a specific color field item'),
'needs-data' => 'color_field',
],
],
'tokens' => $tokens,
];
}
/**
* Implements hook_tokens().
*/
function color_field_tokens($type, $tokens, array $data, array $options, BubbleableMetadata $bubbleable_metadata) {
$replacements = [];
if ($type === 'color_field' && !empty($data['color_field'])) {
/** @var \Drupal\color_field\Plugin\Field\FieldType\ColorFieldType $color_field */
$color_field = $data['color_field'];
$color_hex = new ColorHex($color_field->color, $color_field->opacity);
foreach ($tokens as $name => $original) {
switch ($name) {
case 'hex':
$replacements[$original] = $color_hex->toString(FALSE);
break;
case 'hex:with_opacity':
$replacements[$original] = $color_hex->toString(TRUE);
break;
case 'rgb':
$replacements[$original] = $color_hex->toRgb()->toString(FALSE);
break;
case 'rgba':
$replacements[$original] = $color_hex->toRgb()->toString(TRUE);
break;
case 'rgb:red':
$replacements[$original] = $color_hex->toRgb()->getRed();
break;
case 'rgb:blue':
$replacements[$original] = $color_hex->toRgb()->getBlue();
break;
case 'rgb:green':
$replacements[$original] = $color_hex->toRgb()->getGreen();
break;
case 'rgb:opacity':
$replacements[$original] = $color_hex->toRgb()->getOpacity();
break;
}
}
}
return $replacements;
}
......@@ -83,6 +83,8 @@ class ColorFieldFormatterCss extends FormatterBase implements ContainerFactoryPl
'property' => 'background-color',
'important' => TRUE,
'opacity' => TRUE,
'advanced' => FALSE,
'css' => '',
] + parent::defaultSettings();
}
......@@ -94,16 +96,17 @@ class ColorFieldFormatterCss extends FormatterBase implements ContainerFactoryPl
$elements['selector'] = [
'#title' => $this->t('Selector'),
'#description' => $this->t('A valid CSS selector such as <code>.links > li > a, #logo</code>.'),
'#description' => $this->t('A valid CSS selector such as <code>.links > li > a, #logo</code>. You can use tokens as shown below.'),
'#type' => 'textarea',
'#rows' => '1',
'#default_value' => $this->getSetting('selector'),
'#required' => TRUE,
'#placeholder' => 'body > div > a',
];
$elements['token_help'] = [
'#theme' => 'token_tree_link',
'#token_types' => [$this->fieldDefinition->getTargetEntityTypeId()],
'#states' => [
'visible' => [
':input[name="fields[' . $this->fieldDefinition->getName() . '][settings_edit_form][settings][advanced]"]' => ['checked' => FALSE],
],
],
];
$elements['property'] = [
'#title' => $this->t('Property'),
......@@ -114,12 +117,22 @@ class ColorFieldFormatterCss extends FormatterBase implements ContainerFactoryPl
'background-color' => $this->t('Background color'),
'color' => $this->t('Text color'),
],
'#states' => [
'visible' => [
':input[name="fields[' . $this->fieldDefinition->getName() . '][settings_edit_form][settings][advanced]"]' => ['checked' => FALSE],
],
],
];
$elements['important'] = [
'#title' => $this->t('Important'),
'#description' => $this->t('Whenever this declaration is more important than others.'),
'#type' => 'checkbox',
'#default_value' => $this->getSetting('important'),
'#states' => [
'visible' => [
':input[name="fields[' . $this->fieldDefinition->getName() . '][settings_edit_form][settings][advanced]"]' => ['checked' => FALSE],
],
],
];
if ($this->getFieldSetting('opacity')) {
......@@ -127,8 +140,43 @@ class ColorFieldFormatterCss extends FormatterBase implements ContainerFactoryPl
'#type' => 'checkbox',
'#title' => $this->t('Display opacity'),
'#default_value' => $this->getSetting('opacity'),
'#states' => [
'visible' => [
':input[name="fields[' . $this->fieldDefinition->getName() . '][settings_edit_form][settings][advanced]"]' => ['checked' => FALSE],
],
],
];
}
$elements['advanced'] = [
'#type' => 'checkbox',
'#title' => $this->t('Advanced Mode'),
'#default_value' => $this->getSetting('advanced'),
'#description' => t('Switch to advanced mode and build the css yourself.'),
];
$elements['css'] = [
'#type' => 'textarea',
'#title' => $this->t('CSS'),
'#default_value' => $this->getSetting('css'),
'#description' => t('Create the css statement yourself. This lets you for example, control multiple element aspects at once. You can use tokens as shown below.'),
'#states' => [
'visible' => [
':input[name="fields[' . $this->fieldDefinition->getName() . '][settings_edit_form][settings][advanced]"]' => ['checked' => TRUE],
],
],
'#element_validate' => ['token_element_validate'],
'#token_types' => [
$this->fieldDefinition->getTargetEntityTypeId(),
'color_field',
],
];
$elements['token_help'] = [
'#theme' => 'token_tree_link',
'#token_types' => [
$this->fieldDefinition->getTargetEntityTypeId(),
'color_field',
],
];
return $elements;
}
......@@ -141,19 +189,24 @@ class ColorFieldFormatterCss extends FormatterBase implements ContainerFactoryPl
$settings = $this->getSettings();
$summary = [];
if ($settings['advanced']) {
$summary[] = $this->t('Using advanced mode');
$summary[] = $this->t("CSS statement:\n@css", ['@css' => $settings['css']]);
}
else {
$summary[] = $this->t('CSS selector : @css_selector', [
'@css_selector' => $settings['selector'],
]);
$summary[] = $this->t('CSS property : @css_property', [
'@css_property' => $settings['property'],
]);
$summary[] = $this->t('!important declaration : @important_declaration', [
'@important_declaration' => (($settings['important']) ? $this->t('Yes') : $this->t('No')),
]);
$summary[] = $this->t('CSS selector : @css_selector', [
'@css_selector' => $settings['selector'],
]);
$summary[] = $this->t('CSS property : @css_property', [
'@css_property' => $settings['property'],
]);
$summary[] = $this->t('!important declaration : @important_declaration', [
'@important_declaration' => (($settings['important']) ? $this->t('Yes') : $this->t('No')),
]);
if ($opacity && $settings['opacity']) {
$summary[] = $this->t('Display with opacity.');
if ($opacity && $settings['opacity']) {
$summary[] = $this->t('Display with opacity.');
}
}
return $summary;
......@@ -173,18 +226,23 @@ class ColorFieldFormatterCss extends FormatterBase implements ContainerFactoryPl
];
foreach ($items as $item) {
$value = $this->viewValue($item);
$selector = $this->tokenService->replace(
$settings['selector'],
$tokens
);
$important = ($settings['important']) ? ' !important' : '';
$property = $settings['property'];
$inline_css = $selector . ' { ' . $property . ': ' . $value . $important . '; }';
// @todo: Not sure this is the best way.
// https://www.drupal.org/node/2391025
// https://www.drupal.org/node/2274843
$tokens['color_field'] = $item;
if ($settings['advanced']) {
$inline_css = $this->tokenService->replace(
$settings['css'],
$tokens
);
}
else {
$selector = $this->tokenService->replace(
$settings['selector'],
$tokens
);
$important = ($settings['important']) ? ' !important' : '';
$property = $settings['property'];
$inline_css = $selector . ' { ' . $property . ': ' . $value . $important . '; }';
}
$elements['#attached']['html_head'][] = [[
'#tag' => 'style',
'#value' => $inline_css,
......
......@@ -56,7 +56,7 @@ class ColorFieldFormatterSwatch extends FormatterBase {
'#title' => $this->t('Width'),
'#default_value' => $this->getSetting('width'),
'#min' => 1,
$this->t('Defaults to pixels (px) if a number is entered, otherwise, you can enter any unit (ie %, em, vw)'),
'#description' => $this->t('Defaults to pixels (px) if a number is entered, otherwise, you can enter any unit (ie %, em, vw)'),
];
$elements['height'] = [
'#type' => 'textfield',
......@@ -155,8 +155,8 @@ class ColorFieldFormatterSwatch extends FormatterBase {
'#attributes' => new Attribute([
'class' => [
'color_field__swatch',
"color_field__swatch--{$settings['shape']}"
]
"color_field__swatch--{$settings['shape']}",
],
]),
];
if ($settings['data_attribute']) {
......
......@@ -46,8 +46,8 @@ class ColorFieldFormatterSwatchOptions extends ColorFieldFormatterSwatch {
'#color' => $this->viewValue($item),
'#attributes' => new Attribute([
'class' => [
"color_field__swatch--{$settings['shape']}"
]
"color_field__swatch--{$settings['shape']}",
],
]),
];
if ($settings['data_attribute']) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment