@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.
- package/.env.example +21 -7
- package/.env.production.example +42 -0
- package/README.md +14 -7
- package/dist/config.js +113 -46
- package/dist/knowledge/componentCatalog.js +476 -32
- package/dist/knowledge/componentEvents.js +154 -12
- package/dist/knowledge/errorPath.js +64 -0
- package/dist/knowledge/normalize.js +12 -1
- package/dist/knowledge/outlines.js +9 -2
- package/dist/knowledge/rules.js +184 -3
- package/dist/knowledge/styleResolve.js +485 -0
- package/dist/observability/trace.js +4 -0
- package/dist/platform/http.js +3 -0
- package/dist/platform/responses.js +80 -4
- package/dist/platform/screenshot.js +106 -0
- package/dist/resources/examples/layout-app-shell.json +368 -0
- package/dist/resources/examples/microservice-table-list.json +1 -0
- package/dist/resources/examples/middleware-authenticate.json +243 -47
- package/dist/resources/examples/workflow-basic.json +24 -2
- package/dist/resources/guides/component.md +6 -3
- package/dist/resources/guides/entity.md +33 -1
- package/dist/resources/guides/external-component.md +129 -0
- package/dist/resources/guides/layout.md +147 -0
- package/dist/resources/guides/microservice.md +35 -0
- package/dist/resources/guides/middleware.md +10 -0
- package/dist/resources/guides/page.md +137 -15
- package/dist/resources/guides/translation.md +80 -0
- package/dist/resources/guides/workflow.md +127 -2
- package/dist/server.js +4 -0
- package/dist/tools/externalComponents.js +285 -0
- package/dist/tools/layouts.js +48 -6
- package/dist/tools/microservices.js +2 -2
- package/dist/tools/pages.js +98 -30
- package/dist/tools/platformInfo.js +2 -2
- package/dist/tools/projects.js +7 -2
- package/dist/tools/screens.js +36 -0
- package/dist/tools/translations.js +37 -0
- package/dist/tools/workflows.js +3 -3
- 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 —
|
|
155
|
-
|
|
156
|
-
`
|
|
157
|
-
|
|
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`**
|
|
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
|
|
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
|
-
- *
|
|
487
|
-
mu?* → **`datatable`**;
|
|
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ı.**
|