@appaflytech/zeyrek-ai-mcp 0.0.2 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/.env.example +21 -7
  2. package/.env.production.example +42 -0
  3. package/README.md +14 -7
  4. package/dist/config.js +113 -46
  5. package/dist/knowledge/componentCatalog.js +476 -32
  6. package/dist/knowledge/componentEvents.js +154 -12
  7. package/dist/knowledge/errorPath.js +64 -0
  8. package/dist/knowledge/normalize.js +12 -1
  9. package/dist/knowledge/outlines.js +9 -2
  10. package/dist/knowledge/rules.js +184 -3
  11. package/dist/knowledge/styleResolve.js +485 -0
  12. package/dist/observability/trace.js +4 -0
  13. package/dist/platform/http.js +3 -0
  14. package/dist/platform/responses.js +80 -4
  15. package/dist/platform/screenshot.js +106 -0
  16. package/dist/resources/examples/layout-app-shell.json +368 -0
  17. package/dist/resources/examples/microservice-table-list.json +1 -0
  18. package/dist/resources/examples/middleware-authenticate.json +243 -47
  19. package/dist/resources/examples/workflow-basic.json +24 -2
  20. package/dist/resources/guides/component.md +6 -3
  21. package/dist/resources/guides/entity.md +33 -1
  22. package/dist/resources/guides/external-component.md +129 -0
  23. package/dist/resources/guides/layout.md +147 -0
  24. package/dist/resources/guides/microservice.md +35 -0
  25. package/dist/resources/guides/middleware.md +10 -0
  26. package/dist/resources/guides/page.md +137 -15
  27. package/dist/resources/guides/translation.md +80 -0
  28. package/dist/resources/guides/workflow.md +127 -2
  29. package/dist/server.js +4 -0
  30. package/dist/tools/externalComponents.js +285 -0
  31. package/dist/tools/layouts.js +48 -6
  32. package/dist/tools/microservices.js +2 -2
  33. package/dist/tools/pages.js +98 -30
  34. package/dist/tools/platformInfo.js +2 -2
  35. package/dist/tools/projects.js +7 -2
  36. package/dist/tools/screens.js +36 -0
  37. package/dist/tools/translations.js +37 -0
  38. package/dist/tools/workflows.js +3 -3
  39. package/package.json +4 -1
@@ -0,0 +1,129 @@
1
+ # Kendi komponentinizi yazmak
2
+
3
+ Hazır katalog (`component_list`) ihtiyacınızı karşılamıyorsa üç seçeneğiniz var,
4
+ bu sırayla deneyin:
5
+
6
+ 1. **Hazır komponenti zorlayın.** `component_get` ile prop'lara bakın; çoğu
7
+ "yok" sanılan davranış bir prop ya da event kombinasyonuyla çıkar.
8
+ 2. **`html` kaçış kapısı.** Tek seferlik bir görsel için yeterli — bkz.
9
+ `platform_guide('html')`. Kalıcı, tekrar kullanılacak bir şey değilse burada
10
+ durun.
11
+ 3. **Kendi komponentinizi yayınlayın.** Aynı ihtiyaç birden fazla sayfada
12
+ tekrarlanıyorsa, prop/event sözleşmesi gerekiyorsa ya da `html` içinde
13
+ yönetilemeyecek kadar davranış varsa doğru yol budur. Bu rehberin konusu.
14
+
15
+ Yayınlanan komponent platformun kendi komponentlerinden ayırt edilmez:
16
+ sayfaya sürüklenir, prop'ları property panelinde düzenlenir, event'leri flow'a
17
+ bağlanır, tema değişkenlerini alır. Studio toolbox'ında **"Your Components"**
18
+ başlığı altında listelenir.
19
+
20
+ ## Akış
21
+
22
+ ```
23
+ external_component_scaffold → yerel iskelet (element.mjs + manifest.json)
24
+ ↓ (element.mjs'i yazın, manifest'i gerçek prop/event'lerinize göre düzenleyin)
25
+ external_component_publish → kayıt + paket yüklenir, doğrulama raporu döner
26
+ ↓ (rapor block içeriyorsa düzeltip tekrar publish — depolamaya yazılmadı)
27
+ ↓ taslak: Studio önizlemesinde görünür, yayınlanmış uygulamada görünmez
28
+ external_component_activate → yayına alır (yalnız metadata; kesinti yok)
29
+ ↓
30
+ page_schema_patch → add_component ile sayfaya koyun
31
+ ```
32
+
33
+ Aktivasyondan sonra komponent `component_list` / `component_get` çıktısında
34
+ normal katalog kaydı gibi döner; `add_component` micro-op'unda `type` olarak
35
+ slug'ı kullanın.
36
+
37
+ ## Sözleşme
38
+
39
+ Host element'e şema prop'larını **JS property** olarak yazar — attribute değil,
40
+ böylece dizi ve nesneler bozulmadan geçer. Yanına iki kanal koyar:
41
+
42
+ | Property | İçerik |
43
+ |---|---|
44
+ | şemadaki her prop | çözülmüş değer; yalnız değişen key'ler yeniden yazılır |
45
+ | `zxContext` | `{ elementId, appearance, states, isRequired, editorMode, language }` |
46
+ | `zxMachine` | platform yüzeyi (aşağıda) |
47
+
48
+ Element geriye **tek bir DOM olayıyla** konuşur: `zx-emit`, detail'i
49
+ `{ name, data?, setter?, flowId?, params? }`.
50
+
51
+ - `name` manifest'te bildirdiğiniz event adı olmalı; bildirilmemiş bir ad
52
+ flow'a bağlanamaz.
53
+ - `setter: true` verirseniz `data` içindeki değer aynı adlı prop'a geri yazılır —
54
+ `value` gibi iki yönlü davranan proplar için budur.
55
+
56
+ `zxMachine` sayılı bir yüzeydir; burada olmayan hiçbir şeye erişemezsiniz:
57
+ `getProps`, `getComponents`, `getComponentProps`, `getState`/`setState`,
58
+ `getVariable`/`setVariable`, `getStorage`/`setStorage`,
59
+ `getLanguage`/`setLanguage`, `t`, `checkAuthorization`, `user`, `pageParams`,
60
+ `emit`, `on`.
61
+
62
+ ## Yasaklar — yayınlamayı reddeder
63
+
64
+ Paket sunucuda AST taramasından geçer. Şunlardan biri varsa paket **depolamaya
65
+ hiç yazılmaz**:
66
+
67
+ `eval`, `new Function` / `Function(...)`, dinamik `import()`,
68
+ `document.cookie`, `window.machine`, `navigator.serviceWorker.register`,
69
+ `document.write`, `localStorage.clear()` / `sessionStorage.clear()`.
70
+
71
+ Tarama AST üzerinde çalışır: bir string sabitinin içindeki `eval` kelimesi bulgu
72
+ değildir, `eval(...)` çağrısı bulgudur.
73
+
74
+ ## Uyarılar — rapora yazılır, aktivasyonda onay ister
75
+
76
+ Dış ağ erişimi (`fetch`, `XMLHttpRequest`, `WebSocket`, `EventSource`),
77
+ doğrudan `localStorage`/`sessionStorage` erişimi, `window.X = ...` ataması,
78
+ `innerHTML`/`outerHTML` ataması, ve manifest'te bildirip element'te
79
+ karşılığını yazmadığınız proplar.
80
+
81
+ Uyarısı olan bir sürüm `acknowledgeWarnings: true` olmadan aktive edilemez.
82
+ Uyarıyı gördüğünüzde önce gerçekten gerekli mi diye bakın: veriyi flow ile
83
+ almak `fetch`'ten, `zxMachine.setStorage` doğrudan storage'dan iyidir.
84
+
85
+ ## Kurallar
86
+
87
+ - Slug `x-` ile başlamak zorunda (`^x-[a-z][a-z0-9-]*$`). Bu önek platform
88
+ slug'larıyla çakışmayı imkânsız kılar.
89
+ - Tek `export default`, `HTMLElement` türeten bir sınıf.
90
+ - Prop adları DOM'u bozacak adlar olamaz: `id`, `class`, `className`, `style`,
91
+ `slot`, `name`, `children`, `innerHTML`, `outerHTML`, `textContent`, `zx*`,
92
+ `on*`.
93
+ - `manifest.definition.blocks` boş olamaz — ızgara ayak izi olmayan komponent
94
+ ölçeklenemez.
95
+ - Prop tipleri platformun tanıdığı kümeden olmalı (`text`, `long-text`,
96
+ `number`, `switch`, `dropdown`, `array`, `object`, `flow`, `icon`, `color`,
97
+ `date`, …). Yeni bir prop tipi uyduramazsınız.
98
+ - Paket 2 MB'ı geçemez.
99
+ - Renk, boşluk, tipografi için `--ng-*` tema değişkenlerini kullanın; sabit renk
100
+ yazarsanız komponent kullanıcının temasına uymaz.
101
+
102
+ ## Sürümler ve geri alma
103
+
104
+ Paketler değişmezdir: aynı `(slug, version)` ikinci kez yayınlanamaz, düzeltme
105
+ yeni bir sürüm demektir. `external_component_versions` geçmişi ve her sürümün
106
+ doğrulama raporunu verir; `external_component_activate` ile eski bir sürümü
107
+ aktive etmek geri alma olarak çalışır. Aktivasyon yalnız metadata değiştirir —
108
+ platform yeniden başlamaz, açık oturumlar bozulmaz.
109
+
110
+ ## Editor modu
111
+
112
+ `zxContext.editorMode` true olduğunda element Studio kanvasında statik bir
113
+ önizleme olarak duruyor: zamanlayıcı kurmayın, ağ çağrısı yapmayın, tıklamayı
114
+ işlemeyin. Kanvasta etkileşim host tarafından zaten engellenir, ama gereksiz iş
115
+ yapmamak kanvası hızlı tutar.
116
+
117
+ ## Geliştirici kiti
118
+
119
+ Platform, npm paketi olmadan servis eder:
120
+
121
+ - `{studio}/component-kit/zeyrek-component.d.ts` — protokolün tip bildirimleri
122
+ - `{studio}/component-kit/harness.html` — platformsuz deneme sayfası
123
+ - `{studio}/component-kit/example-rating-stars.mjs` — çalışan örnek
124
+ - `GET {tenant}/{project}/components/external/manifest-schema` — manifest için
125
+ JSON Schema; izin verilen prop tipleri ve rezerve adlar sunucudaki kural
126
+ setinden **üretilir**, statik bir kopya olmadığı için sapmaz.
127
+
128
+ `external_component_scaffold` bu sözleşmeye uyan bir iskeleti yerel dizine
129
+ zaten yazar; kit, iskeleti elle düzenlerken referans olarak işinize yarar.
@@ -0,0 +1,147 @@
1
+ # Layout Rehberi (yerleşim kabuğu)
2
+
3
+ Sayfaların paylaştığı kabuk: yan menü, üst şerit, kullanıcı menüsü ve sayfa içeriğinin
4
+ gireceği delik. Şema gövdesi ve koordinat modeli için `platform_guide('page')` (Kural 1,
5
+ 1d, 1f); komponent sözleşmeleri için `platform_guide('component')`.
6
+
7
+ ## Karar kuralları
8
+
9
+ **1. Layout, tek `slot` içeren SIRADAN bir komponent ağacıdır.** Ayrı bir dil yoktur:
10
+ sayfada kullandığın her kap, her prop, her `appearance` alanı burada da geçerlidir. Araç
11
+ kutusu layout modülünde süzülmez — tüm katalog kullanılabilir.
12
+
13
+ **2. Şema alanının adı `schema` değil `views`.** (LAY-001)
14
+
15
+ **3. Micro-op hattı YOKTUR.** `page_schema_patch`'in layout karşılığı yok (backend'de
16
+ `PATCH /layouts/.../schema` ucu yok). Değişiklik `layout_update` ile yazılır; gateway kaydı
17
+ önce okur ve yalnız verdiğin alanları değiştirir, `views` göndermezsen ağaç korunur.
18
+ Okumak için `layout_schema_get` (summary kipi hedef bulmak için yeterlidir).
19
+
20
+ **4. TEK slot.** Sayfa şeması **her** slot'a ayrı ayrı kopyalanır — iki slot, sayfayı iki
21
+ kez çizer ve `elementId`'leri tekrarlar. (LAY-002 / LAY-006)
22
+
23
+ **5. Kabuğu `container` + `slot` ile kur.** `layout` monoliti (sabit logo/menü/kullanıcı
24
+ bandı — yalnız doldurulur) ve `layout-shell` + `layout-region` ikilisi **emekliye
25
+ ayrıldı**; kayıtlı kalırlar ve mevcut layout'lar çalışır, ama yeni kabuk `container` ile
26
+ kurulur. Sebebi: `container` zaten `layout-region`'ın yaptığının üstünü yapıyor (flex/ızgara
27
+ düzeni, hizalama, gap, wrap), region'ın kattığı tek şey `dock` sözlüğüydü.
28
+
29
+ **5a. Kök, sayfanın `page_container`'ının yerleşim ikizidir.** Studio'nun yeni layout
30
+ iskeleti (`getDefaultLayout`) tam olarak şunu kurar ve sen de aynısını yazmalısın:
31
+ `states.isWrapper: true` (çerçevesiz, başlıksız, saydam) + `appearance.heightType: 'fill'`
32
+ + `blocks` x0/w12. Sarmalayıcı olmayan bir kök, kenarlıklı beyaz bir kart olarak çizilir.
33
+
34
+ **5b. Tam ekran kabuk `heightType: 'fill'` ile kurulur (2026-08-28).** Yükseklik ne
35
+ içerikten (`auto`) ne satır sayısından (`fixed`) gelir — ebeveynin bıraktığı yerden gelir:
36
+ ızgara çocuğunda `height:100%`, flex sütununda `flex:1 1 auto`, flex satırında
37
+ `align-self:stretch`. **Kök** düğümde ekranı doldurur (100vh). Yan menünün tam boy olması
38
+ ve slot'un artan alanı kaplaması bununla ifade edilir; `fixed` + tahmini `size.h` ile
39
+ yapılan eski numaraya artık gerek yok.
40
+
41
+ **6. Konum `blocks[]`'ten gelir, prop'tan değil.** `layout-region`'daki `dock` bölgenin
42
+ NEREDE durduğunu değil, BİÇİMİNİ söyler (dikey kolon / yatay şerit / dolgu yüzeyi). Hem
43
+ runtime hem Studio tuvali bölgeleri 12 kolonluk ızgarayla yerleştirir.
44
+
45
+ **7. Mobilde flex YIĞILMAZ.** Runtime'ın mobil kuralı yalnız ızgara özelliklerini ezer.
46
+ Telefonda alt alta düşmesi gereken satırı `layout:'grid'` ile kur; `layout:'flex'` +
47
+ `direction:'row'` telefonda da yan yana kalır (375px'te ölçüldü: ızgara çocukları 375/375px
48
+ alt alta, flex çocukları 49/310px yan yana).
49
+
50
+ **8. Doğrulama tek yerden:** `page_runtime_get`. Layout'un kendi serve URL'i yoktur —
51
+ gerçek çıktıyı, layout'a bağlı bir sayfanın runtime paketinde görürsün (slot yerleşimi
52
+ dahil). Slot kurgusu için ayrıca `page_state` → `layoutSlots`.
53
+
54
+ ## Mini tarif — uygulama kabuğu
55
+
56
+ Yan menü + üst şerit + içerik. Studio'nun `getDefaultLayout` iskeletiyle birebir aynı ağaç;
57
+ `layout_create`'in `views` alanına doğrudan verilebilir (`resource: layout-app-shell`).
58
+
59
+ ```
60
+ container isWrapper:true heightType:'fill' layout:'flex' direction:'row' gap:'none'
61
+ │ verticalAlign:'stretch' block w12 x0
62
+ ├ container heightType:'fill' layout:'flex' direction:'column' block w2 ← yan menü
63
+ │ └ navigations block w12
64
+ └ container heightType:'fill' layout:'flex' direction:'column' block w10 x2
65
+ ├ container layout:'flex' direction:'row' states.isSticky block w12 h6
66
+ │ └ breadcrumb block w12 h3
67
+ └ slot heightType:'fill' block w12 y6
68
+ ```
69
+
70
+ - **Genişlik kolon payıdır:** yan menü `w:2` = 12'de 2 → 1440px tasarım genişliğinde 240px.
71
+ Sabit piksel istiyorsan `appearance.widthPx: 240` (yalnız flex çocuğunda okunur; ızgara
72
+ kabında okunmaz).
73
+ - **Yükseklik `fill`'dir**, `size.h` değil: kök ekranı doldurur, yan menü ve içerik sütunu
74
+ kökün bıraktığını, slot da üst şeritten artanı alır. Slot'un grid satırı ayrıca açık
75
+ uçludur (`y / auto`), yani sayfa uzadıkça slot uzar.
76
+ - **Kaydırma:** `fill` + `states.isScrollable:true` verilen düğüm büyümek yerine İÇİNDE
77
+ kaydırır — uzun içerikte kabuğu sabit tutmanın yolu budur.
78
+ - **MOBİL UYARISI:** bu ağaç `flex` olduğu için telefonda YIĞILMAZ (Kural 7) — 375px'te yan
79
+ menü ince bir şerite iner. Telefonda alt alta düşmesi gereken bir kabuk için kökü
80
+ `layout:'grid'` kur; o zaman `fill`'in flex anlamı (`flex:1 1 auto`) devreye girmez,
81
+ yükseklik yine `blocks` satırlarından gelir. İkisini aynı anda veren bir yol bugün yok.
82
+ - Menü satırlarını biçimlendirme: **bugün mümkün değil.** `navigations`'ın `style` prop'u
83
+ ölüdür (bkz. `component_get('navigations')`).
84
+
85
+ ## Mini tarif — menüde aktif satır
86
+
87
+ `navigations.activeHref` boş bırakılırsa menü tarayıcıdaki adrese uyan satırı kendi bulur;
88
+ hiç ayar gerekmez. Elle sürmek istersen satırın `href`'iyle aynı biçimde yaz (ham metin,
89
+ bağlantı nesnesi ya da tam yol).
90
+
91
+ ## Kötü / iyi
92
+
93
+ ```jsonc
94
+ // KÖTÜ — iki slot: sayfa iki kez çizilir, elementId'ler çakışır
95
+ { "views": [{ "type": "container", "children": [
96
+ { "type": "slot" }, { "type": "slot" }
97
+ ]}]}
98
+
99
+ // KÖTÜ — sarmalayıcı olmayan, sabit yükseklikli kök: ekranı doldurmaz,
100
+ // kenarlıklı beyaz bir kart olarak çizilir ve yüksekliği tahmini h'den gelir
101
+ { "type": "container", "states": { "isDroppable": true },
102
+ "appearance": { "heightType": "fixed" },
103
+ "blocks": [{ "breakpoint": 1024, "size": { "w": 7, "h": 83 }, "position": { "x": 2, "y": 0 } }] }
104
+
105
+ // İYİ — sarmalayıcı, tam genişlikte, ekranı dolduran kök (Kural 5a/5b)
106
+ { "type": "container",
107
+ "states": { "isDroppable": true, "isWrapper": true },
108
+ "appearance": { "heightType": "fill", "marginType": "none", "paddingType": "none" },
109
+ "props": { "layout": { "type": "static", "data": "flex" },
110
+ "direction": { "type": "static", "data": "row" } },
111
+ "blocks": [{ "breakpoint": 1024, "size": { "w": 12, "h": 80 }, "position": { "x": 0, "y": 0 } }] }
112
+
113
+ // KÖTÜ — telefonda 49px'lik yan menü: row flex mobilde yığılmaz (Kural 7)
114
+ // Mobilde alt alta düşmesi gerekiyorsa kökü layout:'grid' kur — bedeli, fill'in
115
+ // flex anlamının devreye girmemesi.
116
+ ```
117
+
118
+ ## Sayfayı layout'a bağlama
119
+
120
+ `page_update` ile `layoutId`. Bağlı sayfanın kendi şeması slot'un içine girer; sayfanın
121
+ kök `page_container`'ı korunur.
122
+
123
+ ## Bilinen boşluklar (2026-08-28)
124
+
125
+ Bunlar **motorun** eksikleri, senin hatan değil — bir tasarımı karşılayamıyorsan sebebi
126
+ bunlardan biri olabilir:
127
+
128
+ | Eksik | Sonuç |
129
+ |---|---|
130
+ | ~~`heightType` yalnız `auto` \| `fixed`~~ | **28 Ağustos'ta kapandı:** üçüncü değer `fill` (Kural 5b) |
131
+ | ~~Kök kap viewport'a kilitlenmez~~ | **28 Ağustos'ta kapandı:** `fill` verilmiş kök 100vh (Kural 5b) |
132
+ | Flex mobilde yığılmaz | Kural 7 — kabuk bugün bir MASAÜSTÜ kabuğudur |
133
+ | Kırılıma duyarlı prop yok | `direction`/`gap` masaüstü ve mobilde AYNI; yalnız `blocks` ve `appearance.hideOn` kırılım bilir |
134
+ | Mobil çekmece (overlay) yok | Telefonda içeriğin üstüne binen panel kurulamaz |
135
+
136
+ ---
137
+
138
+ **Kaynaklar** — `zeyrek-frontend`: `apps/studio/src/features/layout/layout.functions.ts`
139
+ (`injectPageSchemaIntoSlots`, `getResolvedLayoutViews`), `apps/studio/src/features/page/api/page.mappers.ts`
140
+ (`mapPageLayoutToPreview`), `packages/ng-apps-ui/src/shared/render/render.functions.ts`
141
+ (`resolveNodeBoxStyle` — slot'un `y / auto` satırı, flex çocuk genişliği),
142
+ `packages/ng-apps-ui/src/shared/render/RenderComponent.svelte` (mobil media kuralı),
143
+ `packages/ng-apps-screen-builder/src/flex-layout.ts` (`getFlexChildStyle` — `widthPx` ve
144
+ `heightType:'fill'` dalı; tuval ve runtime aynı fonksiyonu okur),
145
+ `apps/studio/src/features/layout/layout.functions.ts` (`getDefaultLayout` — Kural 5a/5b'deki iskelet),
146
+ `docs/components/layout-composition.md`, `docs/specs/2026-08-28-free-layout-responsive-design.md`,
147
+ `docs/issues.md` ARC-031 / BE-002 / CQ-143.
@@ -1,5 +1,38 @@
1
1
  # Microservice Rehberi
2
2
 
3
+ ## Ucun NE İŞE YARADIĞI yazılır (MS-014, block)
4
+
5
+ Servis listesinde `name` ve `slug` var, "bu uç ne işe yarar" yok. Her microservice bir
6
+ `description` taşır; gateway açıklamasız gövdeyi platforma göndermez.
7
+
8
+ ```jsonc
9
+ { "name": "anket-kaydet", "slug": "anket-kaydet", "source": "workflow",
10
+ "description": "Anket başlığı ve sorularını tek çağrıda kaydeder; oluşan anketin id'sini döner." }
11
+ ```
12
+
13
+ **Çağıranın ne elde ettiğini yaz**, kaynağın şeklini değil: `"workflow kaynaklı POST ucu"`
14
+ gövdeden zaten okunuyor. Alan kalıcıdır, çalışma zamanını etkilemez, Studio'da servis formunda
15
+ görünür ve elle düzeltilebilir. Adım düzeyindeki karşılığı `platform_guide('workflow')` §WF-024.
16
+
17
+ ## Tuzağı varsa `caution` yaz (opsiyonel, kural yok)
18
+
19
+ `description` ucun ne işe yaradığını söyler; `caution` **çağıranın bilmezse yanılacağı şeyi**
20
+ söyler. Hiçbir kural zorlamaz — ucun gerçek bir tuzağı yoksa alanı hiç yazma.
21
+
22
+ - **Anonim uç** — "bu uç auth istemiyor; kimlik kapsaması yalnız bağlı middleware'de yapılır"
23
+ - **Sayfalama yok** — "limit uygulanmaz, tablo büyüdükçe yanıt büyür"
24
+ - **Atomik değil** — "çok adımlı yazım middleware'siz atomik değil; yarıda kalırsa kısmi yazar"
25
+ - **Sessiz boş dönüş** — "filtre eşleşmezse 404 değil boş dizi döner"
26
+
27
+ ```jsonc
28
+ { "name": "urun-listesi", "httpMethod": "Get",
29
+ "description": "Aktif ürünleri ada göre sıralı döner.",
30
+ "caution": "Sayfalama yok; katalog büyüdükçe yanıt boyutu doğrusal büyür." }
31
+ ```
32
+
33
+ Doldurma metin yazma: `"bu uç veri döner, dikkat"` hiçbir şey eklemez. Alan inerttir, Studio'da
34
+ servis formunda görünür ve `microservice_get` outline görünümünde geri okunur.
35
+
3
36
  ## Karar kuralları
4
37
 
5
38
  1. **Kaynak seçimi sırası: `table` → `view` → `workflow` → `query`.**
@@ -297,6 +330,8 @@ kabul etti. Ayrıntı ve doğru rol kapısı tarifi: `platform_guide('middleware
297
330
 
298
331
  ## Sık hatalar
299
332
 
333
+ - `description` boş (MS-014, block — uç listesinde ne işe yaradığı okunamaz)
334
+
300
335
  - `selectFields: []` + join → tüm alanlar + katlanmış maliyet (MS-001, block)
301
336
  - `operation: 'list'` → geçersiz; `get` + `isSingle: false` kullanın (PLT-006)
302
337
  - Üst seviye `entityId` eksik (MS-004, warn)
@@ -13,6 +13,12 @@ kavramı olmayan bir üründe auth middleware'i, ayar tablosu olmayan bir ürün
13
13
  kur** — giriş sayfası + korunacak her uç ve her sayfa `middlewareIds`'e bağlı. Kısmi koruma,
14
14
  sistemi güvenli gösterip açık bırakır.
15
15
 
16
+ ## Açıklama zorunlu
17
+
18
+ Middleware de bir workflow'dur: her adımı ve middleware'in kendisi `description` taşımak
19
+ zorundadır (**WF-024**, block). Guard'larda bu özellikle önemli — "neden reddediyor" sorusunun
20
+ cevabı adımın ifadesinde gizlidir. Ayrıntı ve yazım ölçütü: `platform_guide('workflow')` §WF-024.
21
+
16
22
  ## Çalışma modeli — bunları bilmeden middleware yazma
17
23
 
18
24
  1. **Sıra ada bağlıdır.** Bağlı middleware'ler **ada göre alfabetik** koşar — uç yolunda
@@ -54,6 +60,10 @@ sistemi güvenli gösterip açık bırakır.
54
60
  6. Middleware transaction içinde koşar: hedef başarısız olursa middleware'in yazdıkları da
55
61
  geri alınır (microservice yolu).
56
62
 
63
+ > Gateway middleware tanımına da hata yolunu otomatik ekler (start adımına `global-error` dalı +
64
+ > 500 dönen `gatewayOnError` response adımı). Guard middleware'i patladığında ham exception
65
+ > yerine denetimli bir gövde döner. Ayrıntı: `platform_guide('workflow')` → "Hata yolu".
66
+
57
67
  ## Yalnız middleware'de geçerli step'ler
58
68
 
59
69
  | Step | Ne yapar | Kritik alanlar |
@@ -74,6 +74,10 @@ mümkündür ama doğrulama duvarı ve canlı canvas yalnız `page_schema_patch`
74
74
  `Data = RedirectPage.Slug`). Sabit `'/hastalar'` yazarsan sayfa slug'ı değişince bağlantı
75
75
  sessizce kırılır; `pageId` referansı değişiklikten etkilenmez. Aynısı `flow` prop'u için
76
76
  `type: 'flow'` + `ref: <flowId>`, dosya için `type: 'file'` + `ref: <fileId>`.
77
+ - **Çoklu dilli metin için `type: 'translation'` + `ref: <çeviri anahtarı>`.** Runtime `data`'yı
78
+ her turda çözümlenmiş metinle EZER — anahtar yalnız `ref`'te yaşar, `data`'ya yazıp
79
+ güvenme (`code` prop'uyla aynı davranış). Tam şekil, fallback zinciri ve `translation_*`
80
+ tool'ları için `platform_guide('translation')`.
77
81
  - **`blocks[].size`, komponentin `component_get`'teki `maxSize`'ını aşamaz.** Dikkat: katalog
78
82
  varsayılanı aşabiliyor (`page-header` default `h:8`, `maxSize` `h:4`) — varsayılanı körü körüne
79
83
  kopyalama, doğrulayıcı `"Height of 'page-header' must be between 1 and 4."` ile reddeder.
@@ -151,10 +155,13 @@ olaylarında **boştur** (ölçüm 2026-08-25, kaynak okuması: `flow-machine.ts
151
155
 
152
156
  Pratik kural: **`payload` anahtarları aynı zamanda prop adlarıdır; akışta `self.<anahtar>` ile
153
157
  oku** (ya da `value { type:'property', ref:{ source:'component', element, property } }` ile).
154
- `event.data` yalnız `params` ile gelen olaylarda dolar — pratikte `html` komponentinin
155
- `fireEvent` aksiyonları (`platform_guide('html')`). Sessiz hata örneği: sayfalama akışını
156
- `event.data.limit`'e bağlarsan sorgu `LIMIT null OFFSET null` ile koşar ve **tüm satırları**
157
- döndürür; hata yok, sayfalama yok.
158
+ `event.data` yalnız `params` ile gelen olaylarda dolar — `html` komponentinin `fireEvent`
159
+ aksiyonları (`platform_guide('html')`) ve **2026-08-27 kuşağı komponentler** (`eventcalendar` ·
160
+ `importwizard` · `kanban` · `signature` · `stepper`): bu kuşak `params`'ı da gönderir, yani
161
+ yükleri `event.data.<anahtar>` ile okunur; `kanban` ve `eventcalendar` yükü `self`'e HİÇ
162
+ yazmaz (`component_get` çıktısındaki sözleşme notları ayrımı söyler). Sessiz hata örneği:
163
+ sayfalama akışını `event.data.limit`'e bağlarsan sorgu `LIMIT null OFFSET null` ile koşar ve
164
+ **tüm satırları** döndürür; hata yok, sayfalama yok.
158
165
 
159
166
  | Komponent · olay | Yük (aynı zamanda prop adları) | Akışta nereden okunur |
160
167
  |---|---|---|
@@ -171,7 +178,12 @@ döndürür; hata yok, sayfalama yok.
171
178
  | `tabs.tab` | `{ selected }` | `self.selected` |
172
179
  | `chart.dataPointClick` | `{ name, seriesName, value, dataIndex, row }` | `self.row` (kaynak satırın tamamı) |
173
180
  | `repeater.change` | `{ selectedIndex }` | `item` / `Row` satır bağlamı |
174
- | `html` aksiyonu (`fireEvent`) | ikinci argüman | **`event.data`** (tek istisna) |
181
+ | `html` aksiyonu (`fireEvent`) | ikinci argüman | **`event.data`** |
182
+ | `kanban.cardMove` | `{ id, row, from, to }` | **`event.data`** (self'e yazılmaz) |
183
+ | `eventcalendar.eventMove` | `{ id, row, start, end, previousStart, previousEnd }` | **`event.data`** (self'e yazılmaz) |
184
+ | `importwizard.complete` | `{ rows, errors, fileName, total }` | `self.rows`… ya da `event.data` |
185
+ | `stepper.stepChange` | `{ currentStep, previous }` | `self.currentStep` ya da `event.data` |
186
+ | `signature.change` | `{ value }` | `self.value` ya da `event.data.value` |
175
187
 
176
188
  Adım gövdesi `StepManagementSchema`: `{ stepId, name, type, kind, args, branches }`.
177
189
  **`branches[].nextStepId` bir GUID değil, hedef adımın `stepId` STRING'idir**
@@ -458,8 +470,8 @@ gateway **PAGE-011 / LAY-004** ile istek gitmeden reddeder.
458
470
 
459
471
  | slug | Olaylar | Ayırt edici prop'lar |
460
472
  |---|---|---|
461
- | `table` | 8: `mount · pagination · filter · sort · select · selectionChange · doubleClick · rowChange` | `rowSelection` (none/single/multi), `selectedRow`/`selectedRows`, `filterMode` (panel/hide/row), `filters`, `showSort`, `sortField`/`sortType`, `isEditable`, `showColumnMenu`, `actions`, `emptyIcon/emptyText/emptyActions`, `style` (root/thead/th/tr/td) |
462
- | `datatable` | 1: `mount` | `title`, `locale` (tr/en), `tableStyle` (zebra/plain), kolonlarda `isFilterable`/`isSortable`/`colorMap`/`prefix`/`suffix`/`precision`/`thousands`/`dateFormat`/`imageShape`, `filters`/`sortField`/`sortType` (hidden), `actions` |
473
+ | `table` | 8: `mount · pagination · filter · sort · select · selectionChange · doubleClick · rowChange` | `rowSelection` (none/single/multi), `selectedRow`/`selectedRows`, `filterMode` (panel/hide/row), `filters`, `showSort`, `sortField`/`sortType`, `isEditable`, `showColumnMenu`, `actions`, `emptyIcon/emptyText/emptyActions`, `style` (root/thead/th/tr/td), satır bazlı `_columns`/`_actions` ezmesi (Kural 1e-2) |
474
+ | `datatable` | 1: `mount` | `title`, `locale` (tr/en), `tableStyle` (zebra/plain — satır zemini varyantı), **`style`** (parça bazlı CSS: `&__toolbar`/`&__title`/`&__head`/`&__th`/`&__body`/`&__row`/`&__td`), kolonlarda `isFilterable`/`isSortable`/`colorMap` (statik)/`prefix`/`suffix`/`precision`/`thousands`/`dateFormat`/`imageShape`/**`progress`** kolon tipi, `filters`/`sortField`/`sortType` (hidden), `actions` |
463
475
 
464
476
  **`datatable`'ın tek olay yayması eksiklik değil, tasarım.** Filtre paneli, sıralama ve sayfalama
465
477
  komponentin İÇİNDE: kullanıcı süzdüğünde/sıraladığında/sayfa değiştirdiğinde `datatable` önce
@@ -483,8 +495,18 @@ olarak gider ve ancak `enableDynamicFilters: true` olan bir uçta karşılık bu
483
495
  düzenleme (`isEditable`) ve boş-durum aksiyonları verir.
484
496
  - *Satır seçimi / çift tıkla forma geçiş / hücre düzenleme gerekiyor mu?* → **`table`**; bunlar
485
497
  `datatable`'da yok.
486
- - *Zengin kolon biçimlendirme (renk haritası, para birimi öneki, tarih formatı, avatar) gerekiyor
487
- mu?* → **`datatable`**; kolon şeması bunun için tasarlandı.
498
+ - *Sayı/tarih/görsel biçimlendirme (para birimi öneki, ondalık, binlik ayracı, tarih formatı,
499
+ avatar şekli) gerekiyor mu?* → **`datatable`**; `prefix`/`suffix`/`precision`/`thousands`/
500
+ `dateFormat`/`imageShape` yalnız onun kolon şemasındadır, `table`'da yoktur.
501
+ - *Renk gerekiyor mu?* → **ikisi de yapar ama farklı şeyi.** `datatable`'ın `colorMap`'i
502
+ **statiktir**: hücrenin kendi değerine bakar; satır verisinde rengi taşırsan (`{ label, color }`)
503
+ dinamik de olur. `table` ise satır bazında **koşullu** renklendirir (`_columns` ezmesi,
504
+ Kural 1e-2). İkisinin de `style` prop'u vardır (datatable'ınki 2026-08-27'de eklendi), yani
505
+ renk uğruna stilden vazgeçmen gerekmiyor.
506
+ - *Hücrenin içinde ilerleme çubuğu ya da yüzde halkası mı istiyorsun?* → **`datatable`**, kolon
507
+ tipi `progress`. `progressVariant` çubuk/halka, `thresholds` yüzdeye göre renk, `captionField`
508
+ ise BAŞKA bir satır alanını çubuğun üstüne yazar — ad ve çubuk tek hücrede durur. `table`'da
509
+ böyle bir kolon tipi yok.
488
510
 
489
511
  **Bu, katalogdaki her komponent için geçerlidir:** hangi komponenti kullanacağını
490
512
  `component_list`/`component_get` ile keşfedip kendin seçersin, rehberdeki örnekler tercih değil
@@ -500,6 +522,48 @@ görünür, kullanıcı süzer, hiçbir şey olmaz. Ya süzme arayüzünü kapat
500
522
  > eklersen elementId aynı olsa bile o bağ kopar ve flow'u yeniden kaydetmen gerekir. Tipi
501
523
  > baştan doğru seç.
502
524
 
525
+ ## Kural 1e-2 — Satır bazlı renk `table`'da: `_columns` ezmesi
526
+
527
+ `table` her hücreyi çizerken **satırın kendi `_columns` sözlüğünü** kolon tanımıyla birleştirir
528
+ (`column-view.ts` `resolveColumn` → `Table.svelte:1207` `<TableCell {column}>`). Yani bir satır
529
+ kendi `appearance`/`isBold`'unu dayatabilir; renk, satırın herhangi bir alanından hesaplanır:
530
+
531
+ ```jsonc
532
+ // setter: rows'a yazmadan önce satırları zenginleştir
533
+ { "type": "change", "element": "tbl", "property": "rows", "source": "component",
534
+ "mapping": { "source": "", "mappings": {} },
535
+ "value": { "type": "code", "ref": "(Steps.listele?.data || []).map(function (r) { return Object.assign({}, r, { _columns: [null, null, null, null, { appearance: r.durum === 'İptal' ? 'error' : 'success' }] }); })" } }
536
+ ```
537
+
538
+ **`_columns` bir DİZİDİR ve konum kolonun `columns` dizisindeki İNDEKSİDİR** — yukarıdaki dört
539
+ `null`, hedef kolon 5. sırada (indeks 4) olduğu için var; ezilmeyen kolonlar atlanır.
540
+ `buildViewColumns` `index`'i `isHidden` kolonlar elenmeden ÖNCE atar, yani **görünür sıra değil
541
+ tanım sırası**: gizli bir `id` kolonu indeksleri kaydırmaz, kullanıcının kolon menüsünden kolon
542
+ gizlemesi de kaydırmaz (`hideColumns` `buildViewColumns`'dan SONRA uygulanır).
543
+ Aynı kalıp `_actions[i]` ile satır bazlı **aksiyon** ezmesinde de çalışır (tek bir satırda "Sil"i
544
+ `{ "isHidden": true }` ile gizlemek gibi).
545
+
546
+ > Sözleşme frontend'de belgeli ve testli: `column-view.ts` `resolveColumn` + `column-view.spec.ts`
547
+ > (`applies the row's own override fields on top`, `matches the override by the column definition
548
+ > order`). Ezilebilen alanlar `appearance` · `options` · `isBold`. CSV export'u da bu ezmeyi
549
+ > uygular, yani ekranda gördüğün renk dışa aktarımda da tutarlıdır.
550
+
551
+ İki renk yolu var:
552
+
553
+ | istenen | yol |
554
+ |---|---|
555
+ | Hazır palet | `tag` kolonu + `appearance`: `primary · info · success · warning · error`; `_columns` ile satır satır değişir |
556
+ | Serbest hex | `tags` kolonu + satır verisinde `[{ "value": "kritik", "color": "#da1e28" }]` |
557
+
558
+ **`style` yazarken iki ayrı kural geçerli:** `style.root` emotion'dır (camelCase çalışır, iç
559
+ seçici yazılabilir); `style.thead|th|tr|td` ise satır içi `style` attribute'una basılır
560
+ (`toStyleString` anahtarı olduğu gibi yazar) — bu dördünde **kebab-case zorunludur**, `fontSize`
561
+ sessizce düşer, `font-size` çalışır.
562
+
563
+ > `datatable`'da `style` prop'u **yoktur** (ne şemada ne `.svelte`'de) ve `_columns` ezmesi de
564
+ > yoktur; `tableStyle` CSS değil `zebra`/`plain` varyantıdır. Tabloya CSS ya da koşullu satır
565
+ > rengi gerekiyorsa **`table`**.
566
+
503
567
  ## Kural 1f — Koordinat modeli ve layout-slot yerleşimi
504
568
 
505
569
  Izgara kapsayıcıya görelidir ve **bir satır ≈ 10px**'tir; `w` 12 kolon. Her komponentin
@@ -612,7 +676,11 @@ Dört şeyi bilmeden flex kurma:
612
676
  3. **Flex kapsayıcının yüksekliği içeriğine oturur.** `verticalAlign`'ın dağıtacak boşluğu
613
677
  olması için `appearance.heightType: 'fixed'` + `size.h` vermelisin. **İstisna
614
678
  `page_container`**: `states.isWrapper: true` olduğu için zaten `min-height: 80vh` alır
615
- (Kural 1f), dolayısıyla dikey hizalama onda kutu boyu vermeden de çalışır.
679
+ (Kural 1f), dolayısıyla dikey hizalama onda kutu boyu vermeden de çalışır. Üçüncü yol
680
+ `heightType: 'fill'` (2026-08-28): çocuk kabın bıraktığı yeri alır — sütunda `flex: 1 1 auto`,
681
+ satırda `align-self: stretch` — yani "şu kutu kalan alanı kaplasın" artık tahmini bir `h`
682
+ olmadan yazılabilir. Tam ekran kabuk kurmanın yolu da budur: `platform_guide('layout')`
683
+ Kural 5b.
616
684
  4. **`layout: 'grid'` iken diğer altı prop ÖLÜDÜR.** Katalogda tanımlı oldukları için
617
685
  doğrulama duvarı susar, renderer da okumaz: ızgara kapsayıcıya `direction: 'column'` yazmak
618
686
  sessizce hiçbir şey yapmaz. Gateway bunu **PAGE-015 (uyarı)** ile söyler.
@@ -795,11 +863,11 @@ yapmazsan ekran "platform mavisi" görünür; marka rengine çevirmek tek satır
795
863
  | Küme | Değişkenler |
796
864
  |---|---|
797
865
  | Vurgu | `--ng-accent-primary` · `--ng-accent-hover` · `--ng-accent-muted` · `--ng-accent-subtle` |
798
- | Zemin | `--ng-background-canvas` · `--ng-background-surface` · `--ng-background-surface-alt` · `--ng-background-readonly` · `--ng-background-disabled` · `--ng-background-overlay` |
866
+ | Zemin | `--ng-background-canvas` · `--ng-background-surface` · `--ng-background-surface-alt` · `--ng-background-readonly` · `--ng-background-disabled` · `--ng-background-overlay` · `--ng-background-inverse` (zıt zemin: aydınlıkta koyu, karanlıkta açık) |
799
867
  | Metin | `--ng-text-primary` · `--ng-text-secondary` · `--ng-text-disabled` |
800
- | Çerçeve / köşe / gölge | `--ng-border-primary` · `--ng-border-secondary` · `--ng-rounded` · `--ng-shadow-none/sm/md/lg` |
868
+ | Çerçeve / köşe / gölge | `--ng-border-primary` · `--ng-border-secondary` · `--ng-rounded` (= `--ng-radius-md`) · `--ng-radius-sm/lg/pill` (temanın köşe kademeleri; sm/lg `--ng-rounded`'ın oranı) · `--ng-shadow-none/sm/md/lg` |
801
869
  | Tipografi | `--ng-font` · `--ng-font-size` · `--ng-font-weight` |
802
- | Boşluk | `--ng-spacing` · `--ng-spacing-small` · `--ng-spacing-large` |
870
+ | Boşluk | `--ng-spacing` · `--ng-spacing-xs/sm/md/lg/xl` (kademeler; builder'ın gap preset'leri sm/md/lg'yi okur — custom properties'te de bunları kullan) · `--ng-spacing-small` · `--ng-spacing-large` (eski adlar) |
803
871
  | Durum | `--ng-status-success` · `--ng-status-warning` · `--ng-status-error` · `--ng-status-info` |
804
872
  | Form (girdilerin tamamı) | `--ng-form-color` / `-disabled` / `-placeholder` / `-invalid` · `--ng-form-background` / `-disabled` / `-readonly` · `--ng-form-border` / `-focus` / `-disabled` / `-invalid` · `--ng-form-radius-sm/md/lg` · `--ng-form-height-sm/md/lg` · `--ng-form-padding-x-sm/md/lg` · `--ng-form-font-family` · `--ng-form-font-size-sm/md/lg` · `--ng-form-label-color` / `-font-weight` / `-font-size-*` / `-margin-bottom-*` · `--ng-form-default-size` |
805
873
 
@@ -875,6 +943,47 @@ kaplar — yardım metni opsiyonelse bunu hesaba kat.
875
943
  > `input` `display:none` olduğu için klavye odağı görünmez. Klavyeyle gezilecek ekranlarda
876
944
  > `&__item-input:focus-visible + &__item-text` için de bir dış çizgi tanımlayın.
877
945
 
946
+ ### 1h-4 — Stilin ÜÇ kanalı ve efektif sonucu okuma
947
+
948
+ `style` tek kanal değildir; bir düğümün ekranda aldığı görünüm üç ayrı yerden gelir ve hangisini
949
+ kullanacağını bilmek gereksiz CSS yazmayı önler:
950
+
951
+ | Kanal | Ne için | Nereden yazılır |
952
+ |---|---|---|
953
+ | `appearance` (düğüm alanı) | dış/iç boşluk, genişlik-yükseklik, z-index, opaklık, taşma, **sarmalayıcının** zemini/çerçevesi/gölgesi | `page_schema_patch` ile düğümün `appearance` alanı |
954
+ | Şema prop'ları | yerleşim (`layout`/`direction`/`gap`/`gridColumns`), semantik renkler, boyut (`size`) | `replace_prop` |
955
+ | `style` prop'u | geri kalan her şey; iç seçiciler, pseudo-class, `--ng-*` token ezme | `replace_prop` / `set_binding` |
956
+
957
+ **Dikkat — `appearance` kutunun İÇİNİ boyamaz.** Yüzey stili düğüm sarmalayıcısına
958
+ (`.ng-app__node-item`) yazılır; `box` gibi kendi zeminini çizen bir komponentin içi bundan
959
+ etkilenmez. Tipli stil modeline göçen komponentler bu boşluğu kapatır: `box` (ve emekli
960
+ takma adı `aibox`: `surfaceStyle` · `typographyStyle` · `hoverStyle` · `sectionStyle`),
961
+ `container` (aynı üçlü + `headerStyle`), `text` (`typographyStyle` · `surfaceStyle`;
962
+ hover/bölge yok), `statcard` (üçlü + `valueStyle`) ve `icon` (yalnız `hoverStyle`;
963
+ yüzey/tipografi kararları çip ve boyut prop'larında) — `component_get('<slug>')` sözleşmeyi
964
+ verir, göçen komponentlerin listesi `TYPED_STYLE_COMPONENTS` kaydıdır.
965
+
966
+ **Stil yazma SIRASI (tipli gruplu komponentlerde):** önce tipli gruplar — kararın alanı
967
+ grupta varsa ORAYA yaz; grubun karşılamadığı her CSS kararı `style` kanalına (studio'daki
968
+ "custom properties" alanının veri kanalı budur). Tipli alan dururken aynı özelliği `style`'a
969
+ yazma: `style` kazanır ama panel alanı etkisiz görünür ve tasarımcı yanılır.
970
+ Bileşenin BİLDİRDİĞİ parçalara (`&__header`, `&__body` …) da yazabilirsin: `style: { '&__header':
971
+ { minHeight: '0' } }` — studio'daki "custom properties" bölümünün Hedef seçicisi bunun panel
972
+ yüzüdür. Boyut alanlarında METİN `'0'` gerçek seçimdir (bileşenin taban dolgusunu/yüksekliğini
973
+ kaldırır); sayı `0` "seçilmedi" sayılır.
974
+ **Katman sırası (K4):** tema `componentStyles` → `$preset` TABANDIR (varsayılan verir);
975
+ tipli grup alanları temayı alan alan EZER; düğümün serbest `style`'ı en üstte SON SÖZDÜR.
976
+ Boyut alanları CSS uzunluğu metnidir (`'18px'`, `'1.2em'`); `radius` tek alanda preset
977
+ anahtarı YA DA CSS uzunluğu kabul eder.
978
+ **Tema preset'i bağlamak:** `style: { $preset: 'card' }` (adlar `project_get` → `theme.presets`;
979
+ `componentStyles[type]` referanssız uygulanır). Bir alanı temaya bırakmak = o alanı hiç yazmamak;
980
+ studio'da bunun adı "Temaya dön"dür. Tema değerini gruba kopyalama — bağ kopar, tema değişince izlemez.
981
+
982
+ **Efektif stili okumak:** `page_runtime_get(resolveStyles: true)` her düğüme `resolvedStyle`
983
+ (kaskad çözülmüş birleşik stil) ve `styleLayers` (`{ typedGroups, componentStyle, preset, own }`)
984
+ ekler. "Bu kutu neden böyle görünüyor / benim yazdığım stil neden görünmüyor" sorusunun cevabı
985
+ budur — bir preset ya da `componentStyles` sizin değerinizi eziyorsa `styleLayers` söyler.
986
+
878
987
  ## Kural 2 — Şema değişikliği `page_update` ile YAPILMAZ
879
988
 
880
989
  İki ayrı yazma yolu vardır ve karıştırılmaz:
@@ -1333,14 +1442,18 @@ bağlanır, filtre `source:'expression'` + `value:'user.id'` olur.
1333
1442
  | Kimlik alanları | `email` · `password` |
1334
1443
  | Dosya | `fileUpload` (dropzone) · `fileInput` · `filebutton` · `file-viewer` |
1335
1444
  | Liste | `table` · `datatable` (Kural 1e) · `repeater` (kart listesi VE dinamik form — Kural 1g) · `tree-view` (hiyerarşi; `isSearchable` ile istemci içi arama) · `timeline` (tarihli olay akışı) |
1445
+ | Pano / takvim | `kanban` (durum kolonlarında sürüklenebilir kartlar; taşıma `cardMove` ile `event.data`'dan okunur, kalıcılık AKIŞIN işidir) · `eventcalendar` (ay/hafta/gün; veri `rows`'a akışla yazılır, `monthChange` tazeleme kancasıdır, `month` 1-tabanlı) |
1446
+ | Kayıt detayı | `detailview` — tek kaydı etiket/değer ızgarası basar (alan başına format, iç içe alan yolu); OLAY YAYMAZ, tıklanabilirlik gerekiyorsa kapsayıcıya sar |
1447
+ | Adımlı akış | `stepper` — tabs gibi her adım kendi droppable görünümünü taşır; ileri gidiş `canProceed` kapısıyla (`{{ form1.isValid === true }}` biçimi), adım `currentStep` setter'ıyla sürülür |
1448
+ | İmza / CSV içe aktarma | `signature` (değer PNG data-URL ya da ham SVG; `change` setter'lı) · `importwizard` (3 adımlı sihirbaz; temiz+hatalı satırlar `complete` yükünde — satırları uca yazmak akışın işidir) |
1336
1449
  | Sayfalama (tablo dışı listeler için) | `pagination` — offset/limit yazar, `self.offset`/`self.limit` ile sorguya bağlanır |
1337
1450
  | Grafik / KPI | `chart` (ECharts: bar·line·area·pie·donut + waterfall/histogram/pareto/bullet/tornado/radial) · `statcard` (tek KPI + trend + sparkline) · `progress` |
1338
1451
  | Kapsayıcı / düzen | `container` (ızgara ya da flex — Kural 1f-2) · `form` (düzen prop'u YOK, çocuklar ızgara koordinatıyla dizilir) · `tabs` · `collapsible-container` · `accordion` |
1339
1452
  | Kart görünümü | `card` — **kapsayıcı DEĞİLDİR**, çocuk kabul etmez (`not-droppable`) ve yüksekliği 10-50 aralığındadır. Kutu içinde serbest içerik için `container` kullan. |
1340
1453
  | Katman | `modal` · `drawer` (şema kökünde — Kural 1d) |
1341
1454
  | Geri bildirim | `notification` (sayfa içi kutu) · `toast` (geçici bildirim; isOpen yükselen kenarı) · `form-validation-errors` · `confirm-bar` · `result` (işlem sonucu ekranı) · `emptystate` (boş liste; ikon YA DA görsel + aksiyon düğmeleri) |
1342
- | Gezinme / başlık | `breadcrumb` · `breadcrumb-title` (başlık + daralan iz) · `page-header` · `header` · `sidebar` · `auth-layout` · `language-selector` (dil değiştirici) |
1343
- | Sunum | `text` · `html` · `image` · `video` · `icon` · `qrcode` · `tags` · `avatar` · `badge` (sayaç “99+” / nokta / durum metni) · `carousel` · `iframe` (sandbox’lı gömme) · `jsonviewer` (katlanabilir JSON; JSON METNİNİ de parse eder) · `audit-basic` · `audit-history` |
1455
+ | Gezinme / başlık | `breadcrumb` · `breadcrumb-title` (başlık + daralan iz) · `page-header` · `header` · `sidebar` · `auth-layout` · `language-selector` (dil değiştirici — çoklu dil kurulumu `platform_guide('translation')`) |
1456
+ | Sunum | `text` · `html` · `image` · `video` · `icon` (Material/Phosphor glif; çip + rozet + spin + click/href) · `qrcode` · `tags` · `avatar` · `badge` (sayaç “99+” / nokta / durum metni) · `carousel` · `iframe` (sandbox’lı gömme) · `jsonviewer` (katlanabilir JSON; JSON METNİNİ de parse eder) · `audit-basic` · `audit-history` |
1344
1457
 
1345
1458
  > **`chart` komponenti VAR (2026-08-25 ölçümü) — bu satır düzeltildi.** Rehberin önceki hâli
1346
1459
  > "grafik komponenti yoktur, `html` + `loadScript` kullanın" diyordu; `component_list` çıktısında
@@ -1511,6 +1624,15 @@ micro-op hattına dönün.
1511
1624
  style + Kural 1h deseniyle yeniden kurulunca kart 400px'e ve ortaya oturdu. Gateway bunu **PAGE-014 (uyarı)** ile
1512
1625
  yanıtın `layoutWarnings` alanında bildirir. **Düzeni `style` ile kurmaya hiç kalkışma:**
1513
1626
  ortalama/yaslama/aralık işi kapsayıcının kendi `layout: 'flex'` prop grubuna aittir (Kural 1f-2).
1627
+ - **Menüde "bulunduğun sayfa" vurgusu: `sidebar`/`layout`'ta `activeHref`, `header`'da
1628
+ `activeNavHref`.** `sidebar` ve `layout` menü ağacını ortak renderer'la çizer: `activeHref` boşken
1629
+ tarayıcıdaki adrese uyan satırı kendileri vurgular, prop yazılırsa o satır vurgulanır (akıştan
1630
+ setter ile de yazılabilir). Eşleşmenin iki tarafı da `getHref`'ten geçtiği için satırın ham
1631
+ `href`'ini, bağlantı seçicisinin nesnesini ya da tam yolu yazmak aynı satırı gösterir. `header`
1632
+ yalnız prop'a bakar (adrese bakmaz), `qm-header` ise yalnız adrese bakar (prop'u yoktur). Menü
1633
+ satırları `style`'ın `&__navigations*` parçalarıyla biçimlendirilemez ve menü olay yaymaz —
1634
+ vurgu dışında bir "seçili satır" davranışı kurulamaz. Ayrıntı:
1635
+ `component_get('sidebar' | 'layout' | 'header' | 'qm-header')`.
1514
1636
  - **`isHidden` olmayan komponent listesine `dropdown` da dahildir** (`text`, `multi-select`,
1515
1637
  `dropdown`). Koşullu göstermek için `isHidden`'ı olan bir `container`'a sar (Kural 1g).
1516
1638
  - **Ana sayfayı TAŞIYAMAZSIN — `application_update.homepageId` kalıcı DEĞİL ve yanıtı yanıltıcı.**