From b6e90519d7d2f86fb48edfe8c6d0b1be6c90e470 Mon Sep 17 00:00:00 2001 From: Christian Wiedemann <christian.wiedemann@key-tec.de> Date: Mon, 31 Mar 2025 08:25:54 +0200 Subject: [PATCH 1/6] Add UIStyles widget --- css/color.css | 5 +- css/grid.css | 13 +- src/CSSWidgetTrait.php | 197 ++++++++++++++++++ src/Plugin/UiPatterns/Source/EnumWidget.php | 124 +---------- .../UiPatterns/Source/UiStylesWidget.php | 105 ++++++++++ 5 files changed, 321 insertions(+), 123 deletions(-) create mode 100644 src/CSSWidgetTrait.php create mode 100644 src/Plugin/UiPatterns/Source/UiStylesWidget.php diff --git a/css/color.css b/css/color.css index aa55954..d238d58 100644 --- a/css/color.css +++ b/css/color.css @@ -17,7 +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 c265652..65c58c2 100644 --- a/css/grid.css +++ b/css/grid.css @@ -1,18 +1,27 @@ .uips-layout-grid { display: grid !important; - grid-template-columns: repeat(auto-fill, 64px) !important; gap: 10px !important; } +.uips-layout-grid-4 { + grid-template-columns: repeat(auto-fill, 64px) !important; +} + +.uips-layout-grid-1 { + grid-template-columns: repeat(auto-fill, 100%) !important; +} + .uips-layout-grid .uips-radio-item { display: flex; align-items: center; justify-content: center; - aspect-ratio: 1 / 1; width: 100%; cursor: pointer; } +.uips-layout-grid-4 .uips-radio-item { + aspect-ratio: 1 / 1; +} .uips-layout-grid .form-radio { display: none; } diff --git a/src/CSSWidgetTrait.php b/src/CSSWidgetTrait.php new file mode 100644 index 0000000..c25bf23 --- /dev/null +++ b/src/CSSWidgetTrait.php @@ -0,0 +1,197 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\ui_patterns_settings; + +use Drupal\Core\Render\Element; +use Drupal\Core\StringTranslation\StringTranslationTrait; + +/** + * Trait CSSWidgetTrait. + * + * Provides methods to handle CSS widget settings and configurations. + */ +trait CSSWidgetTrait { + + use StringTranslationTrait; + + /** + * Alters the options based on widget settings. + * + * @param array $options + * The original options array. + * @param array $widget_settings + * The widget settings array. + * + * @return array + * The altered options array. + */ + private function enumAlterOptions(array $options, array $widget_settings): array { + $overwrite_options = $widget_settings['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; + } + + /** + * Retrieves the available widget types. + * + * This method returns an array of widget types, each with its configuration + * such as type, label, wrapper classes, and libraries. + * + * @return array + * An array of widget types. + */ + private function getWidgetTypes(): array { + return [ + 'select' => [ + 'type' => 'select', + 'label' => $this->t('Select'), + ], + 'colors' => [ + 'type' => 'radios', + 'wrapper_classes' => 'uips-layout-color', + 'library' => ['ui_patterns_settings/color'], + 'label' => $this->t('Colors'), + ], + '1_grid' => [ + 'type' => 'radios', + 'wrapper_classes' => 'uips-layout-grid uips-layout-grid-1', + 'library' => ['ui_patterns_settings/grid'], + 'label' => $this->t('1 Column grid'), + ], + '4_grid' => [ + 'type' => 'radios', + 'wrapper_classes' => 'uips-layout-grid uips-layout-grid-4', + 'label' => $this->t('4 Column grid'), + 'library' => ['ui_patterns_settings/grid'], + ], + ]; + } + + /** + * Builds the CSS settings form element. + * + * @param array $element + * The form element array. + * @param array $widget_settings + * The widget settings array. + * + * @return array + * The modified form element array. + */ + public function cssSettingsForm(array $element, array $widget_settings): array { + $element['#options'] = $this->enumAlterOptions($element['#options'], $widget_settings); + $widget = $widget_settings['widget']; + $widget_configs = $this->getWidgetTypes(); + $widget_config = $widget_configs[$widget]; + $element['#type'] = $widget_config['type']; + $configure = $this->getEnumConfiguration($widget_settings); + $configure['css']['wrapper_classes'] .= $widget_config['wrapper_classes'] ?? ''; + $element['#enum_widget'] = $configure; + if ($element['#type'] === 'select') { + $element['#theme'] = 'ui_patterns_settings_select_widget'; + } + elseif ($element['#type'] === 'radios') { + $element['#pre_render'][] = function ($element) use ($configure) { + foreach (Element::children($element) as $key) { + $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; + }; + } + $element['#attached']['library'] = $widget_config['library'] ?? []; + return $element; + } + + /** + * Retrieves the enum configuration from widget settings. + * + * @param array $widget_settings + * The widget settings array. + * + * @return array + * The enum configuration array. + */ + private function getEnumConfiguration(array $widget_settings): array { + return [ + 'widget' => $widget_settings['widget'], + 'overwrite' => $widget_settings['overwrite'], + 'css' => $widget_settings['css'], + ]; + } + + /** + * Builds the CSS widget settings form. + * + * @param array $element + * The form element array. + * @param array $widget_settings + * The widget settings array. + * @param array $options + * The options array for the widget. + * + * @return array + * The modified form element array. + */ + public function cssWidgetSettingsForm(array $element, array $widget_settings, array $options): array { + $configure = $this->getEnumConfiguration($widget_settings); + $options = array_map(fn($widget_type) => $widget_type['label'], $this->getWidgetTypes()); + $element['widget'] = [ + '#type' => 'select', + '#title' => $this->t('Widget'), + '#description' => $this->t('Enum widget type.'), + '#options' => $options, + '#default_value' => $configure['widget'] ?? 'select', + ]; + + $element['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) { + $option_id = str_replace('.', '|||', $option_id); + $element['overwrite'][$option_id] = [ + '#type' => 'details', + '#title' => $this->t('Option: %label', ['%label' => $label]), + ]; + $element['overwrite'][$option_id]['enable'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Enable'), + '#default_value' => $configure['overwrite'][$option_id]['enable'] ?? TRUE, + ]; + $element['overwrite'][$option_id]['title'] = [ + '#type' => 'textfield', + '#title' => $this->t('Title'), + '#default_value' => $configure['overwrite'][$option_id]['title'] ?? '', + ]; + $element['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'] ?? '', + ]; + $element['overwrite'][$option_id]['css'] = [ + '#type' => 'textfield', + '#title' => $this->t('CSS'), + '#default_value' => $configure['overwrite'][$option_id]['css'] ?? '', + ]; + } + return $element; + } + +} diff --git a/src/Plugin/UiPatterns/Source/EnumWidget.php b/src/Plugin/UiPatterns/Source/EnumWidget.php index c78d3d7..67425d7 100644 --- a/src/Plugin/UiPatterns/Source/EnumWidget.php +++ b/src/Plugin/UiPatterns/Source/EnumWidget.php @@ -5,155 +5,43 @@ 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\EnumTrait; use Drupal\ui_patterns\Plugin\UiPatterns\Source\SelectWidget; +use Drupal\ui_patterns_settings\CSSWidgetTrait; /** - * Enum widget source. + * Enum CSS widget source. */ #[Source( id: 'enum_widget', label: new TranslatableMarkup('Enum CSS widget'), - description: new TranslatableMarkup('A drop-down menu or scrolling selection box.'), + description: new TranslatableMarkup('Display enums as grid / colors / etc.'), prop_types: ['enum', 'variant'], tags: ['widget'] )] class EnumWidget extends SelectWidget { 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; - } + use CSSWidgetTrait; /** * {@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'] ?? []); - $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; - if ($form['value']['#type'] === 'select') { - $form['value']['#theme'] = 'ui_patterns_settings_select_widget'; - } - elseif ($form['value']['#type'] === 'radios') { - $form['value']['#pre_render'][] = function ($element) use ($configure) { - foreach (Element::children($element) as $key) { - $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'] = $widget_config['library'] ?? []; + $form['value'] = $this->cssSettingsForm($form['value'], $this->widgetSettings); 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 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; - + return $this->cssWidgetSettingsForm($form, $this->widgetSettings, $options); } } diff --git a/src/Plugin/UiPatterns/Source/UiStylesWidget.php b/src/Plugin/UiPatterns/Source/UiStylesWidget.php new file mode 100644 index 0000000..6997b72 --- /dev/null +++ b/src/Plugin/UiPatterns/Source/UiStylesWidget.php @@ -0,0 +1,105 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\ui_patterns_settings\Plugin\UiPatterns\Source; + +use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\StringTranslation\TranslatableMarkup; +use Drupal\Core\Template\Attribute; +use Drupal\ui_patterns\Attribute\Source; +use Drupal\ui_patterns\PluginWidgetSettingsInterface; +use Drupal\ui_patterns\SourcePluginBase; +use Drupal\ui_patterns\WidgetSettingTrait; +use Drupal\ui_patterns_settings\CSSWidgetTrait; +use Drupal\ui_styles\StylePluginManagerInterface; + +/** + * UI Styles CSS Widget. + * + * This class provides a widget for displaying configured UI styles + * as grids, colors, etc., and allows for customization of CSS settings. + */ +#[Source( + id: 'ui_styles_css_widget', + label: new TranslatableMarkup('UI Styles CSS widget'), + description: new TranslatableMarkup('Display configured UI Styles as grid / colors / etc.'), + prop_types: ['attributes'], + tags: ['widget'] +)] +class UiStylesWidget extends SourcePluginBase implements PluginWidgetSettingsInterface { + + use WidgetSettingTrait; + use CSSWidgetTrait; + + /** + * {@inheritdoc} + */ + public function getPropValue(): mixed { + $attributes = new Attribute(); + return $attributes->addClass(array_keys($this->settings)); + } + + /** + * Gets the style plugin manager service. + */ + protected static function stylesManager(): StylePluginManagerInterface { + return \Drupal::service('plugin.manager.ui_styles'); + } + + /** + * {@inheritdoc} + */ + public function settingsForm(array $form, FormStateInterface $form_state): array { + $style_plugin_manager = self::stylesManager(); + $form = parent::settingsForm($form, $form_state); + $definitions = $style_plugin_manager->getDefinitions(); + foreach ($definitions as $id => $definition) { + $form[$id] = [ + '#title' => $definition->getLabel(), + '#options' => $definition->getOptionsAsOptions(), + '#empty_option' => $definition->getEmptyOption(), + '#default_value' => $this->getSetting($id), + ]; + $enable = $this->widgetSettings[$id]['enable'] ?? TRUE; + if ($enable != '0') { + $form[$id] = $this->cssSettingsForm($form[$id], $this->widgetSettings[$id] ?? []); + $form[$id]['#required'] = ($this->widgetSettings[$id]['required'] ?? FALSE) == TRUE; + } + } + return $form; + } + + /** + * {@inheritdoc} + */ + public function widgetSettingsForm(array $form, FormStateInterface $form_state): array { + $style_plugin_manager = self::stylesManager(); + $form = []; + $definitions = $style_plugin_manager->getDefinitions(); + + foreach ($definitions as $id => $definition) { + $options = $definition->getOptionsAsOptions(); + $form[$id] = [ + '#type' => 'details', + '#title' => $definition->getLabel(), + '#collapsed' => TRUE, + ]; + $form[$id] = $this->cssWidgetSettingsForm($form[$id], $this->widgetSettings[$id] ?? [], $options); + $form[$id]['enable'] = [ + '#weight' => -10, + '#type' => 'checkbox', + '#title' => $this->t('Enable'), + '#default_value' => $this->widgetSettings[$id]['enable'] ?? TRUE, + ]; + $form[$id]['required'] = [ + '#weight' => -10, + '#type' => 'checkbox', + '#title' => $this->t('Required'), + '#default_value' => $this->widgetSettings[$id]['required'] ?? FALSE, + ]; + } + return $form; + } + +} -- GitLab From 75c245125c8468caeec019896aa4664b2e9e25ca Mon Sep 17 00:00:00 2001 From: Christian Wiedemann <christian.wiedemann@key-tec.de> Date: Mon, 31 Mar 2025 08:40:30 +0200 Subject: [PATCH 2/6] Fix widget configuration --- src/CSSWidgetTrait.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/CSSWidgetTrait.php b/src/CSSWidgetTrait.php index c25bf23..9617640 100644 --- a/src/CSSWidgetTrait.php +++ b/src/CSSWidgetTrait.php @@ -30,6 +30,9 @@ trait CSSWidgetTrait { private function enumAlterOptions(array $options, array $widget_settings): array { $overwrite_options = $widget_settings['overwrite'] ?? []; foreach ($overwrite_options as $overwrite_option_id => $overwrite_option) { + if (is_string($overwrite_option_id)) { + $overwrite_option_id = str_replace('|||', '.', $overwrite_option_id); + } if ($overwrite_option['enable'] == '0') { unset($options[$overwrite_option_id]); continue; @@ -146,12 +149,12 @@ trait CSSWidgetTrait { */ public function cssWidgetSettingsForm(array $element, array $widget_settings, array $options): array { $configure = $this->getEnumConfiguration($widget_settings); - $options = array_map(fn($widget_type) => $widget_type['label'], $this->getWidgetTypes()); + $widget_options = array_map(fn($widget_type) => $widget_type['label'], $this->getWidgetTypes()); $element['widget'] = [ '#type' => 'select', '#title' => $this->t('Widget'), '#description' => $this->t('Enum widget type.'), - '#options' => $options, + '#options' => $widget_options, '#default_value' => $configure['widget'] ?? 'select', ]; @@ -163,7 +166,9 @@ trait CSSWidgetTrait { ]; foreach ($options as $option_id => $label) { - $option_id = str_replace('.', '|||', $option_id); + if (is_string($option_id)) { + $option_id = str_replace('.', '|||', $option_id); + } $element['overwrite'][$option_id] = [ '#type' => 'details', '#title' => $this->t('Option: %label', ['%label' => $label]), -- GitLab From d6b88cfcbd8a46e93462d959f94d1731d5f9d1d7 Mon Sep 17 00:00:00 2001 From: Christian Wiedemann <christian.wiedemann@key-tec.de> Date: Mon, 31 Mar 2025 08:53:11 +0200 Subject: [PATCH 3/6] fix small issues --- src/CSSWidgetTrait.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CSSWidgetTrait.php b/src/CSSWidgetTrait.php index 9617640..3f04c1c 100644 --- a/src/CSSWidgetTrait.php +++ b/src/CSSWidgetTrait.php @@ -98,7 +98,7 @@ trait CSSWidgetTrait { $widget_config = $widget_configs[$widget]; $element['#type'] = $widget_config['type']; $configure = $this->getEnumConfiguration($widget_settings); - $configure['css']['wrapper_classes'] .= $widget_config['wrapper_classes'] ?? ''; + $configure['css']['wrapper_classes'] .= ' ' . $widget_config['wrapper_classes'] ?? ''; $element['#enum_widget'] = $configure; if ($element['#type'] === 'select') { $element['#theme'] = 'ui_patterns_settings_select_widget'; -- GitLab From 1115f27a20514205dd3aa8cc3f5851b4e1a3db7b Mon Sep 17 00:00:00 2001 From: Christian Wiedemann <christian.wiedemann@key-tec.de> Date: Mon, 31 Mar 2025 08:54:07 +0200 Subject: [PATCH 4/6] fix small issues --- composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 4eacbf1..ee2bbe9 100644 --- a/composer.json +++ b/composer.json @@ -18,6 +18,7 @@ ], "require-dev": { "drupal/ui_patterns": "2.0.x-dev", - "drupal/field_group": "^3.0" + "drupal/field_group": "^3.0", + "drupal/ui_styles": "^1.0" } } -- GitLab From 319577b46e9e5419760bc063465ad759697ba108 Mon Sep 17 00:00:00 2001 From: Christian Wiedemann <christian.wiedemann@key-tec.de> Date: Mon, 31 Mar 2025 08:58:24 +0200 Subject: [PATCH 5/6] fix small issues --- css/color.css | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/css/color.css b/css/color.css index d238d58..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; } -- GitLab From e77c1f63d6e3a877e0423b2ba1f4bc614ff4c787 Mon Sep 17 00:00:00 2001 From: Christian Wiedemann <christian.wiedemann@key-tec.de> Date: Mon, 31 Mar 2025 09:48:32 +0200 Subject: [PATCH 6/6] fix small issues --- src/CSSWidgetTrait.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CSSWidgetTrait.php b/src/CSSWidgetTrait.php index 3f04c1c..f2892e7 100644 --- a/src/CSSWidgetTrait.php +++ b/src/CSSWidgetTrait.php @@ -98,7 +98,7 @@ trait CSSWidgetTrait { $widget_config = $widget_configs[$widget]; $element['#type'] = $widget_config['type']; $configure = $this->getEnumConfiguration($widget_settings); - $configure['css']['wrapper_classes'] .= ' ' . $widget_config['wrapper_classes'] ?? ''; + $configure['css']['wrapper_classes'] .= ' ' . ($widget_config['wrapper_classes'] ?? ''); $element['#enum_widget'] = $configure; if ($element['#type'] === 'select') { $element['#theme'] = 'ui_patterns_settings_select_widget'; -- GitLab