@appaflytech/zeyrek-ai-mcp 0.0.13 → 0.0.15

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.
@@ -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,42 +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.'
331
+ }
332
+ },
333
+ 'collapsible-container': {
334
+ mount: NO_DATA,
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"
206
342
  }
207
343
  },
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
- 'collapsible-container': { mount: NO_DATA, collapsed: NO_DATA, expanded: NO_DATA },
211
344
  'audit-basic': { mount: NO_DATA },
212
- '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
+ },
213
349
  'form-validation-errors': { mount: NO_DATA },
214
- '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
+ },
215
360
  header: { mount: NO_DATA },
216
361
  sidebar: { mount: NO_DATA },
217
362
  html: { mount: NO_DATA },
218
363
  view: { mount: NO_DATA },
219
364
  'widget-area': { mount: NO_DATA },
220
365
  'document-editor': { mount: NO_DATA },
221
- 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
+ },
222
388
  // — 2026-08-25 eşleme turu: ng-apps-ui'da olay YAYAN ama burada kaydı olmayan komponentler.
223
389
  // Yükler kaynaktaki dispatch('emit', { name, data }) / machine.onEmit(id, { event, data })
224
- // çağrılarından birebir çıkarıldı. Olay yaymayan komponentler (breadcrumb · qrcode · slot · tags ·
225
- // 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
226
393
  // YANLIŞLIKLA yer almıştı — Notification.svelte hem timeout'ta hem kapatma tıklamasında
227
- // dispatch('emit', { name:'toggled', data:{isHidden:true}, setter:true }) çağırıyor (düzeltme
228
- // 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.
229
396
  autocomplete: {
230
397
  mount: NO_DATA,
231
398
  change: {
@@ -244,52 +411,112 @@ export const componentEventContracts = {
244
411
  focus: NO_DATA,
245
412
  blur: NO_DATA
246
413
  },
247
- avatar: { click: NO_DATA },
248
- badge: { click: NO_DATA },
249
- 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
+ },
250
433
  'breadcrumb-title': {
251
434
  mount: NO_DATA,
252
- clickItem: { payload: { currentItem: '{ text, flow, isHidden } — tıklanan iz öğesi' } },
253
- 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
+ }
254
443
  },
255
444
  carousel: {
256
445
  mount: NO_DATA,
257
- slideChange: { payload: { activeIndex: 'number' } },
258
- 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
+ }
259
454
  },
260
455
  chart: {
261
456
  mount: NO_DATA,
262
- 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' },
263
458
  breadcrumbClick: { payload: { filterValue: 'hedef seviyenin filtre değeri (kök seviyede undefined)' } },
264
459
  selectionChange: { payload: { selected: 'seçili veri noktaları' } },
265
460
  legendClick: { payload: { name: 'string (seri adı)', selected: 'seri → görünürlük haritası' } },
266
- axisLabelClick: { payload: { value: 'string (tıklanan eksen etiketi)' } },
267
- 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)' },
268
463
  refresh: NO_DATA,
269
464
  retry: NO_DATA
270
465
  },
271
466
  checkboxgroup: { mount: NO_DATA, change: valueChange('string[] (seçili değerler)'), focus: NO_DATA, blur: NO_DATA },
272
- emptystate: { actionClick: { payload: { text: 'string (aksiyonun metni)', index: 'number' }, reads: "aksiyonun kendi flow'u zaten doğrudan çalışır" } },
273
- 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
+ },
274
483
  jsonviewer: {
484
+ mount: NO_DATA,
275
485
  nodeClick: {
276
486
  payload: {
277
487
  path: "string (nokta/köşeli-parantez yolu — 'user.roles[0].name'; kökte boş)",
278
488
  key: 'string (düğümün anahtarı; dizi öğesinde indeks)',
279
489
  kind: "'object' | 'array' | 'string' | 'number' | 'boolean' | 'null'",
280
490
  value: 'düğümün ham değeri (object/array için alt ağacın tamamı)'
281
- }
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'
282
493
  },
283
494
  copy: {
284
495
  payload: {
285
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ş)",
286
498
  kind: "'root' | 'object' | 'array' | 'string' | 'number' | 'boolean' | 'null'",
287
499
  value: 'kopyalanan değer (tümünü kopyalamada normalize edilmiş TÜM veri)'
288
- }
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. 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"
289
518
  }
290
519
  },
291
- 'language-selector': { change: { payload: { value: 'string (dil kodu)' }, reads: 'runtime ayrıca machine.setLanguage(value) çağırır' } },
292
- notification: { toggled: { payload: { isHidden: 'boolean' } } },
293
520
  otpinput: {
294
521
  mount: NO_DATA,
295
522
  change: valueChange('string (birleşik kod)'),
@@ -298,10 +525,22 @@ export const componentEventContracts = {
298
525
  focus: NO_DATA,
299
526
  blur: NO_DATA
300
527
  },
301
- pagination: { mount: NO_DATA, change: { payload: { offset: 'number', limit: 'number' }, reads: 'self.offset · self.limit (sorguyu bunlara bağla)' } },
302
- 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 },
303
536
  rating: { mount: NO_DATA, change: valueChange('number (0..max; allowHalf ile yarım)'), focus: NO_DATA, blur: NO_DATA },
304
- 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
+ },
305
544
  slider: {
306
545
  mount: NO_DATA,
307
546
  change: valueChange('number (sürüklerken sürekli)'),
@@ -309,7 +548,7 @@ export const componentEventContracts = {
309
548
  focus: NO_DATA,
310
549
  blur: NO_DATA
311
550
  },
312
- 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" } },
313
552
  switcher: {
314
553
  mount: NO_DATA,
315
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" },
@@ -318,15 +557,31 @@ export const componentEventContracts = {
318
557
  focus: NO_DATA,
319
558
  blur: NO_DATA
320
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
+ },
321
567
  timeline: {
322
568
  mount: NO_DATA,
323
- clickItem: { payload: { currentItem: 'tıklanan olay öğesi', index: 'number' }, reads: "öğenin kendi flow'u da doğrudan çalışır" },
324
- 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)' }
325
574
  },
326
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 },
327
576
  toast: {
328
- open: NO_DATA,
329
- 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
+ },
330
585
  click: NO_DATA,
331
586
  actionClick: { payload: { text: 'string (aksiyonun metni)', index: 'number' }, reads: "aksiyonun kendi flow'u zaten doğrudan çalışır" }
332
587
  },
@@ -350,47 +605,96 @@ export const componentEventContracts = {
350
605
  eventcalendar: {
351
606
  mount: NO_DATA,
352
607
  monthChange: {
353
- payload: { month: 'number (1-TABANLI)', year: 'number' },
354
- 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)"
355
624
  },
356
- viewChange: { payload: { view: "'month' | 'week' | 'day'" }, reads: "self'e yazılmaz — event.data ile oku" },
357
625
  dateClick: {
358
626
  payload: { date: "string 'yyyy-MM-dd'" },
359
- 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"
360
628
  },
361
629
  eventCreate: {
362
- payload: { start: "string (ay tıklaması: 'yyyy-MM-dd' · saat slotu: ISO)", end: 'string (slotta start+60dk)', allDay: 'boolean' },
363
- 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"
364
636
  },
365
637
  eventClick: {
366
638
  payload: { id: 'string', title: 'string', row: 'kaynak satırın TAMAMI' },
367
- 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"
368
640
  },
369
641
  eventMove: {
370
- payload: { id: 'string', row: 'kaynak satırın TAMAMI', start: 'string (ISO)', end: 'string (ISO)', previousStart: 'string (ISO)', previousEnd: 'string (ISO)' },
371
- 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"
372
651
  }
373
652
  },
374
653
  importwizard: {
375
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
+ },
376
663
  complete: {
377
664
  payload: {
378
665
  rows: 'Record<string,string>[] (TEMİZ satırlar; değerler hep string)',
379
- errors: 'Array<{ rowIndex, field, message, raw }>',
666
+ errors: 'Array<{ rowIndex, field, code, message, limit?, raw }> (code: required | maxRows)',
380
667
  fileName: 'string',
381
668
  total: 'number (temiz satır + hata KAYDI sayısı)'
382
669
  },
383
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"
384
671
  },
385
- 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
+ }
386
682
  },
387
683
  kanban: {
388
684
  mount: NO_DATA,
389
685
  cardMove: {
390
686
  payload: { id: 'string', row: 'kaynak satırın TAMAMI', from: 'string (kaynak kolon value)', to: 'string (hedef kolon value)' },
391
- 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"
392
688
  },
393
- 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
+ }
394
698
  },
395
699
  signature: {
396
700
  mount: NO_DATA,
@@ -404,7 +708,7 @@ export const componentEventContracts = {
404
708
  mount: NO_DATA,
405
709
  stepChange: {
406
710
  payload: { currentStep: 'number (hedef adım, 0 tabanlı)', previous: 'number (önceki adım)' },
407
- 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"
408
712
  },
409
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' },
410
714
  validationFail: {