BA Barış Akın~/blog

·3 dk okuma·47 okunma

zap Bileşenleri: Sinyallerle Çalışan Küçük Bir Arayüz Kiti

3.7 KB çekirdek, sıfır bağımlılık, 57 bileşen: zap'ın sinyallerle nasıl çalıştığına ve bileşenlerin nasıl kullanıldığına kısa bir bakış. Bileşenlerin hepsi canlı örnekleriyle deck.kartex.net adresinde.

zap Bileşenleri: Sinyallerle Çalışan Küçük Bir Arayüz Kiti

Bu blogun arayüzündeki küçük parçalar (dil seçici, kod görüntüleyici, arama paleti) zap ile yazıldı. zap, sinyallere dayanan, bağımlılığı olmayan küçük bir JavaScript arayüz kütüphanesi ve onunla birlikte gelen bir bileşen kiti. Bu yazıda bileşenleri tek tek anlatmayacağım; hepsi canlı örnekleri ve kodlarıyla deck.kartex.net adresinde yayında. Burada sadece teknolojinin nasıl çalıştığını ve nasıl kullanıldığını kısaca özetliyorum.

deck.kartex.net: bir geri bildirim kartı ve onu üreten kod

Kısaca zap

  • Çekirdek 3.7 KB (gzip). Sanal DOM yok, derleyici yok, build adımı zorunlu değil.
  • Sıfır bağımlılık. Tarayıcıda doğrudan ES modülü olarak çalışır.
  • 57 bileşen: formlar ve girişler, katmanlar ve geri bildirim, gezinme, görüntüleme, veri tabloları, grafikler, medya.
  • SSR ve hydrate: aynı bileşenler sunucuda HTML'e çevrilir, tarayıcıda canlanır. deck sitesinin 65 sayfası bu şekilde önceden üretiliyor.
  • Temalar: CSS değişkenleriyle (--zap-*) Default, Emerald, Violet, Rosé ve macOS Aqua temaları, hepsinin karanlık modu.
  • Erişilebilirlik: roller, aria nitelikleri, odak yönetimi ve klavye kullanımı her bileşende var; prefers-reduced-motion dikkate alınıyor.

Sinyaller

zap'ın kalbi sinyal. Bir sinyal değer tutan bir fonksiyondur; okuyan her yer ona abone olur, değer değişince sadece o yerler güncellenir. Bileşenin tamamı yeniden çizilmez.

import { signal, computed, effect } from "@barisakin/zap";

const count = signal(0);
const double = computed(() => count() * 2);

effect(() => console.log("sayı", count(), "iki katı", double()));

count.set(1);              // effect yeniden çalışır
count.update(n => n + 1);  // 2

untrack bir okumayı abonelik dışında tutar, onCleanup bir effect yeniden çalışmadan ya da bileşen kaldırılmadan önce temizlik yapar. store ise iç içe nesneler için alan bazında reaktiflik verir.

html şablonları

Görünüm, JavaScript'in kendi etiketli şablon dizgileriyle yazılır. Şablona fonksiyon olarak verilen her şey (bir sinyal ya da () => ...) canlıdır; sadece o metin düğümü ya da nitelik güncellenir.

import { signal, html, mount } from "@barisakin/zap";

function Counter() {
  const n = signal(0);
  return html`
    <button onclick=${() => n.update(x => x + 1)}>
      ${n} kez tıklandı
    </button>
  `;
}

mount(Counter, document.getElementById("app"));

Koşullu ve tekrarlı içerik için when ve each var; bind=${sinyal} ise bir input ile sinyali iki yönlü bağlar. Bileşen dediğimiz şey de sadece (props) => Node biçiminde bir fonksiyon; sınıf, yaşam döngüsü metodu ya da özel dosya biçimi yok.

Bileşenleri kullanmak

Her bileşen kendi modülünde durur, sadece kullandığınız kadarı yüklenir. Prop'lar düz değer de olabilir sinyal de; sinyal verirseniz bileşen onu hem okur hem yazar.

import { signal, html } from "@barisakin/zap";
import { Card } from "@barisakin/zap/components/card.js";
import { Rating } from "@barisakin/zap/components/rating.js";
import { Button } from "@barisakin/zap/components/button.js";
import { toast } from "@barisakin/zap/components/toast.js";

const stars = signal(0);

Card({
  title: "Siparişin nasıldı?",
  children: html`${Rating({ value: stars })}`,
  footer: Button({
    label: "Gönder",
    disabled: () => stars() === 0,
    onClick: () => toast.success("Teşekkürler!"),
  }),
});

Açılır pencere de aynı mantıkla çalışır: open bir sinyaldir, onu true yapınca pencere açılır, kapatınca sinyal false olur.

import { Modal } from "@barisakin/zap/components/modal.js";

const open = signal(false);
Modal({ open, title: "Silinsin mi?", children: "Bu işlem geri alınamaz." });
open.set(true);

Açılır menüler, tooltip'ler, popover'lar ve modallar ortak iki katmanı (floating.js ve overlay.js) paylaşır; konumlandırma, odak tuzağı, Escape ile kapanma ve kaydırma kilidi tek yerde çözülür.

Kanban: sürükle bırak ve klavyeyle taşıma

Veri ve grafikler

Büyük tarafta veri tablosu (sanal kaydırma, sıralama, filtre, gruplama, düzenleme), zamanlayıcı, kanban, ağaç ve grafikler var. Grafiğe verilen veri bir sinyal olabilir; değiştirdiğiniz anda grafik animasyonla yeni değere geçer.

import { ColumnChart } from "@barisakin/zap/components/chart.js";

const data = signal([12, 19, 7, 24]);
ColumnChart({ labels: ["Q1", "Q2", "Q3", "Q4"], series: [{ name: "Satış", data }] });

Grafikler: çizgi, alan ve sütun

Router, i18n ve SSR

  • Router: sayfa yenilemeden gezinmeyi sağlayan küçük bir yönlendirici (Router, Link, navigate).
  • i18n: t() ile çeviri, setLocale() ile dil değişimi; bileşenlerin kendi metinleri Türkçe, İngilizce, Almanca, Fransızca, İspanyolca ve Karadağca hazır.
  • SSR: @barisakin/zap/ssr içindeki renderToString aynı bileşeni sunucuda HTML'e çevirir; tarayıcıda hydrate mevcut DOM'u yeniden kullanarak olayları bağlar.
  • TypeScript: tip tanımları (index.d.ts) paketle birlikte gelir.

Kurulum

npm ile:

npm install @barisakin/zap

ya da hiçbir araç kullanmadan CDN'den:

<link rel="stylesheet" href="https://zapjs.baltavista.com/theme.css">
<script type="module">
  import { signal, html, mount } from "https://zapjs.baltavista.com/zap.min.js";
</script>

Hepsini görmek için

Bileşenlerin tamamı, her birinin canlı örneği, kopyalanabilir kodu, tema ve karanlık mod geçişiyle birlikte deck.kartex.net adresinde. Bir bileşeni nasıl kullanacağınızı merak ediyorsanız en hızlı yol oraya bakmak: sol menüden bileşeni seçin, örneği deneyin, kodu kopyalayın.

BA
Barış Akın

25 yılı aşkın deneyime sahip yazılım çözümleri mimarı. FinTech ve dağıtık sistemler; OxiDB, Rill ve Cobra'nın geliştiricisi.