<?php declare(strict_types = 1);

namespace Drupal\{{ machine_name }}\Plugin\Field\FieldFormatter;

{% sort %}
  {% if datetime %}
use Drupal\Core\Datetime\DrupalDateTime;
  {% endif %}
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\FormatterBase;
  {% if list %}
use Drupal\{{ machine_name }}\Plugin\Field\FieldType\{{ type_class }};
  {% endif %}
{% endsort %}

/**
 * Plugin implementation of the '{{ field_id }}_key_value' formatter.
 *
 * @FieldFormatter(
 *   id = "{{ field_id }}_key_value",
 *   label = @Translation("Key-value"),
 *   field_types = {"{{ field_id }}"},
 * )
 */
final class {{ key_value_formatter_class }} extends FormatterBase {

  /**
   * {@inheritdoc}
   */
  public function viewElements(FieldItemListInterface $items, $langcode): array {

    $element = [];

    foreach ($items as $delta => $item) {
      $table = [
        '#type' => 'table',
      ];

{% for subfield in subfields %}
      // {{ subfield.name }}.
      if ($item->{{ subfield.machine_name }}) {
  {% if subfield.type == 'datetime' %}
        $date = DrupalDateTime::createFromFormat('{{ subfield.date_storage_format }}', $item->{{ subfield.machine_name }});
        $date_formatter = \Drupal::service('date.formatter');
        $timestamp = $date->getTimestamp();
    {% if subfield.list %}
        $allowed_values = {{ type_class }}::{{ subfield.allowed_values_method }}();
        $formatted_date = $allowed_values[$item->{{ subfield.machine_name }}];
    {% else %}
        $formatted_date = $date_formatter->format($timestamp, 'long');
    {% endif %}
        $iso_date = $date_formatter->format($timestamp, 'custom', 'Y-m-d\TH:i:s') . 'Z';

  {% elseif subfield.list %}
        $allowed_values = {{ type_class }}::{{ subfield.allowed_values_method }}();

  {% endif %}
        $table['#rows'][] = [
          'data' => [
            [
              'header' => TRUE,
              'data' => [
                '#markup' => $this->t('{{ subfield.name }}'),
              ],
            ],
            [
              'data' => [
  {% if subfield.type == 'boolean' %}
                '#markup' => $item->{{ subfield.machine_name }} ? $this->t('Yes') : $this->t('No'),
  {% elseif subfield.type == 'datetime' %}
                '#theme' => 'time',
                '#text' => $formatted_date,
                '#html' => FALSE,
                '#attributes' => [
                  'datetime' => $iso_date,
                ],
                '#cache' => [
                  'contexts' => [
                    'timezone',
                  ],
                ],
  {% else %}
    {% if subfield.list %}
                '#markup' => $allowed_values[$item->{{ subfield.machine_name }}],
    {% else %}
                '#markup' => $item->{{ subfield.machine_name }},
    {% endif %}
  {% endif %}
              ],
            ],
          ],
          'no_striping' => TRUE,
        ];
      }

{% endfor %}
      $element[$delta] = $table;
    }

    return $element;
  }

}
