BU DERSİN BAŞLIKLARI
Kodlayarak bir Gutenberg Block Editörü bloğu oluşturmayı merak ediyorsan hoş geldin. Bu derste, uygulamalı olarak bir block nasıl kodlanırı anlatıyorum. Keyifli okumalar.
Sonuç olarak elde edeceğimiz bloğun tema görünümü şöyle olacak:
Oluşturacağımız bloğun; Resim Ayarları ve Renkler olmak üzere iki adet ayar paneli olacak olacak:
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
vejs
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.
- Tema tarafı için:
assets/css
klasöründe;- Tema tarafı için:
style.css
- Admin tarafı için:
editor.css
dosyaları olsun.
- Tema tarafı için:
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:
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:
- 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.
- Yani işimiz bitince, eklenti klasörü içinde, bize lazım olacak dosya ve klasörler sadece şu 3 tanesidir.
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 vebuild
klasöründe paketler.- Bu işlem;
npm run start
komutu ilk defa çalıştırıldığındanpm run start
komutu çalıyor iken, dosyaların her kaydedilişinde (Ctrl + s
) gerçekleşir.
- Bu işlem;
build
klasörünü silip, tekrarnpm 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:
- Aşağıdaki komutu girerek, scriptin yüklenmesini bekleyelim:
npm install @wordpress/i18n --save
- Aşağıdaki komutu girerek, scriptin yüklenmesini bekleyelim:
npm install @wordpress/element --save
- Aşağıdaki komutu girerek, scriptin yüklenmesini bekleyelim:
npm install @wordpress/block-editor --save
- 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:
- hero-img-block:
- google-ads-block
- hero-img-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:
- 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'
- Örnek-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' )
- Örnek:
description
: (string) Bloğun tanımıdır. Zorunlu değildir.- Örnek:
description: __( 'Block showing a Book card.' );
- Örnek:
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
- Örnek:
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.)
- Örnek-1:
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',},
},
- Örnek:
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.- Örnek:
example: {
attributes: {
cover: 'https://example.com/image.jpg',
author: 'William Shakespeare',
pages: 500
},
},
- Örnek:
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.
- Fonksiyonun bir tane parametresi vardır ve genellikle
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.
- Fonksiyonun bir tane parametresi vardır ve genellikle
- Parametre: Block Kimliği
Hazırlıklar Bitti, Artık Bloğu Kodlayalı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.
block.js
deki kodların bir kısmı da, block ayarlarına aittir. Bu kodlar ile şu ayarlar oluşturulmuştur:
- 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:
- Resmin üzerine overlay efekti verdik:
- Resimsiz olarak, 100 şeffaflıkta bir overlay kullanarak, metin backgroundu olmayan tasarımlar da mümkün: