View source  
  <?php
namespace Drupal\gridstack\Plugin\gridstack\stylizer;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element;
use Drupal\gridstack\GridStackDefault;
class Classes extends Media {
  
  protected $opacity = [
    20,
    40,
    60,
    80,
    90,
  ];
  
  public function getInternalClasses() {
    $classes = $bg = $bg_pos = $padding = $min_height = $min_height_md = [];
    $min_height_lg = [];
    foreach ($this->opacity as $key) {
      $bg[] = 'bg-dark-' . $key;
    }
    foreach (array_keys(GridStackDefault::breakpoints()) as $key) {
      $min_height[] = 'mh-' . $key;
      $min_height_md[] = 'mh-md-' . $key;
      $min_height_lg[] = 'mh-lg-' . $key;
      $padding[] = 'p-' . $key;
    }
    $positions = [
      'center',
      'bottom',
      'bottom-left',
      'bottom-right',
      'left',
      'right',
      'top',
      'top-left',
      'top-right',
    ];
    foreach ($positions as $key) {
      $bg_pos[] = 'bg-' . $key;
    }
    $classes['background'] = $bg;
    $classes['bg_position'] = $bg_pos;
    $classes['min_height'] = $min_height;
    $classes['min_height_md'] = $min_height_md;
    $classes['min_height_lg'] = $min_height_lg;
    $classes['padding'] = $padding;
    return $classes;
  }
  
  protected function classesElement($optionset, FormStateInterface $form_state, array $settings, array $extras = []) {
    $context = $settings['_scope'];
    $container = !empty($settings['_container']);
    $element = [];
    $wrapper_classes = [];
    $wrapper_class_value = trim($settings['wrapper_classes']);
    if ($wrapper_class_value) {
      $wrapper_classes = array_filter(array_map('trim', explode(" ", $wrapper_class_value)));
    }
    if ($classes = $this->manager
      ->getMergedClasses(FALSE)) {
      
      $problems = [
        'hidden',
        'visible',
        'visibility',
        'height',
      ];
      foreach ($classes as $key => $options) {
        
        if ($container && in_array($key, $problems)) {
          continue;
        }
        
        if (!$optionset
          ->isFramework() && strpos($key, 'height') !== FALSE) {
          continue;
        }
        $refined_options = $this
          ->getPresetOptions($options);
        $element[$key] = $this
          ->classElement($key, $options, $refined_options, $context, $wrapper_classes);
        $element[$key]['#attributes']['class'][] = $optionset
          ->isFramework() ? 'is-gs-css-driven' : 'is-gs-js-driven';
        if ($framework = $this->manager
          ->engineManager()
          ->framework()) {
          if (in_array($key, $framework
            ->previewOptions())) {
            $element[$key]['#is_preview'] = TRUE;
            $element[$key]['#attributes']['class'][] = 'form-wrapper--preview';
            if (in_array($key, [
              'rounded',
              'text_color',
            ])) {
              $element[$key]['#attributes']['class'][] = 'form-wrapper--bg';
            }
          }
        }
      }
    }
    return $element;
  }
  
  protected function rowClassesElement($optionset, FormStateInterface $form_state, array $settings, array $extras = []) {
    $context = $settings['_scope'];
    $container = !empty($settings['_container']);
    $element = [];
    
    if (!$optionset
      ->isFramework() && !$container) {
      return [];
    }
    $wrapper_classes = [];
    $wrapper_class_value = trim($settings['row_classes']);
    if ($wrapper_class_value) {
      $wrapper_classes = array_filter(array_map('trim', explode(" ", $wrapper_class_value)));
    }
    if ($classes = $this->manager
      ->engineManager()
      ->getClassOptions('row')) {
      foreach ($classes as $key => $options) {
        $refined_options = $this
          ->getPresetRowOptions($options);
        $element[$key] = $this
          ->classElement($key, $options, $refined_options, $context, $wrapper_classes);
      }
    }
    return $element;
  }
  
  protected function classElement($key, $options, $refined_options, $context, $wrapper_classes = []) {
    $title = str_replace([
      '_',
      '-',
    ], ' ', $key);
    $value = '';
    
    if ($wrapper_classes) {
      $values = array_values($options);
      $values = array_combine($values, $values);
      foreach ($wrapper_classes as $wrapper_class) {
        if (isset($values[$wrapper_class])) {
          $value = $values[$wrapper_class];
          break;
        }
      }
    }
    $css_classes = [
      'form-wrapper--' . str_replace('_', '-', $key),
      'is-collapsible',
      'is-collapsed',
      'is-gs-fieldset',
    ];
    return [
      '#type' => 'radios',
      '#title' => $this
        ->t('@title', [
        '@title' => Unicode::ucfirst($title),
      ]),
      '#options' => [
        '' => $this
          ->t('- None -'),
      ] + $refined_options,
      '#default_value' => $value,
      '#region' => $context,
      '#is_preview' => FALSE,
      '#after_build' => [
        [
          $this,
          'afterBuildPreset',
        ],
      ],
      '#group_name' => $key,
      '#attributes' => [
        'class' => $css_classes,
        'data-gs-preset-region' => $context,
      ],
    ];
  }
  
  public function afterBuildPreset(array $element) {
    foreach (Element::children($element) as $key) {
      $removed = [
        'form-wrapper--preview',
        'form-wrapper--' . str_replace('_', '-', $key),
        'form-wrapper--' . str_replace('_', '-', $element['#group_name']),
        'is-collapsible',
        'is-collapsed',
        'is-gs-fieldset',
      ];
      
      if (!empty($element['#is_preview'])) {
        $element[$key]['#wrapper_attributes']['class'][] = $key;
      }
      
      if (isset($element[$key]['#attributes']['class'])) {
        $classes = $element[$key]['#attributes']['class'];
        $classes = array_diff($classes, $removed);
        $element[$key]['#attributes']['class'] = $classes;
      }
      
    }
    return $element;
  }
  
  protected function getPresetOptions(array $data) {
    $rm = [
      'bg-',
      'gradient-',
      'padding-',
      'mh-',
      'text-',
      'hidden-',
      'rounded-',
      'visible-',
    ];
    return $this
      ->getBasePresetOptions($data, $rm, 'gridstack_classes_preset_options');
  }
  
  protected function getPresetRowOptions(array $data) {
    $rm = [
      'flex-',
      'justify-content-',
      'align-items-',
      'align-content-',
      'align-self-',
    ];
    return $this
      ->getBasePresetOptions($data, $rm, 'gridstack_classes_preset_row_options');
  }
  
  protected function getBasePresetOptions(array $data, array $rm, $alter = 'gridstack_classes_preset_options') {
    $options = [];
    foreach ($data as $option) {
      $title = str_replace($rm, '', $option);
      $title = str_replace([
        '_',
        '-',
      ], ' ', $title);
      $options[$option] = $this
        ->t('@title', [
        '@title' => Unicode::ucfirst($title),
      ]);
    }
    $this->manager
      ->getModuleHandler()
      ->alter($alter, $options, $data);
    ksort($options);
    return $options;
  }
}