diff --git a/css/table-themes.css b/css/table-themes.css new file mode 100644 index 0000000000000000000000000000000000000000..aeff5c260a68bb22d8d771fb43cae729a551652b --- /dev/null +++ b/css/table-themes.css @@ -0,0 +1,113 @@ +:root { + --table-width: 100%; + --table-vertical-align: top; + --table-border-color: #dee2e6; + --table-caption-side: bottom; + --table-border-collapse: collapse; + --table-border-width: 1px; + --table-cell-padding: 0.5rem; + --table-striped-bg: rgba(0, 0, 0, 0.05); + --table-striped-color: #212529; + --table-hover-bg: rgba(0, 0, 0, 0.075); + --table-hover-color: #212529; + --table-head-bg: #212529; + --table-head-color: #fff; +} + +/* Material Design Blue Theme */ +.table-blue { + --table-border-color: #bbdefb; + --table-striped-bg: #e3f2fd; + --table-striped-color: #0a2248; + --table-hover-bg: #90caf9; + --table-hover-color: white; + --table-head-bg: #2196f3; +} + +/* Material Design Green Theme */ +.table-green { + --table-border-color: #c8e6c9; + --table-striped-bg: #e8f5e9; + --table-striped-color: #073a0a; + --table-hover-bg: #a5d6a7; + --table-hover-color: white; + --table-head-bg: #4caf50; +} + +/* Material Design Purple Theme */ +.table-purple { + --table-border-color: #e1bee7; + --table-striped-bg: #f3e5f5; + --table-striped-color: #230646; + --table-hover-bg: #ce93d8; + --table-hover-color: white; + --table-head-bg: #9c27b0; +} + +/* Base styles */ +.table-ultimate { + display: block; + overflow-x: auto; + width: 100%; + -webkit-overflow-scrolling: touch; + -ms-overflow-style: -ms-auto-hiding-scrollbar; +} + +.table-ultimate table { + width: var(--table-width); + caption-side: var(--table-caption-side); + vertical-align: var(--table-vertical-align); + border-collapse: var(--table-border-collapse); + border-color: var(--table-border-color); +} + +.table-ultimate thead { + vertical-align: bottom; +} + +.table-ultimate tbody, +.table-ultimate td, +.table-ultimate tfoot, +.table-ultimate th, +.table-ultimate thead, +.table-ultimate tr { + border-width: 0; + border-style: solid; + border-color: inherit; +} + +.table-ultimate table > :not(caption) > * > * { + padding: var(--table-cell-padding); + border-bottom-width: var(--table-border-width); +} + +.table-ultimate th { + text-align: inherit; + text-align: -webkit-match-parent; +} + +/* Variants */ +.table-ultimate .striped-odd > tbody > tr:nth-of-type(odd) { + color: var(--table-striped-color); + background-color: var(--table-striped-bg); +} + +.table-ultimate .striped-even > tbody > tr:nth-of-type(even) { + color: var(--table-striped-color); + background-color: var(--table-striped-bg); +} + +.table-ultimate .filled-head > thead > * { + color: var(--table-head-color); + background-color: var(--table-head-bg); +} + +.table-ultimate .row-hover > tbody > tr:hover { + color: var(--table-hover-color); + background-color: var(--table-hover-bg); +} + +.table-ultimate .side-filled > tbody > tr > td:first-child { + color: var(--table-head-color); + background-color: var(--table-head-bg); +} diff --git a/src/Element/UltimateTable.php b/src/Element/UltimateTable.php index f50a89a1ffaacf59669c3f68ba044d92f361e9a4..933ddb339f3bf7c31ad52630e536eda0818e7b22 100644 --- a/src/Element/UltimateTable.php +++ b/src/Element/UltimateTable.php @@ -108,6 +108,7 @@ class UltimateTable extends FormElement implements ContainerFactoryPluginInterfa '#type' => 'markup', '#markup' => !empty($label) ? '<strong class="form-item__label ' . ($required ? 'js-form-required form-required' : '') . '">' . $label . '</strong>' : '', ]; + $element['nb_unit'] = [ '#type' => 'number', '#default_value' => 1, @@ -210,6 +211,17 @@ class UltimateTable extends FormElement implements ContainerFactoryPluginInterfa ], ]; + // Add legend field if enabled. + if (!empty($element['#enable_legend'])) { + $element['legend'] = [ + '#type' => 'text_format', + '#title' => t('Legend'), + '#format' => 'full_html', + '#default_value' => $values['legend'] ?? '', + '#rows' => 3, + ]; + } + $element['#attached']['library'][] = 'ultimate_table_field/style'; $element['#attached']['library'][] = 'ultimate_table_field/table-actions'; $element['#attached']['library'][] = 'core/drupal.dialog.ajax'; @@ -358,7 +370,7 @@ class UltimateTable extends FormElement implements ContainerFactoryPluginInterfa $items_data = $data ? Json::decode($data) : []; unset($items_data[$k]); $response = new AjaxResponse(); - $update_button_selector = 'input[name="update_table::' . $id . '"]'; + $update_button_selector = 'input[name="update_table__' . $id . '"]'; $data_input_selector = '#data-input-' . $i . '-' . $j . '--' . $formatted_id; $response->addCommand(new InvokeCommand($data_input_selector, 'val', [Json::encode($items_data)])) ->addCommand(new InvokeCommand($update_button_selector, 'trigger', ['mousedown'])); @@ -386,7 +398,12 @@ class UltimateTable extends FormElement implements ContainerFactoryPluginInterfa public static function valueCallback(&$element, $input, FormStateInterface $form_state) { $columns_values = []; $rows_values = []; + $legend = ''; + if ($input) { + if (isset($input['legend'])) { + $legend = $input['legend']['value']; + } $input = $input['table'] ?? $input; $columns = $input[0]; unset($input[0]); @@ -430,6 +447,7 @@ class UltimateTable extends FormElement implements ContainerFactoryPluginInterfa 'values' => [ 'columns' => $columns_values, 'rows' => $rows_values, + 'legend' => $legend, ], ]; diff --git a/src/Plugin/Field/FieldFormatter/UltimateTableFieldFormatter.php b/src/Plugin/Field/FieldFormatter/UltimateTableFieldFormatter.php index 0d6483cfa19b38b92e0f4ae639716a51e785d734..164fe41b0f354d1fa32bc0e267a1c2ba401b3aaa 100644 --- a/src/Plugin/Field/FieldFormatter/UltimateTableFieldFormatter.php +++ b/src/Plugin/Field/FieldFormatter/UltimateTableFieldFormatter.php @@ -5,6 +5,7 @@ namespace Drupal\ultimate_table_field\Plugin\Field\FieldFormatter; use Drupal\Core\Field\FieldItemListInterface; use Drupal\Core\Field\FormatterBase; use Symfony\Component\DependencyInjection\ContainerInterface; +use Drupal\Core\Form\FormStateInterface; /** * Plugin implementation of the ultimate table field widget. @@ -44,6 +45,74 @@ class UltimateTableFieldFormatter extends FormatterBase { return $instance; } + /** + * {@inheritdoc} + */ + public static function defaultSettings() { + return [ + 'legend_position' => 'before', + 'table_theme' => 'default', + 'table_color' => '', + 'table_style' => [], + ] + parent::defaultSettings(); + } + + /** + * {@inheritdoc} + */ + public function settingsForm(array $form, FormStateInterface $form_state) { + $form = parent::settingsForm($form, $form_state); + + $form['legend_position'] = [ + '#type' => 'select', + '#title' => $this->t('Legend position'), + '#options' => [ + 'before' => $this->t('Before table'), + 'after' => $this->t('After table'), + ], + '#default_value' => $this->getSetting('legend_position'), + ]; + + $form['table_theme'] = [ + '#type' => 'select', + '#title' => $this->t('Table color theme'), + '#options' => [ + '' => $this->t('Default'), + 'blue' => $this->t('Blue'), + 'green' => $this->t('Green'), + 'purple' => $this->t('Purple'), + ], + '#default_value' => $this->getSetting('table_theme'), + ]; + + $form['table_style'] = [ + '#type' => 'checkboxes', + '#title' => $this->t('Table styles'), + '#options' => [ + 'striped-odd' => $this->t('Striped rows (odd)'), + 'striped-even' => $this->t('Striped rows (even)'), + 'filled-head' => $this->t('Filled header'), + 'row-hover' => $this->t('Row hover effect'), + 'side-filled' => $this->t('Side filled'), + ], + '#default_value' => $this->getSetting('table_style'), + ]; + + // Make striped-odd and striped-even mutually exclusive. + $form['table_style']['striped-odd']['#states'] = [ + 'disabled' => [ + ':input[name="fields[' . $this->fieldDefinition->getName() . '][settings_edit_form][settings][table_style][striped-even]"]' => ['checked' => TRUE], + ], + ]; + $form['table_style']['striped-even']['#states'] = [ + 'disabled' => [ + ':input[name="fields[' . $this->fieldDefinition->getName() . '][settings_edit_form][settings][table_style][striped-odd]"]' => ['checked' => TRUE], + ], + ]; + + return $form; + } + /** * {@inheritDoc} */ @@ -53,6 +122,19 @@ class UltimateTableFieldFormatter extends FormatterBase { $values = $item->value; $columns = $values['columns'] ?? []; $rows = $values['rows'] ?? []; + $legend = $values['legend'] ?? ''; + + $element = []; + + // Add legend based on position setting. + if ($legend && $this->getSetting('legend_position') === 'before') { + $element['legend'] = [ + '#type' => 'markup', + '#markup' => $legend, + ]; + } + + // Add table. foreach ($rows as &$row) { foreach ($row as $j => $items) { if ($j === 0) { @@ -62,18 +144,58 @@ class UltimateTableFieldFormatter extends FormatterBase { $cell_field_instance = $this->ultimateTableCellFieldManager->createInstance($cell_item['type']); $cell_item = $cell_field_instance->cellFieldFormatter($cell_item); } - // @phpstan-ignore-next-line - $row[$j] = $this->renderer->renderPlain($items); + $row[$j] = $this->renderer->renderInIsolation($items); } } - $elements[] = [ + + // Add table element. + $element['table'] = [ '#type' => 'table', '#header' => $columns, '#rows' => $rows, '#empty' => t('No entries available'), + '#attributes' => [ + 'class' => $this->getTableClasses(), + ], + '#prefix' => '<div class="table-ultimate">', + '#suffix' => '</div>', + '#attached' => [ + 'library' => ['ultimate_table_field/table-themes'], + ], ]; + + // Add legend after table if configured. + if ($legend && $this->getSetting('legend_position') === 'after') { + $element['legend'] = [ + '#type' => 'markup', + '#markup' => $legend, + ]; + } + + $elements[] = $element; } return $elements; } + /** + * Gets the CSS classes for the table. + * + * @return array + * An array of CSS classes. + */ + protected function getTableClasses() { + $classes = ['custom-bordered-table']; + + // Add color theme. + if ($theme = $this->getSetting('table_theme')) { + $classes[] = 'table-' . $theme; + } + + // Add selected styles. + $styles = array_filter($this->getSetting('table_style')); + $classes = array_merge($classes, array_keys($styles)); + + return $classes; + } + } diff --git a/src/Plugin/Field/FieldType/UltimateTableFieldType.php b/src/Plugin/Field/FieldType/UltimateTableFieldType.php index 8ba4f61235cd10220985649a3aacbb7253a864ca..da3f91768d50d45a4d93dbbefe1f66e8fa631fee 100644 --- a/src/Plugin/Field/FieldType/UltimateTableFieldType.php +++ b/src/Plugin/Field/FieldType/UltimateTableFieldType.php @@ -95,6 +95,7 @@ class UltimateTableFieldType extends FieldItemBase { public static function defaultFieldSettings() { return [ 'allowed_types' => [], + 'enable_legend' => FALSE, ] + parent::defaultFieldSettings(); } @@ -112,6 +113,14 @@ class UltimateTableFieldType extends FieldItemBase { '#default_value' => $this->getSetting('allowed_types') ?? [], '#description' => $this->t('Select table cell allowed field types plugins, leave empty to allow all types'), ]; + + $form['enable_legend'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Enable legend field'), + '#default_value' => $this->getSetting('enable_legend'), + '#description' => $this->t('Add a legend field to the table.'), + ]; + return $form; } diff --git a/src/Plugin/Field/FieldWidget/UltimateTableFieldWidget.php b/src/Plugin/Field/FieldWidget/UltimateTableFieldWidget.php index eecb6bb480059886cca78662b53fd571ac73fb9c..60e4a1a04fec717c45aace075ba08f218e738d6c 100644 --- a/src/Plugin/Field/FieldWidget/UltimateTableFieldWidget.php +++ b/src/Plugin/Field/FieldWidget/UltimateTableFieldWidget.php @@ -36,6 +36,8 @@ class UltimateTableFieldWidget extends WidgetBase { '#tree' => TRUE, '#allowed_types' => array_values($allowed_value), '#default_value' => $default_value, + '#enable_legend' => $this->getFieldSetting('enable_legend'), + '#enable_summary' => $this->getFieldSetting('enable_summary'), ]; return $element; diff --git a/ultimate_table_field.libraries.yml b/ultimate_table_field.libraries.yml index 889d9b45d91c5f44bb160c1426c57afdaf28f5e8..f79adf4e4c6fb6c5b04257d297a6addb73508f39 100644 --- a/ultimate_table_field.libraries.yml +++ b/ultimate_table_field.libraries.yml @@ -10,4 +10,10 @@ table-actions: 'assets/js/ultimate-table.js': {} dependencies: - core/drupal - - core/jquery \ No newline at end of file + - core/jquery + +table-themes: + version: 1.x + css: + theme: + css/table-themes.css: {} \ No newline at end of file