From 3493bac6d1ef527a0e592db9e98ab1845c771b48 Mon Sep 17 00:00:00 2001
From: Christian Wiedemann <christian.wiedemann@key-tec.de>
Date: Sat, 15 Feb 2025 16:09:53 +0100
Subject: [PATCH 1/7] Add select 2 widget

---
 src/Plugin/UiPatterns/Source/SelectWidget.php | 66 +++++++++++++++++++
 ui_patterns_settings.module                   |  9 +++
 2 files changed, 75 insertions(+)
 create mode 100644 src/Plugin/UiPatterns/Source/SelectWidget.php

diff --git a/src/Plugin/UiPatterns/Source/SelectWidget.php b/src/Plugin/UiPatterns/Source/SelectWidget.php
new file mode 100644
index 0000000..36b1772
--- /dev/null
+++ b/src/Plugin/UiPatterns/Source/SelectWidget.php
@@ -0,0 +1,66 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\ui_patterns_settings\Plugin\UiPatterns\Source;
+
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\ui_patterns\Plugin\UiPatterns\Source\SelectWidget as BaseSelectWidget;
+
+/**
+ * Plugin overwrite of the source.
+ */
+class SelectWidget extends BaseSelectWidget {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsForm(array $form, FormStateInterface $form_state): array {
+    $form = parent::settingsForm($form, $form_state);
+    $active_options = $this->configuration['configure']['options'] ?? [];
+    if (count($active_options) > 0) {
+      $options = $form['value']['#options'] ?? [];
+      foreach ($options as $option => $label) {
+        if (isset($active_options[$option]) && $active_options[$option] === 0) {
+          unset($options[$option]);
+        }
+      }
+    }
+    $overwrite_options = $this->configuration['configure']['overwrite_options'] ?? [];
+    if (!empty($overwrite_options)) {
+      $lines = explode("\r\n", $overwrite_options);
+      foreach ($lines as $line) {
+        $key_value = explode('|', $line);
+        if ($options[$key_value[0]] && !empty($key_value[1])) {
+          $options[$key_value[0]] = $key_value[1];
+        }
+      }
+    }
+    $form['value']['#options'] = $options;
+
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function configureForm(array $form, FormStateInterface $form_state): array {
+    $form = parent::configureForm($form, $form_state);
+    $options = self::getEnumOptions($this->getPropDefinition());
+    $form['options'] = [
+      '#type' => 'checkboxes',
+      '#title' => $this->t('Selectable options'),
+      '#description' => $this->t('Leave empty to select all options.'),
+      '#options' => $options,
+      '#default_value' => $this->configuration['configure']['options'] ?? [],
+    ];
+    $form['overwrite_options'] = [
+      '#type' => 'textarea',
+      '#title' => $this->t('Overwrite option Labels'),
+      '#description' => $this->t('Overwrite "existing" option labels by adding key|label entry.'),
+      '#default_value' => $this->configuration['configure']['overwrite_options'] ?? [],
+    ];
+    return $form;
+  }
+
+}
diff --git a/ui_patterns_settings.module b/ui_patterns_settings.module
index 68201a6..63c5a2d 100644
--- a/ui_patterns_settings.module
+++ b/ui_patterns_settings.module
@@ -4,3 +4,12 @@
  * @file
  * Contains ui_patterns_settings.module.
  */
+
+/**
+ * Implements hook_ui_patterns_source_info_alter().
+ */
+function ui_patterns_settings_ui_patterns_source_info_alter(array &$info) {
+  if (isset($info['select'])) {
+    $info['select']['class'] = '\Drupal\ui_patterns_settings\Plugin\UiPatterns\Source\SelectWidget';
+  }
+}
-- 
GitLab


From a69cf2a1ec4b9bc4aea97a3e62bec5120522fea1 Mon Sep 17 00:00:00 2001
From: Christian Wiedemann <christian.wiedemann@key-tec.de>
Date: Sun, 16 Feb 2025 15:25:10 +0100
Subject: [PATCH 2/7] Refactor to trait

---
 src/EnumSourceTrait.php                       | 75 +++++++++++++++++++
 src/Plugin/UiPatterns/Source/SelectWidget.php | 42 ++---------
 2 files changed, 81 insertions(+), 36 deletions(-)
 create mode 100644 src/EnumSourceTrait.php

diff --git a/src/EnumSourceTrait.php b/src/EnumSourceTrait.php
new file mode 100644
index 0000000..c62c876
--- /dev/null
+++ b/src/EnumSourceTrait.php
@@ -0,0 +1,75 @@
+<?php
+
+namespace Drupal\ui_patterns_settings;
+
+use Drupal\ui_patterns\EnumTrait;
+
+trait EnumSourceTrait {
+  use EnumTrait;
+
+  protected function enumAlterOptions(array $options, array $configure): array {
+    $active_options = $configure['options'] ?? [];
+    if (count($active_options) > 0) {
+
+      foreach ($options as $option => $label) {
+        if (isset($active_options[$option]) && $active_options[$option] === 0) {
+          unset($options[$option]);
+        }
+      }
+    }
+    $overwrite_options = $configure['overwrite_options'] ?? [];
+    if (!empty($overwrite_options)) {
+      $lines = explode("\r\n", $overwrite_options);
+      foreach ($lines as $line) {
+        $key_value = explode('|', $line);
+        if ($options[$key_value[0]] && !empty($key_value[1])) {
+          $options[$key_value[0]] = $key_value[1];
+        }
+      }
+    }
+    return $options;
+  }
+
+  /**
+   * @param array $form
+   *
+   * @return array
+   */
+  public function enumConfigureForm(array $configure, array $prop_definition): array {
+    $options = self::getEnumOptions($prop_definition);
+    $form = [];
+    $form['options'] = [
+      '#type' => 'checkboxes',
+      '#title' => $this->t('Limit options'),
+      '#description' => $this->t('Leave empty to select all options.'),
+      '#options' => $options,
+      '#default_value' => $configure['options'] ?? [],
+    ];
+    $form['overwrite_options'] = [
+      '#type' => 'textarea',
+      '#title' => $this->t('Overwrite Option Labels'),
+      '#description' => $this->t('Overwrite "existing" option labels by adding key|label entry.'),
+      '#default_value' => $configure['configure']['overwrite_options'] ?? [],
+    ];
+
+    $form['css'] = [
+      '#type' => 'details',
+      '#title' => $this->t('CSS classes'),
+      '#description' => $this->t('Assign CSS classes to each option.'),
+    ];
+    $form['css']['wrapper_classes'] = [
+      '#type' => 'textfield',
+      '#title' => $this->t('Wrapper CSS classes'),
+      '#description' => $this->t('Classes assigned to wrapping select element'),
+      '#default_value' => $configure['css']['wrapper_classes'] ?? '',
+    ];
+    foreach ($options as $option_id => $label) {
+      $form['css'][$option_id] = [
+        '#type' => 'textfield',
+        '#title' => $this->t('Classes for option: %class', ['%class' => $label]),
+        '#default_value' => $this->selectWidget->getConfiguration()['configure']['css'][$option_id] ?? '',
+      ];
+    }
+    return $form;
+  }
+}
\ No newline at end of file
diff --git a/src/Plugin/UiPatterns/Source/SelectWidget.php b/src/Plugin/UiPatterns/Source/SelectWidget.php
index 36b1772..8f4dd15 100644
--- a/src/Plugin/UiPatterns/Source/SelectWidget.php
+++ b/src/Plugin/UiPatterns/Source/SelectWidget.php
@@ -6,38 +6,21 @@ namespace Drupal\ui_patterns_settings\Plugin\UiPatterns\Source;
 
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\ui_patterns\Plugin\UiPatterns\Source\SelectWidget as BaseSelectWidget;
+use Drupal\ui_patterns_settings\EnumSourceTrait;
 
 /**
  * Plugin overwrite of the source.
  */
 class SelectWidget extends BaseSelectWidget {
 
+  use EnumSourceTrait;
+
   /**
    * {@inheritdoc}
    */
   public function settingsForm(array $form, FormStateInterface $form_state): array {
     $form = parent::settingsForm($form, $form_state);
-    $active_options = $this->configuration['configure']['options'] ?? [];
-    if (count($active_options) > 0) {
-      $options = $form['value']['#options'] ?? [];
-      foreach ($options as $option => $label) {
-        if (isset($active_options[$option]) && $active_options[$option] === 0) {
-          unset($options[$option]);
-        }
-      }
-    }
-    $overwrite_options = $this->configuration['configure']['overwrite_options'] ?? [];
-    if (!empty($overwrite_options)) {
-      $lines = explode("\r\n", $overwrite_options);
-      foreach ($lines as $line) {
-        $key_value = explode('|', $line);
-        if ($options[$key_value[0]] && !empty($key_value[1])) {
-          $options[$key_value[0]] = $key_value[1];
-        }
-      }
-    }
-    $form['value']['#options'] = $options;
-
+    $form['value']['#options'] = $this->enumAlterOptions($form['value']['#options'], $this->getConfiguration()['configure'] ?? []);
     return $form;
   }
 
@@ -46,21 +29,8 @@ class SelectWidget extends BaseSelectWidget {
    */
   public function configureForm(array $form, FormStateInterface $form_state): array {
     $form = parent::configureForm($form, $form_state);
-    $options = self::getEnumOptions($this->getPropDefinition());
-    $form['options'] = [
-      '#type' => 'checkboxes',
-      '#title' => $this->t('Selectable options'),
-      '#description' => $this->t('Leave empty to select all options.'),
-      '#options' => $options,
-      '#default_value' => $this->configuration['configure']['options'] ?? [],
-    ];
-    $form['overwrite_options'] = [
-      '#type' => 'textarea',
-      '#title' => $this->t('Overwrite option Labels'),
-      '#description' => $this->t('Overwrite "existing" option labels by adding key|label entry.'),
-      '#default_value' => $this->configuration['configure']['overwrite_options'] ?? [],
-    ];
-    return $form;
+    return $form + $this->enumConfigureForm($this->getConfiguration()['configure'] ?? [], $this->getPropDefinition());
   }
 
+
 }
-- 
GitLab


From f58f8f2eaf85f027552bc7d96b2170491dbf82f2 Mon Sep 17 00:00:00 2001
From: Christian Wiedemann <christian.wiedemann@key-tec.de>
Date: Mon, 24 Feb 2025 16:13:55 +0100
Subject: [PATCH 3/7] Add intial radio and select widget

---
 css/color.css                                 |  4 +
 css/layout.css                                |  0
 src/EnumSourceTrait.php                       | 83 ++++++++++---------
 src/Plugin/UiPatterns/Source/EnumWidget.php   | 65 +++++++++++++++
 src/Plugin/UiPatterns/Source/SelectWidget.php | 36 --------
 ...i-patterns-settings-radio-widget.html.twig |  4 +
 ...-patterns-settings-radios-widget.html.twig |  1 +
 ...-patterns-settings-select-widget.html.twig | 27 ++++++
 ui_patterns_settings.libraries.yml            |  8 ++
 ui_patterns_settings.module                   | 46 ++++++++--
 10 files changed, 193 insertions(+), 81 deletions(-)
 create mode 100644 css/color.css
 create mode 100644 css/layout.css
 create mode 100644 src/Plugin/UiPatterns/Source/EnumWidget.php
 delete mode 100644 src/Plugin/UiPatterns/Source/SelectWidget.php
 create mode 100644 templates/ui-patterns-settings-radio-widget.html.twig
 create mode 100644 templates/ui-patterns-settings-radios-widget.html.twig
 create mode 100644 templates/ui-patterns-settings-select-widget.html.twig
 create mode 100644 ui_patterns_settings.libraries.yml

diff --git a/css/color.css b/css/color.css
new file mode 100644
index 0000000..8a89599
--- /dev/null
+++ b/css/color.css
@@ -0,0 +1,4 @@
+.uips-layout-color {
+  border: 0 !important;
+  margin: 0 !important;
+}
\ No newline at end of file
diff --git a/css/layout.css b/css/layout.css
new file mode 100644
index 0000000..e69de29
diff --git a/src/EnumSourceTrait.php b/src/EnumSourceTrait.php
index c62c876..667e9a3 100644
--- a/src/EnumSourceTrait.php
+++ b/src/EnumSourceTrait.php
@@ -2,72 +2,77 @@
 
 namespace Drupal\ui_patterns_settings;
 
+use Drupal\Core\Render\Markup;
 use Drupal\ui_patterns\EnumTrait;
 
 trait EnumSourceTrait {
   use EnumTrait;
 
   protected function enumAlterOptions(array $options, array $configure): array {
-    $active_options = $configure['options'] ?? [];
-    if (count($active_options) > 0) {
-
-      foreach ($options as $option => $label) {
-        if (isset($active_options[$option]) && $active_options[$option] === 0) {
-          unset($options[$option]);
-        }
-      }
-    }
-    $overwrite_options = $configure['overwrite_options'] ?? [];
-    if (!empty($overwrite_options)) {
-      $lines = explode("\r\n", $overwrite_options);
-      foreach ($lines as $line) {
-        $key_value = explode('|', $line);
-        if ($options[$key_value[0]] && !empty($key_value[1])) {
-          $options[$key_value[0]] = $key_value[1];
-        }
-      }
+    $overwrite_options = $configure['overwrite'] ?? [];
+    foreach ($overwrite_options as $overwrite_option_id => $overwrite_option) {
+       if ($overwrite_option['enable'] == '0') {
+         unset($options[$overwrite_option_id]);
+         continue;
+       }
+      if (!empty($overwrite_option['title'])) {
+        $options[$overwrite_option_id] = $overwrite_option['title'];
+       }
     }
     return $options;
   }
 
   /**
-   * @param array $form
+   * @param array $configure
+   *   The configure array.
+   * @param array $prop_definition
+   *   The prop definition
    *
    * @return array
+   *   The form.
    */
   public function enumConfigureForm(array $configure, array $prop_definition): array {
     $options = self::getEnumOptions($prop_definition);
     $form = [];
-    $form['options'] = [
-      '#type' => 'checkboxes',
-      '#title' => $this->t('Limit options'),
-      '#description' => $this->t('Leave empty to select all options.'),
-      '#options' => $options,
-      '#default_value' => $configure['options'] ?? [],
-    ];
-    $form['overwrite_options'] = [
-      '#type' => 'textarea',
-      '#title' => $this->t('Overwrite Option Labels'),
-      '#description' => $this->t('Overwrite "existing" option labels by adding key|label entry.'),
-      '#default_value' => $configure['configure']['overwrite_options'] ?? [],
+    $form['widget'] = [
+      '#type' => 'select',
+      '#title' => $this->t('Widget'),
+      '#description' => $this->t('Enum widget type.'),
+      '#options' => ['select' => $this->t('Select'), 'radios' => $this->t('Radio')],
+      '#default_value' => $configure['widget'] ?? 'select',
     ];
 
-    $form['css'] = [
-      '#type' => 'details',
-      '#title' => $this->t('CSS classes'),
-      '#description' => $this->t('Assign CSS classes to each option.'),
-    ];
     $form['css']['wrapper_classes'] = [
       '#type' => 'textfield',
       '#title' => $this->t('Wrapper CSS classes'),
       '#description' => $this->t('Classes assigned to wrapping select element'),
       '#default_value' => $configure['css']['wrapper_classes'] ?? '',
     ];
+
     foreach ($options as $option_id => $label) {
-      $form['css'][$option_id] = [
+      $form['overwrite'][$option_id] = [
+        '#type' => 'details',
+        '#title' => $this->t('Option: %label', ['%label' => $label]),
+      ];
+      $form['overwrite'][$option_id]['enable'] = [
+        '#type' => 'checkbox',
+        '#title' => $this->t('Enable'),
+        '#default_value' => $configure['overwrite'][$option_id]['enable'] ?? TRUE,
+      ];
+      $form['overwrite'][$option_id]['title'] = [
+        '#type' => 'textfield',
+        '#title' => $this->t('Title'),
+        '#default_value' => $configure['overwrite'][$option_id]['title'] ?? '',
+      ];
+      $form['overwrite'][$option_id]['icon'] = [
+        '#type' => 'icon_autocomplete',
+        '#title' => $this->t('Icon'),
+        '#default_value' => $configure['overwrite'][$option_id]['icon'] ?? '',
+      ];
+      $form['overwrite'][$option_id]['css'] = [
         '#type' => 'textfield',
-        '#title' => $this->t('Classes for option: %class', ['%class' => $label]),
-        '#default_value' => $this->selectWidget->getConfiguration()['configure']['css'][$option_id] ?? '',
+        '#title' => $this->t('CSS'),
+        '#default_value' => $configure['overwrite'][$option_id]['css'] ?? '',
       ];
     }
     return $form;
diff --git a/src/Plugin/UiPatterns/Source/EnumWidget.php b/src/Plugin/UiPatterns/Source/EnumWidget.php
new file mode 100644
index 0000000..fa75194
--- /dev/null
+++ b/src/Plugin/UiPatterns/Source/EnumWidget.php
@@ -0,0 +1,65 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\ui_patterns_settings\Plugin\UiPatterns\Source;
+
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Render\Element;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+use Drupal\ui_patterns\Attribute\Source;
+use Drupal\ui_patterns\Plugin\UiPatterns\Source\SelectWidget as BaseSelectWidget;
+use Drupal\ui_patterns_settings\EnumSourceTrait;
+
+/**
+ * Plugin overwrite of the source.
+ */
+#[Source(
+  id: 'enum_widget',
+  label: new TranslatableMarkup('Enum CSS widget'),
+  description: new TranslatableMarkup('A drop-down menu or scrolling selection box.'),
+  prop_types: ['enum', 'variant'],
+  tags: ['widget']
+)]
+class EnumWidget extends BaseSelectWidget {
+
+  use EnumSourceTrait;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsForm(array $form, FormStateInterface $form_state): array {
+    $form = parent::settingsForm($form, $form_state);
+    $form['value']['#options'] = $this->enumAlterOptions($form['value']['#options'], $this->getConfiguration()['configure'] ?? []);
+    $configure = $this->getConfiguration()['configure'] ?? [];
+    $form['value']['#type'] = $configure['widget'] ?? 'select';
+    $form['value']['#enum_widget'] = $configure;
+    $form['value']['#attributes']['class'][] = 'ui-patterns-enum';
+    if (isset($configure['css']['wrapper_classes'])) {
+      $form['value']['#wrapper_attributes']['class'][] = $configure['css']['wrapper_classes'];
+    }
+    if ($form['value']['#type'] === 'select') {
+      $form['value']['#theme'] = 'ui_patterns_settings_select_widget';
+    } else if ($form['value']['#type'] === 'radios') {
+      $form['value']['#pre_render'][] = function ($element) use ($configure) {
+        $element['#theme_wrappers'][] = ['ui_patterns_settings_radios_widget'];
+        foreach (Element::children($element) as $key) {
+          $element[$key]['#theme'] = 'ui_patterns_settings_radio_widget';
+          $element[$key]['#enum_widget'] = $configure;
+        }
+        return $element;
+      };
+    }
+    $form['value']['#attached']['library'] = ['ui_patterns_settings/color', 'ui_patterns_settings/layout'];
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function configureForm(array $form, FormStateInterface $form_state): array {
+    $form = parent::configureForm($form, $form_state);
+    return $form + $this->enumConfigureForm($this->getConfiguration()['configure'] ?? [], $this->getPropDefinition());
+  }
+
+}
diff --git a/src/Plugin/UiPatterns/Source/SelectWidget.php b/src/Plugin/UiPatterns/Source/SelectWidget.php
deleted file mode 100644
index 8f4dd15..0000000
--- a/src/Plugin/UiPatterns/Source/SelectWidget.php
+++ /dev/null
@@ -1,36 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace Drupal\ui_patterns_settings\Plugin\UiPatterns\Source;
-
-use Drupal\Core\Form\FormStateInterface;
-use Drupal\ui_patterns\Plugin\UiPatterns\Source\SelectWidget as BaseSelectWidget;
-use Drupal\ui_patterns_settings\EnumSourceTrait;
-
-/**
- * Plugin overwrite of the source.
- */
-class SelectWidget extends BaseSelectWidget {
-
-  use EnumSourceTrait;
-
-  /**
-   * {@inheritdoc}
-   */
-  public function settingsForm(array $form, FormStateInterface $form_state): array {
-    $form = parent::settingsForm($form, $form_state);
-    $form['value']['#options'] = $this->enumAlterOptions($form['value']['#options'], $this->getConfiguration()['configure'] ?? []);
-    return $form;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function configureForm(array $form, FormStateInterface $form_state): array {
-    $form = parent::configureForm($form, $form_state);
-    return $form + $this->enumConfigureForm($this->getConfiguration()['configure'] ?? [], $this->getPropDefinition());
-  }
-
-
-}
diff --git a/templates/ui-patterns-settings-radio-widget.html.twig b/templates/ui-patterns-settings-radio-widget.html.twig
new file mode 100644
index 0000000..7409646
--- /dev/null
+++ b/templates/ui-patterns-settings-radio-widget.html.twig
@@ -0,0 +1,4 @@
+<div{{ layout_attributes }}>
+
+</div>
+<input{{ attributes }} />{{ children }}
diff --git a/templates/ui-patterns-settings-radios-widget.html.twig b/templates/ui-patterns-settings-radios-widget.html.twig
new file mode 100644
index 0000000..2360b63
--- /dev/null
+++ b/templates/ui-patterns-settings-radios-widget.html.twig
@@ -0,0 +1 @@
+{{ element }}
\ No newline at end of file
diff --git a/templates/ui-patterns-settings-select-widget.html.twig b/templates/ui-patterns-settings-select-widget.html.twig
new file mode 100644
index 0000000..ba88344
--- /dev/null
+++ b/templates/ui-patterns-settings-select-widget.html.twig
@@ -0,0 +1,27 @@
+{#
+/**
+ * @file
+ * Default theme implementation for a select element.
+ *
+ * Available variables:
+ * - attributes: HTML attributes for the <select> tag.
+ * - options: The <option> element children.
+ *
+ * @see template_preprocess_select()
+ *
+ * @ingroup themeable
+ */
+#}
+<select{{ attributes }}>
+  {% for option in options %}
+    {% if option.type == 'optgroup' %}
+      <optgroup label="{{ option.label }}">
+        {% for sub_option in option.options %}
+          <option{{ option.attributes }} value="{{ sub_option.value }}"{{ sub_option.selected ? ' selected="selected"' }}>{{ sub_option.label }}</option>
+        {% endfor %}
+      </optgroup>
+    {% elseif option.type == 'option' %}
+      <option{{ option.attributes }} value="{{ option.value }}"{{ option.selected ? ' selected="selected"' }}>{{ option.label }}</option>
+    {% endif %}
+  {% endfor %}
+</select>
diff --git a/ui_patterns_settings.libraries.yml b/ui_patterns_settings.libraries.yml
new file mode 100644
index 0000000..b2a2e4d
--- /dev/null
+++ b/ui_patterns_settings.libraries.yml
@@ -0,0 +1,8 @@
+layout:
+  css:
+    theme:
+      css/layout.css: {}
+color:
+  css:
+    theme:
+      css/color.css: {}
diff --git a/ui_patterns_settings.module b/ui_patterns_settings.module
index 63c5a2d..f611ee0 100644
--- a/ui_patterns_settings.module
+++ b/ui_patterns_settings.module
@@ -5,11 +5,45 @@
  * Contains ui_patterns_settings.module.
  */
 
-/**
- * Implements hook_ui_patterns_source_info_alter().
- */
-function ui_patterns_settings_ui_patterns_source_info_alter(array &$info) {
-  if (isset($info['select'])) {
-    $info['select']['class'] = '\Drupal\ui_patterns_settings\Plugin\UiPatterns\Source\SelectWidget';
+use Drupal\Core\Render\Element;
+use Drupal\Core\Render\Element\RenderElementBase;
+use Drupal\Core\Template\Attribute;
+
+function ui_patterns_settings_theme() {
+  return [
+    'ui_patterns_settings_select_widget' => [
+      'render element' => 'element',
+    ],
+    'ui_patterns_settings_radios_widget' => [
+      'render element' => 'element',
+    ],
+    'ui_patterns_settings_radio_widget' => [
+      'render element' => 'element',
+    ],
+  ];
+}
+
+function template_preprocess_ui_patterns_settings_select_widget(&$variables) {
+  $element = $variables['element'];
+  Element::setAttributes($element, ['id', 'name', 'size']);
+  RenderElementBase::setAttributes($element, ['form-select']);
+  $variables['attributes'] = $element['#attributes'];
+  $options = form_select_options($element);
+  foreach ($options as $delta => $option) {
+    if (isset($element['#enum_widget']['overwrite'][$option['value']]['css'])) {
+      $options[$delta]['attributes'] = new Attribute(
+        ['class'=> $element['#enum_widget']['overwrite'][$option['value']]['css']]
+      );
+    }
   }
+  $variables['options'] = $options;
+}
+
+
+function template_preprocess_ui_patterns_settings_radio_widget(&$variables) {
+  template_preprocess_input($variables);
+  $element = &$variables['element'];
+  $variables['layout_attributes'] = new Attribute();
+  $css_config = $element['#enum_widget']['overwrite'][$element['#value']]['css'] ?? NULL;
+  $variables['layout_attributes']->addClass($css_config);
 }
-- 
GitLab


From 0a0417ad8cb5dce3e65e72b93e26764c351f3460 Mon Sep 17 00:00:00 2001
From: Christian Wiedemann <christian.wiedemann@key-tec.de>
Date: Sun, 2 Mar 2025 19:07:59 +0100
Subject: [PATCH 4/7] feat: Add enum widget

---
 css/color.css                                 |  23 +++-
 css/grid.css                                  |  22 +++
 css/layout.css                                |   0
 src/EnumSourceTrait.php                       |  80 -----------
 src/Plugin/UiPatterns/Source/EnumWidget.php   | 130 +++++++++++++++---
 ...i-patterns-settings-radio-widget.html.twig |   9 +-
 ...ns-settings-radio-wrapper-widget.html.twig |  76 ++++++++++
 ...-patterns-settings-radios-widget.html.twig |   1 -
 ui_patterns_settings.libraries.yml            |   8 +-
 ui_patterns_settings.module                   |  37 ++++-
 10 files changed, 274 insertions(+), 112 deletions(-)
 create mode 100644 css/grid.css
 delete mode 100644 css/layout.css
 delete mode 100644 src/EnumSourceTrait.php
 create mode 100644 templates/ui-patterns-settings-radio-wrapper-widget.html.twig
 delete mode 100644 templates/ui-patterns-settings-radios-widget.html.twig

diff --git a/css/color.css b/css/color.css
index 8a89599..ad7807f 100644
--- a/css/color.css
+++ b/css/color.css
@@ -1,4 +1,21 @@
 .uips-layout-color {
-  border: 0 !important;
-  margin: 0 !important;
-}
\ No newline at end of file
+  display: grid !important;
+  grid-template-columns: repeat(auto-fill, 32px) !important;
+  gap: 10px !important;
+}
+
+.uips-layout-color .uips-radio-item {
+  width: 100%;
+  aspect-ratio: 1 / 1;
+  cursor: pointer;
+  border-radius: 50%;
+}
+
+.uips-layout-color .form-radio {
+  display: none;
+}
+
+.uips-layout-color .form-radio:checked + .uips-radio-item {
+  border: 2px solid black;
+  box-shadow: 0 0 2px #fff,0 0 0 4px #222330;
+}
diff --git a/css/grid.css b/css/grid.css
new file mode 100644
index 0000000..56d8a28
--- /dev/null
+++ b/css/grid.css
@@ -0,0 +1,22 @@
+.uips-layout-grid {
+  display: grid !important;
+  grid-template-columns: repeat(auto-fill, 64px) !important;
+  gap: 10px !important;
+}
+
+.uips-layout-grid .uips-radio-item {
+  width: 100%;
+  aspect-ratio: 1 / 1;
+  cursor: pointer;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+.uips-layout-grid .form-radio {
+  display: none;
+}
+
+.uips-layout-grid .form-radio:checked + .uips-radio-item {
+  border: 2px solid black;
+}
diff --git a/css/layout.css b/css/layout.css
deleted file mode 100644
index e69de29..0000000
diff --git a/src/EnumSourceTrait.php b/src/EnumSourceTrait.php
deleted file mode 100644
index 667e9a3..0000000
--- a/src/EnumSourceTrait.php
+++ /dev/null
@@ -1,80 +0,0 @@
-<?php
-
-namespace Drupal\ui_patterns_settings;
-
-use Drupal\Core\Render\Markup;
-use Drupal\ui_patterns\EnumTrait;
-
-trait EnumSourceTrait {
-  use EnumTrait;
-
-  protected function enumAlterOptions(array $options, array $configure): array {
-    $overwrite_options = $configure['overwrite'] ?? [];
-    foreach ($overwrite_options as $overwrite_option_id => $overwrite_option) {
-       if ($overwrite_option['enable'] == '0') {
-         unset($options[$overwrite_option_id]);
-         continue;
-       }
-      if (!empty($overwrite_option['title'])) {
-        $options[$overwrite_option_id] = $overwrite_option['title'];
-       }
-    }
-    return $options;
-  }
-
-  /**
-   * @param array $configure
-   *   The configure array.
-   * @param array $prop_definition
-   *   The prop definition
-   *
-   * @return array
-   *   The form.
-   */
-  public function enumConfigureForm(array $configure, array $prop_definition): array {
-    $options = self::getEnumOptions($prop_definition);
-    $form = [];
-    $form['widget'] = [
-      '#type' => 'select',
-      '#title' => $this->t('Widget'),
-      '#description' => $this->t('Enum widget type.'),
-      '#options' => ['select' => $this->t('Select'), 'radios' => $this->t('Radio')],
-      '#default_value' => $configure['widget'] ?? 'select',
-    ];
-
-    $form['css']['wrapper_classes'] = [
-      '#type' => 'textfield',
-      '#title' => $this->t('Wrapper CSS classes'),
-      '#description' => $this->t('Classes assigned to wrapping select element'),
-      '#default_value' => $configure['css']['wrapper_classes'] ?? '',
-    ];
-
-    foreach ($options as $option_id => $label) {
-      $form['overwrite'][$option_id] = [
-        '#type' => 'details',
-        '#title' => $this->t('Option: %label', ['%label' => $label]),
-      ];
-      $form['overwrite'][$option_id]['enable'] = [
-        '#type' => 'checkbox',
-        '#title' => $this->t('Enable'),
-        '#default_value' => $configure['overwrite'][$option_id]['enable'] ?? TRUE,
-      ];
-      $form['overwrite'][$option_id]['title'] = [
-        '#type' => 'textfield',
-        '#title' => $this->t('Title'),
-        '#default_value' => $configure['overwrite'][$option_id]['title'] ?? '',
-      ];
-      $form['overwrite'][$option_id]['icon'] = [
-        '#type' => 'icon_autocomplete',
-        '#title' => $this->t('Icon'),
-        '#default_value' => $configure['overwrite'][$option_id]['icon'] ?? '',
-      ];
-      $form['overwrite'][$option_id]['css'] = [
-        '#type' => 'textfield',
-        '#title' => $this->t('CSS'),
-        '#default_value' => $configure['overwrite'][$option_id]['css'] ?? '',
-      ];
-    }
-    return $form;
-  }
-}
\ No newline at end of file
diff --git a/src/Plugin/UiPatterns/Source/EnumWidget.php b/src/Plugin/UiPatterns/Source/EnumWidget.php
index fa75194..c78d3d7 100644
--- a/src/Plugin/UiPatterns/Source/EnumWidget.php
+++ b/src/Plugin/UiPatterns/Source/EnumWidget.php
@@ -8,11 +8,11 @@ use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Render\Element;
 use Drupal\Core\StringTranslation\TranslatableMarkup;
 use Drupal\ui_patterns\Attribute\Source;
-use Drupal\ui_patterns\Plugin\UiPatterns\Source\SelectWidget as BaseSelectWidget;
-use Drupal\ui_patterns_settings\EnumSourceTrait;
+use Drupal\ui_patterns\EnumTrait;
+use Drupal\ui_patterns\Plugin\UiPatterns\Source\SelectWidget;
 
 /**
- * Plugin overwrite of the source.
+ * Enum widget source.
  */
 #[Source(
   id: 'enum_widget',
@@ -21,9 +21,26 @@ use Drupal\ui_patterns_settings\EnumSourceTrait;
   prop_types: ['enum', 'variant'],
   tags: ['widget']
 )]
-class EnumWidget extends BaseSelectWidget {
+class EnumWidget extends SelectWidget {
 
-  use EnumSourceTrait;
+  use EnumTrait;
+
+  /**
+   * Alter enum options.
+   */
+  protected function enumAlterOptions(array $options, array $configure): array {
+    $overwrite_options = $configure['overwrite'] ?? [];
+    foreach ($overwrite_options as $overwrite_option_id => $overwrite_option) {
+      if ($overwrite_option['enable'] == '0') {
+        unset($options[$overwrite_option_id]);
+        continue;
+      }
+      if (!empty($overwrite_option['title'])) {
+        $options[$overwrite_option_id] = $overwrite_option['title'];
+      }
+    }
+    return $options;
+  }
 
   /**
    * {@inheritdoc}
@@ -31,35 +48,112 @@ class EnumWidget extends BaseSelectWidget {
   public function settingsForm(array $form, FormStateInterface $form_state): array {
     $form = parent::settingsForm($form, $form_state);
     $form['value']['#options'] = $this->enumAlterOptions($form['value']['#options'], $this->getConfiguration()['configure'] ?? []);
-    $configure = $this->getConfiguration()['configure'] ?? [];
-    $form['value']['#type'] = $configure['widget'] ?? 'select';
+    $form['#attached']['library'][] = 'ui_patterns_settings/layout';
+    $form['#attached']['library'][] = 'ui_patterns_settings/color';
+    $widget = $this->getWidgetSetting('widget');
+    $widget_configs = [
+      'select' => ['type' => 'select'],
+      'colors' => [
+        'type' => 'radios',
+        'wrapper_classes' => 'uips-layout-color',
+        'library' => ['ui_patterns_settings/color'],
+      ],
+      '4_grid' => [
+        'type' => 'radios',
+        'wrapper_classes' => 'uips-layout-grid',
+        'library' => ['ui_patterns_settings/grid'],
+      ],
+    ];
+    $widget_config = $widget_configs[$widget];
+    $form['value']['#type'] = $widget_config['type'];
+    $configure = $this->getEnumConfiguration();
+    $configure['css']['wrapper_classes'] .= $widget_config['wrapper_classes'] ?? '';
     $form['value']['#enum_widget'] = $configure;
-    $form['value']['#attributes']['class'][] = 'ui-patterns-enum';
-    if (isset($configure['css']['wrapper_classes'])) {
-      $form['value']['#wrapper_attributes']['class'][] = $configure['css']['wrapper_classes'];
-    }
     if ($form['value']['#type'] === 'select') {
       $form['value']['#theme'] = 'ui_patterns_settings_select_widget';
-    } else if ($form['value']['#type'] === 'radios') {
+    }
+    elseif ($form['value']['#type'] === 'radios') {
       $form['value']['#pre_render'][] = function ($element) use ($configure) {
-        $element['#theme_wrappers'][] = ['ui_patterns_settings_radios_widget'];
         foreach (Element::children($element) as $key) {
-          $element[$key]['#theme'] = 'ui_patterns_settings_radio_widget';
+          $element[$key]['#theme_wrappers'][0] = ['ui_patterns_settings_radio_wrapper_widget'];
+          $element[$key]['#theme'] = ['ui_patterns_settings_radio_widget'];
           $element[$key]['#enum_widget'] = $configure;
         }
         return $element;
       };
     }
-    $form['value']['#attached']['library'] = ['ui_patterns_settings/color', 'ui_patterns_settings/layout'];
+    $form['value']['#attached']['library'] = $widget_config['library'] ?? [];
     return $form;
   }
 
+  /**
+   * Returns base enum configuration.
+   */
+  private function getEnumConfiguration(): array {
+    return [
+      'widget' => $this->getWidgetSetting('widget'),
+      'overwrite' => $this->getWidgetSetting('overwrite'),
+      'css' => $this->getWidgetSetting('css'),
+    ];
+  }
+
   /**
    * {@inheritdoc}
    */
-  public function configureForm(array $form, FormStateInterface $form_state): array {
-    $form = parent::configureForm($form, $form_state);
-    return $form + $this->enumConfigureForm($this->getConfiguration()['configure'] ?? [], $this->getPropDefinition());
+  public function widgetSettingsForm(array $form, FormStateInterface $form_state): array {
+    $form = parent::widgetSettingsForm($form, $form_state);
+    $configure = $this->getEnumConfiguration();
+    $options = self::getEnumOptions($this->getPropDefinition());
+
+    $form['widget'] = [
+      '#type' => 'select',
+      '#title' => $this->t('Widget'),
+      '#description' => $this->t('Enum widget type.'),
+      '#options' => [
+        'select' => $this->t('Select'),
+        'colors' => $this->t('Colors'),
+        '4_grid' => $this->t('4 Grid / Eg. Icons'),
+      ],
+      '#default_value' => $configure['widget'] ?? 'select',
+    ];
+
+    $form['css']['wrapper_classes'] = [
+      '#type' => 'textfield',
+      '#title' => $this->t('Wrapper CSS classes'),
+      '#default_value' => $configure['css']['wrapper_classes'] ?? '',
+      '#description' => $this->t('Classes assigned to wrapping select element'),
+    ];
+
+    foreach ($options as $option_id => $label) {
+      $form['overwrite'][$option_id] = [
+        '#type' => 'details',
+        '#title' => $this->t('Option: %label', ['%label' => $label]),
+      ];
+      $form['overwrite'][$option_id]['enable'] = [
+        '#type' => 'checkbox',
+        '#title' => $this->t('Enable'),
+        '#default_value' => $configure['overwrite'][$option_id]['enable'] ?? TRUE,
+      ];
+      $form['overwrite'][$option_id]['title'] = [
+        '#type' => 'textfield',
+        '#title' => $this->t('Title'),
+        '#default_value' => $configure['overwrite'][$option_id]['title'] ?? '',
+      ];
+      $form['overwrite'][$option_id]['icon'] = [
+        '#type' => 'icon_autocomplete',
+        '#title' => $this->t('Icon'),
+        '#return_id' => TRUE,
+        '#description' => $this->t('May not work with your widget.'),
+        '#default_value' => $configure['overwrite'][$option_id]['icon']['target_id'] ?? '',
+      ];
+      $form['overwrite'][$option_id]['css'] = [
+        '#type' => 'textfield',
+        '#title' => $this->t('CSS'),
+        '#default_value' => $configure['overwrite'][$option_id]['css'] ?? '',
+      ];
+    }
+    return $form;
+
   }
 
 }
diff --git a/templates/ui-patterns-settings-radio-widget.html.twig b/templates/ui-patterns-settings-radio-widget.html.twig
index 7409646..627ae71 100644
--- a/templates/ui-patterns-settings-radio-widget.html.twig
+++ b/templates/ui-patterns-settings-radio-widget.html.twig
@@ -1,4 +1,7 @@
-<div{{ layout_attributes }}>
-
-</div>
 <input{{ attributes }} />{{ children }}
+<div{{ layout_attributes.addClass('uips-radio-item') }}>
+    {% if icon_id is not empty %}
+        {{ icon_preview(pack_id, icon_id) }}
+    {% endif %}
+</div>
+
diff --git a/templates/ui-patterns-settings-radio-wrapper-widget.html.twig b/templates/ui-patterns-settings-radio-wrapper-widget.html.twig
new file mode 100644
index 0000000..e7ba34d
--- /dev/null
+++ b/templates/ui-patterns-settings-radio-wrapper-widget.html.twig
@@ -0,0 +1,76 @@
+
+{#
+/**
+ * @file
+ * Default theme implementation for a form element.
+ *
+ * Available variables:
+ * - attributes: HTML attributes for the containing element.
+ * - errors: (optional) Any errors for this form element, may not be set.
+ * - prefix: (optional) The form element prefix, may not be set.
+ * - suffix: (optional) The form element suffix, may not be set.
+ * - required: The required marker, or empty if the associated form element is
+ *   not required.
+ * - type: The type of the element.
+ * - name: The name of the element.
+ * - label: A rendered label element.
+ * - label_display: Label display setting. It can have these values:
+ *   - before: The label is output before the element. This is the default.
+ *     The label includes the #title and the required marker, if #required.
+ *   - after: The label is output after the element. For example, this is used
+ *     for radio and checkbox #type elements. If the #title is empty but the
+ *     field is #required, the label will contain only the required marker.
+ *   - invisible: Labels are critical for screen readers to enable them to
+ *     properly navigate through forms but can be visually distracting. This
+ *     property hides the label for everyone except screen readers.
+ *   - attribute: Set the title attribute on the element to create a tooltip but
+ *     output no label element. This is supported only for checkboxes and radios
+ *     in \Drupal\Core\Render\Element\CompositeFormElementTrait::preRenderCompositeFormElement().
+ *     It is used where a visual label is not needed, such as a table of
+ *     checkboxes where the row and column provide the context. The tooltip will
+ *     include the title and required marker.
+ * - description: (optional) A list of description properties containing:
+ *    - content: A description of the form element, may not be set.
+ *    - attributes: (optional) A list of HTML attributes to apply to the
+ *      description content wrapper. Will only be set when description is set.
+ * - description_display: Description display setting. It can have these values:
+ *   - before: The description is output before the element.
+ *   - after: The description is output after the element. This is the default
+ *     value.
+ *   - invisible: The description is output after the element, hidden visually
+ *     but available to screen readers.
+ * - disabled: True if the element is disabled.
+ * - title_display: Title display setting.
+ *
+ * @see template_preprocess_form_element()
+ *
+ * @ingroup themeable
+ */
+#}
+{%
+    set classes = [
+    'js-form-item',
+    'form-item',
+    'js-form-type-' ~ type|clean_class,
+    'form-item-' ~ name|clean_class,
+    'js-form-item-' ~ name|clean_class,
+    title_display not in ['after', 'before'] ? 'form-no-label',
+    disabled == 'disabled' ? 'form-disabled',
+    errors ? 'form-item--error',
+]
+%}
+{%
+    set description_classes = [
+    'description',
+    description_display == 'invisible' ? 'visually-hidden',
+]
+%}
+<label{{ attributes.addClass(classes) }}>
+
+    {{ children }}
+    {% if errors %}
+        <div class="form-item--error-message">
+            {{ errors }}
+        </div>
+    {% endif %}
+</label>
diff --git a/templates/ui-patterns-settings-radios-widget.html.twig b/templates/ui-patterns-settings-radios-widget.html.twig
deleted file mode 100644
index 2360b63..0000000
--- a/templates/ui-patterns-settings-radios-widget.html.twig
+++ /dev/null
@@ -1 +0,0 @@
-{{ element }}
\ No newline at end of file
diff --git a/ui_patterns_settings.libraries.yml b/ui_patterns_settings.libraries.yml
index b2a2e4d..37e7cad 100644
--- a/ui_patterns_settings.libraries.yml
+++ b/ui_patterns_settings.libraries.yml
@@ -1,8 +1,8 @@
-layout:
-  css:
-    theme:
-      css/layout.css: {}
 color:
   css:
     theme:
       css/color.css: {}
+grid:
+  css:
+    theme:
+      css/grid.css: {}
diff --git a/ui_patterns_settings.module b/ui_patterns_settings.module
index f611ee0..826e26f 100644
--- a/ui_patterns_settings.module
+++ b/ui_patterns_settings.module
@@ -9,12 +9,15 @@ use Drupal\Core\Render\Element;
 use Drupal\Core\Render\Element\RenderElementBase;
 use Drupal\Core\Template\Attribute;
 
+/**
+ * Implements hook_theme().
+ */
 function ui_patterns_settings_theme() {
   return [
     'ui_patterns_settings_select_widget' => [
       'render element' => 'element',
     ],
-    'ui_patterns_settings_radios_widget' => [
+    'ui_patterns_settings_radio_wrapper_widget' => [
       'render element' => 'element',
     ],
     'ui_patterns_settings_radio_widget' => [
@@ -23,6 +26,9 @@ function ui_patterns_settings_theme() {
   ];
 }
 
+/**
+ * Implements hook_preprocess_ui_patterns_settings_select_widget().
+ */
 function template_preprocess_ui_patterns_settings_select_widget(&$variables) {
   $element = $variables['element'];
   Element::setAttributes($element, ['id', 'name', 'size']);
@@ -32,18 +38,43 @@ function template_preprocess_ui_patterns_settings_select_widget(&$variables) {
   foreach ($options as $delta => $option) {
     if (isset($element['#enum_widget']['overwrite'][$option['value']]['css'])) {
       $options[$delta]['attributes'] = new Attribute(
-        ['class'=> $element['#enum_widget']['overwrite'][$option['value']]['css']]
+        ['class' => $element['#enum_widget']['overwrite'][$option['value']]['css']]
       );
+
+    }
+    if (isset($element['#enum_widget']['overwrite'][$option['value']]['icon']['target_id'])) {
+      [$options[$delta]['pack_id'], $options[$delta]['icon_id']] = explode(':', $element['#enum_widget']['overwrite'][$option['value']]['icon']['target_id'] ?? '');
     }
   }
   $variables['options'] = $options;
 }
 
+/**
+ * Implements hook_radios().
+ */
+function ui_patterns_settings_preprocess_radios(&$variables) {
+  if (isset($variables['element']['#enum_widget'])) {
+    $variables['attributes']['class'][] = $variables['element']['#enum_widget']['css']['wrapper_classes'];
+    $variables['attributes']['class'][] = 'ck-reset';
 
+  }
+}
+
+/**
+ * Implements hook_preprocess_ui_patterns_settings_radio_wrapper_widget().
+ */
+function template_preprocess_ui_patterns_settings_radio_wrapper_widget(&$variables) {
+  template_preprocess_form_element($variables);
+}
+
+/**
+ * Implements hook_preprocess_ui_patterns_settings_radio_widget().
+ */
 function template_preprocess_ui_patterns_settings_radio_widget(&$variables) {
   template_preprocess_input($variables);
   $element = &$variables['element'];
   $variables['layout_attributes'] = new Attribute();
-  $css_config = $element['#enum_widget']['overwrite'][$element['#value']]['css'] ?? NULL;
+  $css_config = $element['#enum_widget']['overwrite'][$element['#return_value']]['css'] ?? NULL;
   $variables['layout_attributes']->addClass($css_config);
+  [$variables['pack_id'], $variables['icon_id']] = explode(':', $element['#enum_widget']['overwrite'][$element['#return_value']]['icon']['target_id'] ?? '');
 }
-- 
GitLab


From 7ee1c5da1df04dc9e665a0af79a33e70e6f357ba Mon Sep 17 00:00:00 2001
From: Christian Wiedemann <christian.wiedemann@key-tec.de>
Date: Sat, 29 Mar 2025 15:55:51 +0100
Subject: [PATCH 5/7] fix linting

---
 .cspell-project-words.txt   |  1 +
 css/color.css               |  3 ++-
 css/grid.css                |  2 +-
 ui_patterns_settings.module | 10 +++++-----
 4 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/.cspell-project-words.txt b/.cspell-project-words.txt
index a3a6be5..1c342ab 100644
--- a/.cspell-project-words.txt
+++ b/.cspell-project-words.txt
@@ -15,3 +15,4 @@ sdc's
 subcomponent
 toolset
 daisyui
+uips
\ No newline at end of file
diff --git a/css/color.css b/css/color.css
index ad7807f..7b4e295 100644
--- a/css/color.css
+++ b/css/color.css
@@ -17,5 +17,6 @@
 
 .uips-layout-color .form-radio:checked + .uips-radio-item {
   border: 2px solid black;
-  box-shadow: 0 0 2px #fff,0 0 0 4px #222330;
+  box-shadow: 0 0 2px #fff,
+              0 0 0 4px #222330;
 }
diff --git a/css/grid.css b/css/grid.css
index 56d8a28..6b5272f 100644
--- a/css/grid.css
+++ b/css/grid.css
@@ -7,8 +7,8 @@
 .uips-layout-grid .uips-radio-item {
   width: 100%;
   aspect-ratio: 1 / 1;
-  cursor: pointer;
   display: flex;
+  cursor: pointer;
   align-items: center;
   justify-content: center;
 }
diff --git a/ui_patterns_settings.module b/ui_patterns_settings.module
index 826e26f..e55ca90 100644
--- a/ui_patterns_settings.module
+++ b/ui_patterns_settings.module
@@ -12,7 +12,7 @@ use Drupal\Core\Template\Attribute;
 /**
  * Implements hook_theme().
  */
-function ui_patterns_settings_theme() {
+function ui_patterns_settings_theme(): array {
   return [
     'ui_patterns_settings_select_widget' => [
       'render element' => 'element',
@@ -29,7 +29,7 @@ function ui_patterns_settings_theme() {
 /**
  * Implements hook_preprocess_ui_patterns_settings_select_widget().
  */
-function template_preprocess_ui_patterns_settings_select_widget(&$variables) {
+function template_preprocess_ui_patterns_settings_select_widget(array &$variables): void {
   $element = $variables['element'];
   Element::setAttributes($element, ['id', 'name', 'size']);
   RenderElementBase::setAttributes($element, ['form-select']);
@@ -52,7 +52,7 @@ function template_preprocess_ui_patterns_settings_select_widget(&$variables) {
 /**
  * Implements hook_radios().
  */
-function ui_patterns_settings_preprocess_radios(&$variables) {
+function ui_patterns_settings_preprocess_radios(array &$variables): void {
   if (isset($variables['element']['#enum_widget'])) {
     $variables['attributes']['class'][] = $variables['element']['#enum_widget']['css']['wrapper_classes'];
     $variables['attributes']['class'][] = 'ck-reset';
@@ -63,14 +63,14 @@ function ui_patterns_settings_preprocess_radios(&$variables) {
 /**
  * Implements hook_preprocess_ui_patterns_settings_radio_wrapper_widget().
  */
-function template_preprocess_ui_patterns_settings_radio_wrapper_widget(&$variables) {
+function template_preprocess_ui_patterns_settings_radio_wrapper_widget(array &$variables): void {
   template_preprocess_form_element($variables);
 }
 
 /**
  * Implements hook_preprocess_ui_patterns_settings_radio_widget().
  */
-function template_preprocess_ui_patterns_settings_radio_widget(&$variables) {
+function template_preprocess_ui_patterns_settings_radio_widget(array &$variables): void {
   template_preprocess_input($variables);
   $element = &$variables['element'];
   $variables['layout_attributes'] = new Attribute();
-- 
GitLab


From 208bac2a2c206ec0d0bc9614738a7cd3d71967c2 Mon Sep 17 00:00:00 2001
From: Christian Wiedemann <christian.wiedemann@key-tec.de>
Date: Sat, 29 Mar 2025 16:04:47 +0100
Subject: [PATCH 6/7] fix linting

---
 css/color.css | 5 +++--
 css/grid.css  | 6 +++---
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/css/color.css b/css/color.css
index 7b4e295..aa55954 100644
--- a/css/color.css
+++ b/css/color.css
@@ -17,6 +17,7 @@
 
 .uips-layout-color .form-radio:checked + .uips-radio-item {
   border: 2px solid black;
-  box-shadow: 0 0 2px #fff,
-              0 0 0 4px #222330;
+  box-shadow:
+    0 0 2px #fff,
+    0 0 0 4px #222330;
 }
diff --git a/css/grid.css b/css/grid.css
index 6b5272f..14ed26e 100644
--- a/css/grid.css
+++ b/css/grid.css
@@ -5,12 +5,12 @@
 }
 
 .uips-layout-grid .uips-radio-item {
-  width: 100%;
+  align-items: center;
   aspect-ratio: 1 / 1;
-  display: flex;
   cursor: pointer;
-  align-items: center;
+  display: flex;
   justify-content: center;
+  width: 100%;
 }
 
 .uips-layout-grid .form-radio {
-- 
GitLab


From 67ff0ab11922f3ffcd52b451c5fbc5a9ac413f13 Mon Sep 17 00:00:00 2001
From: Christian Wiedemann <christian.wiedemann@key-tec.de>
Date: Sat, 29 Mar 2025 18:12:29 +0100
Subject: [PATCH 7/7] fix linting

---
 css/grid.css | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/css/grid.css b/css/grid.css
index 14ed26e..c265652 100644
--- a/css/grid.css
+++ b/css/grid.css
@@ -5,12 +5,12 @@
 }
 
 .uips-layout-grid .uips-radio-item {
-  align-items: center;
-  aspect-ratio: 1 / 1;
-  cursor: pointer;
   display: flex;
+  align-items: center;
   justify-content: center;
+  aspect-ratio: 1 / 1;
   width: 100%;
+  cursor: pointer;
 }
 
 .uips-layout-grid .form-radio {
-- 
GitLab