@appaflytech/zeyrek-ai-mcp 0.0.20 → 0.0.21

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 (65) hide show
  1. package/README.md +14 -13
  2. package/dist/config.js +0 -2
  3. package/dist/knowledge/componentCatalog.js +940 -215
  4. package/dist/knowledge/componentEvents.js +368 -75
  5. package/dist/knowledge/normalize.js +66 -63
  6. package/dist/knowledge/rules.js +29 -6
  7. package/dist/knowledge/styleResolve.js +1 -1
  8. package/dist/knowledge/themeResolve.js +3 -3
  9. package/dist/platform/diagnostics.js +85 -0
  10. package/dist/platform/domSummary.js +1 -1
  11. package/dist/platform/ifExists.js +129 -0
  12. package/dist/platform/responses.js +2 -1
  13. package/dist/platform/{capture/capture.js → screenshot.js} +509 -23
  14. package/dist/platform/strictArguments.js +22 -2
  15. package/dist/platform/writeDiff.js +58 -31
  16. package/dist/platform/writeView.js +17 -0
  17. package/dist/resources/guides/component.md +9 -6
  18. package/dist/resources/guides/functions.md +32 -3
  19. package/dist/resources/guides/getting-started.md +35 -0
  20. package/dist/resources/guides/layout.md +7 -11
  21. package/dist/resources/guides/page.md +49 -71
  22. package/dist/resources/guides/translation.md +5 -6
  23. package/dist/resources/schema-fingerprint.json +2 -2
  24. package/dist/resources/schemas/GlobalFunctionUpdateResultDto.json +18 -0
  25. package/dist/server.js +0 -2
  26. package/dist/tools/applications.js +3 -60
  27. package/dist/tools/components.js +10 -50
  28. package/dist/tools/designSchemaPatch.js +13 -18
  29. package/dist/tools/externalComponents.js +4 -25
  30. package/dist/tools/flows.js +38 -51
  31. package/dist/tools/functions.js +20 -10
  32. package/dist/tools/layouts.js +9 -41
  33. package/dist/tools/microservices.js +39 -11
  34. package/dist/tools/pages.js +95 -127
  35. package/dist/tools/platformInfo.js +1 -2
  36. package/dist/tools/schemaOps.js +2 -2
  37. package/dist/tools/screenWrite.js +2 -2
  38. package/dist/tools/screens.js +3 -9
  39. package/dist/tools/workflows.js +39 -12
  40. package/package.json +7 -2
  41. package/dist/knowledge/mobileComponentCatalog.js +0 -331
  42. package/dist/knowledge/mobileComponentEvents.js +0 -50
  43. package/dist/knowledge/platform/lint.js +0 -205
  44. package/dist/knowledge/platform/mobile.js +0 -78
  45. package/dist/knowledge/platform/mobileRules.js +0 -121
  46. package/dist/knowledge/platform/mobileTabs.js +0 -108
  47. package/dist/knowledge/platform/profile.js +0 -20
  48. package/dist/knowledge/platform/resolve.js +0 -122
  49. package/dist/knowledge/platform/web.js +0 -38
  50. package/dist/knowledge/styleResolveNative.js +0 -410
  51. package/dist/platform/capture/actions.js +0 -333
  52. package/dist/platform/capture/browser.js +0 -1
  53. package/dist/platform/capture/index.js +0 -10
  54. package/dist/platform/capture/readiness.js +0 -103
  55. package/dist/platform/capture/summary.js +0 -77
  56. package/dist/platform/capture/target.js +0 -5
  57. package/dist/platform/capture/targets/studio-mobile.js +0 -15
  58. package/dist/platform/capture/targets/studio-web.js +0 -5
  59. package/dist/resources/examples/mobile-app-shell-drawer.json +0 -209
  60. package/dist/resources/examples/mobile-app-shell-stack.json +0 -123
  61. package/dist/resources/examples/mobile-app-shell-tab.json +0 -174
  62. package/dist/resources/examples/mobile-list-detail-form.json +0 -656
  63. package/dist/resources/guides/mobile.md +0 -215
  64. package/dist/tools/mobile.js +0 -203
  65. package/dist/tools/profileWrite.js +0 -45
@@ -22,11 +22,49 @@ export const componentEventContracts = {
22
22
  mount: { payload: {}, reads: 'self.filters · self.sortField · self.sortType · self.offset · self.limit' }
23
23
  },
24
24
  button: { mount: NO_DATA, click: NO_DATA },
25
- card: { click: NO_DATA },
26
- compound: { click: NO_DATA },
27
- image: { click: NO_DATA },
25
+ card: {
26
+ mount: NO_DATA,
27
+ click: NO_DATA,
28
+ buttonClick: {
29
+ payload: {},
30
+ reads: 'Kartın kendi butonuna (buttonText) basılınca yayılır. Kabarcığı DURDURMAZ: aynı tıklama kartın click olayını da çalıştırır — yalnız buton eylemi isteniyorsa click bağını boş bırakın.'
31
+ }
32
+ },
33
+ compound: {
34
+ mount: NO_DATA,
35
+ click: {
36
+ payload: {},
37
+ reads: 'Düğmeye tıklanınca yayılır — href YAZILIYKEN DE yayılır, yani gezinme ile akış birlikte koşar. isDisabled ya da isLoading açıkken hiç yayılmaz.'
38
+ }
39
+ },
40
+ image: {
41
+ mount: NO_DATA,
42
+ click: {
43
+ payload: {},
44
+ reads: 'Görsele (ya da kırık/boş kaynağın yedek kutusuna) tıklanınca yayılır. isZoomable açıkken aynı tıklama büyütülmüş önizlemeyi de açar; akış iptal edilmez.'
45
+ }
46
+ },
47
+ qrcode: {
48
+ mount: NO_DATA,
49
+ click: {
50
+ payload: {},
51
+ reads: 'Koda tıklanınca yayılır, ama YALNIZ akışa bağlıysa ve ekranda gerçek bir kod varken (yer tutucu ve iskelet tıklanmaz). Bağlıyken düğüm <button> olur ve odak sırasına girer; bağlı değilken role="img" taşıyan salt görsel bir <div>tür.'
52
+ },
53
+ error: {
54
+ payload: {
55
+ errorText: 'string (kütüphanenin kendi mesajı, ör. "Data too long: expected 1273 but got 1600")'
56
+ },
57
+ reads: 'self.errorText YA DA event.data.errorText — ikisi de dolu. YALNIZ üretim başarısızlığında yayılır — pratikte tek sebebi kapasite: seçilen errorCorrectionLevel’de sığmayan data (bayt sınırı L 2953 · M 2331 · Q 1663 · H 1273). BOŞ data hata DEĞİLDİR ve bu olayı çalıştırmaz, kesikli yer tutucu çizilir. Veri düzelince hata bir sonraki çizim turunda temizlenir ve olay yeniden yayılmaz.'
58
+ }
59
+ },
28
60
  'qm-card': { click: NO_DATA },
29
- form: { mount: NO_DATA, submit: NO_DATA },
61
+ form: {
62
+ mount: NO_DATA,
63
+ submit: {
64
+ payload: {},
65
+ reads: "Yalnız BÜTÜN kurallar geçince yayılır (alan kuralları + formun kendi validations dizisi); kalırsa olay çalışmaz, alanlar işaretlenir. event.data BOŞ. event.source.id = formu gönderen düğmenin ADI, event.source.props = onun prop'ları (Type='submit' düğme; Enter'la gönderimde formun ilk submit düğmesi; formda hiç submit düğmesi yoksa event.source formun KENDİSİDİR) — aynı formu iki düğme gönderiyorsa ('Kaydet' / 'Kaydet ve kapat') dallanma buradan. Toplu değer self.value = { <alan adı>: değer } (Page.components.<form>.value ile de okunur), self.isValid bu anda her zaman true."
66
+ }
67
+ },
30
68
  container: { mount: NO_DATA },
31
69
  aibox: { mount: NO_DATA },
32
70
  box: { mount: NO_DATA },
@@ -34,8 +72,8 @@ export const componentEventContracts = {
34
72
  divider: {},
35
73
  spacer: {},
36
74
  popover: {
37
- open: { payload: { isOpen: 'boolean (true)' }, reads: 'setter: self.isOpen da yazılır — akış paneli isOpen prop’unu değiştirerek de açıp kapatabilir' },
38
- close: { payload: { isOpen: 'boolean (false)' }, reads: 'setter: self.isOpen da yazılır' }
75
+ open: { payload: { isOpen: 'boolean (true)' }, reads: 'Tetikleyici yolunda setter: self.isOpen da yazılır. Akış isOpen’ı kendisi yazınca da open çıkar (setter’sız, prop zaten yazılmış) — açılış nasıl olursa olsun tek olay. İlk çizimde çıkmaz; editörde tetikleyici çalışmaz.' },
76
+ close: { payload: { isOpen: 'boolean (false)' }, reads: 'Tetikleyici, dışarı tıklama, Escape ya da hover ayrılışı: setter, self.isOpen yazılır. Akış isOpen’ı false yazınca da close çıkar (setter’sız).' }
39
77
  },
40
78
  phoneinput: {
41
79
  mount: NO_DATA,
@@ -70,9 +108,9 @@ export const componentEventContracts = {
70
108
  payload: { text: 'string', parentId: "string (yanıtsa üst yorumun id’si, kök yorumda '')", mentions: 'string[] (metinden çözülmüş @kişi listesi)', author: 'string (currentUser)' },
71
109
  reads: 'Komponent yorumu ANINDA iyimser olarak listeye ekler (bekleyen katman); kalıcılık akışın işidir — rows tazelenmezse bekleyen satır bir sonraki içerik değişiminde kaybolur'
72
110
  },
73
- like: { payload: { id: 'string', liked: 'boolean (yeni durum)', author: 'string' }, reads: 'beğeni de iyimserdir; sayaç rows tazelenene kadar yerel' },
74
- edit: { payload: { id: 'string', text: 'string (yeni metin)', author: 'string' } },
75
- delete: { payload: { id: 'string', author: 'string' }, reads: 'satır listeden hemen çıkarılır; uca yazmak akışın işidir' }
111
+ like: { payload: { id: 'string', liked: 'boolean (yeni durum)', author: 'string (currentUser — işlemi yapan)' }, reads: 'beğeni de iyimserdir; sayaç rows tazelenene kadar yerel. isDisabled/isReadonly/isViewmode açıkken yayılmaz' },
112
+ edit: { payload: { id: 'string', text: 'string (yeni metin)', author: 'string (currentUser — işlemi yapan)' }, reads: 'düzenleme de iyimserdir; yeni metin "düzenlendi" işaretiyle rows tazelenene kadar yerel. Metin değişmediyse yayılmaz' },
113
+ delete: { payload: { id: 'string', author: 'string (currentUser — işlemi yapan)' }, reads: 'satır (kök yorumsa yanıtlarıyla birlikte) listeden hemen gizlenir; uca yazmak akışın işidir' }
76
114
  },
77
115
  'auth-layout': { mount: NO_DATA, primaryClick: NO_DATA, secondaryClick: NO_DATA },
78
116
  layout: { mount: NO_DATA, logout: NO_DATA },
@@ -113,7 +151,18 @@ export const componentEventContracts = {
113
151
  focus: NO_DATA,
114
152
  blur: NO_DATA
115
153
  },
116
- incrementalinput: { mount: NO_DATA, change: valueChange('string'), blur: NO_DATA },
154
+ incrementalinput: {
155
+ mount: NO_DATA,
156
+ change: {
157
+ payload: {
158
+ value: "string (elle yazılan metin) YA DA { Prefix, Separator, Counter, DigitCount, FieldId } (sunucudan kod gelince: kodun METNİ DEĞİL, kodu üreten şekil)"
159
+ },
160
+ reads: 'setter: self.value da yazılır. Elle yazarken HER TUŞTA, otomatik kod gelince bir kez yayılır — pahalı akışı changed’e bağla'
161
+ },
162
+ changed: valueChange('string (alan bırakılınca kesinleşen metin; yalnız ELLE düzenlemede yayılır)'),
163
+ focus: NO_DATA,
164
+ blur: NO_DATA
165
+ },
117
166
  // Adlar 2026-09-11'de `on` önekinden kurtuldu: şema onMount/onChange diyordu, runtime
118
167
  // mount/change yayıyordu ve flow-machine eşleşmeyi ADLA yaptığı için bu bileşene bağlanan
119
168
  // hiçbir akış çalışmıyordu.
@@ -144,6 +193,13 @@ export const componentEventContracts = {
144
193
  dropdown: { mount: NO_DATA, change: { payload: { value: 'seçilen option değeri', selectedLabel: "seçilen option'ın label metni (temizlemede '')" } }, search: { payload: { searchText: 'string' } }, focus: NO_DATA, blur: NO_DATA },
145
194
  'multi-select': { mount: NO_DATA, change: { payload: { value: "seçilen değerlerin dizisi: [{ value, label, id, text }] — id/text, value/label'ın eski adlı ikizleridir" } }, search: { payload: { searchText: 'string' } }, focus: NO_DATA, blur: NO_DATA },
146
195
  'tag-input': { mount: NO_DATA, change: { payload: { value: 'etiket dizisi: [{ value, color? }] — renk verilmemiş etikette color anahtarı HİÇ bulunmaz' } }, search: { payload: { searchText: 'string' } }, focus: NO_DATA, blur: NO_DATA },
196
+ tags: {
197
+ mount: NO_DATA,
198
+ clickItem: {
199
+ payload: { currentItem: 'tıklanan öğe (values’taki nesnenin tamamı; düz metin dizisinde metin)', index: 'number (values dizisindeki gerçek yer; atlanan öğeler kaydırmaz)' },
200
+ reads: "event.data.currentItem ve event.data.index ile oku; currentItem ayrıca self.currentItem'a yazılır, index self'e YAZILMAZ. clickItem satırı yoksa etiketler tıklanamaz. Bileşen isActive'i değiştirmez — seçimi akış values'a yazar"
201
+ }
202
+ },
147
203
  datepicker: {
148
204
  mount: NO_DATA,
149
205
  change: {
@@ -190,46 +246,153 @@ export const componentEventContracts = {
190
246
  focus: NO_DATA,
191
247
  blur: NO_DATA
192
248
  },
193
- fileUpload: { change: { payload: {}, reads: 'self.value' } },
194
- fileInput: { change: { payload: { value: 'Array<{ type, value }>', fileName: 'string' } } },
195
- filebutton: { change: { payload: { value: 'Array<{ type, value }>', fileName: 'string' } } },
196
- 'file-viewer': { mount: NO_DATA },
249
+ fileUpload: {
250
+ change: {
251
+ payload: { value: "Array<{ value: base64 data URL, fileName: string, type: 'file', ref: '' }>" },
252
+ reads: 'self.value — dosya EKLENİNCE de SİLİNİNCE de (çipe tıklama) aynı olay yayılır ve yük her seferinde KALAN TÜM listedir, yalnız yeni dosyalar değil. isMultiple:false iken dizi tek elemanlıdır. Kilitliyken (isDisabled/isReadonly/isViewmode) hiç yayılmaz; tür/boyut/adet sınırına takılan dosya listeye girmez ve uyarı komponentin içinde çizilir, ama kabul KISMİDİR: geçen dosya varsa olay GEÇENLERLE yayılır, yalnız hepsi reddedilirse hiç yayılmaz. enableCrop açıkken görsel dosyalar kırpma katmanından geçtikten SONRA yayılır (İptal dosyayı düşürür; hepsi düşerse olay çalışmaz).'
253
+ }
254
+ },
255
+ fileInput: {
256
+ mount: NO_DATA,
257
+ change: {
258
+ payload: {
259
+ value: '{ type: "file", fileName: string, value: string (base64 data URL) } — isMultiple açıkken bu nesnelerin DİZİSİ; boşaltma { type: "ref", value: null } (çoklu seçimde tek elemanlı dizisi)'
260
+ },
261
+ reads: 'Tek anahtar value düğümün prop’una yazılır: akış self.value ile okur, dosya adı self.value.fileName’dedir (ÜST DÜZEY fileName anahtarı YOKTUR — 2026-09-17’de kayıttan çıkarıldı, runtime hiç göndermiyordu). Çoklu seçimde yeni dosyalar eskilerin üstüne EKLENİR ve yük KALAN TÜM listedir. Tür/boyut/adet sınırına takılan dosya listeye girmez ve uyarı alanın altına yerel mesaj olarak yazılır, ama kabul KISMİDİR: geçen dosya varsa change GEÇENLERLE yayılır (5 dosya + maxFileCount:3 → 3’ü akışa gider), yalnız hepsi elenirse hiç yayılmaz — tek dosyalık alanda zaten hepsi ya da hiçbiri. Açılır listedeki × o dosyayı siler ve change’i KALAN listeyle yayar; son dosya silinince ve çipin temizle düğmesiyle boşaltma değeri yazılır. Kilitliyken (isDisabled/isReadonly/isViewmode) hiç yayılmaz; enableCrop açıkken görseller kırpma katmanından geçtikten SONRA yayılır (İptal dosyayı düşürür, hepsi düşerse olay çalışmaz)'
262
+ }
263
+ },
264
+ filebutton: {
265
+ mount: NO_DATA,
266
+ change: {
267
+ payload: {
268
+ value: "tekli kipte { type: 'file', value: base64 data URL, fileName: string, ref: '' } TEK nesne (temizlenince null); çoklu kipte aynı nesnelerin DİZİSİ (temizlenince [])"
269
+ },
270
+ reads: "self.value — düğümün value prop'una yazılır. fileName üst düzey anahtar DEĞİLDİR, her dosyanın kendi alanıdır (2026-09-17'de düzeltildi; kayıt runtime'ın hiç göndermediği bir yük anlatıyordu). Çoklu kipte yük KALAN TÜM listedir: yeni parti mevcut listenin ÜSTÜNE eklenir, X bir satırı siler, 'Tümünü temizle' [] yayar. Kilitliyken (isDisabled/isReadonly/isViewmode) hiç yayılmaz; tür/boyut/adet sınırına takılan dosya listeye girmez, uyarı komponentin içinde çizilir ve hepsi elenirse olay çalışmaz."
271
+ }
272
+ },
273
+ 'file-viewer': { mount: NO_DATA, load: NO_DATA, error: NO_DATA },
197
274
  modal: { open: NO_DATA, close: NO_DATA },
198
275
  drawer: { open: NO_DATA, close: NO_DATA },
199
- repeater: { mount: NO_DATA, change: { payload: { selectedIndex: 'number' }, reads: 'item / Row (satır bağlamı)' } },
200
- tabs: { mount: NO_DATA, tab: { payload: { selected: 'string (sekme anahtarı)' } } },
276
+ repeater: {
277
+ mount: NO_DATA,
278
+ change: {
279
+ payload: { selectedIndex: 'number (satırın sırası, 0’dan)' },
280
+ reads: 'self.selectedItem (seçilen satırın verisi) — seçilen satır DEĞİŞİNCE yayılır: satıra tıklama ya da satırdaki bir çocuğun olayı. Aynı satıra tekrar tıklamak change üretmez. Akış satır bağlamında koşmaz: item/Row burada boştur, satırı self.selectedItem ile oku'
281
+ },
282
+ select: {
283
+ payload: { selectedIndex: 'number (tıklanan satırın sırası, 0’dan)' },
284
+ reads: 'self.selectedItem — satıra ulaşan HER tıklamada yayılır (aynı satır dahil; tıklamayı yutan dropdown-button/tag-input/tarih seçici gibi çocuklarda gelmez, etiket tıklaması tek sayılır); satır değiştiyse change ondan önce yayılır. Satırdaki butonun kendi click akışı select’ten önce başlar'
285
+ }
286
+ },
287
+ tabs: {
288
+ mount: NO_DATA,
289
+ tab: {
290
+ payload: { selected: 'string (geçilen sekmenin key\'i; key boşsa sırası "0", "1"…)' },
291
+ reads: "selected self'e yazılır; event.data.selected da dolu gelir. Yalnız kullanıcı selected'dan farklı key'li sekmeye geçince (tıklama, ←/→/Home/End) yayılır — selected'ın gösterdiği sekmeye tekrar tıklamak ve akışın selected yazması olay üretmez; görünen sekme bir geri düşüşse ona tıklamak yayar"
292
+ }
293
+ },
201
294
  'tree-view': {
202
295
  mount: NO_DATA,
203
296
  click: {
204
297
  payload: { selected: 'string (tıklanan satırın key’i)', currentItem: 'tıklanan satırın tamamı ({ key, text, subtle, icon, image, children… })' },
205
- reads: "aksiyon menüsü AYRI olay yaymaz: aksiyonun kendi flow'u çalışır ve satır yine self.currentItem'a yazılır"
298
+ reads: "event.data.selected / event.data.currentItem ya da self.selected / self.currentItem — ikisi de dolu. isDisabled satır tıklanmaz. Aksiyon menüsü AYRI olay yaymaz: aksiyonun kendi flow'u çalışır, orada event.data = { currentItem, actionKey } ve satır yine self.currentItem'a yazılır"
299
+ },
300
+ change: {
301
+ payload: {
302
+ checkedKeys: "string[] (normalize edilmiş işaretli key'ler, belge sırasıyla; ağaçta çizilmeyen key'ler sonda)",
303
+ currentItem: 'kutusuna tıklanan satırın tamamı',
304
+ isChecked: 'boolean (tıklamadan sonra o satır tam işaretli mi; yalnız event.data’da)'
305
+ },
306
+ reads: "event.data.checkedKeys ya da self.checkedKeys; self.currentItem da yazılır, isChecked yalnız event.data'da. Yalnız isCheckable:true iken kullanıcı kutuya tıklayınca yayılır — akışın checkedKeys yazması olay üretmez"
307
+ }
308
+ },
309
+ 'dropdown-button': {
310
+ mount: NO_DATA,
311
+ click: {
312
+ payload: {},
313
+ reads: 'Butonun kendisine basılınca (menüyü açan/kapatan tıklama) yayılır — menü açılmasa bile. isDisabled/isLoading iken hiç yayılmaz. Menü SATIRI bu olayı yaymaz.'
314
+ },
315
+ clickItem: {
316
+ payload: {
317
+ currentItem: 'tıklanan menü öğesinin TAMAMI ({ key, text, icon, flow, isDanger, isDisabled… }) — akışta self.currentItem ile okunur'
318
+ },
319
+ reads: "Her satır tıklamasında yayılır. Satırın kendi flow'u (options[].flow) varsa o akış AYRICA çalışır ve aynı currentItem'ı görür; yani flow bağlı bir satır iki akış tetikleyebilir."
320
+ }
321
+ },
322
+ 'confirm-bar': {
323
+ mount: NO_DATA,
324
+ click: {
325
+ payload: { currentItem: 'tıklanan aksiyonun TAMAMI (key, text, kind, variant, icon, flow, href, isDisabled, isLoading…)' },
326
+ reads: "self.currentItem — şeridin aksiyon butonuna basılınca yayılır. Aksiyonun kendi flow'u varsa o akış ÖNCE koşar ve click olayına bağlı akışlar AYRICA koşar (tek tıklamada iki akış); yalnız biri istensin diye ya aksiyonun flow alanını ya da click bağını boş bırakın. href yazılmış aksiyon LİNK olur: tarayıcı adrese gider, click YAYILMAZ (Button'un type:'link' sözleşmesi). isDisabled/isLoading aksiyonun tıklaması hiç yayılmaz."
327
+ },
328
+ close: {
329
+ payload: { isHidden: 'true' },
330
+ reads: 'Yalnız showCloseButton:true iken çizilen kapatma düğmesine basılınca yayılır. Şerit KENDİNİ gizler: isHidden düğümün prop\'una yazılır (self.isHidden true olur) ve render katmanı şeridi söker — geri getirmek için akışta isHidden:false yazın. Tasarımcı kanvasında gizlenme uygulanmaz.'
206
331
  }
207
332
  },
208
- 'dropdown-button': { mount: NO_DATA, click: NO_DATA, clickItem: { payload: { currentItem: 'tıklanan menü öğesi' } } },
209
- 'confirm-bar': { mount: NO_DATA, click: { payload: { currentItem: 'tıklanan buton tanımı' } } },
210
333
  'collapsible-container': {
211
334
  mount: NO_DATA,
212
- collapsed: { payload: { isOpen: 'boolean — false; yük kabın yeni durumudur ve bileşenin isOpen prop\'una yazılır' } },
213
- expanded: { payload: { isOpen: 'boolean — true; yük kabın yeni durumudur ve bileşenin isOpen prop\'una yazılır' } }
335
+ collapsed: {
336
+ payload: {},
337
+ reads: "Kullanıcı bölümü KAPATINCA yayılır; komponent aynı anda isOpen'ı false'a yazar, akışta self.isOpen ile okunur. Akıştan (setter ile) isOpen yazmak bu olayı YAYMAZ. Kapanışta gövdedeki komponentler DOM'dan sökülür: onların durumu kaybolur, açılışta mount'ları yeniden koşar"
338
+ },
339
+ expanded: {
340
+ payload: {},
341
+ reads: "Kullanıcı bölümü AÇINCA yayılır (isOpen true olarak geri yazılır, akışta self.isOpen). Kapalı bölümün içi hiç kurulmadığı için verinin çekileceği doğru yer budur; her açılışta yeniden koşar, tek seferlik değildir"
342
+ }
214
343
  },
215
344
  'audit-basic': { mount: NO_DATA },
216
- 'audit-history': { mount: NO_DATA },
345
+ 'audit-history': {
346
+ mount: NO_DATA,
347
+ showMore: { payload: {}, reads: 'yalnız histories visibleLogCount’u aşınca çıkan "Daha fazla göster" düğmesine basılınca; görünür sınır visibleLogCount kadar büyür, kalan kalmayınca düğme kaybolur. Bileşen veri çekmez; backend kayıt başına en fazla 5 işlem verdiği için meta.history bağlıyken düğme ancak visibleLogCount < 5 iken çıkar' }
348
+ },
217
349
  'form-validation-errors': { mount: NO_DATA },
218
- 'page-header': { mount: NO_DATA },
350
+ 'page-header': {
351
+ mount: NO_DATA,
352
+ clickItem: {
353
+ payload: {
354
+ currentItem: 'tıklanan links satırının tamamı (düz metin dizisinde metnin kendisi)',
355
+ index: 'number (links dizisindeki gerçek yer; metinsiz satırlar atlanır ama kaydırmaz). Kök öğe yoktur, -1 gelmez'
356
+ },
357
+ reads: "event.data.currentItem ve event.data.index ile oku. currentItem düğüme de yazılır (şemada gizli durum prop'u) ama self.currentItem ifade yüzeyine yalnız düğüm o anahtarı kayıtta taşıyorsa çıkar (makine anahtar kümesini kurulurken düğümün prop'larından toplar) — güvenilir yol event.data'dır; index self'e YAZILMAZ. Olayı içteki breadcrumb yayar, page-header olduğu gibi geçirir — yalnız page-header düğümünde bir akış bağlıysa yayılır, bağsız tıklama düğüme hiçbir şey yazmaz. Başlık (pageTitle, izin son öğesi) tıklanabilir DEĞİLDİR, bu olayı hiç yaymaz. Adresi olan öğe <a> olduğu için bağlı tıklama hem bu olayı yayar HEM de adrese gider — yalnız akış karar versin isteniyorsa satırın href'ini boş bırak"
358
+ }
359
+ },
219
360
  header: { mount: NO_DATA },
220
361
  sidebar: { mount: NO_DATA },
221
362
  html: { mount: NO_DATA },
222
363
  view: { mount: NO_DATA },
223
364
  'widget-area': { mount: NO_DATA },
224
365
  'document-editor': { mount: NO_DATA },
225
- video: { mount: NO_DATA, click: NO_DATA, play: NO_DATA, pause: NO_DATA, ended: NO_DATA },
366
+ video: {
367
+ mount: {
368
+ payload: {},
369
+ reads: "Bileşen mount'u KENDİSİ yaymaz — ortak render katmanı (RenderComponent.handleMount) her düğüm için bir kez yayar. 2026-09-16 turuna kadar Video.svelte de kendi onMount'unda yayıyordu ve mount'a bağlı akış İKİ KEZ koşuyordu (ARC-006, kapandı)"
370
+ },
371
+ click: {
372
+ payload: {},
373
+ reads: 'Yalnız akışa bağlıysa sarmalayıcı tıklanabilir olur; controls açıkken oynat/duraklat düğmesine basmak da bu olayı tetikler (tıklama sarmalayıcıya kabarır). isLoading:true iken HİÇ çalışmaz — o dalda oynatıcı yerine iskelet çizilir ve sarmalayıcı tıklanabilir değildir'
374
+ },
375
+ play: {
376
+ payload: { isPlaying: 'boolean (true)' },
377
+ reads: "setter: self.isPlaying da yazılır — akış props.isPlaying'e true yazarak videoyu BAŞLATABİLİR de (sesli videoda tarayıcı reddeder). event.data ayrıca { currentTime: number (saniye), duration: number (saniye; meta yüklenmemişse VE canlı yayında — süresi Infinity — 0) } taşır"
378
+ },
379
+ pause: {
380
+ payload: { isPlaying: 'boolean (false)' },
381
+ reads: "setter: self.isPlaying da yazılır; akış false yazarak duraklatabilir. event.data: { currentTime, duration }. DİKKAT: video BİTTİĞİNDE de yayılır — HTML spesifikasyonu bitişte önce pause sonra ended yayar, yani 'kullanıcı duraklattı' demek değildir; ayırmak için currentTime ≈ duration karşılaştır"
382
+ },
383
+ ended: {
384
+ payload: { isPlaying: 'boolean (false)' },
385
+ reads: 'loop açıkken HİÇ yayılmaz (döngü videosu bitmez). event.data: { currentTime, duration } — bitişte currentTime pratikte duration’a eşittir. Bitişte pause’dan SONRA gelir (spesifikasyon sırası), yani ended akışı pause akışının ardından koşar'
386
+ }
387
+ },
226
388
  // — 2026-08-25 eşleme turu: ng-apps-ui'da olay YAYAN ama burada kaydı olmayan komponentler.
227
389
  // Yükler kaynaktaki dispatch('emit', { name, data }) / machine.onEmit(id, { event, data })
228
- // çağrılarından birebir çıkarıldı. Olay yaymayan komponentler (breadcrumb · qrcode · slot · tags ·
229
- // text) bilinçli olarak kayıtsızdır. `notification` bu listede
390
+ // çağrılarından birebir çıkarıldı. Olay yaymayan komponentler (slot ·
391
+ // text) bilinçli olarak kayıtsızdır. `breadcrumb` de bu listedeydi; 2026-09-17
392
+ // component-analiz turunda şemaya mount + clickItem eklendi ve kaydı yukarıda açıldı. `notification` bu listede
230
393
  // YANLIŞLIKLA yer almıştı — Notification.svelte hem timeout'ta hem kapatma tıklamasında
231
- // dispatch('emit', { name:'toggled', data:{isHidden:true}, setter:true }) çağırıyor (düzeltme
232
- // 2026-08-25c, `docs/20-komponent-bilgi-katmani.md` §9).
394
+ // emit yayıyor (düzeltme 2026-08-25c, `docs/20-komponent-bilgi-katmani.md` §9); o emit'in adı
395
+ // 2026-09-17'de toggled → close oldu ve şemada bildirildi, kaydı aşağıda.
233
396
  autocomplete: {
234
397
  mount: NO_DATA,
235
398
  change: {
@@ -248,52 +411,112 @@ export const componentEventContracts = {
248
411
  focus: NO_DATA,
249
412
  blur: NO_DATA
250
413
  },
251
- avatar: { click: NO_DATA },
252
- badge: { click: NO_DATA },
253
- icon: { click: NO_DATA },
414
+ avatar: { mount: NO_DATA, click: NO_DATA },
415
+ badge: {
416
+ mount: NO_DATA,
417
+ click: {
418
+ payload: {},
419
+ reads: 'yalnız şemada bir akış bağlıysa yayılır; bağlıyken rozet <button> olur, bağlı değilken salt görsel <span> kalır ve olay hiç çıkmaz'
420
+ }
421
+ },
422
+ icon: { mount: NO_DATA, click: NO_DATA },
423
+ breadcrumb: {
424
+ mount: NO_DATA,
425
+ clickItem: {
426
+ payload: {
427
+ currentItem: 'tıklanan öğe (items satırının tamamı; düz metin dizisinde metin). KÖK öğede items satırı yoktur, yük { title: homeTitle, href: homeHref } taşır',
428
+ index: 'number (items dizisindeki gerçek yer; metinsiz öğeler atlanır ama kaydırmaz). KÖK öğede -1'
429
+ },
430
+ reads: "event.data.currentItem ve event.data.index ile oku; currentItem ayrıca self.currentItem'a yazılır (şemada gizli durum prop'u), index self'e YAZILMAZ. Yalnız şemada bir akış bağlıysa yayılır — bağsız tıklama düğüme hiçbir şey yazmaz. Bulunulan sayfa (currentTitle) tıklanabilir DEĞİLDİR, bu olayı hiç yaymaz. Adresi olan öğe <a> olduğu için bağlı tıklama hem bu olayı yayar HEM de adrese gider — yalnız akış karar versin isteniyorsa öğenin href'ini boş bırak; href'i de clickItem bağı da olmayan öğe düz metindir, tıklanamaz"
431
+ }
432
+ },
254
433
  'breadcrumb-title': {
255
434
  mount: NO_DATA,
256
- clickItem: { payload: { currentItem: '{ text, flow, isHidden } — tıklanan iz öğesi' } },
257
- clickRoot: NO_DATA
435
+ clickItem: {
436
+ payload: { currentItem: '{ key, text, flow, isHidden } — tıklanan iz öğesi (satır içi ya da … menüsünden, ikisi de aynı yükü yayar)' },
437
+ reads: 'self.currentItem — öğe düğümün prop’una da yazılır; akış hangi adımın seçildiğini self.currentItem.key ile okur. Öğenin kendi flow’u varsa ÖNCE o çalışır, sonra clickItem yayılır.'
438
+ },
439
+ clickRoot: {
440
+ payload: {},
441
+ reads: 'Kök ikonuna her basışta yayılır — rootHref yazılıyken de (o durumda yalnız rootFlow atlanır, gezinme olaydan sonra başlar).'
442
+ }
258
443
  },
259
444
  carousel: {
260
445
  mount: NO_DATA,
261
- slideChange: { payload: { activeIndex: 'number' } },
262
- slideClick: { payload: { currentItem: 'slayt nesnesi', index: 'number' } }
446
+ slideChange: {
447
+ payload: { activeIndex: 'number (görünen slaytın 0-tabanlı indeksi)' },
448
+ reads: "event.data.activeIndex ile oku; aynı değer setter ile düğümün kendi activeIndex prop'una da yazılır (self.activeIndex). Ok, nokta, klavye (←/→), swipe ve otomatik geçişin hepsi bu olaydan geçer; aynı indekse gitmek olay yaymaz"
449
+ },
450
+ slideClick: {
451
+ payload: { currentItem: 'tıklanan slayt nesnesinin tamamı (items satırı)', index: 'number (items dizisindeki yer)' },
452
+ reads: "event.data.currentItem ve event.data.index ile oku; currentItem ayrıca self.currentItem'a yazılır, index self'e YAZILMAZ. HER slayt tıklamasında yayılır (href/flow şart değil); slaytta flow varsa bu olayın akışı da slaytın kendi flow'u da çalışır, ikisi de aynı event.data'yı alır. Eşiği aşan sürükleme ve ok/nokta düğmeleri bu olayı tetiklemez"
453
+ }
263
454
  },
264
455
  chart: {
265
456
  mount: NO_DATA,
266
- dataPointClick: { payload: { name: 'string (kategori)', seriesName: 'string', value: 'number | null', dataIndex: 'number', row: 'kaynak satırın TAMAMI | null' } },
457
+ dataPointClick: { payload: { name: 'string (kategori); scatter grafiğinde x değeri', seriesName: 'string', value: 'number | null; scatter grafiğinde y', dataIndex: 'number', row: 'kaynak satırın TAMAMI | null' }, reads: 'YALNIZ seri noktasında yayılır; eksen etiketi tıklaması axisLabelClick’tir (2026-09-16 öncesinde o da boş bir dataPointClick üretiyordu). scatter noktası ECharts tarafında [x, y, size] dizisidir, yük tek değere indirgenir: name = x, value = y' },
267
458
  breadcrumbClick: { payload: { filterValue: 'hedef seviyenin filtre değeri (kök seviyede undefined)' } },
268
459
  selectionChange: { payload: { selected: 'seçili veri noktaları' } },
269
460
  legendClick: { payload: { name: 'string (seri adı)', selected: 'seri → görünürlük haritası' } },
270
- axisLabelClick: { payload: { value: 'string (tıklanan eksen etiketi)' } },
271
- zoom: { payload: { start: 'number (görünen aralığın başlangıç yüzdesi)', end: 'number (bitiş yüzdesi)' }, reads: "ECharts dataZoom params'ı olduğu gibi geçer; sürüme göre batch/startValue/endValue de gelebilir" },
461
+ axisLabelClick: { payload: { value: 'string (tıklanan eksen etiketi)' }, reads: 'Kategori ekseni hangi eksene düşerse oradan gelir — yatay yönelimde yAxis (2026-09-16 öncesinde yatayda hiç yayılmıyordu)' },
462
+ zoom: { payload: { start: 'number | null (görünen aralığın başlangıç yüzdesi)', end: 'number | null (bitiş yüzdesi)', startValue: 'number | null (eksenin kendi birimindeki mutlak alt sınır)', endValue: 'number | null (mutlak üst sınır)' }, reads: 'Yük normalize edilir: ECharts iki dataZoom bileşeniyle alanları batch içine koysa da akış her zaman bu dört alanı görür. Aralığı sorguya çevirecekseniz yüzdeleri değil startValue/endValue kullanın (2026-09-16)' },
272
463
  refresh: NO_DATA,
273
464
  retry: NO_DATA
274
465
  },
275
466
  checkboxgroup: { mount: NO_DATA, change: valueChange('string[] (seçili değerler)'), focus: NO_DATA, blur: NO_DATA },
276
- emptystate: { actionClick: { payload: { text: 'string (aksiyonun metni)', index: 'number' }, reads: "aksiyonun kendi flow'u zaten doğrudan çalışır" } },
277
- iframe: { mount: NO_DATA, load: NO_DATA, error: NO_DATA },
467
+ emptystate: {
468
+ mount: NO_DATA,
469
+ actionClick: { payload: { text: 'string (aksiyonun metni)', index: 'number' }, reads: "aksiyonun kendi flow'u zaten doğrudan çalışır; index GÖRÜNEN aksiyonların sırasıdır (isHidden olanlar elenmiş). href dolu satırda olay YİNE yayılır ama aynı sekmede gezinme sayfayı değiştirir ve olayın sayfa-içi sonucu görünmeden kaybolur — ikisini birlikte görmek için satırda isNewTabLink aç" }
470
+ },
471
+ iframe: {
472
+ mount: NO_DATA,
473
+ load: NO_DATA,
474
+ error: NO_DATA,
475
+ message: {
476
+ payload: {
477
+ message: 'gömülü sayfanın postMessage ile yolladığı ham değer (structured clone; string, sayı, nesne…)',
478
+ origin: "string — mesajı yollayan belgenin origin'i; isSandboxed AÇIKKEN opak origin yüzünden 'null' gelir"
479
+ },
480
+ reads: "yalnız event.data.message / event.data.origin — message hiçbir prop yazmaz. Gömülü sayfa window.parent.postMessage(payload, '*') çağırır; YALNIZ bu çerçeveden gelen mesaj kabul edilir (event.source karşılaştırması), sayfadaki başka bir iframe ya da uygulamanın kendi postMessage'ı olayı çalıştırmaz. Origin süzgeci runtime'da YOKTUR — güvenilecek origin kararı akışa aittir"
481
+ }
482
+ },
278
483
  jsonviewer: {
484
+ mount: NO_DATA,
279
485
  nodeClick: {
280
486
  payload: {
281
487
  path: "string (nokta/köşeli-parantez yolu — 'user.roles[0].name'; kökte boş)",
282
488
  key: 'string (düğümün anahtarı; dizi öğesinde indeks)',
283
489
  kind: "'object' | 'array' | 'string' | 'number' | 'boolean' | 'null'",
284
490
  value: 'düğümün ham değeri (object/array için alt ağacın tamamı)'
285
- }
491
+ },
492
+ reads: 'event.data.path / key / kind / value; self.currentItem’a value’suz { path, key, kind } yazılır. Aç/kapa oku ve satırın kopyala düğmesi bu olayı yaymaz'
286
493
  },
287
494
  copy: {
288
495
  payload: {
289
496
  path: "string (kopyalanan düğümün yolu; araç çubuğundan TÜMÜNÜ kopyalamada boş + kind:'root')",
497
+ key: "string (düğümün anahtarı; tümünü kopyalamada boş)",
290
498
  kind: "'root' | 'object' | 'array' | 'string' | 'number' | 'boolean' | 'null'",
291
499
  value: 'kopyalanan değer (tümünü kopyalamada normalize edilmiş TÜM veri)'
292
- }
500
+ },
501
+ reads: 'yalnız event.data — copy hiçbir prop yazmaz. Pano yazılamazsa (izin/güvensiz bağlam) olay yayılmaz'
502
+ }
503
+ },
504
+ 'language-selector': {
505
+ mount: { ...NO_DATA, reads: 'self.value BOŞTUR: enjekte edilen geçerli dil düğümün prop kaydına yazılmıyor, oraya yalnız change yükü yazılıyor (ölçüldü 2026-09-18, ARC-098). Dili okuyacak akışı change’e bağla' },
506
+ change: {
507
+ payload: { value: 'string (seçilen dil kodu, projenin yazdığı biçimde)' },
508
+ reads: 'Yük düğümün kendi value prop’una yazılır (yazmayı machine.onEmit yapar, çünkü olayda data var), akış self.value ile okur; aynı yük params kanalından da iner, yani event.data.value da dolu. Dili DEĞİŞTİREN yazma bu değildir: render katmanı aynı olayda machine.setLanguage(value) + setAppLocale(value) çağırır. Yalnız kullanıcı seçiminde yayılır; akışın value’ya yazması hiçbir şeyi değiştirmez (enjekte edilen değer ezer)'
509
+ },
510
+ focus: NO_DATA,
511
+ blur: NO_DATA
512
+ },
513
+ notification: {
514
+ mount: { payload: {}, reads: 'Ortak render katmanından gelir ve band GÖRÜNÜR olduğunda bir kez yayılır; isHidden:true iken yayılmaz' },
515
+ close: {
516
+ payload: { isHidden: 'boolean (her zaman true — band kendini kapatırken props.isHidden yazar)' },
517
+ reads: "event.data.reason — kapatma düğmesi 'user', zaman aşımı 'timeout'. Bandı yeniden açmak akışın işidir: props.isHidden false yazılmadıkça kapalı kalır. 2026-09-17'den önce bu emit toggled adıyla yayılıyordu ve şemada bildirilmediği için akışa BAĞLANAMIYORDU"
293
518
  }
294
519
  },
295
- 'language-selector': { change: { payload: { value: 'string (dil kodu)' }, reads: 'runtime ayrıca machine.setLanguage(value) çağırır' } },
296
- notification: { toggled: { payload: { isHidden: 'boolean' } } },
297
520
  otpinput: {
298
521
  mount: NO_DATA,
299
522
  change: valueChange('string (birleşik kod)'),
@@ -302,10 +525,22 @@ export const componentEventContracts = {
302
525
  focus: NO_DATA,
303
526
  blur: NO_DATA
304
527
  },
305
- pagination: { mount: NO_DATA, change: { payload: { offset: 'number', limit: 'number' }, reads: 'self.offset · self.limit (sorguyu bunlara bağla)' } },
306
- progress: { complete: NO_DATA },
528
+ pagination: {
529
+ mount: NO_DATA,
530
+ change: {
531
+ payload: { offset: 'number (yeni sayfanın offset’i; limit değişince 0)', limit: 'number' },
532
+ reads: 'event.data.offset / event.data.limit ya da self.offset · self.limit — ikisi de dolu (sorguyu bunlara bağla). Yalnız offset ya da limit gerçekten değişince yayılır; akışın yazması yaymaz'
533
+ }
534
+ },
535
+ progress: { mount: NO_DATA, click: NO_DATA, complete: NO_DATA },
307
536
  rating: { mount: NO_DATA, change: valueChange('number (0..max; allowHalf ile yarım)'), focus: NO_DATA, blur: NO_DATA },
308
- result: { actionClick: { payload: { text: 'string (aksiyonun metni)', index: 'number' }, reads: "aksiyonun kendi flow'u zaten doğrudan çalışır" } },
537
+ result: {
538
+ mount: NO_DATA,
539
+ actionClick: {
540
+ payload: { text: 'string (aksiyonun metni)', index: 'number' },
541
+ reads: "aksiyonun kendi flow'u zaten doğrudan çalışır. index GÖRÜNEN sıradır: isHidden satırlar çizilmeden ELENİR, yani gizli satırı olan bir listede index actions dizisindeki sıra DEĞİLDİR — akışı sıraya değil text'e ya da aksiyonun kendi flow'una bağla. isLoading açıkken HİÇ yayılmaz (iskelet çizilirken düğme de yoktur); isDisabled satır da yaymaz"
542
+ }
543
+ },
309
544
  slider: {
310
545
  mount: NO_DATA,
311
546
  change: valueChange('number (sürüklerken sürekli)'),
@@ -313,7 +548,7 @@ export const componentEventContracts = {
313
548
  focus: NO_DATA,
314
549
  blur: NO_DATA
315
550
  },
316
- statcard: { mount: NO_DATA, click: NO_DATA, footerClick: { payload: {}, reads: "footerFlow zaten doğrudan çalışır; footerHref varsa tıklama ona gider" } },
551
+ statcard: { mount: NO_DATA, click: { payload: {}, reads: "Yalnız bir akış bağlıysa yayılır; bağlıyken kartın ana yüzeyi <button> olur (alt satır bunun dışındadır)" }, footerClick: { payload: {}, reads: "Alt satır HER tıklamada yayar — footerHref verilmiş olsa bile; tarayıcı gezinirken akış yarıda kalabilir, isNewTabLink açıkken kalmaz" } },
317
552
  switcher: {
318
553
  mount: NO_DATA,
319
554
  change: { payload: { value: 'boolean' }, reads: "setter: self.value da yazılır. Her geçişte İKİ olay yayılır — change ve (yeni duruma göre) checked ya da unchecked; ikisini birden bağlarsan akış iki kez koşar" },
@@ -322,15 +557,31 @@ export const componentEventContracts = {
322
557
  focus: NO_DATA,
323
558
  blur: NO_DATA
324
559
  },
560
+ 'theme-toggle': {
561
+ mount: NO_DATA,
562
+ change: {
563
+ payload: { value: "'light' | 'dark' | '' (boş = tercih temizlendi, projenin teması geçerli)" },
564
+ reads: "setter: self.value da yazılır. Kullanıcı tıklamasında yayılır. Akışın SETTER adımıyla value yazması temayı değiştirir ama bu olayı yaymaz (geri besleme döngüsü olurdu); CODE adımından yazmak (Page.components.x.value = 'dark') ise onEmit üzerinden gittiği için düğümün change akışlarını ÇALIŞTIRIR — ikisini karıştırma. Studio kanvasında hiç yayılmaz (_editorMode). Boş değer yalnız hasAutoMode açıkken çıkabilir"
565
+ }
566
+ },
325
567
  timeline: {
326
568
  mount: NO_DATA,
327
- clickItem: { payload: { currentItem: 'tıklanan olay öğesi', index: 'number' }, reads: "öğenin kendi flow'u da doğrudan çalışır" },
328
- showMore: NO_DATA
569
+ clickItem: {
570
+ payload: { currentItem: 'tıklanan olay öğesi (items’taki nesnenin tamamı)', index: 'number (items dizisindeki gerçek yer; reverse/maxCount’tan etkilenmez)' },
571
+ reads: "event.data.currentItem ve event.data.index ile oku; currentItem ayrıca self.currentItem'a yazılır, index self'e YAZILMAZ. Her satır tıklamasında yayılır; öğede flow varsa bu olayın akışı da öğenin kendi flow'u da çalışır (bu olay önce başlatılır, biri diğerini beklemez; ikisi de aynı event.data) — aynı akışı iki yere bağlarsan iki kez çalışır"
572
+ },
573
+ showMore: { payload: {}, reads: 'yalnız maxCount aşılınca çıkan "Show more" düğmesine basılınca; kalan öğelerin tamamı açılır ve düğme kaybolur (items yeni diziyle değişince yeniden çıkar)' }
329
574
  },
330
575
  timepicker: { mount: NO_DATA, change: { payload: { value: "string 'HH:mm' (temizlenince '')", selectedLabel: "seçilen saatin gösterilen metni — 12h kipinde '01:00 PM' (temizlenince '')" } }, focus: NO_DATA, blur: NO_DATA },
331
576
  toast: {
332
- open: NO_DATA,
333
- close: NO_DATA,
577
+ open: {
578
+ payload: {},
579
+ reads: 'Toast KUYRUĞA girdiğinde yayılır: delay kadar beklenir; duplicates ignore/count ile atılan ya da do-not-disturb ile bastırılan tetikleme open YAYMAZ. Aynı konumda 5 toast doluysa fazlası ekranda görünmeden de open yayar (görünürlük ayrı bir katman). isOpen’ı false’a döndüren change setter’ı bundan bağımsız, her tetiklemede hemen yayılır'
580
+ },
581
+ close: {
582
+ payload: { reason: "'timeout' | 'user' | 'programmatic'" },
583
+ reads: 'Toast kapanınca yayılır; akışta self.reason ile okunur. timeout = süre doldu; user = kullanıcı kapattı (× düğmesi, closeOnClick tıklaması, kaydırma, Escape, aksiyon düğmesi, Clear all); programmatic = koddan dismiss/dismissAll. duplicates ile atılan tetikleme ve delay beklerken iptal edilen toast close YAYMAZ'
584
+ },
334
585
  click: NO_DATA,
335
586
  actionClick: { payload: { text: 'string (aksiyonun metni)', index: 'number' }, reads: "aksiyonun kendi flow'u zaten doğrudan çalışır" }
336
587
  },
@@ -354,47 +605,96 @@ export const componentEventContracts = {
354
605
  eventcalendar: {
355
606
  mount: NO_DATA,
356
607
  monthChange: {
357
- payload: { month: 'number (1-TABANLI)', year: 'number' },
358
- reads: "yük self'e YAZILMAZ — event.data ile oku; gezinme okları/Bugün ile her görünümde yayılır, ilk mount'ta yayılmaz"
608
+ payload: {
609
+ month: 'number (1-TABANLI, imlecin ayı)',
610
+ year: 'number',
611
+ view: "'month' | 'week' | 'day' | 'agenda'",
612
+ start: "string 'yyyy-MM-dd' (görünen ilk gün, dahil)",
613
+ end: "string 'yyyy-MM-dd' (görünen son gün, dahil)"
614
+ },
615
+ reads: "yük self'e YAZILMAZ — event.data ile oku; gezinme okları/Bugün ile her görünümde yayılır, ilk mount'ta yayılmaz, isLoading'de de yayılır. Veri sorgusunu start/end'e KESİŞİM olarak bağla: etkinlikBaşlangıç < end+1 gün VE etkinlikBitiş >= start (end tarih-yalnız ve dahil; ay ızgarası komşu ay günlerini, ajanda/hafta ay sınırını kapsar)"
616
+ },
617
+ viewChange: {
618
+ payload: {
619
+ view: "'month' | 'week' | 'day' | 'agenda'",
620
+ start: "string 'yyyy-MM-dd' (yeni görünümün ilk günü)",
621
+ end: "string 'yyyy-MM-dd' (yeni görünümün son günü)"
622
+ },
623
+ reads: "self'e yazılmaz — event.data ile oku; yalnız görünüm düğmesiyle yayılır (defaultView değişince yayılmaz)"
359
624
  },
360
- viewChange: { payload: { view: "'month' | 'week' | 'day'" }, reads: "self'e yazılmaz — event.data ile oku" },
361
625
  dateClick: {
362
626
  payload: { date: "string 'yyyy-MM-dd'" },
363
- reads: "yalnız AY görünümünde ve isCreatable KAPALIYKEN; self'e yazılmaz — event.data ile oku"
627
+ reads: "yalnız AY görünümünde, isCreatable KAPALIYKEN ve isLoading değilken; self'e yazılmaz — event.data ile oku"
364
628
  },
365
629
  eventCreate: {
366
- payload: { start: "string (ay tıklaması: 'yyyy-MM-dd' · saat slotu: ISO)", end: 'string (slotta start+60dk)', allDay: 'boolean' },
367
- reads: "self'e yazılmaz — event.data ile oku"
630
+ payload: {
631
+ start: "string (tüm gün: 'yyyy-MM-dd' · saatli: ISO)",
632
+ end: "string (tüm gün: son gün DAHİL 'yyyy-MM-dd' · saatli: ISO; tek slotta start+60dk, seçimde son slotun sonu)",
633
+ allDay: 'boolean'
634
+ },
635
+ reads: "self'e yazılmaz — event.data ile oku; tıklama ya da sürükleyerek aralık seçimi (fare/kalem; dokunmatikte yalnız tek hücre), bırakmada tek olay; etkinlik eklenmez, akış yazıp rows'u tazeler"
368
636
  },
369
637
  eventClick: {
370
638
  payload: { id: 'string', title: 'string', row: 'kaynak satırın TAMAMI' },
371
- reads: "self'e yazılmaz — event.data ile oku"
639
+ reads: "self'e yazılmaz — event.data ile oku; ay/hafta/gün/ajanda hepsinde, isLoading'de yayılmaz"
372
640
  },
373
641
  eventMove: {
374
- payload: { id: 'string', row: 'kaynak satırın TAMAMI', start: 'string (ISO)', end: 'string (ISO)', previousStart: 'string (ISO)', previousEnd: 'string (ISO)' },
375
- reads: "self'e yazılmaz — event.data ile oku; akış kalıcılaştırıp rows'u tazelemezse taşınan etkinlik geri döner"
642
+ payload: {
643
+ id: 'string',
644
+ row: 'kaynak satırın TAMAMI',
645
+ start: "string (tüm gün: 'yyyy-MM-dd' · saatli: ISO)",
646
+ end: "string (tüm gün: 'yyyy-MM-dd' · saatli: ISO)",
647
+ previousStart: 'string (aynı biçim; ekranda görünen önceki aralık)',
648
+ previousEnd: 'string (aynı biçim)'
649
+ },
650
+ reads: "self'e yazılmaz — event.data ile oku; taşıma ve kenardan boyutlandırma aynı olay; akış kalıcılaştırıp rows'u tazelemezse etkinlik geri döner"
376
651
  }
377
652
  },
378
653
  importwizard: {
379
654
  mount: NO_DATA,
655
+ change: {
656
+ payload: {
657
+ currentStep: 'number (0 dosya · 1 eşleme · 2 önizleme)',
658
+ fileName: 'string (okunan dosyanın adı; henüz dosya yoksa "")',
659
+ rowCount: 'number (dosyadaki HAM veri satırı sayısı — doğrulamadan önce)'
660
+ },
661
+ reads: "adım her değiştiğinde yayılır; currentStep ve fileName düğüme de yazılır (self.currentStep), rowCount yalnız event.data'dadır"
662
+ },
380
663
  complete: {
381
664
  payload: {
382
665
  rows: 'Record<string,string>[] (TEMİZ satırlar; değerler hep string)',
383
- errors: 'Array<{ rowIndex, field, message, raw }>',
666
+ errors: 'Array<{ rowIndex, field, code, message, limit?, raw }> (code: required | maxRows)',
384
667
  fileName: 'string',
385
668
  total: 'number (temiz satır + hata KAYDI sayısı)'
386
669
  },
387
670
  reads: "hem self.rows/self.errors/… hem event.data dolu gelir (params kuşağı); satırları uca yazmak complete akışının işidir"
388
671
  },
389
- cancel: NO_DATA
672
+ cancel: {
673
+ payload: {
674
+ currentStep: 'number (her zaman 0)',
675
+ fileName: 'string (her zaman "")',
676
+ rows: 'Record<string,string>[] (her zaman [])',
677
+ errors: 'Array<…> (her zaman [])',
678
+ total: 'number (her zaman 0)'
679
+ },
680
+ reads: '✕ sıfırlaması: aynı boş yük düğüme de yazılır, yani cancel sonrası self.rows/self.total bayat kalmaz'
681
+ }
390
682
  },
391
683
  kanban: {
392
684
  mount: NO_DATA,
393
685
  cardMove: {
394
686
  payload: { id: 'string', row: 'kaynak satırın TAMAMI', from: 'string (kaynak kolon value)', to: 'string (hedef kolon value)' },
395
- reads: "BİLİNÇLİ olarak self'e yazılmaz — event.data ile oku; yeni kolonu uca yaz + rows'u tazele, yoksa kart geri döner"
687
+ reads: "BİLİNÇLİ olarak self'e yazılmaz — event.data ile oku; yeni kolonu uca yaz + rows'u tazele, yoksa kart geri döner. isLoading:true iken sürükleme başlamaz, olay yayılmaz"
396
688
  },
397
- cardClick: { payload: { id: 'string', row: 'kaynak satırın TAMAMI' }, reads: "self'e yazılmaz — event.data ile oku" }
689
+ cardClick: { payload: { id: 'string', row: 'kaynak satırın TAMAMI' }, reads: "self'e yazılmaz — event.data ile oku; isLoading:true iken yayılmaz" },
690
+ cardAdd: {
691
+ payload: { column: 'string (düğmesine basılan kolonun value değeri)' },
692
+ reads: "self'e yazılmaz — event.data.column ile oku. Yalnız isAddable:true iken kolon altındaki düğmeden yayılır; kart EKLENMEZ — akış satırı uca yazıp rows'u tazeler (ya da form açar). isLoading:true iken yayılmaz"
693
+ },
694
+ cardRemove: {
695
+ payload: { id: 'string', row: 'kaynak satırın TAMAMI', column: 'string (kartın o anki kolonu; atanmamış kuyrukta ham değer)' },
696
+ reads: "self'e yazılmaz — event.data ile oku. Yalnız isRemovable:true iken kartın × düğmesinden yayılır, cardClick YAYMAZ; kart GİZLENMEZ — akış (onay alıp) satırı siler ve rows'u tazeler. isLoading:true iken yayılmaz"
697
+ }
398
698
  },
399
699
  signature: {
400
700
  mount: NO_DATA,
@@ -408,7 +708,7 @@ export const componentEventContracts = {
408
708
  mount: NO_DATA,
409
709
  stepChange: {
410
710
  payload: { currentStep: 'number (hedef adım, 0 tabanlı)', previous: 'number (önceki adım)' },
411
- reads: "currentStep self'e yazılır; event.data da dolu gelir"
711
+ reads: "currentStep self'e yazılır; event.data da dolu gelir. Gizli adımlar atlanır (currentStep bir sonraki görünür adımın indeksidir, previous ile ardışık olmayabilir); previous kullanıcının GÖRDÜĞÜ adımdır (gizli adıma yazılmış currentStep değil); isLoading:true iken düğme ve başlıklar devre dışı, olay yayılmaz"
412
712
  },
413
713
  finish: { payload: { currentStep: 'number (son adımın indeksi)' }, reads: 'adımı değiştirmez; yalnız son adımda kapı açıkken yayılır' },
414
714
  validationFail: {
@@ -425,15 +725,8 @@ export const eventPayloadNote = "Olay yükü motorda komponentin KENDİ prop'una
425
725
  "payload boşsa olay veri taşımaz; 'reads' verilmişse değer yükte değil komponentin başka bir prop'undadır. " +
426
726
  "self yerine value { type:'property', ref:{ source:'component', element:'<elementId>', property:'<prop>' } } de kullanılabilir. " +
427
727
  "payload alanı yoksa yük sözlüğe henüz işlenmemiştir; tahmin etmeyin.";
428
- /**
429
- * `platformContracts` platforma özgü sözlüktür (mobilde `mobileComponentEvents.ts`): aynı olayda
430
- * web sözleşmesinin ÖNÜNE geçer, web'de karşılığı olmayan bileşenin tek kaynağıdır.
431
- */
432
- export function eventContractsFor(slug, names, platformContracts) {
433
- const own = (source) => slug !== undefined && source !== undefined && Object.hasOwn(source, slug) ? source[slug] : undefined;
434
- const web = own(componentEventContracts);
435
- const platform = own(platformContracts);
436
- const contracts = web || platform ? { ...web, ...platform } : undefined;
728
+ export function eventContractsFor(slug, names) {
729
+ const contracts = slug ? componentEventContracts[slug] : undefined;
437
730
  return names.map(name => {
438
731
  const contract = contracts?.[name];
439
732
  if (!contract)