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