@appaflytech/zeyrek-ai-mcp 0.0.22 → 0.0.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/knowledge/componentCatalog.js +3 -1
- package/dist/knowledge/componentEvents.js +3 -3
- package/dist/knowledge/mobileComponentCatalog.js +86 -1
- package/dist/knowledge/mobileComponentEvents.js +12 -0
- package/dist/knowledge/platform/mobile.js +1 -1
- package/dist/knowledge/platform/mobileRules.js +8 -5
- package/dist/knowledge/platform/web.js +1 -1
- package/dist/knowledge/rules.js +50 -4
- package/dist/resources/guides/mobile.md +21 -2
- package/dist/resources/guides/page.md +15 -2
- package/package.json +1 -1
|
@@ -769,7 +769,7 @@ export const componentKnowledge = {
|
|
|
769
769
|
value: "Seçili dosya(lar). Panelde ÇİZİLİR ve akıştan yazılabilir (2026-09-17'ye kadar gizliydi, bu yüzden AI sözlüğünde de görünmüyordu): kayıtlı bir dosyayı forma geri basmanın yolu budur. Tekli kipte nesne, çoklu kipte dizi; boşaltmak için null (çoklu kipte []). Kipiyle uyuşmayan şekil de OKUNUR: çoklu kipte yazılan tek nesne listelenir, tekli kipte yazılan dizinin ilk dosyası çizilir (2026-09-17'ye kadar ikisi de sessizce hiçbir şey göstermiyordu). İçeriği olmayan kayıt (ne value ne data ne absolute_path) hiç çizilmez.",
|
|
770
770
|
text: 'Butonun üzerindeki metin (varsayılan "Attach File"); ikon sabittir. Alanın başlığı ayrı bir prop\'tur: label.',
|
|
771
771
|
description: 'Butonun altındaki yardım metni. Dosya seçilir seçilmez yerini dosya listesi alır, seçim temizlenince geri gelir (fileInput ile aynı kural).',
|
|
772
|
-
allowedFiletypes: 'İzin verilen uzantılar (çoklu seçim, kapalı liste). Hem dosya diyaloğunun accept süzgecini hem de seçimden SONRAKİ denetimi besler: liste dışı bir dosya seçilirse değere girmez ve komponentin içinde "desteklenmiyor" uyarısı çizilir (2026-09-17; öncesinde yalnız diyalog süzgeciydi, "Tüm dosyalar" ile aşılabiliyordu). Hem allowedFiletypes hem customFiletypes boşsa her tür serbesttir.',
|
|
772
|
+
allowedFiletypes: 'İzin verilen uzantılar (çoklu seçim, kapalı liste). Hem dosya diyaloğunun accept süzgecini hem de seçimden SONRAKİ denetimi besler: liste dışı bir dosya seçilirse değere girmez ve komponentin içinde "desteklenmiyor" uyarısı çizilir (2026-09-17; öncesinde yalnız diyalog süzgeciydi, "Tüm dosyalar" ile aşılabiliyordu). Hem allowedFiletypes hem customFiletypes boşsa her tür serbesttir. Akış prop\'a düz metin yazabilir ("pdf,png", customFiletypes ile aynı ayraçlar) — 2026-09-25`e kadar bu komponenti `input.map is not a function` ile düşürüyordu (fileInput okuyordu).',
|
|
773
773
|
customFiletypes: 'Listede olmayan uzantılar, serbest metin ("heic, dwg;psd"). Virgül, noktalı virgül ve boşluk ayraçtır; baştaki nokta ve yıldız atılır, büyük/küçük harf fark etmez. allowedFiletypes ile BİRLEŞİR, onun yerine geçmez (fileInput ile aynı ad ve aynı kural). Çok parçalı uzantı da yazılabilir ("tar.gz"): eşleşme adın SONUNA bakar, son noktadan sonrasına değil.',
|
|
774
774
|
maxFileSizeMb: 'Dosya BAŞINA en büyük boyut (MB). Boş/0/negatif değer sınırsız demektir; aşan dosya değere girmez, uyarı komponentin içinde çizilir.',
|
|
775
775
|
maxFileCount: "Çoklu kipte toplam dosya sayısı sınırı — zaten seçili olanlar da sayılır. Boş/0/negatif sınırsız. Tekli kipte hiç okunmaz ve panelde de gizlidir (isMultiple'a bağlı).",
|
|
@@ -1553,6 +1553,8 @@ export const componentKnowledge = {
|
|
|
1553
1553
|
'aggregate/sort/topN/nullMode veriyi çizimden ÖNCE dönüştürür — aynı işi akışta yapmana gerek yok.',
|
|
1554
1554
|
'isDrillDown:true iken veri noktasına tıklamak kırıntı seviyesi ekler; dataPointClick yükü kaynak satırın TAMAMINI (row) taşır, böylece alt seviye sorgusu tek olayla kurulur. Geri dönüş breadcrumbClick ile bildirilir ve yeniden sorgulamak akışın işidir.',
|
|
1555
1555
|
'isExportable "tablo olarak gör" + dışa aktarma araç çubuğunu açar; showRefresh refresh olayını yayan bir yenile düğmesi ekler.',
|
|
1556
|
+
"OLAYLAR (2026-09-25 düzeltmesi): nokta tıklaması YALNIZ dataPointClick, kategori ekseninin etiketine basış YALNIZ axisLabelClick yayar (yatay çubukta etiketler y eksenindedir). Öncesinde axisLabelClick her nokta tıklamasında noktanın değeriyle geliyor, etikete basış ise hiç gelmiyordu: triggerEvent eksen yerine axisLabel altındaydı ve olay sorgusu nesne olduğu için süzmüyordu. Hedef çizgisi, bant ve eksen başlığı tıklaması olay değildir; selectionChange yalnız selectionMode açıkken gelir (kapalıyken ECharts'ın boş seçimi self.selected'ı eziyordu); dataPointClick.row kategori adıyla bulunur (nullMode skip sonrası kayan dataIndex yanlış satırı veriyordu). Eşleme mobil chart ile ortak (chart-events.ts).",
|
|
1557
|
+
'BOZUK BAĞLI VERİ (2026-09-25): series/rows beklenmedik şekilde gelirse (dizi yerine metin, okunamayan alan) grafik düşmez — veri çözülemezse emptyText, seçenek kurulamazsa önceki çizim kalır. Eksen başlığı (categoryAxis.title / valueAxis.title) varsayılan ızgarada tuvalden taşar ve görünmez (ARC-129).',
|
|
1556
1558
|
"PASTA/HALKA ETİKETİ (2026-08-27 düzeltmesi): dataLabels.show artık pie/donut'a da geçiyor. Öncesinde prop bu dala hiç ulaşmıyordu ve dilim etiketleri HİÇBİR ayarla kapatılamıyordu — çekme çizgileri legend'in üstüne bindiği için halka fiilen kullanılamıyordu. Temiz halka için dataLabels:{ show:false } yaz.",
|
|
1557
1559
|
'LEGENDDEN SERİ GİZLEME ÇALIŞIYOR (2026-09-16 düzeltmesi): legend tıklaması artık kalıcı. Öncesinde tıklama ~8 ms sonra kendiliğinden geri alınıyordu — olay yükü prop’lara yazılıyor, tepkime notMerge çizim yapıyor ve ECharts’ın legend.selected durumu siliniyordu. Seçim çizimden önce option’a geri yazılıyor; listede olmayan seri adları elenir.',
|
|
1558
1560
|
'YATAY + İKİNCİL EKSEN ÇİZİLİYOR (2026-09-16 düzeltmesi): orientation:"horizontal" ile bir seride axis:"secondary" birlikte verilince grafik SESSİZCE boş çiziliyordu — yatayda değer eksenleri xAxis dizisindedir, yAxis tek kategori eksenidir. Kombo grafiği artık iki yönelimde de kurulabilir.',
|
|
@@ -454,11 +454,11 @@ export const componentEventContracts = {
|
|
|
454
454
|
},
|
|
455
455
|
chart: {
|
|
456
456
|
mount: NO_DATA,
|
|
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
|
|
457
|
+
dataPointClick: { payload: { name: 'string (kategori); scatter grafiğinde x değeri', seriesName: 'string', value: 'number | null; scatter grafiğinde y', dataIndex: 'number (çizimdeki sıra)', row: 'kaynak satırın TAMAMI | null' }, reads: 'YALNIZ seri noktasına basışta; eksen etiketi tıklaması axisLabelClick’tir (2026-09-16 öncesinde o da boş bir dataPointClick üretiyordu), hedef çizgisi (referenceLines) ve bant (plotBands) olay değildir. row kategori adıyla — scatter’da x değeriyle — bulunur (nullMode skip ya da huni sıralaması dataIndex`i kaydırır); kategorisi olmayan noktada (histogram kutusu, radar serisi, funnelflow düğümü/bağı) null. scatter noktası ECharts tarafında [x, y, size] dizisidir, yük tek değere indirgenir: name = x, value = y' },
|
|
458
458
|
breadcrumbClick: { payload: { filterValue: 'hedef seviyenin filtre değeri (kök seviyede undefined)' } },
|
|
459
|
-
selectionChange: { payload: { selected: 'seçili veri noktaları' } },
|
|
459
|
+
selectionChange: { payload: { selected: 'seçili veri noktaları' }, reads: "yalnız selectionMode 'single'/'multi' iken; 'none' iken ECharts'ın her tıklamada attığı boş seçim yayılmaz (2026-09-25 öncesi yayılıyordu)" },
|
|
460
460
|
legendClick: { payload: { name: 'string (seri adı)', selected: 'seri → görünürlük haritası' } },
|
|
461
|
-
axisLabelClick: { payload: { value: 'string (tıklanan eksen etiketi)' }, reads: '
|
|
461
|
+
axisLabelClick: { payload: { value: 'string (tıklanan eksen etiketi)' }, reads: 'yalnız kategori ekseninin etiketine basışta; kategori ekseni hangi eksene düşerse oradan gelir — yatay yönelimde yAxis (2026-09-16 öncesinde yatayda hiç yayılmıyordu). Nokta tıklaması ve eksen başlığı (categoryAxis.title) bu olayı yaymaz — 2026-09-25 öncesinde nesne sorgusu süzmediği için her nokta tıklamasında noktanın değeriyle yayılıyordu' },
|
|
462
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)' },
|
|
463
463
|
refresh: NO_DATA,
|
|
464
464
|
retry: NO_DATA
|
|
@@ -520,7 +520,7 @@ export const mobileComponentKnowledge = {
|
|
|
520
520
|
'Vuruş sürerken sayfanın ve `scroll-view`un kaydırması kilitlidir: dikey vuruş sayfayı sürüklemez (web`de pedin `touch-action: none`ı); parmak kalkınca sayfa normal kayar.',
|
|
521
521
|
'Temizle düğmesi (`<elementId>__clear`, `clearText`, boşsa "Clear") çizim ya da değer varken ve alan kilitsizken görünür; basınca önce `change { value: \'\' }`, sonra `clear`. Ped `<elementId>__pad`. Tasarım kipinde çizilmez, Temizle basılmaz.',
|
|
522
522
|
'Boyu kabuktan gelen düğümde (`heightType: fixed` ya da `fill`) ped kabuğu doldurur; yoksa taban yükseklik boya göre 72/96/128 dp. Kayıtlı `value` PNG ise görsel, SVG (ham işaretleme ya da `data:image/svg+xml`) ise vektör olarak çizilir; tanınmayan metin çizilmez. Düşen: `style`.',
|
|
523
|
-
'iOS`ta sistem jesti imzadan önce gelir: iOS 26`da yığına itilmiş sayfada pede SAĞA atılan vuruş sayfayı kapatır (
|
|
523
|
+
'iOS`ta sistem jesti imzadan önce gelir: iOS 26`da yığına itilmiş sayfada pede SAĞA atılan vuruş sayfayı kapatır (iOS 26`nın içerikten geri kaydırması — platform davranışı, ölçüldü), `modal` sunumlu sayfada aşağı vuruş sayfayı kapatabilir (ölçülmedi). İmzayı sekme kökündeki ya da itilmemiş sayfaya koyun.'
|
|
524
524
|
]
|
|
525
525
|
},
|
|
526
526
|
webview: {
|
|
@@ -539,5 +539,90 @@ export const mobileComponentKnowledge = {
|
|
|
539
539
|
injectedJs: 'Belge yüklenince koşan JavaScript (ör. `window.ReactNativeWebView.postMessage(document.title)`); cihazda iki içerikte, web`de yalnız `html`de. Gömülen sayfada tam yetkiyle koşar — yalnız güvenilen içerikte kullanın.',
|
|
540
540
|
title: 'Erişilebilirlik etiketi (ekran okuyucu; web`de `<iframe title>`).'
|
|
541
541
|
}
|
|
542
|
+
},
|
|
543
|
+
chart: {
|
|
544
|
+
summary: 'Grafik; prop`lar, on altı tip (scatter dahil) ve kalan olaylar web ikizininki. Seçenek ve olay eşlemesi web`in modülünden gelir (`buildChartOption`, `chart-events.ts`): iki platform aynı ECharts seçeneğini çizer, aynı olayları yayar.',
|
|
545
|
+
differences: [
|
|
546
|
+
'Cihazda ECharts `@wuba/react-native-echarts`in SVG motoruyla (`react-native-svg`) çizilir, kanvas ve önizlemede ECharts`ın kendi tuvaliyle. Tema renkleri ve yazı ailesi temanın `--ng-*` değişkenlerinden; cihazda yazı yığının ilk ailesidir, yüklü değilse platform yazı tipi.',
|
|
547
|
+
'Düşenler: `style`; `isExportable` ve `exportFileName` (CSV/PNG indirme, tablo görünümü, tam ekran — dosya kaydetmek ayrı native modül ister); `showTypeSwitcher` ve `showRefresh` ile `refresh` olayı (tip akışla `chartType` yazılarak, yenileme sayfanın kaydırarak yenilemesiyle); `isDrillDown` ile `breadcrumbClick` (tıklanan noktanın satırı `dataPointClick { row }` ile yine gelir).',
|
|
548
|
+
'Kutu: kabuktan gelen boy (`heightType: fixed` ölçülü ya da `fill`) ya da panelin `aspectRatio`su, yoksa 240 dp; `caption` web`deki gibi kutunun altında metindir ve grafik alanından pay alır. Durum web`in sırasıyla: yükleniyor (ortada dönen gösterge — web kutuyu boş bırakır, ARC-127), hata (`errorText` + Yeniden dene düğmesi `<elementId>__retry`, `retry` yayar), veri yok (`emptyText`).',
|
|
549
|
+
'Dokunuş: noktaya dokunmak YALNIZ `dataPointClick` (seri), kategori ekseninin etiketine dokunmak YALNIZ `axisLabelClick` (yatay çubukta etiketler y ekseninde), legend maddesi `legendClick`; hedef çizgisi, bant ve eksen başlığı olay değildir, `selectionChange` yalnız `selectionMode` açıkken gelir (web ile aynı). Dokunulan noktada ipucu açılır; sayfa kaydırılınca açık kalır, grafiğin başka yerine dokununca yer değiştirir. Grafiğin üstünden dikey kaydırma sayfayı kaydırır; 4 px`ten uzun sürükleme tıklama sayılmaz.',
|
|
550
|
+
'Olay yükü düğüme yazılınca grafik yeniden KURULMAZ: seçim, gizlenen legend serisi ve yakınlaştırma korunur; seçenek girdinin içeriği değişince yeniden uygulanır ve legend seçimi sıfırlanır (web onu korur — ARC-131). Bozuk bağlı veri bileşeni düşürmez: çözülemezse `emptyText`, seçenek kurulamazsa önceki çizim kalır. Başlıklı kartezyen grafikte başlık çizim alanının tepesine biner (ARC-126), eksen başlığı tuvalden taşar (ARC-129) — ikisi web ile aynı.'
|
|
551
|
+
]
|
|
552
|
+
},
|
|
553
|
+
datepicker: {
|
|
554
|
+
summary: 'Tek gün seçici; kutuya dokununca cihazda işletim sisteminin seçicisi (iOS satır içi takvim, Android iletişim kutusu), önizlemede (`/preview`, `/dev`) tarayıcının seçicisi açılır — kanvasta alan kilitlidir. Değer, sınır ve olaylar web ikizininki.',
|
|
555
|
+
differences: [
|
|
556
|
+
'Kutu `dropdown` tetikleyicisinin görünümündedir (`role="combobox"`, iç rol `<elementId>__trigger`, temizleme `<elementId>__clear`); X değer varken, alan kilitli değilken ve yüklenmiyorken çizilir. `isLoading` ikonun yerinde dönen gösterge çizer, kilit değildir (kutu açılır — web gibi).',
|
|
557
|
+
'Seçici: iOS`ta alttan açılan sayfada satır içi takvim — gün seçilip Tamam/Done (`<elementId>__done`) ile yazılır, dışına dokunmak vazgeçer (seçimde yazılmaz: seçili güne yeniden dokunmak değer bildirmez, takvimin ay/yıl çarkı bildirir — ikisi iOS 26.2 simülatöründe ölçüldü, 09 adım 4); Android`de sistem iletişim kutusu (Android cihazda ölçülmedi). Önizlemede kutunun içindeki görünmez `<input type="date">` tarayıcının seçicisini açar (`showPicker()`).',
|
|
558
|
+
'Otomasyon: `page_screenshot` `set` KÖKE değil `<elementId>__input`a yazılır, HTML biçimiyle — `yyyy-MM-dd` (`2026-08-01`). Kök `set` kutunun `role="combobox"`u yüzünden açılır kutu yoluna girer ve "açılır kutu AÇILMADI" der; biçimsiz değer (`1 Ağu 2026`, saatli metin) tarayıcıda boşalır ve yok sayılır — alan yalnız X`le (`__clear`) boşalır.',
|
|
559
|
+
'Değer web gibi yerel duvar saati `yyyy-MM-ddTHH:mm:ss` (seçimde `T00:00:00`); `minDate`/`maxDate` gün sınırıdır — seçici dışını kapatır, yazılan değer sınır gününe çekilir; `valueOffset`/`displayOffset` web kuralı. `focus` seçici açılınca, `blur` kapanınca gelir.',
|
|
560
|
+
'Kutu metni web`in deseniyle (`tr` `d MMM yyyy`, diğerleri `MMM d, yyyy`); dil alanın `locale`i, yoksa uygulama dili. Düşen: `style`.'
|
|
561
|
+
]
|
|
562
|
+
},
|
|
563
|
+
timepicker: {
|
|
564
|
+
summary: 'Saat seçici (`HH:mm`); cihazda işletim sisteminin saat çarkı/kutusu, önizlemede tarayıcının seçicisi. `change` web gibi `{ value, selectedLabel }`.',
|
|
565
|
+
differences: [
|
|
566
|
+
'Web`in listesi yerine işletim sisteminin seçicisi: iOS`ta alttan açılan sayfada çark + Tamam/Done, Android`de sistem saat kutusu; önizlemede `<input type="time">` tarayıcı seçicisi. Çark izinli en yakın saatte açılır — kaydırmadan Tamam yazılanı görünenle aynı tutar. Kutu, temizleme ve otomasyon `datepicker` ile aynı (`set` `<elementId>__input`a `HH:mm`). Web listesi gibi `isLoading` iken açılmaz.',
|
|
567
|
+
'Sistem seçicisi tek tek saati KAPATAMAZ: `minTime`/`maxTime` dışındaki, `disabledTimes`taki ya da adım dışı seçim İZİNLİ EN YAKIN saate yaslanır (eşitlikte erken olan; iOS çarkı sınırı zaten uygular); izinli saat yoksa hiçbir şey yazılmaz. Web`de bu saatler listede kapalı görünür. Ters sınır (`22:00`–`06:00`) seçiciye verilmez — her saat kapalı sayılır, web gibi.',
|
|
568
|
+
'`format: 12h` web gibi yalnız gösterimdir (kutu ve `selectedLabel` `01:00 PM`, değer `13:00`); iOS çarkı dilin kendi saat düzeniyle açılır (Türkçe 24, İngilizce 12 saat); Android saat kutusuna `format` verilir (Android cihazda ölçülmedi). `clearable: false` X`i kaldırır.',
|
|
569
|
+
'Düşenler: `style`, `emptyText` (web listesinin aramasındaki "sonuç yok" metni; sistem seçicisinde arama yok).'
|
|
570
|
+
],
|
|
571
|
+
propNotes: {
|
|
572
|
+
minutesStep: 'Çarkın adımı, adımı bölen en büyük desteklenen aralıktır (60 → 30`luk çark); seçim yine adıma yaslanır.'
|
|
573
|
+
}
|
|
574
|
+
},
|
|
575
|
+
datetimepicker: {
|
|
576
|
+
summary: 'Tarih + saat tek kutuda; cihazda iOS satır içi takvim + saat tek sayfada (Tamam/Done ile gösterilen an yazılır — boş alan şimdiyle, adımın ızgarasında açılır), Android önce tarih sonra saat (saatten vazgeçmek hiçbir şey yazmaz — kodla, Android cihazda ölçülmedi); önizlemede `<input type="datetime-local">`.',
|
|
577
|
+
differences: [
|
|
578
|
+
'Web`in iki kutusu (tarih + saat) mobilde TEK kutudur: metin tarih ve saati birlikte gösterir (İngilizcede 12 saat, diğer dillerde 24; saat metni platformun Intl`iyle — cihaz `3:00 PM`, web `03:00 PM`); boşken `placeholder` görünür.',
|
|
579
|
+
'Seçilen an saniyesi sıfırlanıp web`in saat başı ızgarasına (`minutesStep`; 45 dakikada :00 ve :45, saatten uzun adımda saat başları) ve `minDate`/`maxDate` an sınırına çekilir, `valueOffset` eklenir: `yyyy-MM-ddTHH:mm:ss`. Android`de saat kutusundan vazgeçmek hiçbir şey yazmaz (web: boş alanda yalnız gün seçmek yaymaz, CQ-237).',
|
|
580
|
+
'Kutu, temizleme, otomasyon (`set` `<elementId>__input`a `yyyy-MM-ddTHH:mm`) ve `focus`/`blur` `datepicker` ile aynı. Düşenler: `style`, `timePlaceholder` (web`in ayrı saat kutusunun metni).'
|
|
581
|
+
]
|
|
582
|
+
},
|
|
583
|
+
fileInput: {
|
|
584
|
+
summary: 'Dosya alanı; kutuya ya da Gözat`a dokununca cihazda `source`un seçicisi (varsayılan belge seçici), önizlemede tarayıcının dosya penceresi açılır — kanvasta alan kilitlidir. Değer, kapılar ve `change` web ikizininki — dosya YÜKLENMEZ, base64 veri URL`si düğüme yazılır.',
|
|
585
|
+
differences: [
|
|
586
|
+
'Seçici `source` ile seçilir (yalnız mobilde): `files` belge seçicisi (bütün türleri gösterir; izin listesi seçimden SONRA uygulanır ve web`in tür uyarısını çizer), `library` fotoğraf arşivi, `camera` kamera (izin istenir, verilmezse hiçbir şey olmaz), `ask` her seferinde sorar. Önizlemede görünmez `<input type="file">` açılır (`library`/`camera` `accept="image/*"`); otomasyon `<elementId>__input`a dosya verir. Seçici açıkken ve okuma sürerken alan meşguldür: ikinci seçici açılmaz, satır silme ve temizleme bekler.',
|
|
587
|
+
'Değer web gibi `{ value: base64 veri URL`si, fileName, type: "file" }` (çoklu kipte dizi, yeni seçim üstüne eklenir; boşaltma `{ type: "ref", value: null }`, çoklu kipte `[{ type: "ref", value: null }]`). Base64 sayfa durumunda taşındığı için `maxFileSizeMb` koyun. Fotoğraf arşivinden gelen HEIC iOS`ta JPEG`e çevrilir (`.jpg` — web`de Safari`nin yaptığı gibi), fotoğraflar `quality` ile sıkıştırılır.',
|
|
588
|
+
'Tür/boyut/adet kapısı web kuralıdır (tek uyarı, tür ihlali önce; uyarı metni uygulama dilinde). İç roller: kutu `<elementId>__field`, Gözat `__browse`, temizle `__clear`, çoklu kipte satır silme `__file-<n>__delete`. `isReadonly`/`isViewmode` Gözat`ı ve X`i gizler.',
|
|
589
|
+
'Düşenler: `style`, `enableCrop` ve `cropAspectRatio` (kırpma katmanı yok).'
|
|
590
|
+
],
|
|
591
|
+
propNotes: {
|
|
592
|
+
source: 'Dosyanın geldiği yer: `files` (belgeler, varsayılan), `library` (fotoğraf arşivi), `camera`, `ask` (Kamera / Fotoğraflar / Dosyalar sorulur). `library` ve `camera` yalnız fotoğraf verir.',
|
|
593
|
+
quality: 'Fotoğrafın JPEG sıkıştırma kalitesi, 0,1–1 (varsayılan 0,8); `source: files` iken panelde gizlidir. Belgeye dokunmaz.'
|
|
594
|
+
}
|
|
595
|
+
},
|
|
596
|
+
filebutton: {
|
|
597
|
+
summary: 'Ataşlı dosya düğmesi; dokununca varsayılan olarak kaynak sorulur (Kamera / Fotoğraflar / Dosyalar), önizlemede tarayıcının dosya penceresi açılır — kanvasta düğme kilitlidir. Değer, kapılar ve `change` web ikizininki — dosya YÜKLENMEZ.',
|
|
598
|
+
differences: [
|
|
599
|
+
'`source` varsayılanı `ask`: iOS`ta eylem sayfası, Android`de üç düğmeli uyarı (dışına dokunmak vazgeçer; Android cihazda ölçülmedi); `files`/`library`/`camera` doğrudan açar. Vazgeçmek değeri değiştirmez; seçici açıkken ve okuma sürerken düğme meşguldür (ikinci seçici açılmaz, satır silme bekler). Simülatörde kamera açılır ama görüntü üretmez — çekim gerçek cihazda sınanır.',
|
|
600
|
+
'Değer web gibi `{ type: "file", value: base64 veri URL`si, fileName, ref: "" }` (çoklu kipte dizi, yeni seçim üstüne eklenir; boşaltma `null`, çoklu kipte `[]`). Tür ve sınır web gibi İKİ bağımsız uyarıdır. HEIC fotoğraf iOS`ta JPEG`e çevrilir (`.jpg`); kameradan gelen fotoğrafın özgün adı olmadığı için geçici dosya adıyla yazılır.',
|
|
601
|
+
'İç roller: düğme `<elementId>__button`, satır silme `__file-<n>__delete`, çoklu kipte "Tümünü temizle" `__clear`. Açıklama yalnız dosya yokken görünür (web gibi).',
|
|
602
|
+
'Düşen: `style`.'
|
|
603
|
+
],
|
|
604
|
+
propNotes: {
|
|
605
|
+
source: 'Dosyanın geldiği yer: `ask` (varsayılan; Kamera / Fotoğraflar / Dosyalar sorulur), `files`, `library`, `camera`. `library` ve `camera` yalnız fotoğraf verir.',
|
|
606
|
+
quality: 'Fotoğrafın JPEG sıkıştırma kalitesi, 0,1–1 (varsayılan 0,8); `source: files` iken panelde gizlidir.'
|
|
607
|
+
}
|
|
608
|
+
},
|
|
609
|
+
map: {
|
|
610
|
+
summary: 'Harita ve işaretçiler (FlutterFlow GoogleMap). Web`de karşılığı YOKTUR.',
|
|
611
|
+
differences: [
|
|
612
|
+
'Cihazda `react-native-maps`: iOS Apple Haritalar, Android Google Haritalar (Expo Go`da anahtarsız; geliştirme/EAS derlemesinde Android Google anahtarı ve konum izin metinleri gerekir — ARC-128). Kanvas ve önizlemede Leaflet + OpenStreetMap karoları (anahtarsız, köşede OSM atfı; OSM`nin ortak karo sunucusu yoğun trafiğe açık değildir). Kanvasta dokunuş almaz ve sürüklenmez; karolar ve işaretçiler çizilir.',
|
|
613
|
+
'Görünüm üç sayıdır: `latitude`, `longitude`, `zoom` (web harita ölçeği 1–19, kesirli olabilir; cihazda Apple/Google bölgesine çevrilir). Nesne `center` prop`u YOKTUR: bağlanan düz nesne runtime`da bozulur (ARC-117).',
|
|
614
|
+
'Akış `latitude`/`longitude`/`zoom` yazınca harita oraya gider (web`de anında, cihazda kısa canlandırmayla) ve `regionChange` YAYMAZ. Kullanıcı sürükleyip yakınlaştırınca bıraktığı görünüm `regionChange { latitude, longitude, zoom }` ile düğüme geri yazılır (`carousel.activeIndex` gibi: prop`a bağlı ifade o an ezilir). Kutu ya da pencere boyunun değişmesi olay sayılmaz.',
|
|
615
|
+
'İşaretçiye dokunmak `markerClick { markerId }` yayar ve başlığı ya da açıklaması varsa balon açar. Harita işaretçiye ORTALANMAZ; kenardaki işaretçinin balonu sığmazsa harita sığdıracak kadar kayar ve bu kayma `regionChange` yayar (iOS ve web`de ölçüldü). Üst üste binen işaretçilerde iOS`ta `markerId` açılan balonunkinden farklı olabilir (ARC-130). İşaretçi rengi temanın ana rengidir. Döndürme ve eğme kapalıdır (ölçek kuzey yukarı görünümün ölçeğidir).',
|
|
616
|
+
'`interactive: false` sürüklemeyi ve yakınlaştırmayı kapatır, işaretçiler dokunulabilir kalır ve sayfa haritanın üstünden kayar. Açıkken haritanın üstündeki dikey sürükleme haritayı kaydırır, sayfayı değil.',
|
|
617
|
+
'Kutu `webview` kuralından: kabuktan gelen boy ya da panelin `aspectRatio`su, yoksa 300 dp.'
|
|
618
|
+
],
|
|
619
|
+
propNotes: {
|
|
620
|
+
latitude: 'Merkezin enlemi (−90…90; Mercator sınırı ±85,05`e kırpılır). Sayı metni de okunur (`41,0082`); geçersiz ya da boş değer varsayılana (İstanbul) düşer.',
|
|
621
|
+
longitude: 'Merkezin boylamı; −180…180 dışındaki değer sarılır (190 → −170).',
|
|
622
|
+
zoom: 'Web harita ölçeği: 1 kıtalar, 19 bina; kesirli olabilir, aralık dışı kırpılır. Dünyadan geniş görünüm cihazda sığdırılır (iOS 180°/360°`ten geniş bölgeyi reddeder) ve Apple Haritalar küçük kutuda daha uzağa açılmaz: 402×300 kutuda `zoom: 1`, kullanıcı hareketinden sonra `zoom: 2` olarak yazılır (yazılan her zaman gerçek ölçektir).',
|
|
623
|
+
markers: '[{ id, latitude, longitude, title, description }] — bağlı sorgunun satırları da olur; `latitude`/`longitude`u sayı (ya da sayı metni) olmayan satır çizilmez. `id` boşsa sırası kimliktir (`markerClick { markerId }`).',
|
|
624
|
+
interactive: 'Sürükleme ve yakınlaştırma (varsayılan açık); kapalıyken işaretçiler yine dokunulur.',
|
|
625
|
+
showUser: 'Kullanıcının konumunu çizer. Cihazda iOS izni MapKit sorar, Android`de bileşen çalışma anı izni ister; web`de tarayıcı konum izni. Yalnız runtime`da. "Konumum" düğmesi yoktur (Android`inki kamerayı `regionChange` yaymadan taşırdı); konuma gitmek akışın `latitude`/`longitude` yazmasıdır.'
|
|
626
|
+
}
|
|
542
627
|
}
|
|
543
628
|
};
|
|
@@ -59,6 +59,18 @@ export const mobileComponentEventContracts = {
|
|
|
59
59
|
message: { payload: { data: "string — sayfanın window.ReactNativeWebView.postMessage(metin) ile yolladığı metin, olduğu gibi; makine data prop'una yazar (self.data)" } },
|
|
60
60
|
error: { payload: {}, reads: "cihazda sayfa yüklenemeyince (ağ hatası) yayılır, görünüm yer tutucu çizer; web'de pratikte gelmez (iframe gibi)" }
|
|
61
61
|
},
|
|
62
|
+
map: {
|
|
63
|
+
mount: NO_DATA,
|
|
64
|
+
markerClick: { payload: { markerId: "string — dokunulan işaretçinin `id`si (boşsa listedeki sırası); makine markerId prop'una yazar (self.markerId). Başlığı ya da açıklaması olan işaretçide balon da açılır" } },
|
|
65
|
+
regionChange: {
|
|
66
|
+
payload: {
|
|
67
|
+
latitude: 'number — kullanıcının bıraktığı merkezin enlemi (6 basamak)',
|
|
68
|
+
longitude: 'number — merkezin boylamı (6 basamak, −180…180)',
|
|
69
|
+
zoom: 'number — web harita ölçeği (2 basamak, 1–19)'
|
|
70
|
+
},
|
|
71
|
+
reads: "yalnız kullanıcının sürüklemesi ya da yakınlaştırması bitince yayılır; akışın yazdığı görünüm ve kutu boyu değişimi yaymaz. Makine üç prop'u da yazar (self.latitude, self.longitude, self.zoom)"
|
|
72
|
+
}
|
|
73
|
+
},
|
|
62
74
|
markdown: {
|
|
63
75
|
mount: NO_DATA,
|
|
64
76
|
linkClick: {
|
|
@@ -53,7 +53,7 @@ export const mobileProfile = Object.freeze({
|
|
|
53
53
|
},
|
|
54
54
|
style: { freeStyle: false, hoverStyle: false, resolver: 'native' },
|
|
55
55
|
steps: {
|
|
56
|
-
registered: new Set([...ENGINE_STEP_TYPES, 'alert', 'confirm', 'redirect', 'navigate', 'storage', 'setcookie', 'download']),
|
|
56
|
+
registered: new Set([...ENGINE_STEP_TYPES, 'alert', 'confirm', 'redirect', 'navigate', 'storage', 'setcookie', 'download', 'share']),
|
|
57
57
|
aliases: STEP_ALIASES,
|
|
58
58
|
infoOnly: new Set(['download', 'setcookie'])
|
|
59
59
|
},
|
|
@@ -58,15 +58,17 @@ export const REDIRECT_PRESENTATIONS = new Set(['push', 'modal', 'replace']);
|
|
|
58
58
|
* Mobil pakete giren bileşen Dalga 2/3 listesinden DÜŞER: yayında olduğunu mobil sözlükteki kaydı
|
|
59
59
|
* söyler (`mobileComponentKnowledge`, parite testiyle `components.json`'a kilitli). Katalog A
|
|
60
60
|
* (2026-09-24) sekiz web ikizini buradan indirdi: `radio`, `checkboxgroup`, `slider`, `tabs`, `badge`,
|
|
61
|
-
* `avatar`, `progress`, `collapsible-container`; Katalog C (09) Dalga 3'ten `video
|
|
62
|
-
*
|
|
61
|
+
* `avatar`, `progress`, `collapsible-container`; Katalog C (09) Dalga 3'ten `video`, `signature`, `chart`,
|
|
62
|
+
* `fileInput` ve `filebutton`ı, Dalga 2'den `datepicker` ve `timepicker`ı (`fileUpload`un sürükle-bırak alanı
|
|
63
|
+
* dokunmatikte yok: web'e özgü, karşılığı iki dosya alanı); dil dalgası (plans/mobil-coklu-dil F1, 2026-09-25)
|
|
64
|
+
* Dalga 2'den `language-selector`ı. Dalga 1
|
|
63
65
|
* listesi artık yalnız `mobileNotes`'un bilgi satırıdır — MOB-003'te yayındaki bileşeni sözlük tanır
|
|
64
66
|
* (`box-section` Dalga 1'de ama pakette yok).
|
|
65
67
|
*/
|
|
66
68
|
export const MOBILE_COMPONENT_WAVES = Object.fromEntries([
|
|
67
69
|
...['container', 'box-section', 'form', 'slot', 'text', 'icon', 'image', 'divider', 'spacer', 'button', 'textinput', 'textarea', 'numberinput', 'password', 'checkbox', 'switch', 'dropdown', 'repeater', 'card', 'emptystate', 'form-validation-errors', 'modal', 'drawer', 'app-bar'].map(slug => [slug, 1]),
|
|
68
|
-
...['box', '
|
|
69
|
-
...['datatable', '
|
|
70
|
+
...['box', 'phoneinput', 'statcard', 'detailview', 'page-header', 'autocomplete'].map(slug => [slug, 2]),
|
|
71
|
+
...['datatable', 'kanban', 'timeline', 'texteditor', 'html', 'stepper', 'tree-view'].map(slug => [slug, 3])
|
|
70
72
|
]);
|
|
71
73
|
export const MOBILE_WEB_ONLY = {
|
|
72
74
|
iframe: "'webview' (src ya da html; bağlantılar varsayılan olarak sistem tarayıcısında açılır)",
|
|
@@ -79,7 +81,8 @@ export const MOBILE_WEB_ONLY = {
|
|
|
79
81
|
popover: "'modal' widget'ı",
|
|
80
82
|
'theme-toggle': 'cihaz teması otomatik (koyu/açık)',
|
|
81
83
|
pagination: "'repeater' + daha fazla yükle düğmesi",
|
|
82
|
-
breadcrumb: "yığın gezinmesi (app-bar geri düğmesi)"
|
|
84
|
+
breadcrumb: "yığın gezinmesi (app-bar geri düğmesi)",
|
|
85
|
+
fileUpload: "'fileInput' (alan) ya da 'filebutton' (düğme) — dokunmatikte sürükle-bırak yok; ikisi de aynı base64 değeri yazar"
|
|
83
86
|
};
|
|
84
87
|
const STYLE_REPLACEMENTS = {
|
|
85
88
|
className: "yerine surfaceStyle (zemin, kenar, köşe, gölge) ve typographyStyle tipli gruplarını kullanın",
|
|
@@ -20,7 +20,7 @@ export const webProfile = Object.freeze({
|
|
|
20
20
|
},
|
|
21
21
|
style: { freeStyle: true, hoverStyle: true, resolver: 'css' },
|
|
22
22
|
steps: {
|
|
23
|
-
registered: new Set([...ENGINE_STEP_TYPES, 'alert', 'confirm', 'redirect', 'download', 'storage', 'setcookie']),
|
|
23
|
+
registered: new Set([...ENGINE_STEP_TYPES, 'alert', 'confirm', 'redirect', 'download', 'storage', 'setcookie', 'share']),
|
|
24
24
|
aliases: STEP_ALIASES,
|
|
25
25
|
infoOnly: new Set()
|
|
26
26
|
},
|
package/dist/knowledge/rules.js
CHANGED
|
@@ -154,7 +154,7 @@ const flowBranchNames = {
|
|
|
154
154
|
*/
|
|
155
155
|
export const knownFlowStepTypes = new Set([
|
|
156
156
|
'start', 'end', 'query', 'setter', 'download', 'condition', 'redirect', 'setcookie', 'alert', 'confirm',
|
|
157
|
-
'microservice', 'validation', 'flow-trigger', 'storage', 'navigate', 'code', 'function'
|
|
157
|
+
'microservice', 'validation', 'flow-trigger', 'storage', 'navigate', 'code', 'function', 'share'
|
|
158
158
|
]);
|
|
159
159
|
const flowFreeBranchTypes = new Set(['condition']);
|
|
160
160
|
/** `condition.types.ts` ConditionArgumentRuleType — motorun tanıdığı üçlü. */
|
|
@@ -167,7 +167,8 @@ const conditionRuleIdPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}
|
|
|
167
167
|
// Runtime.svelte'de HAM verilir (`argument: step.args`), yani bu alanlarda ifade değerlendirilmez.
|
|
168
168
|
const flowLiteralTextFields = new Map([
|
|
169
169
|
['alert', ['message', 'description']],
|
|
170
|
-
['confirm', ['message', 'title', 'confirmText', 'cancelText']]
|
|
170
|
+
['confirm', ['message', 'title', 'confirmText', 'cancelText']],
|
|
171
|
+
['share', ['title']]
|
|
171
172
|
]);
|
|
172
173
|
const flowExpressionLooking = /\$\{|\b(?:Steps|Page|Row|Widget|LocalStorage|state|self|item|event|error|cookie)\s*(?:\?\.|\.|\[)/;
|
|
173
174
|
// Barındırıcıya özel tipler BURADA kural üretmez. `navigate`i gateway normalizasyonu zaten
|
|
@@ -2365,7 +2366,7 @@ export const policyRules = [
|
|
|
2365
2366
|
id: 'FLOW-022',
|
|
2366
2367
|
module: 'flow',
|
|
2367
2368
|
appliesTo: ['create', 'update'],
|
|
2368
|
-
sourceRef: "alert.ts `const { message, alertType, description } = task.argument` → toast.error(message, { description }) / dialog.alert(message); confirm.ts `dialog.confirm(message, { title, confirmText, cancelText })` (boş çerçeve metni dialog.functions.ts resolveDialogFrame'de sabit metne düşer). Argüman Runtime.svelte'de HAM geçer (`argument: step.args`) — bu alanlarda hiçbir ifade değerlendirilmez, yazılan metin ekranda harfi harfine görünür (2026-09-06·2 koşusu S-13'ün ikinci turu: rehber hata mesajını göstermek için alert adımını öneriyordu)",
|
|
2369
|
+
sourceRef: "alert.ts `const { message, alertType, description } = task.argument` → toast.error(message, { description }) / dialog.alert(message); confirm.ts `dialog.confirm(message, { title, confirmText, cancelText })` (boş çerçeve metni dialog.functions.ts resolveDialogFrame'de sabit metne düşer). Argüman Runtime.svelte'de HAM geçer (`argument: step.args`) — bu alanlarda hiçbir ifade değerlendirilmez, yazılan metin ekranda harfi harfine görünür (2026-09-06·2 koşusu S-13'ün ikinci turu: rehber hata mesajını göstermek için alert adımını öneriyordu). share adımında (2026-09-25) yalnız `title` düz metindir: @ng-apps/flow resolveShareContent onu olduğu gibi verir, `message` ve `path` ifadedir",
|
|
2369
2370
|
check: definition => flowAllSteps(definition)
|
|
2370
2371
|
.flatMap((step) => {
|
|
2371
2372
|
const type = String(step.type ?? '');
|
|
@@ -2378,11 +2379,56 @@ export const policyRules = [
|
|
|
2378
2379
|
.map(field => ({
|
|
2379
2380
|
ruleId: 'FLOW-022',
|
|
2380
2381
|
severity: 'warn',
|
|
2381
|
-
message:
|
|
2382
|
+
message: type === 'share'
|
|
2383
|
+
? `'${flowStepLabel(step)}' share adımının '${field}' alanı ifade içeriyor ama bu alan DÜZ METİNDİR: başlık paylaşım penceresine olduğu gibi gider (iOS'ta e-posta konusu, Android'de seçici başlığı), ifade değerlendirilmez. Değişen içeriği ifade olan 'message' alanına yazın — ör. message: "'Şuna bak: ' + Page.properties.name"; bağlantı 'path' alanındadır.`
|
|
2384
|
+
: `'${flowStepLabel(step)}' ${type} adımının '${field}' alanı ifade içeriyor ama bu alan DÜZ METİNDİR: ${type}.ts task.argument.${field}'i doğrudan ekrana geçirir ve args hiçbir yerde değerlendirilmez (Runtime.svelte \`argument: step.args\`). Kullanıcı ifadenin sonucunu değil ifadenin KENDİSİNİ görür. Ucun mesajını göstermek için bir setter (ya da code) adımı kullanın — value { type: 'code', ref: 'Steps.error?.message' }; hata metninin nerede durduğu page.md §hata yolu'nda.`,
|
|
2382
2385
|
guide: 'ngapps://guides/page'
|
|
2383
2386
|
}));
|
|
2384
2387
|
})
|
|
2385
2388
|
},
|
|
2389
|
+
{
|
|
2390
|
+
id: 'FLOW-027',
|
|
2391
|
+
module: 'flow',
|
|
2392
|
+
appliesTo: ['create', 'update'],
|
|
2393
|
+
sourceRef: "share adımının argümanı StepManagementArgument'ın Title/Message/Path alanlarında saklanır (StepType.cs `share`, kök docs/adr/0001-share-akis-adimi.md); url/link/text gibi anahtarlar sözleşmede YOKTUR ve platform onları 200 ile sessizce düşürür — adım hiçbir şey paylaşmadan akış sürer. `message` ve `path` İFADEDİR (@ng-apps/flow resolveShareContent → runCode): tırnaksız 'https://…' JS'te etiket + yorumdur, undefined döner",
|
|
2394
|
+
check: definition => flowAllSteps(definition)
|
|
2395
|
+
.filter(step => step.type === 'share')
|
|
2396
|
+
.flatMap((step) => {
|
|
2397
|
+
const args = (step.args ?? {});
|
|
2398
|
+
const filled = (key) => typeof args[key] === 'string' && String(args[key]).trim().length > 0;
|
|
2399
|
+
const findings = [];
|
|
2400
|
+
const strayLinks = ['url', 'link', 'href'].filter(filled);
|
|
2401
|
+
const strayTexts = ['text', 'body', 'content'].filter(filled);
|
|
2402
|
+
if (strayLinks.length > 0) {
|
|
2403
|
+
findings.push({
|
|
2404
|
+
ruleId: 'FLOW-027',
|
|
2405
|
+
severity: filled('path') ? 'warn' : 'block',
|
|
2406
|
+
message: `'${flowStepLabel(step)}' share adımının bağlantısı args.${strayLinks.join('/args.')} alanında: bu anahtar StepManagementArgument sözleşmesinde YOK, platform onu 200 ile sessizce düşürür ve adım bağlantısız kalır. Bağlantıyı args.path'e ifade olarak yazın — ör. "'https://ornek.app/urun/' + Page.queryParams.id".`,
|
|
2407
|
+
guide: 'ngapps://guides/page'
|
|
2408
|
+
});
|
|
2409
|
+
}
|
|
2410
|
+
if (strayTexts.length > 0) {
|
|
2411
|
+
findings.push({
|
|
2412
|
+
ruleId: 'FLOW-027',
|
|
2413
|
+
severity: filled('message') ? 'warn' : 'block',
|
|
2414
|
+
message: `'${flowStepLabel(step)}' share adımının metni args.${strayTexts.join('/args.')} alanında: bu anahtar StepManagementArgument sözleşmesinde YOK, platform onu sessizce düşürür. Metni args.message'a ifade olarak yazın — ör. "'Şuna bak: ' + Page.properties.name".`,
|
|
2415
|
+
guide: 'ngapps://guides/page'
|
|
2416
|
+
});
|
|
2417
|
+
}
|
|
2418
|
+
for (const key of ['message', 'path']) {
|
|
2419
|
+
const value = typeof args[key] === 'string' ? String(args[key]).trim() : '';
|
|
2420
|
+
if (/^[a-z][a-z\d+\-.]*:\/\//i.test(value)) {
|
|
2421
|
+
findings.push({
|
|
2422
|
+
ruleId: 'FLOW-027',
|
|
2423
|
+
severity: 'block',
|
|
2424
|
+
message: `'${flowStepLabel(step)}' share adımının '${key}' alanı tırnaksız bir adres: '${value}'. Bu alan İFADEDİR — tırnaksız adres JS'te etiket + yorumdur, undefined döner ve hiçbir şey paylaşılmaz. Dize olarak yazın: "'${value}'".`,
|
|
2425
|
+
guide: 'ngapps://guides/page'
|
|
2426
|
+
});
|
|
2427
|
+
}
|
|
2428
|
+
}
|
|
2429
|
+
return findings;
|
|
2430
|
+
})
|
|
2431
|
+
},
|
|
2386
2432
|
{
|
|
2387
2433
|
id: 'FLOW-023',
|
|
2388
2434
|
module: 'flow',
|
|
@@ -37,7 +37,7 @@ Mobil uygulamanın bileşen kataloğu ayrıdır (backend satırları `(slug, typ
|
|
|
37
37
|
mobil farkları: düşen prop, değişen etkileşim, mobile özgü prop notları) ve `mobileNotes` (bütün
|
|
38
38
|
mobil bileşenlere geçen notlar). Web'de karşılığı olmayan bileşende (`app-bar`, `safe-area`,
|
|
39
39
|
`scroll-view`, `choice-chips`, `tooltip`, `markdown`, `calendar`, `stack`, `list-item`, `fab`, `timer`,
|
|
40
|
-
`audio`, `lottie`, `webview`) bilgi yalnız `mobileKnowledge`'tadır. Olay yükleri
|
|
40
|
+
`audio`, `lottie`, `webview`, `map`) bilgi yalnız `mobileKnowledge`'tadır. Olay yükleri
|
|
41
41
|
(`events[].payload`) önce mobile özgü sözleşmeden okunur (`app-bar.clickAction`, `repeater.swipe`,
|
|
42
42
|
`choice-chips.change`…), yoksa web'inkinden.
|
|
43
43
|
|
|
@@ -74,11 +74,28 @@ mobil bileşenlere geçen notlar). Web'de karşılığı olmayan bileşende (`ap
|
|
|
74
74
|
İkisinde çalma `isPlaying` prop'udur: akış `true`/`false` yazar, bileşen `play`/`pause`/`ended` ya da
|
|
75
75
|
`finish` olayında `{ isPlaying }` yayar ve prop'u gerçeğe döndürür.
|
|
76
76
|
İkinci adım: `signature` web ikizidir (her vuruşta `change { value }` PNG data URL; vuruş sürerken sayfa
|
|
77
|
-
kaymaz; iOS'
|
|
77
|
+
kaymaz; iOS 26'da itilmiş sayfada sağa vuruş sayfayı kapatır — platformun geri jesti) ve `webview` mobile özgüdür (web
|
|
78
78
|
`iframe`inin karşılığı): `src` ya da `html`; yüklemeden sonra başka belgeye giden gezinme varsayılan olarak
|
|
79
79
|
engellenir ve `navigate { url }` yayar, adres yalnız kullanıcının dokunduğu bağlantıda sistem tarayıcısında
|
|
80
80
|
açılır (`allowNavigation` görünümde açar); sayfa akışa `window.ReactNativeWebView.postMessage(metin)` →
|
|
81
81
|
`message { data }` ile yazar, yüklenemeyen sayfa `error` yayar.
|
|
82
|
+
Üçüncü adım: `chart` web ikizidir — seçenek ve olay eşlemesi web'in modülünden gelir, iki platform aynı
|
|
83
|
+
ECharts seçeneğini çizer (cihazda SVG); dışa aktarma, tip değiştirici, yenile ve kırıntı araç çubuğu
|
|
84
|
+
düşer. `map` mobile özgüdür (cihazda Apple/Google Haritalar, kanvas ve önizlemede Leaflet +
|
|
85
|
+
OpenStreetMap): görünüm `latitude`/`longitude`/`zoom` sayılarıdır ve akış yazınca harita oraya gider;
|
|
86
|
+
kullanıcı haritayı hareket ettirince `regionChange { latitude, longitude, zoom }` düğüme geri yazılır,
|
|
87
|
+
işaretçiye dokunmak `markerClick { markerId }` yayar.
|
|
88
|
+
Dördüncü adım: `datepicker`, `timepicker` ve `datetimepicker` web ikizleridir — kutuya dokununca cihazda
|
|
89
|
+
işletim sisteminin seçicisi (iOS alttan açılan sayfa, seçim Tamam'la yazılır; Android iletişim kutusu),
|
|
90
|
+
önizlemede tarayıcının seçicisi açılır; değer ve `change` yükü web ile aynıdır. Sistem seçicisi tek tek
|
|
91
|
+
saati kapatamadığı için `minTime`/`maxTime`/`disabledTimes` dışındaki seçim izinli en yakın saate yaslanır;
|
|
92
|
+
`datetimepicker` tek kutudur (`timePlaceholder` yok). `page_screenshot` `set` kökte değil
|
|
93
|
+
`<elementId>__input`ta, HTML biçimiyle çalışır (`2026-08-01`, `09:30`, `2026-08-01T09:30`). `fileInput` ve `filebutton` de web ikizidir:
|
|
94
|
+
değer web gibi base64 veri URL'sidir (dosya yüklenmez), tür/boyut/adet kapısı ve uyarılar web kuralı.
|
|
95
|
+
Seçiciyi mobile özgü `source` seçer — `files` (belge seçici), `library` (fotoğraf arşivi), `camera`,
|
|
96
|
+
`ask` (her seferinde sorar; `filebutton`'ın varsayılanı); fotoğraflar `quality` ile sıkıştırılır ve
|
|
97
|
+
iOS'ta HEIC JPEG'e çevrilir. Önizlemede tarayıcının dosya penceresi açılır (kanvasta alan kilitli);
|
|
98
|
+
kırpma yoktur.
|
|
82
99
|
- Web'e özgü bileşenlerin mobil karşılığı:
|
|
83
100
|
|
|
84
101
|
| Web | Mobilde |
|
|
@@ -89,6 +106,7 @@ mobil bileşenlere geçen notlar). Web'de karşılığı olmayan bileşende (`ap
|
|
|
89
106
|
| `breadcrumb` | yığın gezinmesi (app-bar geri düğmesi) |
|
|
90
107
|
| `iframe` | `webview` (`src` ya da `html`) |
|
|
91
108
|
| `theme-toggle` | cihaz teması |
|
|
109
|
+
| `fileUpload` | `fileInput` (alan) ya da `filebutton` (düğme) — sürükle-bırak yok |
|
|
92
110
|
|
|
93
111
|
**Harici bileşen mobilde yoktur** (`MOB-006`): protokol v1 tarayıcı `.mjs` paketidir;
|
|
94
112
|
`external_component_*` araçları mobil uygulamada platforma gitmez.
|
|
@@ -230,6 +248,7 @@ Motorun kendi adımları (`setter`, `condition`, `microservice`, `code`, `functi
|
|
|
230
248
|
| `download` | adres cihazın açma sayfasında açılır, gövde paylaşım sayfasına gider (`MOB-005`, bilgi) |
|
|
231
249
|
| `storage` | cihaz deposu |
|
|
232
250
|
| `setcookie` | cihaz deposuna yazar (`MOB-005`, bilgi); paletten yalnız web'de sunulur |
|
|
251
|
+
| `share` | RN paylaşım sayfası (metin + bağlantı; Android'de bağlantı metne eklenir, `title` iOS'ta e-posta konusu, Android'de seçici başlığı); akış `always` ile sürer — iOS'ta sayfa kapanınca, Android'de seçici açılır açılmaz (RN kapanışı bildirmez). Argümanlar `platform_guide('page')` §`share` adımı |
|
|
233
252
|
|
|
234
253
|
Sayfa ve layout `mount` akışları ilk çizimden sonra, `destroy` akışları sayfa kalkarken koşar.
|
|
235
254
|
`Functions.<ad>()` uygulama ve sayfa fonksiyonlarını görür (`platform_guide('functions')`).
|
|
@@ -514,7 +514,7 @@ Tarif: `platform_guide('middleware')`.
|
|
|
514
514
|
|
|
515
515
|
**Sözlükler** (`StepType.cs`, `StepParameterValueType.cs` — hepsi küçük harf):
|
|
516
516
|
`start · microservice · setter · setcookie · validation · condition · redirect · alert ·
|
|
517
|
-
confirm · flow-trigger · storage · navigate · code · download · function · end`
|
|
517
|
+
confirm · flow-trigger · storage · navigate · code · download · function · share · end`
|
|
518
518
|
değer tipleri: `static · page · property · storage · variable · code · item · state`
|
|
519
519
|
|
|
520
520
|
> **Sözlükte olmak KOŞACAĞI anlamına gelmez — koşan tipler barındırıcıdan gelir.** Motor yedi
|
|
@@ -527,7 +527,7 @@ değer tipleri: `static · page · property · storage · variable · code · it
|
|
|
527
527
|
> |---|---|---|---|
|
|
528
528
|
> | `start` · `setter` · `code` · `condition` · `microservice` · `validation` · `flow-trigger` · `function` | ✅ | ✅ | `flow-engine.ts` — motorun kendisi |
|
|
529
529
|
> | `alert` · `redirect` · `setcookie` · `storage` | ✅ | ✅ | barındırıcı; mobilde `setcookie` cihaz deposuna yazar (`MOB-005`) |
|
|
530
|
-
> | `confirm` · `download` | ✅ | ✅ | `Runtime.svelte` · `runtime-tasks.ts` (`download` mobilde açma/paylaşım — `MOB-005`) |
|
|
530
|
+
> | `confirm` · `download` · `share` | ✅ | ✅ | `Runtime.svelte` · `runtime-tasks.ts` (`download` mobilde açma/paylaşım — `MOB-005`; `share` aşağıda) |
|
|
531
531
|
> | `navigate` | ❌ | ✅ (`redirect` takma adı) | web'deki karşılığı `redirect`; gateway `redirect`'e çevirir |
|
|
532
532
|
> | `end` · `query` | ❌ | ❌ | hiçbir yerde — üstelik `query` backend sözlüğünde de yok (`StepType.cs` onu saymaz), yalnız frontend enum'unda duruyor |
|
|
533
533
|
>
|
|
@@ -564,6 +564,19 @@ değer tipleri: `static · page · property · storage · variable · code · it
|
|
|
564
564
|
> adımında ve `{{ }}` bağlamasında `Functions.<ad>(…)` ile de çağrılır; gateway bilinmeyen adı ve
|
|
565
565
|
> fazla argümanı FLOW-025 ile uyarır. Tam gövde `ngapps://examples/flow-call-function`, kurallar
|
|
566
566
|
> **`platform_guide('functions')`**.
|
|
567
|
+
>
|
|
568
|
+
> **`share` adımı ("Share")** metin ve bağlantı paylaşır: `args: { title, message, path }`. `title`
|
|
569
|
+
> DÜZ METİNDİR (ifade yazılırsa FLOW-022 uyarır); `message` ve `path` `storage.value` gibi
|
|
570
|
+
> İFADEDİR — düz metin tırnak ister (`"'Şuna bak'"`, `"'https://…/urun/' + Page.queryParams.id"`).
|
|
571
|
+
> Bağlantının adı `url` DEĞİL `path`'tir: backend `Title`/`Message`/`Path` alanlarında saklar ve
|
|
572
|
+
> tanımadığı anahtarı 200 ile sessizce düşürür (FLOW-027 `url`/`link`/`text`'i ve tırnaksız adresi
|
|
573
|
+
> bloklar). Bağlantı ŞEMALI TAM ADRES olmalı (`https://…`, `mailto:…`): şemasız değer (`www.…`,
|
|
574
|
+
> `urun/42`) adres sayılmaz, metnin sonuna eklenir. İfadenin sonucu yalnız dize ya da sayıysa
|
|
575
|
+
> paylaşılır; `false` (`koşul && 'x'`), `null` ve nesne boş sayılır. Cihazda paylaşım sayfası açılır
|
|
576
|
+
> (Android'de bağlantı metnin sonuna eklenir), web'de tarayıcının paylaşım penceresi, yoksa ya da
|
|
577
|
+
> reddederse metin + bağlantı panoya yazılır ve bildirim çıkar. Tek dal `always`: iOS'ta sayfa
|
|
578
|
+
> kapanınca, Android'de seçici açılır açılmaz (RN seçicinin kapanışını bildirmez) sürer; metin de
|
|
579
|
+
> bağlantı da boşsa hiçbir şey açılmaz, akış hemen sürer.
|
|
567
580
|
|
|
568
581
|
> Bir microservice adımı kaydedildiğinde platform `args.microserviceSchema`'yı
|
|
569
582
|
> (parameterScheme + returnScheme + `isReturnArray`) kendisi doldurur — `flow_get` ile geri
|
package/package.json
CHANGED