Gutenberg (Block) Editör İçin Bir Block (Blok) Kodlama


SiteCenneti-Gutenberg-Block-Tasarlama-Eklenti-Ekleme-Kodlama-6

Merhaba sayın okuyucum, hoş geldin. Bu derste, örnek bir kodlama ile, bir Gutenberg Block Editörü bloğu oluşturmayı gösteriyorum.

Sonuç olarak elde edeceğimiz bloğun tem görünümü şöyle olacak:

SiteCenneti-Gutenberg-Block-Tasarlama-Eklenti-Ekleme-Kodlama-Örnek-Tasarım-1

SiteCenneti-Gutenberg-Block-Tasarlama-Eklenti-Ekleme-Kodlama-Örnek-Tasarım-2

Oluşturacağımız bloğun; Resim Ayarları ve Renkler olmak üzere iki adet ayar paneli olacak olacak:

SiteCenneti-Gutenberg-Block-Tasarlama-Eklenti-Ekleme-Kodlama-Block-Ayarları-

SiteCenneti-Gutenberg-Block-Tasarlama-Eklenti-Ekleme-Kodlama-6

Blok (Block) Kodlamak İçin Ne Gerekli?

Gutenberg (Block) Editör İçin Bir Block Tasarlama işi ile ilgilendiğinize göre, kodlama konusunda temel bilgilere sahipsinizdir diye düşünüyorum. Bu yüzden, burada, temel kavramlar üzerinde durmadan, doğrudan işin teknik boyutlarını açıklamayı düşünüyorum.

Ben bu derste, block geliştirmek için şu gereçleri kullanacağım:

  • Xampp server ile localde kurulmuş bir WordPress ile çalışacağız
  • Visiual Sutdio Code (Kod editörü olarak kullanacağız)
  • npm (yüklü olmalı)
  • webpack
  • es6
  • jsx

Listeyi görüp, karamsarlığa kapılan arkadaşlar için şunu söyleyebilirim: Çok da sıkıntı yapmayın, sırayı bozmandan, burada verilenleri takip edin. Bazen, kervanı yolda düzmek de fena fikir değildir. Ama, tek bir yazıda bütün bu teknolojileri açıklayabileceğim gibi bir iyimserlik içinde olmanızı da istemem. Ben sizlere örnek bir blok kodlayacağım, verdiğim kodların incelenmesi ve anlaşılmasını sizlere bırakacağım.

Önce Bir Eklenti Oluşturalım

Gutenberg Editörü’nde kullanılan “blocklar”, tema dosyaları ile değil eklentiler ile eklenir. Bu yüzden öncelikle bir eklenti oluşturmamız gerekiyor.

  • Bir eklenti oluşturmak için öncelikle;
    • wp-content/plugins dizinine gideriz.
    • Türkçe karakter ve boşluk kullanmadan, küçük harfler ile bir klasör ismi oluştururuz. (Klasörün ismi, genellikle, eklentiye vereceğimiz ismin nicename’i olur.) : deneme-blocks
    • Bu klasörün içine, bir php dosyası ekleriz: plugin.php
// Eklenti klasörü ve dosyaları
|- wp-content (klasör)
|-- plugins (klasör)
|--- deneme-blocks (klasör)
|---- plugin.php (dosya)
  • plugin.php dosyasında, eklentimizi WordPress ile tanıştırıyoruz:

plugin.php

<?php
/*
Plugin Name: Deneme Blocks
Description: Bu bir deneme eklentisidir.
Text Domain: deneme_textd

Version: 1.0.0
*/

defined('ABSPATH') || exit(); // Doğrudan ulaşım kapalı

Eklenti Klasöründe Block İçin Gerekli Dosya ve Klasörleri Oluşturalım

  • Eklentimizde, oluşturacağımız blokların css ve js dosyaları için, assets adında bir klasör oluşturuyoruz:
    • assets klasörünün içinde, js ve css dosyaları için iki klasör daha açalım ki kafamız karışmasın.
      • assets/js klasöründe;
        • Tema tarafı için: scripts.js
        • Admin tarafı için: editor.js dosyaları olsun.
      • assets/css klasöründe;
        • Tema tarafı için: style.css
        • Admin tarafı için: editor.css dosyaları olsun.
  • src klasörü oluşturuyoruz.
    • src: Kaynak klasörü. Block için yazacağımız kodların merkezi burası olacaktır.
    • Bu klasörün içinde, index.js adında bir dosya oluşturuyoruz.
      • src/index.js: Block, bu dosyada tasarlanacak, webpack tarafından derlenecektir ve ilgili klasörlere aktarılacak.
  • Bu klasör ve dosyalar oluşturulduktan sonra, eklenti dizinimiz şu hali alacaktır:
// Eklenti klasörü ve dosyaları
|- wp-content (klasör)
|-- plugins (klasör)
|--- deneme-blocks (klasör)
|---- assets (klasör)
|----- js (klasör)
|------ sripts.js (dosya)
|------ editor.js (dosya)
|----- css (klasör)
|------ style.css (dosya)
|------ editor.css (dosya)
|---- src(klasör)
|----- index.js (dosya)
|---- plugin.php (dosya)
  • Gutenberg blokları için oluşturduğumuz bu dosyaları WordPress’e tanıtıyoruz:

plugin.php

<?php
/*
Plugin Name: Deneme Blocks
Description: Bu bir deneme eklentisidir.
Text Domain: deneme_textd
Version: 1.0.0
*/

defined('ABSPATH') || exit(); // Doğrudan ulaşım kapalı

/**
 * HER EVE LAZIM
 */
define( 'STCNNT_BLOCKS_PLUGIN_PATH', trailingslashit( plugin_dir_path( __FILE__ ) ) );
define( 'STCNNT_BLOCKS_PLUGIN_URL', trailingslashit( plugins_url( '/', __FILE__ ) ) );

/**
 * BLOCK İÇİN GEREKLİ JS VE CSS DOSYALARINI TANITILYORUZ
 */
function stcnnt_deneme_blocks_scripts() {

    // Bu klasör ve dosya, otomatik olarak oluşturulacak
    $asset_file = include( STCNNT_BLOCKS_PLUGIN_PATH . 'build/index.asset.php');
    wp_register_script(
        'stcnnt-deneme-blocks-editor-js',
        STCNNT_BLOCKS_PLUGIN_URL . 'build/index.js',
        $asset_file['dependencies'],
        $asset_file['version']
    );
 
    wp_register_style(
        'stcnnt-deneme-blocks-editor-style',
        STCNNT_BLOCKS_PLUGIN_URL . 'assets/css/editor.css',
        array( 'wp-edit-blocks', ),
        filemtime( plugin_dir_path( __FILE__ ) . '/assets/css/editor.css' )
    );
 
    wp_register_style(
        'stcnnt-deneme-blocks-style',
        STCNNT_BLOCKS_PLUGIN_URL . 'assets/css/style.css',
        array(),
        filemtime( plugin_dir_path( __FILE__ ) . '/assets/css/style.css' )
    );
 
    register_block_type( 'stcnnt-deneme-blocks/hero-img-block', array(
        'api_version' => 2,
        'style' => 'stcnnt-deneme-blocks-style', // Hem tema hem de editor tarafında
        'editor_style' => 'stcnnt-deneme-blocks-editor-style', // Sadece editor tarafında
        'editor_script' => 'stcnnt-deneme-blocks-js', // Sadece editor tarafında
    ) );

    register_block_type( 'stcnnt-deneme-blocks/google-ads-block', array(
        'api_version' => 2,
        'style' => 'stcnnt-deneme-blocks-style', // Hem tema hem de editor tarafında
        'editor_style' => 'stcnnt-deneme-blocks-editor-style', // Sadece editor tarafında
        'editor_script' => 'stcnnt-deneme-blocks-editor-js',  // Sadece editor tarafında
    ) );
}
add_action( 'init', 'stcnnt_deneme_blocks_scripts' );

/**
 * OLUŞTURACAĞIMIZ BLOCKLAR AYRI BİR KATEGORİDE GÖRÜNSÜN
 */
function stcnnt_block_category( $categories, $post ) {
    return array_merge(
        $categories,
        array(
            array(
                'slug' => 'stcnnt-deneme-blocks-category',
                'title' => __( 'Stcnnt Deneme Blockları', 'deneme_textd' ),
            ),
        )
    );
}
add_filter( 'block_categories', 'stcnnt_block_category', 10, 2);


/**
 * Bloklar için bağımsız iki adet js dosayası da kenarda dursun
 */
//sadece tema tarafında çalışır.
function stcnnt_enqueue_theme_scripts(){
    wp_enqueue_script(
        'stcnnt-only-theme-js',
        STCNNT_BLOCKS_PLUGIN_URL . 'assets/js/scripts.js',
        array('jquery'),
        true
    );
}
add_action( 'init', 'stcnnt_enqueue_theme_scripts' );

// Sadece editör tarafında çalışır
function stcnnt_enqueue_admin_scripts(){
    wp_enqueue_script(
        'stcnnt-only-admin-js',
        STCNNT_BLOCKS_PLUGIN_URL . 'assets/js/editor.js',
        array('jquery'),
        true
    );
}
add_action( 'admin_enqueue_scripts', 'stcnnt_enqueue_admin_scripts' );
  • Artık eklentimiz kullanıma hazırdır ve yönetim panelinde, “Eklentiler” menüsünde yer almaktadır:
    SiteCenneti-Gutenberg-Block-Tasarlama-Eklenti-Ekleme
    Henüz, eklentiyi “Etkinleştir“mek için erken. Bu aşamada çalıştırırsak, uyarı mesajları alabiliriz.

npm İşleri

  • Visiual Studio Code editöründe, mümkünse yönetici olarak, eklenti klasörünü açıyoruz.
  • Bu klasörde iken, “Terminali” açıyoruz ve komut satırı eklenti dizininde olmalıdır:
    PS C:\xampp\htdocs\benimsitem\wp-content\plugins\deneme-blocks>
  • Bu dizinde iken şu komutu çalıştırıyoruz ve fare imleci tekrar eklenti dizininin sonunda belirene kadar bekliyoruz:
npm init --yes
  • Bu koddan sonra, eklenti dizinimize package.json adına bir dosya daha eklenmiş olacak ve dizinin son hali şöyle olacaktır:
// Eklenti klasörü ve dosyaları
|- wp-content (klasör)
|-- plugins (klasör)
|--- deneme-blocks (klasör)
|---- assets (klasör)
|----- js (klasör)
|------ sripts.js (dosya)
|------ editor.js (dosya)
|----- css (klasör)
|------ style.css (dosya)
|------ editor.css (dosya)
|---- src(klasör)
|----- index.js (dosya)
|---- plugin.php (dosya)
|---- package.json (dosya)
  • Eklenen package.json dosyasının içeriği şöyledir:

package.json

{
  "name": "deneme-blocks",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}
  • Yine aynı dizinde şu komutu çalıştırıyoruz ve uzunca bir süre bekliyoruz:
npm i --save-dev @wordpress/scripts
  • Yukarıdaki komuttan sonra, dizinimize “node_modules” adında kocaman bir klasör yüklenir ve eklenti dizinimiz şöyle görünür:
// Eklenti klasörü ve dosyaları
|- wp-content (klasör)
|-- plugins (klasör)
|--- deneme-blocks (klasör)
|---- assets (klasör)
|----- js (klasör)
|------ sripts.js (dosya)
|------ editor.js (dosya)
|----- css (klasör)
|------ style.css (dosya)
|------ editor.css (dosya)
|---- node_modules (klasör)
|---- src(klasör)
|----- index.js (dosya)
|---- plugin.php (dosya)
|---- package.json (dosya)

Artık, bir block geliştirmek için, WordPress’in bütün yardımcı elemanları elimizin altında.

  • Bu kodu çalıştırdıktan sonra package.json dosyası şöyle görünmelidir:
{
  "name": "deneme-blocks",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@wordpress/scripts": "^16.1.3"
  }
}
  • package.json dosyasını aşağıdaki şekilde düzenlememiz gerekiyor:

package.json

{
  "name": "deneme-blocks",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "wp-scripts start",
    "build": "wp-scripts build"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@wordpress/scripts": "^16.1.3"
  }
}
  • Bu aşamada terminalde aşağıdaki komutu yazıp, enter tuşuna basmalı ve biraz beklemeliyiz:
npm run start
  • Her şey yolunda giderse, terminal bize, aşağıdaki gibi bir cevap vermelidir:
    SiteCenneti-Gutenberg-Block-Tasarlama-Eklenti-Ekleme-Kodlama-2
  • Bu cevap bize diyor ki:
    • build adında bir klasör oluşturduk.
    • Bu klasörün içinde, index.asset.php adına bir dosya oluşturduk.
    • Bu klasörün içinde, index.js adında bir dosya daha oluşturduk.
    • Bu klasörün içinde, index.js.map adında bir dosya daha oluşturduk.
      • İşte bütün bu işleri yapan, webpack adındaki paketleyicidir.
      • Biraz önce yüklediğimiz @wordpress/scripts paketi, bizim için, gerekli webpack ayarlarını yapmıştır.
  • build klasörü, bizim eklentimizin oluştuğu klasördür.
    • Yani işimiz bitince, eklenti klasörü içinde, bize lazım olacak dosya ve klasörler sadece şu 3 tanesidir.
      • plugin.php dosyası
      • build klasörü
      • assets klasörü
    • Bu üçünün dışındaki bütün dosya ve klasörler, block yazmak için bize yadım ederler.
    • Kodladığımız eklentiyi alıp giderken, eklenti klasörünün içindeki diğer dosyalara ihtiyacımız olmayacaktır.

npm run start Komutu

  • Bu komut; editörün bizi devamlı dinlemesini sağlar.
  • Bu komut çalıştırıldığında, terminal dinleme moduna geçer.
  • Terminal dinleme modunda iken;
    • komut kabul etmez
    • yaptığımız değişiklerden sonra, bir dosyayı kaydettiğimizde;
      • build klasörü yoksa tekrar oluşturulur, varsa üzerine yazılır.
      • kodlarımızın otomatik olarak derlenir ve build klasörüne taşınır.
      • derleme işlemi webpack marifetiyle yapılır.
  • Dinleme modundan tekrar komut satırına geçmek için Ctrl + C tuş çiftine birlikte basmamız yeterlidir.

build ve src Klasörleri Nedir?

  • src klasörü bizim mutfağımızdır, block ile ilgili bütün kodları burada yazarız.
  • Block yazarken, web tarayıcıların henüz desteklemediği; babel, jsx, esnext gibi js uygulamalarını/kütüphanelerini de kullanırız.
  • webpack paketi; src klasöründe yazılan kodları, tarayıcıların anlayabildiği şekle getirir ve build klasöründe paketler.
    • Bu işlem;
      • npm run start komutu ilk defa çalıştırıldığında
      • npm run start komutu çalıyor iken, dosyaların her kaydedilişinde (Ctrl + s) gerçekleşir.
  • build klasörünü silip, tekrar npm run start dersek veya bu komut çalıştıktan sonra bir dosyayı kaydedersek, build klasörü ve içindeki dosyalar, tekrar en güncel haliyle oluştur.
    • src klasörünün başına bir iş gelmediği müddetçe, build klasörünü en güncel haliyle oluşturmak tek bir komut kadar kolaydır.
  • Bu aşamada, eklenti dizinimiz şöyle görünmelidir:
// Eklenti klasörü ve dosyaları
|- wp-content (klasör)
|-- plugins (klasör)
|--- deneme-blocks (klasör)
|---- assets (klasör)
|----- js (klasör)
|------ sripts.js (dosya)
|------ editor.js (dosya)
|----- css (klasör)
|------ style.css (dosya)
|------ editor.css (dosya)
|---- build (klasör)
|----- index.asset.php (dosya)
|----- index.js (dosya)
|----- index.js.map (dosya)
|---- node_modules (klasör)
|---- src(klasör)
|----- index.js (dosya)
|---- plugin.php (dosya)
|---- package.json (dosya)
  • Artık eklentimizi etkinleştirebiliriz. (Yönetim paneli: Eklentiler -> Deneme Blocks -> Etkinleştir)

npm – Block Kodlaması İçin Gerekli Scriptleri Yükleme

  • npm run start komutundan sonra, terminal bizi dinleme moduna geçmiştir.
  • Terminal dinleme modunda iken, bir dosyada bir değişiklik yaparsak bunu algılar ve dosyanın en güncel haliyle tekrar derlenmesini sağlar.
    • Terminali, dinleme modundan çıkarıp tekrar bir komut girebilmek için, öncelikte, fare terminalde iken:
Ctrl + C

ikilisine basmamız gerekiyor.

  • Bu tuşlardan sonra karşımıza şöyle bir soru çıkacaktır:
Terminate batch job (Y/N)?
  • Bu soruyu, “Y” ve enter tuşlarına basarak cevaplıyoruz.
  • Bu işlemlerden sonra, terminal, dinleme modundan çıkacak ve komut satırı tekrar aktif olacaktır.
  • Komut satırı eklentinin kök dizininde iken, aşağıdaki komutu girerek, scriptin yüklenmesini bekleyelim (İşlem biraz uzun sürebilir.):
npm install @wordpress/blocks --save
  • Block kodlamaya geçemeden önce, kodlama esnasında ihtiyacımız olacak bazı paketleri yükleyelim.
  • Bunun için, eklentinin kök dizininde iken, aşağıdaki işlemleri yapalım:
  1. Aşağıdaki komutu girerek, scriptin yüklenmesini bekleyelim:
npm install @wordpress/i18n --save
  1. Aşağıdaki komutu girerek, scriptin yüklenmesini bekleyelim:
npm install @wordpress/element --save
  1. Aşağıdaki komutu girerek, scriptin yüklenmesini bekleyelim:
npm install @wordpress/block-editor --save
  1. Aşağıdaki komutu girerek, scriptin yüklenmesini bekleyelim:
npm install @wordpress/components --save

Birden Çok Bloğu Tek Eklentide Kodlama

  • Amacımız bir tane block kodlamak ise;
    • src/index.js dosyası yeterlidir.
  • Birden fazla block kodlamak istiyorsak:
    • src/block-1/index.js
    • src/block-2/index.js

    • şeklinde, alt klasörler ile dilediğimiz kadar block oluşturabiliriz.
  • Biz, iki tane block kodlayacağız. Bu blockların isimleri şöyle olacak:
    1. hero-img-block:
      SiteCenneti-Gutenberg-Block-Tasarlama-Eklenti-Ekleme-Kodlama-3
    2. google-ads-block
  • Bu iki bloğu kodlamak için, eklenti dizininde, src klasörüne şu iki klasör ve dosyayı ekliyoruz:
    • hero-img-block (klasör)
      • block.js (dosya)
    • google-ads-block (klasör)
      • block.js (dosya)
  • Bu aşamadan sonra, eklenti dizinimiz şöyle görünecektir:
// Eklenti klasörü ve dosyaları
|- wp-content (klasör)
|-- plugins (klasör)
|--- deneme-blocks (klasör)
|---- assets (klasör)
|----- js (klasör)
|------ sripts.js (dosya)
|------ editor.js (dosya)
|----- css (klasör)
|------ style.css (dosya)
|------ editor.css (dosya)
|---- build (klasör)
|----- index.asset.php (dosya)
|----- index.js (dosya)
|----- index.js.map (dosya)
|---- node_modules (klasör)
|---- src(klasör)
|----- hero-img-block (klasör)
|------ block.js (dosya)
|----- google-ads-block (klasör)
|------ block.js (dosya)
|----- index.js (dosya)
|---- plugin.php (dosya)
|---- package.json (dosya)
  • Eklediğimiz blockları, src/index.js dosyasına tanıtalım:

src/index.js

import './hero-img-block/block.js';
import './google-ads-block/block.js';

Temel Block Kodları

  • İki tane block kodlayacağımızı belirtmiştik.
    • Önce hero-img-block adını verdiğimiz block üzerinden, bir block nasıl kodlanır görelim:

Örnek Bir Block: hero-img-block

  • Bizim hazırladığımız eklenti dizininde hero-img-block bloğunun temel dosyası hero-img-block/block.js dosyasıdır.
  • Bir WordPress Gutenberg Editörü bloğu, ana hatları ile şu şablona göre kodlanır:

hero-img-block/block.js

import { registerBlockType } from '@wordpress/blocks';

registerBlockType( 'stcnnt-deneme-blocks/hero-img-block', {
    apiVersion: 2,
    title: '',
    icon: '',
    category: '',
    attributes: {},
    example: {},
    edit: ( props ) => {
        return (
            <p>Burası sadece editör sayfasında görünür.</p>
        );
    },
    save: ( props ) => {
        return (
            <p>Burası sadece temada görünür.</p>
        );
    },
} );

Block Şablonundaki Kodların Anlamları:

import { registerBlockType } from '@wordpress/blocks';
  • Yukarıdaki kod, bir block kaydetmek için gerekli olan registerBlockType fonksiyonunu çağırır.
  • Block ile ilgili bütün kodlar bu fonksiyonun parametreleridir.
registerBlockType( 'blok-kimliği', {block argümanları})
  • Yukarıdaki fonksiyon, bir bloğun bütün kodlarının barındığı fonksiyondur.
  • Fonksiyonun 2 parametresi vardır:
    1. Parametre: Block Kimliği
      • Bloğun veritabanına kaydedilecek ismidir.
      • Bu isim, plugin.php dosaysında, register_block_type() fonksiyonunun birinci parametresi ile aynı olmalıdır.
        • Örnek-1:
          'benim-super-blocklarim/super-bir-block'
        • Örnek-2:
          'benim-super-blocklarim/super-başka-bir-block'
    1. Parametre: Block Argümanları
      • Bir javascript nesnesidir.
      • Bloğun adı, kategorisi, ikonu, örnek görünümü, editör görünümü, tema görünümü…. gibi bütün özellikleri bu parametrede belirlenir.
      • Block argümanları şunlardır:
        • title: (string) Bloğun adıdır. Block, editörde bu ad ile karşımıza çıkar.
          • Örnek:
            title: __( 'Book' )
        • description: (string) Bloğun tanımıdır. Zorunlu değildir.
          • Örnek:
            description: __( 'Block showing a Book card.' );
        • category: (string) Bloğun, diğer blocklar için kullanılan kategorilerden hangisinde gösterileceğini belirtir.
          • Örnek:
            category: 'widgets',
          • WordPress’in block kategorileri:
            • text
            • common
            • formatting 
            • layout
            • media
            • design
            • widgets
            • theme
            • embed
        • icon: (string|object) Bloğun ikonudur. Zorunlu değildir.
          • Örnek-1:
            icon: 'book-alt',
          • Örnek-2:
            icon: <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path fill="none" d="M0 0h24v24H0V0z" /><path d="M19 13H5v-2h14v2z" /></svg>
          • Örnek-3:
            icon: {
            background: '#7e70af',
            foreground: '#fff',
            src: <svg viewBox="0 0 24 24"xmlns="http://www.w3.org/2000/svg"><path fill="none"d="M0 0h24v24H0V0z"/><path d="M19 13H5v-2h14v2z"/></svg>,} ,
          • Kullanabileceğiniz bütün WordPress’in dashiconları (seçtiğiniz ikonun isminin önündeki dashicon- ifadesini kullanmayın.)
        • attributes: (object) Block için yapacağımız ayarlarda kullanacağımız değişkenlerdir.
          • Örnek:
            attributes: {
            cover: {type: 'string', source: 'attribute', selector: 'img', attribute: 'src',},
            author: {type: 'string',source: 'html',selector: '.book-author',},
            pages: {type: 'number',},
            },
        • example: (object) Block için varsayılan bir görünüm oluşturmak için, kullanılır. Editörde, bloğu seçmeden önce, fareyi üzerinde bekletirsek, burada verdiğimiz değerlere göre bir örnek görünüm oluşur.
        • edit: Bloğun, editör görünümüne ait html yapısını döndüren bir fonksiyondur. Block için kullanacağımız bütün ayarlar, form elemanları bu fonksiyonun içinde döndürülür.
          • Fonksiyonun bir tane parametresi vardır ve genellikle props adıyla çağırılır.
          • Bu parametre, attributes nesnesinde tanımladığımız değişkenler de dahil bir çok gerekli elemana sahiptir.
        • save: Bloğun, tema görünümüne ait html yapısını döndüren bir fonksiyondur.
          • Fonksiyonun bir tane parametresi vardır ve genellikle props adıyla çağırılır.
          • Bu parametre, attributes nesnesinde tanımladığımız değişkenler de dahil bir çok gerekli elemana sahiptir.

Hazırlıklar Bitti, Artık Bloğu Kodlayalım

SiteCenneti-Gutenberg-Block-Tasarlama-Eklenti-Ekleme-Kodlama-3
“SC Hero Resmi” Bloğu – Tema Görünümü
  • registerBlockType fonksiyonuna gerekli bilgileri girerek, yukarıdaki gibi görünecek olan, ilk bloğumuzu oluşturalım:

hero-img-block/block.js


import { registerBlockType } from '@wordpress/blocks';
import { __ } from '@wordpress/i18n';
import {
    useBlockProps,
    RichText,
    AlignmentToolbar,
    BlockControls,
    InspectorControls,
    ColorPalette,
    MediaUpload,
} from '@wordpress/block-editor';

import { Panel, PanelBody, PanelRow, Button, ToggleControl, SelectControl } from '@wordpress/components';
import { __experimentalNumberControl as NumberControl } from '@wordpress/components';
import { image } from '@wordpress/icons';

registerBlockType( 'stcnnt-deneme-blocks/hero-img-block', {
    apiVersion: 2,
    title: 'SC Hero Resmi',
    icon: 'format-image', //dashicons-format-image
    category: 'stcnnt-deneme-blocks-category',
    attributes: {
        useContent: {
            type: 'boolean',
            default: true,
        },
        content: {
            type: 'array',
            source: 'children',
            selector: 'p',
        },
        alignment: {
            type: 'string',
            default: 'none',
        },
        useOverlay: {
            type: 'boolean',
            default: true,
        },
        overlayColor: {
            type: 'string',
            default: null // varsayılan bir renk yok
        },
        overlayColorAlpha: {
            type: 'string',
            default: '40'
        },
        fontColor: {
            type: 'string',
            default: '#ffffff'
        },
        fontTag: {
            type: 'string',
            default: 'p'
        },
        useFontBg: {
            type: 'boolean',
            default: true,
        },
        backgroundImage: {
            type: 'string',
            default: null, // isterseniz varsayılan bir resim atayabilirsiniz
        }
    },
    example: {
        attributes: {
            content: __('Herkese Merhaba :)', 'deneme_textd'),
            alignment: 'right',
        },
    },
    edit: ( { attributes, setAttributes } ) => {
        
        const onChangeContent = ( newContent ) => {
            setAttributes( { content: newContent } );
        };
 
        const onChangeAlignment = ( newAlignment ) => {
            setAttributes( {
                alignment: newAlignment === undefined ? 'none' : newAlignment,
            } );
        };

        const onImageSelect = ( imageObject ) => {
            setAttributes( {
                backgroundImage: imageObject.sizes.full.url
            } );
        };

        const onOverlayColorChange = ( changes ) => {
            setAttributes( {
                overlayColor: changes
            } );
        };

        const onTextColorChange = ( changes ) => {
            setAttributes( {
                fontColor: changes
            } );
        };

        const resmiKaldir = () => {
            setAttributes( {
                backgroundImage: null
            } );
        }

        const useOverlaySelection = (val) => {
            setAttributes( {useOverlay: val} );
        }

        const useContentSelection = (val) => {
            setAttributes( {useContent: val} );
        }
        
        const useFontBgSelection = (val) => {
            setAttributes( {useFontBg: val} );
        }
        
        const overlayColorAlphaChange = (val) => {
            setAttributes( {overlayColorAlpha: val} );
        }

        const scSettingsSection = (attributes) => (
            <Panel header="">
                <PanelBody title="Resim Ayarları" className="wp-block-stcnnt-deneme-blocks-hero-setting" initialOpen={ true }>
                    <PanelRow className="wp-block-stcnnt-deneme-blocks-hero-img-container">
                        {attributes.backgroundImage != null ?
                        <img className="sc-hero-img" src={attributes.backgroundImage} />
                        :
                        <p className="sc-hero-img-placeholder">{__('Resim yüklenmedi.', 'deneme_textd')}</p>
                        }
                    </PanelRow>
                    <PanelRow>
                        <div>
                            <MediaUpload
                                onSelect={ onImageSelect }
                                type="image"
                                value={attributes.backgroundImage} // make sure you destructured backgroundImage from props.attributes!
                                render={({ open }) => (
                                    <Button
                                        variant="primary"
                                        icon= {image}
                                        onClick={open}>
                                        {attributes.backgroundImage != null ? __('Değiştir', 'deneme_textd') : __('Resim yükle', 'deneme_textd')}
                                    </Button>
                                )}
                            />
                            {attributes.backgroundImage != null ? 
                                <Button
                                variant="primary"
                                icon= {image}
                                onClick={resmiKaldir}
                                className="sc-resmi-kaldir"
                                >{__('Kaldır', 'deneme_textd')}</Button>
                                : null
                            }
                        </div>
                    </PanelRow>
                    <hr />
                    <PanelRow>
                        <ToggleControl
                            label= {__('Overlay kullan', 'deneme_textd')}
                            help= {__('Resmin üzerinde yarı şeffaf bir tabaka oluşturmak için kullanılır.', 'deneme_textd')}
                            checked={ attributes.useOverlay }
                            onChange={ useOverlaySelection }
                        />
                    </PanelRow>
                    <PanelRow>
                        <ToggleControl
                            label= {__('Metin kullan', 'deneme_textd')}
                            help= {__('Resmin üzerine kısa bir açıklama yazmak için kullanılır.', 'deneme_textd')}
                            checked={ attributes.useContent }
                            onChange={ useContentSelection }
                        />
                    </PanelRow>
                    <PanelRow>
                        <SelectControl
                            label="Metnin HTML etiketi:"
                            value={ attributes.fontTag }
                            options={ [
                                { label: 'p', value: 'p' },
                                { label: 'h1', value: 'h1' },
                                { label: 'h2', value: 'h2' },
                                { label: 'h3', value: 'h3' },
                                { label: 'h4', value: 'h4' },
                                { label: 'h5', value: 'h5' },
                                { label: 'h6', value: 'h6' },
                                { label: 'div', value: 'div' },
                                { label: 'span', value: 'span' },
                            ] }
                            onChange={ ( val ) => {
                                setAttributes( { fontTag: val } );
                            } }
                        />
                    </PanelRow>
                    <PanelRow>
                        <ToggleControl
                            label= {__('Metin için arkplan kullan:', 'deneme_textd')}
                            help= {__('Resmin metni için arkplan oluşturur.', 'deneme_textd')}
                            checked={ attributes.useFontBg }
                            onChange={ useFontBgSelection }
                        />
                    </PanelRow>
                </PanelBody>
                <PanelBody title={__('Renkler', 'deneme_textd')} initialOpen={ false }>
                    <PanelRow>
                        <div>
                            <label className="sc-setting-section-label">{__('Overlay rengi:', 'deneme_textd')}</label>
                            <ColorPalette
                                value={attributes.overlayColor}
                                onChange={onOverlayColorChange}
                            />
                        </div>
                    </PanelRow>
                    <PanelRow>
                        <label>{__('Şeffaflık değeri:', 'deneme_textd')}</label>
                        <NumberControl
                            onChange={ overlayColorAlphaChange }
                            value={ attributes.overlayColorAlpha }
                        />
                    </PanelRow>
                    <hr />
                    <PanelRow>
                        <div>
                            <label className="sc-setting-section-label">{__('Metin rengi:', 'deneme_textd')}</label>
                            <ColorPalette
                                value={attributes.fontColor}
                                onChange={onTextColorChange}
                            />
                        </div>
                    </PanelRow>
                </PanelBody>
            </Panel>
        );
 
        const textBg = attributes.useFontBg ? ' sc-text-bg' : '';

        return (
            [   
                <InspectorControls>
                    {scSettingsSection(attributes)}
                </InspectorControls>,
                <div
                { ...useBlockProps() }
                style={{
                    backgroundImage: `url(${attributes.backgroundImage})`,
                    backgroundSize: 'cover',
                    backgroundPosition: 'center',
                    height: '300px',
                }}>
                    {
                        <BlockControls>
                            <AlignmentToolbar
                                value={ attributes.alignment }
                                onChange={ onChangeAlignment }
                            />
                        </BlockControls>
                    }
                    {attributes.useContent ?
                    <div className={`sc-hero-text-container ${textBg}`}
                    style={{
                        color: attributes.fontColor,
                        textAlign: attributes.alignment,
                    }}
                    >
                        <RichText
                            className={ attributes.className }
                            tagName= {attributes.fontTag}
                            onChange={ onChangeContent }
                            value={ attributes.content  }
                            placeholder={__('Resim metni...', 'deneme_textd')}
                        />
                    </div>
                    : null
                    }
                    {attributes.useOverlay ?
                        <div
                        className="sc-hero-img-overlay"
                        style={{
                            backgroundColor: attributes.overlayColor,
                            opacity: attributes.overlayColorAlpha/100,
                        }}
                        ></div>
                        : null
                    }
                </div>
            ]
        );
    },
    save: ( { attributes } ) => {
        const blockProps = useBlockProps.save();
        const textBg = attributes.useFontBg ? ' sc-text-bg' : '';

        return (
            <div { ...blockProps }
            style={{
                backgroundImage: `url(${attributes.backgroundImage})`,
                backgroundSize: 'cover',
                backgroundPosition: 'center',
                height: '300px',
            }}
            >
                {(attributes.content.length != 0 && attributes.useContent) ?
                    <div
                    className={ `sc-hero-text-container align-${ attributes.alignment } ${textBg}` }
                    style={{
                        color: `${attributes.fontColor} !important`,
                    }}
                    >
                        <RichText.Content
                            tagName={attributes.fontTag}
                            value={ attributes.content }
                            className='sc-hero-text'
                        />
                    </div>
                    : null    
                }
                {attributes.useOverlay ?
                    <div
                    className="sc-hero-img-overlay"
                    style={{
                        backgroundColor: attributes.overlayColor,
                        opacity: attributes.overlayColorAlpha/100,
                    }}
                    ></div>
                    : null
                }
            </div>
        );
    },
} );
  • Yukarıdaki kodları kaydettikten sonra, dinleme modunda değilse, terminalde şu komutu çalıştırıyoruz:
npm run start
  • Artık, kendimize ait bir bloğumuz var.
  • Yönetim panelinden, block editörü açıp, bloklar içinde ‘SC Hero Resmi‘ araması yaparsak, oluşturduğumuz block karşımıza çıkacaktır.
    SiteCenneti-Gutenberg-Block-Tasarlama-Eklenti-Ekleme-Kodlama-4
  • block.js deki kodların bir kısmı da, block ayarlarına aittir. Bu kodlar ile şu ayarlar oluşturulmuştur:
SiteCenneti-Gutenberg-Block-Tasarlama-Eklenti-Ekleme-Kodlama-Block-Ayarları-
SiteCenneti-Gutenberg-Block-Tasarlama-Eklenti-Ekleme-Kodlama-Block-Ayarları-
SiteCenneti-Gutenberg-Block-Tasarlama-Eklenti-Ekleme-Kodlama-6
Block Ayarları
  • Bloğun editör görünümü için biraz CSS yaptık:

assets/css/editor.css

.interface-complementary-area {
    width: auto !important;
    max-width: 280px !important;
    overflow-x: hidden !important;
}

.wp-block-stcnnt-deneme-blocks-hero-img-block .sc-hero-text-container
{
    z-index: 2;
    height: 35px;
    min-width: 100px;
    display: table;
    margin:0 auto;
}

.wp-block-stcnnt-deneme-blocks-hero-img-block .sc-hero-text-container p
{
    margin-top: 0 !important;
    margin-bottom: 0 !important;
}

label.sc-setting-section-label
{
    padding-bottom: 15px;
}

.sc-hero-img-placeholder
{
    width: 80%;
    position: relative;
    margin: 10px auto;
    background-color: rgb(226, 226, 226);
    height: 90px;
    display: flex;
    justify-content: center;
    align-items: center;
}

.css-1wgusda-Text-BaseLabel.css-1wgusda-Text-BaseLabel.css-1wgusda-Text-BaseLabel
{
    text-overflow: inherit !important;
}
  • Tema tarafı için de biraz CSS yapalım:

assets/css/style.css

.wp-block-stcnnt-deneme-blocks-hero-img-block
{
    position: relative;
    border: 9px solid rgba(0, 0, 0, .5);
    display: flex;
    justify-content: center;
    align-items: center;
    border-radius: 20px;
}
.wp-block-stcnnt-deneme-blocks-hero-img-block .sc-hero-img-overlay
{
    position:absolute;
    width: 100%;
    height: 100%;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
}
.wp-block-stcnnt-deneme-blocks-hero-img-block .sc-hero-text-container
{
    font-size: 4.5rem;
    padding: 15px;
    border-radius: 20px;
    z-index: 2;
    display: flex;
    justify-content: center;
    align-items: center;
}
.sc-text-bg {
    border: 3px solid rgba(156, 150, 150, 0.5);
    background-color: rgba(0, 0, 0, .5);
}

.sc-hero-text
{
    color: inherit !important;
    font-size: inherit !important;
    margin: 0 !important;
    padding: 0 !important;
}
.align-left
{
    text-align: left;
}
.align-right
{
    text-align: right;
}
.align-center
{
    text-align: center;
}

SC Hero Resmi Bloğu İle Örnek Tasarımlar

Yeteneklerini görmek için, oluşturduğumuz blockla neler yapabiliriz bir bakalım:

  • Overlay kullanmadan bir resim ve metin örneği:

SiteCenneti-Gutenberg-Block-Tasarlama-Eklenti-Ekleme-Kodlama-Örnek-Tasarım-1

  • Resmin üzerine overlay efekti verdik:

SiteCenneti-Gutenberg-Block-Tasarlama-Eklenti-Ekleme-Kodlama-Örnek-Tasarım-2

  • Resimsiz olarak, 100 şeffaflıkta bir overlay kullanarak, metin backgroundu olmayan tasarımlar da mümkün:

SiteCenneti-Gutenberg-Block-Tasarlama-Eklenti-Ekleme-Kodlama-Örnek-Tasarım-3

DERSİN SONU

Kimya Özel Dersi Al

Yorum yaparak bize destek olabilirsiniz.