@appaflytech/zeyrek-ai-mcp 0.0.21 → 0.0.22
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/config.js +2 -0
- package/dist/knowledge/componentCatalog.js +3 -3
- package/dist/knowledge/componentEvents.js +9 -2
- package/dist/knowledge/mobileComponentCatalog.js +543 -0
- package/dist/knowledge/mobileComponentEvents.js +98 -0
- package/dist/knowledge/normalize.js +52 -11
- package/dist/knowledge/platform/lint.js +205 -0
- package/dist/knowledge/platform/mobile.js +78 -0
- package/dist/knowledge/platform/mobileRules.js +123 -0
- package/dist/knowledge/platform/mobileTabs.js +108 -0
- package/dist/knowledge/platform/profile.js +20 -0
- package/dist/knowledge/platform/resolve.js +122 -0
- package/dist/knowledge/platform/web.js +38 -0
- package/dist/knowledge/rules.js +6 -8
- package/dist/knowledge/styleResolve.js +1 -1
- package/dist/knowledge/styleResolveNative.js +410 -0
- package/dist/knowledge/themeResolve.js +3 -3
- package/dist/platform/capture/actions.js +333 -0
- package/dist/platform/capture/browser.js +1 -0
- package/dist/platform/{screenshot.js → capture/capture.js} +23 -509
- package/dist/platform/capture/index.js +10 -0
- package/dist/platform/capture/readiness.js +103 -0
- package/dist/platform/capture/summary.js +77 -0
- package/dist/platform/capture/target.js +5 -0
- package/dist/platform/capture/targets/studio-mobile.js +15 -0
- package/dist/platform/capture/targets/studio-web.js +5 -0
- package/dist/platform/domSummary.js +1 -1
- package/dist/resources/examples/mobile-app-shell-drawer.json +209 -0
- package/dist/resources/examples/mobile-app-shell-stack.json +123 -0
- package/dist/resources/examples/mobile-app-shell-tab.json +174 -0
- package/dist/resources/examples/mobile-list-detail-form.json +656 -0
- package/dist/resources/guides/component.md +6 -1
- package/dist/resources/guides/functions.md +1 -1
- package/dist/resources/guides/layout.md +11 -7
- package/dist/resources/guides/mobile.md +264 -0
- package/dist/resources/guides/page.md +55 -15
- package/dist/resources/guides/translation.md +1 -1
- package/dist/server.js +2 -0
- package/dist/tools/applications.js +60 -3
- package/dist/tools/components.js +50 -10
- package/dist/tools/designSchemaPatch.js +13 -4
- package/dist/tools/externalComponents.js +25 -4
- package/dist/tools/flows.js +9 -2
- package/dist/tools/layouts.js +41 -9
- package/dist/tools/mobile.js +203 -0
- package/dist/tools/pages.js +115 -35
- package/dist/tools/platformInfo.js +2 -1
- package/dist/tools/profileWrite.js +45 -0
- package/dist/tools/screenWrite.js +2 -2
- package/dist/tools/screens.js +9 -3
- package/package.json +1 -1
|
@@ -0,0 +1,543 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bütün mobil komponentler için geçerli kurallar. Kayıt başına tekrarlanmaz;
|
|
3
|
+
* okuyucu (`component_get`) bu notları `mobileNotes`'a ekler
|
|
4
|
+
* (`platform/mobileRules.ts` `mobileComponentNotes`). Yerleşim (MOB-001) ve stil
|
|
5
|
+
* (MOB-002) notları kural koduyla birlikte orada durur, burada tekrarlanmaz.
|
|
6
|
+
*/
|
|
7
|
+
export const MOBILE_COMPONENT_NOTES = [
|
|
8
|
+
"Tasarım kipinde (Studio kanvası) alanlar yazılamaz ve düğmeler basılamaz: dokunuş kanvasın seçim jestidir.",
|
|
9
|
+
"Olay yükleri web ile AYNI sözleşmedir (`componentEvents.ts`): alanlar `change`/`changed`/`enter`/`focus`/`blur`, seçim bileşenleri `change` + `checked`/`unchecked`, katmanlar kapanışta `change { isOpen: false }` ve `open`/`close` yayar; `type: submit` düğme `click` yaymaz, üstteki `form`un `submit`ini tetikler (`formId` varsa o formun). Web'deki istemci tarafı şema doğrulaması (`validations` → zod) mobilde YOKTUR: doğrulamayı akışta yapın.",
|
|
10
|
+
"Bileşenler shadcn/ui görünümünde çizilir (react-native-reusables ilkelleri, NativeWind); renk ve köşe yine PROJE TEMASINDAN gelir: `--ng-*` değişkenleri shadcn token'larına (`--primary`, `--secondary`, `--muted`, `--destructive`, `--border`, `--input`, `--ring`…) ve köşe ölçeğine köprüyle çevrilir (`shadcn-vars.ts`), koyu kip aynı köprünün ikinci çözümüdür. Tema değişince web ve mobil birlikte hareket eder; web sayfası kendi bileşen ailesiyle çizildiği için iki platformun görünüm farkı bilinçlidir. Ölçü (alan yüksekliği, punto, iç boşluk) temanın `--ng-form-*` değişkenlerinden gelir. Yazı AİLESİ köprüde yoktur: temanın ailesi alanlarda (metin, sayı, parola, açılır liste), başlıklarda (`app-bar`, `form`, `modal`/`drawer`, boş durum) ve sekme çubuğunda uygulanır; `text` ve düğme etiketi ata kabın `typographyStyle` ailesini, o da yoksa platform yazı tipini kullanır; alan, anahtar ve onay kutusu etiketleri HER ZAMAN platform yazı tipiyle çizilir.",
|
|
11
|
+
"Boyut panelinin en-boy oranı (`appearance.aspectRatio`, SAYI — 16:9 için `1.78`) boyu genişlikten türetir ve düğüm KABUĞUNA yazılır (zemin, kenar ve iç boşluk dahil görünen kutu tam oranda). Üç koşul: `heightType: 'auto'` (web ile aynı; `fixed`/`fill` ya da yazılmamış boy oranı ezer), genişlik BELLİ — `widthType: 'fill'` ya da `'fixed'` + `widthString` (içerik genişliğinde react-native-web boyu genişlikten, cihazın Yoga'sı genişliği boydan türetir; iki kutu ayrışmasın diye oran o durumda uygulanmaz), düğüm widget örneği değil. Web'den farkı AKIŞ KAPLARI: `container`, `form`, `safe-area`, `scroll-view` mobilde oran alır ve akışları oranlı boyu doldurur (`verticalAlign` `middle`/`bottom`/`stretch` web gibi çalışır). Öteki bırakılabilir tipler (`collapsible-container`, `repeater`, `tabs`, `tooltip`), sayfa kökü ve katmanlar (`modal`, `drawer`) oran almaz; `image` oranı kendi çizimine yazar."
|
|
12
|
+
];
|
|
13
|
+
/**
|
|
14
|
+
* Web sözlüğünün `STATE_FLAG_NOTES`'undan mobilde FARKLI olan bayraklar. `component_get` mobil
|
|
15
|
+
* uygulamada bunları web notlarının üstüne yazar; kaydı olmayan bayrak web notunu korur.
|
|
16
|
+
* Kaynak: `packages/ng-apps-ui-native/src/renderer/renderer.functions.ts` `aspectRatioStyle`.
|
|
17
|
+
*/
|
|
18
|
+
export const MOBILE_STATE_FLAG_NOTES = {
|
|
19
|
+
isDroppable: "Düğüm çocuk kabul eder ve iç dolgusunu padding kutusundan alır. Web'den farklı olarak mobilde AKIŞ KAPLARI (`container`, `form`, `safe-area`, `scroll-view`) appearance.aspectRatio'yu uygular — boy `auto` ve genişlik `fill`/`fixed` iken; kabın akışı oranlı boyu doldurur. Öteki bırakılabilir tipler (katlanır kap, liste, sekmeler, ipucu, katmanlar) oranı yok sayar."
|
|
20
|
+
};
|
|
21
|
+
export const mobileComponentKnowledge = {
|
|
22
|
+
container: {
|
|
23
|
+
summary: 'Flex akışı; mobil sayfanın tek yerleşim kabı.',
|
|
24
|
+
differences: [
|
|
25
|
+
"`layout` düşer (flex-only), `hoverStyle` düşer (dokunmatikte hover durumu yoktur), `style` düşer.",
|
|
26
|
+
'Yüzey (zemin, köşe, kenarlık, gölge) düğüm kabuğunda derlenir; kabın kendisi yalnız yön, hizalama ve aralık (`gap`) taşır.',
|
|
27
|
+
"Hiza adları web ile aynı eşlenir: `verticalAlign: 'middle'` ve `horizontalAlign: 'center'` ortalar. Dikey hizanın kullanacağı boşluk kabın boyundan gelir — `heightType` `fill`, `fixed` ya da en-boy oranlı kapta akış kabuğun boyunu doldurur; boyu içerikten gelen SÜTUN kapta dikey hiza etkisizdir (satır kapta farklı boydaki kardeşleri yine hizalar). `stretch` de web gibi: ana eksende (sütunda `verticalAlign`, satırda `horizontalAlign`) çocukları eksen boyunca yayar, çapraz eksende gerer.",
|
|
28
|
+
'Kutu modeli web ile AYNI kural ve varsayılanlarla çizilir (`appearance.marginType/paddingType`, `normal` = 4 / 10 dp, `custom` kenar kenar): tipi yazılmamış düğüm `normal` dış boşluk, bırakılabilir kap `normal` iç boşluk alır — kenara yaslanacak kapta `none` yazın. `wrap: true` iken satırlar çapraz hizayı izler (web `flex-layout` ile aynı: `stretch` kabı doldurur, `top`/`left` üstten dizer).'
|
|
29
|
+
]
|
|
30
|
+
},
|
|
31
|
+
'widget-area': {
|
|
32
|
+
summary: 'Konteyner widget`ının kökü; yerleşim sözleşmesi `container` ile aynıdır.',
|
|
33
|
+
differences: [
|
|
34
|
+
'`layout` düşer (flex-only), `style` düşer.',
|
|
35
|
+
'Özel sekme çubuğu (Ayarlar › Sekmeler › Özel widget, K14) bu kökü taşıyan mobil widget`tır: runtime onu `Widget.tabs = { items: [{ page, slug, label, icon, active }], activePage }` parametresiyle çizer, kök kimliği `__tabs`.'
|
|
36
|
+
]
|
|
37
|
+
},
|
|
38
|
+
'safe-area': {
|
|
39
|
+
summary: 'Güvenli alan kabı: içeriği durum çubuğu, çentik ve ev göstergesinden uzak tutar (D15).',
|
|
40
|
+
differences: [
|
|
41
|
+
'Web`de karşılığı YOKTUR — mobile özgü şema; yerleşim alanları mobil `container` ile aynıdır, varsayılan yön sütun.',
|
|
42
|
+
'Pay barındırıcının cihaz bilgisinden gelir (`host.device.insets`): cihazda gerçek güvenli alan, Studio kanvasında seçili cihaz ön ayarı, önizlemede çerçevenin cihazı. Tarayıcıda tam sayfa `/dev`de pay yoktur.',
|
|
43
|
+
'`edges`: all (dört kenar) · top · bottom · vertical. Tasarım kanvası ve önizleme payı KENDİLİĞİNDEN BIRAKMAZ; mobil sayfanın kökü genellikle `safe-area` (ya da içinde `app-bar`) olmalıdır.',
|
|
44
|
+
'Varsayılan sütun + `stretch` ve kenara yaslı: boşluk tipi yazılmamışsa dış/iç boşluk `none` sayılır (`safe-area`, `scroll-view`, `app-bar` — açıkça seçilen değer uygulanır).'
|
|
45
|
+
]
|
|
46
|
+
},
|
|
47
|
+
'scroll-view': {
|
|
48
|
+
summary: 'Kaydırılabilir kap; uzun içeriği kaydıran açık bir karardır.',
|
|
49
|
+
differences: [
|
|
50
|
+
'Web`de karşılığı YOKTUR — mobil ekran kendiliğinden kaymaz; `heightType: fill` ile ekranın kalanını kaplatın.',
|
|
51
|
+
'`horizontal` yatay kaydırır; yerleşim alanları içerik kabına uygulanır. Sona varınca `scrollEnd` yayılır.',
|
|
52
|
+
'`refreshable` YALNIZ dikey kaydırmada ve yalnız runtime kipinde çekerek yenileyi açar (`refresh` olayı); tasarım kanvasında jest çizilmez. Barındırıcı (Expo) kendi çekerek yenilesini bu durumda KAPATIR, yoksa iki gösterge üst üste biner.',
|
|
53
|
+
'`stickyHeader` (FlutterFlow StickyHeader) İLK çocuğu kaydırırken üstte tutar — tasarım kanvasında da; yalnız dikey kaydırmada (RN `stickyHeaderIndices`), `horizontal` açıkken yok sayılır ve panel alanı gizler.'
|
|
54
|
+
],
|
|
55
|
+
propNotes: {
|
|
56
|
+
refreshable: 'Çekerek yenile; akış bir söz döndürürse gösterge onu bekler, döndürmezse 600 ms döner.',
|
|
57
|
+
stickyHeader: 'İlk çocuk yapışır: başlık olacak kabı ilk sıraya koyun ve ona kendi zeminini verin — yapışan kap saydamsa altından akan içerik görünür.'
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
text: {
|
|
61
|
+
summary: 'Metin; punto temanın tip ölçeğinden gelir.',
|
|
62
|
+
differences: [
|
|
63
|
+
'`wordBreak` düşer: React Native metni `numberOfLines`/`ellipsizeMode` ile sınırlar, CSS kırma kuralının karşılığı yoktur.',
|
|
64
|
+
"Seviyenin mobil karşılığı varsa (`--ng-font-size-<seviye>-mobile`) o kullanılır; metin stili ATA KAPTAN MİRAS ALINMAZ (RN'de miras yoktur), kabuk tipografiyi bağlama yazar."
|
|
65
|
+
]
|
|
66
|
+
},
|
|
67
|
+
button: {
|
|
68
|
+
summary: "Tıklama kaynağı; shadcn `Button` ilkeli. `kind` semantik rengi, `variant` o rengin kullanımını seçer; mobil kırılım shadcn'in `secondary`/`ghost`/`link` varyantlarını ve `icon` boyunu ekler (web şeması değişmez).",
|
|
69
|
+
differences: [
|
|
70
|
+
'`isNewTabLink` düşer: mobilde sekme yoktur, bağlantı sistem tarayıcısına ya da derin bağlantıya gider (F5/F6).',
|
|
71
|
+
'`isLoading` açıkken metnin yanında `ActivityIndicator` döner.',
|
|
72
|
+
"`icon`, `iconPosition`, `badgeValue` ve `badgeColor` şemada durur ama mobil çizer bugün ÇİZMEZ: düğmede yalnız etiket ve yükleniyor göstergesi vardır.",
|
|
73
|
+
"Etiketin rengi düğmenin kendi kararıdır (`kind`/`variant` kontrastı): ata kabın `typographyStyle.color`ı etikete İNMEZ, punto da temanın form ölçüsünden gelir; aile ve kalınlık gibi öteki tipografi alanları iner."
|
|
74
|
+
],
|
|
75
|
+
propNotes: {
|
|
76
|
+
variant: "shadcn varyantına çevrilir: `solid` → `default` (`kind: error` iken `destructive`) · `outline` → `outline` (`--background` zemin, `--border` kenar) · `text` (web'in adı) ve `ghost` → `ghost` (zeminsiz) · `secondary` → `secondary` (nötr `--secondary` dolgu) · `link` → `link` (zeminsiz, etiket `--primary`). `secondary`, `ghost` ve `link` YALNIZ mobil şemada seçenektir.",
|
|
77
|
+
kind: "Rengin nerede göründüğü varyanta bağlıdır. `solid`: zemin `primary` → `--primary`, `error` → `--destructive`, `info`/`success`/`warning` → `--status-*`. `outline`: `primary` NÖTR kalır (`--border` kenar, ön plan rengi etiket), `error` ve durum renkleri kenarı ve etiketi boyar. `text`: `primary` nötr ön plan etiketi, `error` ve durum renkleri etiketi boyar (`ghost` `primary`/`error`'da aynı). `secondary`: nötr dolgu, `error` etiketi `--destructive` yapar. `link`: etiket `--primary`, `error` iken `--destructive`. BİLİNEN HATA: `info`/`success`/`warning` `ghost`, `secondary` ya da `link` ile verilirse zemin de etiket de aynı durum rengine boyanır ve etiket okunmaz — bu üç varyantta `kind`'ı `primary` ya da `error` bırakın.",
|
|
78
|
+
size: "`sm` → shadcn `sm`, `md` → `default`, `lg` → `lg`, boş (`''`) temanın varsayılanı (`--ng-form-default-size`); bu kademelerde yükseklik, punto ve yatay iç boşluk sınıftan değil temanın `--ng-form-height-*`/`--ng-form-font-size-*`/`--ng-form-padding-x-*` değişkenlerinden gelir. `icon` (yalnız mobil) için temada `--ng-form-*-icon` değişkeni YOKTUR: satır içi yükseklik tanımsız kalır, iç boşluk `spacing.md`'ye, punto taban puntoya düşer ve düğme ikon da çizmez — bu kademe bugün kullanışlı değildir."
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
form: {
|
|
82
|
+
summary: 'Alanları taşıyan kap; yerleşim sözleşmesi `container` ile aynıdır.',
|
|
83
|
+
differences: [
|
|
84
|
+
'`layout` düşer (flex-only).',
|
|
85
|
+
'Doğrulama ve `submit` akışı F5 runtime fazında bağlanır; tasarım kipinde form yalnız alanları dizer.'
|
|
86
|
+
]
|
|
87
|
+
},
|
|
88
|
+
'form-validation-errors': {
|
|
89
|
+
summary: 'Formun topladığı hataların listesi; renk temanın hata renginden gelir.',
|
|
90
|
+
differences: [
|
|
91
|
+
'Satır metni `label` + `message` birleşiminden çıkar; düz metin dizisi de kabul edilir.',
|
|
92
|
+
'Başlık `hideFormValidationMessage` ile gizlenir; liste ve başlık ikisi de boşsa komponent HİÇ çizilmez (web kutuyu boş çizer).'
|
|
93
|
+
]
|
|
94
|
+
},
|
|
95
|
+
textinput: {
|
|
96
|
+
summary: 'Tek satırlık metin alanı; etiket/açıklama/hata kabuğu bütün alanlarda ortaktır.',
|
|
97
|
+
differences: [
|
|
98
|
+
'`inputMask` düşer: web maskesi DOM olayına bağlıdır, mobil karşılığı (klavye tipi + biçimleyici) Faz 3.',
|
|
99
|
+
'`clearable` düşer: temizleme düğmesi Dalga 1b`in `icon` komponentini bekliyor.',
|
|
100
|
+
'Sayaç kuralı web ile aynı: yalnız `showCounter` açık VE `maxChars` > 0 iken çizilir.'
|
|
101
|
+
]
|
|
102
|
+
},
|
|
103
|
+
textarea: {
|
|
104
|
+
summary: 'Çok satırlı metin alanı.',
|
|
105
|
+
differences: [
|
|
106
|
+
'Yükseklik satır sayısından hesaplanır (`lines`, `minLines`, `maxLines`): React Native `TextInput` satır sayısını kendi ölçmez, yükseklik açıkça verilmelidir.'
|
|
107
|
+
]
|
|
108
|
+
},
|
|
109
|
+
numberinput: {
|
|
110
|
+
summary: 'Sayısal klavye açan alan; değer `Intl.NumberFormat` ile biçimlenir.',
|
|
111
|
+
differences: [
|
|
112
|
+
'Klavye `allowDemicalPoints` açıkken `decimal-pad`, kapalıyken `number-pad`. Yazılan değer ayrıştırılabildiği anda `minValue`/`maxValue` aralığına kırpılarak yazılır.',
|
|
113
|
+
'Web alanı artı/eksi düğmelerini HEP çizer; mobilde düz alan varsayılandır. Düğmeler `variant: stepper` ile gelir — YALNIZ mobil şemada (web şeması değişmez; FlutterFlow Count Controller): alanın iki yanında `-`/`+` (shadcn `outline` `icon`), alana elle yazmak açık kalır; web gibi salt okunur ve görüntüleme kipinde çizilmez, yüklenirken pasiftir. İç roller `<elementId>__decrement` / `<elementId>__increment` — `page_screenshot` `click` onlarla basar.'
|
|
114
|
+
],
|
|
115
|
+
propNotes: {
|
|
116
|
+
variant: "`input` (varsayılan) düz alan; `stepper` ± düğmeli. Basış web `stepBy` gibi değeri `step` kadar değiştirir ve sırayla `change` ile `changed` yayar (`{ value }`): boş değer 0'dan başlar, `step` yoksa ya da pozitif değilse 1; sonuç ve adım alanın GÖSTERDİĞİ basamağa oturur (tam sayı alanında adım en az 1, ondalıkta `decimalPlaces`), yani saklanan değer ekrandakiyle aynıdır; `minValue`/`maxValue`'ya kırpılır. Web kuralıyla `+` yalnız değer üst sınırın altındayken, `-` alt sınırın üstündeyken basılır (aralık dışındaki değerde ters yöne götüren düğme pasif); tasarım kipinde basılamaz."
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
password: {
|
|
120
|
+
summary: 'Gizli metin alanı; göster/gizle düğmesi alanın içindedir.',
|
|
121
|
+
differences: [
|
|
122
|
+
"`autofill` düşer: tarayıcının `autocomplete` sözlüğüdür, mobil karşılığı `textContentType`/`autoComplete` (Faz 3).",
|
|
123
|
+
'Göster/gizle düğmesi şimdilik METİNDİR (`Show`/`Hide`); `icon` Dalga 1b`de inince ikona döner. Kimliği `<elementId>__reveal` — `page_screenshot` `click` onunla basar.'
|
|
124
|
+
]
|
|
125
|
+
},
|
|
126
|
+
checkbox: {
|
|
127
|
+
summary: 'Onay kutusu; shadcn `Checkbox` ilkeli (`@rn-primitives/checkbox`), işaret Material Symbols glifidir. Kutu ölçüsü temanın form puntosundan çıkar.',
|
|
128
|
+
differences: [
|
|
129
|
+
'`isIndeterminate` `value`yu bastırır ve tire (`remove` glifi) çizer; belirsiz kutuya dokunmak onu seçili yapar.',
|
|
130
|
+
'Etikete dokunmak da kutuyu çevirir (basış satırın `Pressable`ında toplanır).',
|
|
131
|
+
'`labelPosition` yalnız `left`/`right`; `left` seçilince etiket ile kutu satırın iki ucuna yaslanır.'
|
|
132
|
+
]
|
|
133
|
+
},
|
|
134
|
+
switch: {
|
|
135
|
+
summary: 'Açma/kapama anahtarı; shadcn `Switch` ilkeli (`@rn-primitives/switch`) — üç barındırıcıda AYNI görünüm.',
|
|
136
|
+
differences: [
|
|
137
|
+
'Platformun kendi anahtarı (iOS/Android `Switch`) KULLANILMAZ: açıkken zemin `--primary`, kapalıyken `--input`, baş `--background`; kanvas, önizleme ve cihaz aynı bileşeni çizer.',
|
|
138
|
+
'`isReadonly` ve `isDisabled` anahtarı kilitler ve soldurur; `isDisabled` etiketi de soldurur. Tasarım kanvasında anahtar basılamaz olduğu için HER anahtar soluk çizilir — önizlemede ve cihazda değil.'
|
|
139
|
+
]
|
|
140
|
+
},
|
|
141
|
+
dropdown: {
|
|
142
|
+
summary: 'Seçim listesi; liste tam ekran `Modal` olarak açılır.',
|
|
143
|
+
differences: [
|
|
144
|
+
'Açılır liste kutunun altına DEĞİL, ekranın altından açılan tam ekran modala çizilir: küçük ekranda kutunun altına açılan liste klavyeyle çakışıyor.',
|
|
145
|
+
'Tetikleyici shadcn `Input` görünümündedir (`--input` kenarı; yükseklik, köşe ve punto öteki alanlarla aynı `--ng-form-*` ölçüsü); liste `--popover` yüzeyinde, seçili satırda `check` glifi. Tetikleyici `role="combobox"` taşır (iç rol `<elementId>__trigger`, temizleme düğmesi `<elementId>__clear`), seçilebilir satırlar `role="option"` + `data-value`; liste katmanda açıldığı için `page_screenshot` `select` seçeneği belgede arar ve değerle ya da görünen metinle seçer.',
|
|
146
|
+
'Seçenekler normalize edilir: düz metin dizisi, nesne dizisi ve `optionType: "grouped"` çocukları tek biçime iner; grup başlığı seçilemez, etiketi olmayan seçenek değerini gösterir.'
|
|
147
|
+
]
|
|
148
|
+
},
|
|
149
|
+
'language-selector': {
|
|
150
|
+
summary: 'Dil değiştirici; `dropdown`un tam ekran `Modal` listesiyle çizilir, seçim uygulama çapında kalıcı olur.',
|
|
151
|
+
differences: [
|
|
152
|
+
"Çizim `dropdown`un kendisidir (plans/mobil-coklu-dil K4): tetikleyici `role=\"combobox\"` (iç rol `<elementId>__trigger`), liste tam ekran `Modal`da `role=\"option\"` + `data-value` satırları; temizleme düğmesi YOK (dil boş olamaz). `page_screenshot` `select: '<elementId>', value: 'en'` ile seçilir, seçenek metni dilin yerel adıdır (`LANGUAGE_NAMES`: `tr` → Türkçe, `en` → English).",
|
|
153
|
+
"Diller ve aktif dil makineden enjekte edilir (web `RenderComponent` ile aynı): `languages` = projenin dil listesi (`project_update(languages)`), `value` = `machine.getLanguage()`. Seçim `machine.setLanguage(value)` ile bütün düğümlere `reload` yayar (çeviriye bağlı prop'lar yerinde çözülür), sonra `change { value, selectedLabel }` sayfa akışına gider.",
|
|
154
|
+
"Seçim makineye VERİLEN depoya `zeyrek:<app>:lang` anahtarıyla yazılır: `/preview` ve `/dev|/view`'da tarayıcı `localStorage`, cihazda uygulamanın kv-store'u — uygulama yeniden açılınca o dille başlar. Cihazda barındırıcı seçimi uygulama çapında yayar (`onLanguageChange`): öteki sekmelerin ekranları ve sekme etiketleri de değişir; `?lang` yalnız web barındırıcısında vardır.",
|
|
155
|
+
"Projede dil tanımlı değilse (`languages` boş) liste boş çizilir — önce `project_update(languages, defaultLanguage)`; `project_get` yanıtındaki `localization` bloğu runtime'ın çevirileri çözüp çözemeyeceğini söyler."
|
|
156
|
+
],
|
|
157
|
+
propNotes: {
|
|
158
|
+
label: 'Alan etiketi (`FieldShell`); boşsa yalnız tetikleyici çizilir.'
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
divider: {
|
|
162
|
+
summary: 'Çizgi; etiket verilirse çizgi etiketin iki yanına bölünür.',
|
|
163
|
+
differences: [
|
|
164
|
+
"Kesikli/noktalı desen `borderStyle` ile çizilir (arka planla çizilen düz çizgide desen görünmez); kalınlık kenarlığa yazılır.",
|
|
165
|
+
'Dikey kipte çizgi kabın yüksekliğini alır (`alignSelf: stretch`).'
|
|
166
|
+
]
|
|
167
|
+
},
|
|
168
|
+
spacer: {
|
|
169
|
+
summary: 'Boşluk; `flex` kipinde kalan alanı yer, `fixed` kipinde `size` kadar.',
|
|
170
|
+
differences: [
|
|
171
|
+
'Tasarım kipinde `showInEditor` açıkken kesikli çerçeveyle görünür olur; runtime`da iz bırakmaz (web ile aynı sözleşme).'
|
|
172
|
+
]
|
|
173
|
+
},
|
|
174
|
+
image: {
|
|
175
|
+
summary: 'Görsel; kaynak düz URL ya da platformun dosya nesnesi olabilir.',
|
|
176
|
+
differences: [
|
|
177
|
+
'RN `Image` kullanılır (expo-image değil): paket üç barındırıcıda da aynı kodla çalışır.',
|
|
178
|
+
'Kaynak çözülemezse (boş prop, tanınmayan nesne) YER TUTUCU çizilir — boş kutu tasarımcıya "kaynak boş" demenin tek yolu.',
|
|
179
|
+
'Boyut panelinin en-boy oranı (`appearance.aspectRatio`) görselin KENDİSİNE yazılır (web`de de medya oranı kendi uygular): genişlik satırı kaplar, boy oranla gelir. Koşullar kaplarla aynı: boy `auto` ve genişlik `fill`/`fixed`; değilse (ya da oran yoksa) görsel 96 dp taban boyla çizilir.'
|
|
180
|
+
]
|
|
181
|
+
},
|
|
182
|
+
icon: {
|
|
183
|
+
summary: 'Tek glif; Material Symbols LİGATÜRÜ olarak çizilir.',
|
|
184
|
+
differences: [
|
|
185
|
+
'Glif bir metindir: ad (`home`) yazı tipi tarafından glife çevrilir, ayrı svg seti taşınmaz. Studio sayfası yazı tipini yüklü tutar; Expo uygulaması `expo-font` ile yükler (F6).',
|
|
186
|
+
'`isSpinning` düşer: dönen ikon `Animated` döngüsü ister, v1`de animasyon yok.',
|
|
187
|
+
'`isNewTabLink` düşer (button ile aynı gerekçe).'
|
|
188
|
+
]
|
|
189
|
+
},
|
|
190
|
+
card: {
|
|
191
|
+
summary: 'Görsel + başlık + açıklama + düğme.',
|
|
192
|
+
differences: [
|
|
193
|
+
'`imageFit` RN `resizeMode`a çevrilir: cover→cover, contain→contain, fill→stretch, none→center.',
|
|
194
|
+
'Kartın TAMAMI dokunulabilir ve tek `click` yayar (web ile aynı: düğmenin kendi olayı yoktur); liste satırına dokunmak repeater şablonundaki kartın `click`idir. Kart çocuk ALMAZ — satırın alanlarını `title`/`description` kod bağıyla (`{ type: \'code\', ref: \'{{ item.alan }}\' }`) verin.'
|
|
195
|
+
]
|
|
196
|
+
},
|
|
197
|
+
emptystate: {
|
|
198
|
+
summary: 'Liste boşken çizilen ikon + başlık + açıklama + eylemler.',
|
|
199
|
+
differences: [
|
|
200
|
+
'İkon `icon` komponentiyle aynı ligatür yolunu kullanır.',
|
|
201
|
+
'Metni olmayan eylem kaydı çizilmez; eylem kimlikleri `__action-<sıra>`.'
|
|
202
|
+
]
|
|
203
|
+
},
|
|
204
|
+
slot: {
|
|
205
|
+
summary: 'Layout`un sayfa yuvası; runtime`da sayfanın şeması buraya enjekte edilir.',
|
|
206
|
+
differences: [
|
|
207
|
+
'Tasarım kipinde YER TUTUCU çizilir (kesikli kutu + ad): boş `View` yuvayı görünmez yapıyor, layout`ta yeri kestirilemiyordu.'
|
|
208
|
+
]
|
|
209
|
+
},
|
|
210
|
+
repeater: {
|
|
211
|
+
summary: 'Şablon düğümlerini satır başına tekrarlar; satır kimlikleri `__row-<i>`.',
|
|
212
|
+
differences: [
|
|
213
|
+
'`FlatList` v1`de KULLANILMAZ: sanallaştırma yalnız gerçek veriyle anlamlı, tasarım kipinde ölçüm haritasını bozar (kaplama görünmeyen satırın kutusunu bulamaz).',
|
|
214
|
+
'Tasarım kipinde şablon BİR kez çizilir. Runtime`da her satır web ile AYNI makine parametresiyle (`index`, `row`, `repeaterId`) çizilir: bağlı prop`lar ve akışlar `Row` / `RowIndex` okur; satır yoksa hiçbir şey çizilmez (web ile aynı).',
|
|
215
|
+
'Satırdaki bir düğümün olayı ÖNCE tekrarlayıcıya `change { selectedIndex }` yazar (aynı satırsa yazmaz), sonra kendi akışını koşar (web sırası): akışta tıklanan satır `<tekrarlayıcı>.selectedItem`dır. `item`/`Row`/`RowIndex` yalnız prop BAĞLARINDA satırdır; akış ifadesinde tanımsız döner (ölçüldü 2026-09-19).',
|
|
216
|
+
'`columnCount` > 1 iken satırlar yüzde genişlikle sarılır (RN`de CSS grid yok).',
|
|
217
|
+
'`swipeActions` ve `itemPressable` MOBİLE ÖZGÜDÜR (webde yok). Jest RN `Animated` + `PanResponder` ile kurulur — paket v1`de `reanimated`/`gesture-handler` yok — ve yalnız YATAY harekette yakalanır, böylece dikey kaydırma kaba kalır. Tasarım kipinde satırlar şablon olarak çizildiği için jest hiç bağlanmaz.',
|
|
218
|
+
'`swipe` ve `itemPress` yükleri satırı `row` alanında TAŞIR; akış ifadesindeki `Row`/`RowIndex` bağı ayrı bir konudur (ARC-080).'
|
|
219
|
+
],
|
|
220
|
+
propNotes: {
|
|
221
|
+
itemPressable: 'Satıra dokunulabilir yapar; dokunuş önce `change { selectedIndex }`, sonra `itemPress` yayar.',
|
|
222
|
+
swipeActions: 'Sola kaydırınca açılan eylemler: `key` (zorunlu), `label`, `tone` (default · danger), `icon`. Her eylem 72 pt genişliktedir.'
|
|
223
|
+
}
|
|
224
|
+
},
|
|
225
|
+
modal: {
|
|
226
|
+
summary: 'Widget kökü; sayfa akışının dışında, üstte açılan katman.',
|
|
227
|
+
differences: [
|
|
228
|
+
'RN `Modal` kullanılır; genişlik web kademelerinden ekran ORANINA çevrilir (small 0.75 · medium 0.85 · large 0.95).',
|
|
229
|
+
'Görünüm temanın shadcn token`larından: perde `--overlay` yarı saydam, gövde `--background` zemin + `--border` kenar + büyük köşe + gölge. Açılış, kapanış ve olaylar değişmedi.',
|
|
230
|
+
'Gövdenin kapatma (×) düğmesinin iç rol kimliği `<elementId>__overlay` (adı tarihsel; `isDismissDisabled` açıkken çizilmez) — `page_screenshot` `click` onunla kapatır.',
|
|
231
|
+
'Tasarım kipinde HER ZAMAN açık ve YERİNDE (sayfa akışında) çizilir: kapalı bir widget`ın içi düzenlenemez; RN `Modal` react-native-web`de sayfanın tamamını kaplayan bir portal açtığı için kanvasta kullanılmaz.',
|
|
232
|
+
'`presentation` YALNIZ mobil şemadadır (web şeması değişmez; FlutterFlow BottomSheet): `center` ortadaki kutu, `sheet` alt sayfa, `fullscreen` tam ekran. Tasarım kipinde üçü de yerinde, kendi görünümüyle çizilir.'
|
|
233
|
+
],
|
|
234
|
+
propNotes: {
|
|
235
|
+
presentation: "`center` (varsayılan; kayıtlı modallar böyle kalır) web ile aynı kutu, genişlik `size`dan. `sheet`: ekranın altına yapışık, tam genişlik, üst köşeleri yuvarlak ve tutamaçlı; cihazda alttan kayarak açılır. Tutamaç + başlık şeridinden aşağı sürükleyince — boyunun üçte biri ya da hızlı savurma — `change { isOpen: false }` ile kapanır; `isDismissDisabled` açıkken yerine döner. İçerik kendi kaydırmasını korur (sürükleme yalnız şeritte); alt sayfa en çok ekranın %90'ıdır, uzun içerik kesilir — kaydırmak için içine `scroll-view` koyun. Kapanış isteği tutmazsa (bir bağ `isOpen`'ı geri yazarsa) sayfa 300 ms sonra yerine döner. `fullscreen`: perdesiz tam ekran, çentik ve ev göstergesi payı dolguda; cihazda kayarak açılır. `size` yalnız `center`da anlamlıdır, panel diğer ikisinde gizler."
|
|
236
|
+
}
|
|
237
|
+
},
|
|
238
|
+
drawer: {
|
|
239
|
+
summary: 'Mobil ÇEKMECE (D14): expo-router Drawer navigator`ı yerine widget.',
|
|
240
|
+
differences: [
|
|
241
|
+
'RN `Modal` + kenara yaslı panel; kenardan kaydırma ve yumuşak geçiş Faz 3 (reanimated/gesture-handler v1`de paket bağımlılığı değil).',
|
|
242
|
+
'Görünüm temanın shadcn token`larından: perde `--overlay` yarı saydam, panel `--background` zemin + iç kenarda `--border` çizgisi + gölge.',
|
|
243
|
+
'`size` kademeleri ekran oranına iner (default 0.72 … full 1); `position` yalnız left/right.',
|
|
244
|
+
'Kaplamaya dokunuş kapatır (`__overlay` iç rolü), `isDismissDisabled` açıkken dokunuş yutulur.',
|
|
245
|
+
'`app-bar.menuTarget` bu widget`ı açar (`host.shell.openMenu` → makinede `isOpen: true`); kapanış `change { isOpen: false }` yazar, geçişte `open`/`close` yayılır.',
|
|
246
|
+
'Tasarım kipinde yerinde çizilir (modal ile aynı gerekçe).'
|
|
247
|
+
]
|
|
248
|
+
},
|
|
249
|
+
'app-bar': {
|
|
250
|
+
summary: 'Ekranın üst çubuğu: başlık, sol uç (geri ya da çekmece menüsü) ve sağ eylemler.',
|
|
251
|
+
differences: [
|
|
252
|
+
'Web`de karşılığı YOKTUR — mobile özgü şema (web `header` sayfa akışının parçasıdır, bu ekranın kabuğudur).',
|
|
253
|
+
'`leading: auto` runtime`da `host.shell.canGoBack`tan çözülür: geri gidilebiliyorsa geri, gidilemiyorsa `menuTarget` varsa menü, yoksa boş. Tasarım kipinde çubuk boş kalmasın diye menü/geri çizilir.',
|
|
254
|
+
'İç roller `__back`, `__menu`, `__action-<key>` (K2 kalıbı); `page_screenshot` eylemleri bunları kullanır.',
|
|
255
|
+
'Üst güvenli alan payı çubuğun işi DEĞİLDİR: düz kanvas kararından (D15) sonra payı kullanıcı `SafeAreaView` ile kurar.'
|
|
256
|
+
]
|
|
257
|
+
},
|
|
258
|
+
badge: {
|
|
259
|
+
summary: 'Sayaç ya da durum rozeti; taşma (99+) ve nokta kipi var.',
|
|
260
|
+
differences: [
|
|
261
|
+
'`isPulsing` DÜŞÜRÜLDÜ: nabız animasyonu web CSS keyframe`idir, mobilde karşılığı yoktur.',
|
|
262
|
+
'İkon İSTEĞE BAĞLIDIR ve verilmediğinde ÇİZİLMEZ — ortak ikon çözücü boş prop`ta `star`a düştüğü için bu slug prop`un gerçekten verilip verilmediğine kendisi bakar.'
|
|
263
|
+
],
|
|
264
|
+
propNotes: {
|
|
265
|
+
color: 'Renk SINIFTAN gelir (`bg-status-*`); `custom` seçilirse `customColor` ham renktir.',
|
|
266
|
+
maxCount: 'Aşıldığında metin `<maxCount>+` olur (99 → `99+`). Web ikiziyle aynı beş altın vaka `badge-logic.spec.ts`te kilitli.'
|
|
267
|
+
}
|
|
268
|
+
},
|
|
269
|
+
avatar: {
|
|
270
|
+
summary: 'Kullanıcı avatarı: görsel, baş harf yedeği ve `+N` grup kipi.',
|
|
271
|
+
differences: [
|
|
272
|
+
'Grup kipinde üst üste binme `spacing` ile negatif kenar boşluğundan çizilir; web`in `z-index` katmanı yerine çizim SIRASI belirler.'
|
|
273
|
+
]
|
|
274
|
+
},
|
|
275
|
+
progress: {
|
|
276
|
+
summary: 'Çubuk ilerleme göstergesi; eşiklere göre renk değiştirir.',
|
|
277
|
+
differences: [
|
|
278
|
+
'`variant` (dairesel), `isStriped` ve `isIndeterminate` DÜŞÜRÜLDÜ: üçü de CSS animasyonu ya da `conic-gradient` ister.',
|
|
279
|
+
'Kutu satırın tamamını kaplar (`width: 12`).'
|
|
280
|
+
]
|
|
281
|
+
},
|
|
282
|
+
radio: {
|
|
283
|
+
summary: 'Tek seçimli seçenek listesi.',
|
|
284
|
+
differences: [
|
|
285
|
+
'`autofocus` DÜŞÜRÜLDÜ: mobilde odak kavramı yoktur.',
|
|
286
|
+
'Seçenekler HER ZAMAN alt alta çizilir — dokunma hedefi korunur.',
|
|
287
|
+
'Seçeneğin iç rol kimliği `<elementId>__option-<değer>` (runtime\'da `data-element-id`) — `page_screenshot` `click` seçeneğe onunla basar.'
|
|
288
|
+
]
|
|
289
|
+
},
|
|
290
|
+
checkboxgroup: {
|
|
291
|
+
summary: 'Seçili değerleri bir liste oluşturan onay kutusu grubu.',
|
|
292
|
+
differences: [
|
|
293
|
+
'`autofocus` ve `columnCount` DÜŞÜRÜLDÜ: çok sütun telefon genişliğinde dokunma hedefini bozar; yerine `direction: horizontal` sarmalı kullanılır.',
|
|
294
|
+
'Kutu satırın tamamını kaplar (`width: 12`).',
|
|
295
|
+
'İç roller `<elementId>__option-<değer>` ve (`showSelectAll` açıkken) `<elementId>__select-all` — `page_screenshot` `click` onlarla basar.'
|
|
296
|
+
]
|
|
297
|
+
},
|
|
298
|
+
'choice-chips': {
|
|
299
|
+
summary: 'Dokunma için boyutlandırılmış, satır sarmalı seçilebilir çip dizisi. Web`de karşılığı YOKTUR.',
|
|
300
|
+
differences: [
|
|
301
|
+
'Mobile özgü şema: web`de bu işi `checkboxgroup`/`radio` görür; dokunmatikte çip dizisi daha az yer kaplar.',
|
|
302
|
+
'`multiple` açıkken `value` virgülle ayrılmış listedir, kapalıyken tek değer.',
|
|
303
|
+
'İkon İSTEĞE BAĞLIDIR ve verilmediğinde çizilmez (`badge` ile aynı gerekçe).',
|
|
304
|
+
'Çipin iç rol kimliği `<elementId>__chip-<değer>` — `page_screenshot` `click` çipe onunla basar.'
|
|
305
|
+
]
|
|
306
|
+
},
|
|
307
|
+
'collapsible-container': {
|
|
308
|
+
summary: 'Başlığa dokununca açılıp kapanan kap; çocuklar gövdeye iner.',
|
|
309
|
+
differences: [
|
|
310
|
+
'Bırakılabilir bir KAPTIR (`isDroppable`), gövdesi çocuklardır.',
|
|
311
|
+
'Açılma animasyonu YOKTUR: yükseklik anında değişir (düzen animasyonu bu dalgada kullanılmadı).',
|
|
312
|
+
'Başlığa basmak web ile AYNI olayı yayar (`expanded`/`collapsed { isOpen }`); makine `isOpen`\'ı yazar ve gövde açılıp kapanır. Tetikleyicinin iç rol kimliği `<elementId>__trigger` — `page_screenshot` `click` onunla basar.'
|
|
313
|
+
]
|
|
314
|
+
},
|
|
315
|
+
slider: {
|
|
316
|
+
summary: 'En küçük ve en büyük değer arasında sayısal kaydırıcı.',
|
|
317
|
+
differences: [
|
|
318
|
+
'`marks`, `showTicks` ve `autofocus` DÜŞÜRÜLDÜ.',
|
|
319
|
+
'Jest `PanResponder` ile çözülür ve YALNIZ YATAY sürüklemeyi yakalar: dokunuşu başlangıçta yakalasaydı sayfa kaydırması değeri değiştirirdi (ölçüldü — kaydırma 40`ı 100 yapıyordu).',
|
|
320
|
+
'Sürüklerken `change`, parmak kalkınca `changed` yayılır; akış genelde `changed`e bağlanır. İze dokunuş değeri o noktaya getirir (`change` + `changed`). Jest `modal`/çekmece içinde de çalışır.'
|
|
321
|
+
]
|
|
322
|
+
},
|
|
323
|
+
tabs: {
|
|
324
|
+
summary: 'Başlıkların altında içerik gösteren sekme kabı.',
|
|
325
|
+
differences: [
|
|
326
|
+
'İçerik modeli web ile AYNI: her sekmenin gövdesi SIRADAKİ çocuk düğümdür — etkin sekmenin (`selected` anahtarı) `tabs` dizisindeki sırası hangi çocuğun çizileceğini seçer; gizli/pasif sekme sırayı kaydırmaz.',
|
|
327
|
+
'Basılan sekme web ile AYNI olayı yayar (`tab { selected }`); makine `selected`\'ı yazar ve gövde değişir. Sekmenin iç rol kimliği `<elementId>__tab-<anahtar>` (runtime\'da `data-element-id`) — `page_screenshot` `tab` onu anahtarla bulur.',
|
|
328
|
+
'Sekme başlıkları taşarsa yatay kaydırılır; telefonda sarmalanmaz.'
|
|
329
|
+
]
|
|
330
|
+
},
|
|
331
|
+
tooltip: {
|
|
332
|
+
summary: 'DOKUNUŞLA açılan ipucu balonu; çocuklar tetikleyicidir. Web`de karşılığı YOKTUR.',
|
|
333
|
+
differences: [
|
|
334
|
+
'Web`de ipucu hover ile açılır; dokunmatikte hover yoktur (MOB-002), bu yüzden jest DOKUNUŞTUR — ikinci dokunuş kapatır, dışarı dokunmak da kapatır.',
|
|
335
|
+
'Bırakılabilir bir KAPTIR: tetikleyici çocuklarıdır, yani her şeye (düğme, ikon, kart) ipucu takılabilir.',
|
|
336
|
+
'TASARIM KİPİNDE BALON ÇİZİLMEZ: kanvasta açık balon ölçümü ve seçim kutusunu kaydırırdı. Tasarımcı metni panelden düzenler.',
|
|
337
|
+
'Balon sayfa ağacının DIŞINA, barındırıcının katmanına çizilir (`modal`/`drawer` ile aynı çerçeve) — kaydırma kabı ya da kırpan kap onu kesmesin diye.'
|
|
338
|
+
],
|
|
339
|
+
propNotes: {
|
|
340
|
+
side: 'Balonun tetikleyiciye göre yanı. Seçilen yan ekrana sığmazsa balon ÇEVRİLMEZ, yalnız ekran içine kaydırılır.'
|
|
341
|
+
}
|
|
342
|
+
},
|
|
343
|
+
markdown: {
|
|
344
|
+
summary: 'Markdown metnini çizer: başlık, paragraf, liste, bağlantı, kod, alıntı, ayraç, tablo, görsel. Web`de karşılığı YOKTUR — web `html` ayrı bileşendir ve HTML çalıştırır.',
|
|
345
|
+
differences: [
|
|
346
|
+
'Metin `marked` ile ayrıştırılır ve bileşenin kendi ilkelleriyle çizilir: HTML üretilmez, hiçbir şey çalıştırılmaz. Satır içi HTML etiketi düşer (içindeki metin kalır), blok HTML etiketsiz metne iner; `&` gibi varlıklar çözülür — kod aralığında çözülmez, orada ham metindir.',
|
|
347
|
+
'HTML gibi: yumuşak satır sonu boşluktur ve ardışık boşluklar teke iner, yalnız sert kırılma (satır sonunda iki boşluk) satır kırar. GFM görev maddesi (`- [ ]`, `- [x]`) nokta yerine ☐/☑ çizilir (sıralı listede numaranın yanında); sıralı liste yazıldığı sayıdan başlar (`0.` dahil).',
|
|
348
|
+
'Başlık puntoları `text` bileşeninin tip ölçeğinden (`h1`–`h4`; 5 ve 6 `h4` puntosunda), renkler token sınıflarından: kod `--muted` zemin, bağlantı `--primary`, alıntı ve tablo `--border` çizgi. Düğümün `typographyStyle`ı her metne iner; puntosu ve satır yüksekliği GÖVDE metnindir, başlık kendi puntosunu korur.',
|
|
349
|
+
'Görsel yalnız tek başına bir paragrafta ve http(s) adresiyle çizilir (tam genişlik, 180 dp yükseklik, `contain`); satır içindeki görsel alt metnine iner.',
|
|
350
|
+
'Bağlantıya dokunuş `linkClick { href }` yayar (ham adres); `linkOpensExternal` açıkken (varsayılan) yalnız http(s), mailto ve tel adresi sistem tarayıcısında açılır — `javascript:` ya da göreli adres açılmaz ama olay yine gelir, gezinmeye akış karar verir. Tasarım kipinde bağlantı basılamaz; boş içerik tasarımda yer tutucu, runtime`da hiçbir şey çizer.'
|
|
351
|
+
],
|
|
352
|
+
propNotes: {
|
|
353
|
+
content: "Markdown metni (CommonMark + GFM tablo ve üstü çizili); bağlanabilir: `{ type: 'code', ref: '{{ ... }}' }`.",
|
|
354
|
+
linkOpensExternal: 'false iken bağlantı yalnız `linkClick` yayar, hiçbir şey açmaz — gezinmeyi akış yapar (ör. `redirect`).'
|
|
355
|
+
}
|
|
356
|
+
},
|
|
357
|
+
calendar: {
|
|
358
|
+
summary: 'Satır içi ay takvimi: tek gün ya da aralık seçer. Web`de katalog bileşeni DEĞİLDİR (web `calendar` yalnız `datepicker`ın açılır ızgarası); ızgara kuralı onunla aynı modülden.',
|
|
359
|
+
differences: [
|
|
360
|
+
'Prop adları web `datepicker`ınkiler (`value`, `minDate`, `maxDate`, `locale`) ve `change` yükü onun biçimidir (`yyyy-MM-ddT00:00:00`, yerel duvar saati, dilim eki yok) — iki bileşen akışlarda birbirinin yerine geçer. Gelen değer web `datepicker`ın `toDate` kuralıyla okunur: yalın `yyyy-MM-dd` yerel gündür; dilim taşıyan metin (`…Z`, `+00:00` — platform statik tarih değerini UTC`ye çevirip kaydeder) yerel güne çevrilir; sayı zaman damgası da okunur.',
|
|
361
|
+
'Izgara altı haftadır (42 gün); hafta Türkçede Pazartesi, İngilizcede Pazar başlar. `locale` boşsa uygulamanın dili; Türkçe olmayan dil İngilizceye, bilinmeyen dil Türkçeye düşer.',
|
|
362
|
+
'İç roller: `<elementId>__prev` ve `<elementId>__next` (ay), `<elementId>__day-yyyy-MM-dd` (gün) — `page_screenshot` `click` onlarla basar. Ay dışındaki güne basış o aya da geçer.',
|
|
363
|
+
'Salt okunurken aylar gezilir ama gün seçilmez; pasifken ikisi de kapalı. Değer akıştan başka bir aya yazılınca takvim o aya döner. Tasarım kipinde statik ay çizilir, basılamaz.'
|
|
364
|
+
],
|
|
365
|
+
propNotes: {
|
|
366
|
+
mode: "`single` (varsayılan) ya da `range`. Aralıkta ilk basış başlangıç (`value`), ikinci basış bitiş (`endValue`); başlangıçtan önceki gün ya da tamamlanmış aralığa basış yeni aralık başlatır. `change` iki alanı birlikte yazar.",
|
|
367
|
+
endValue: "Aralığın bitişi; yalnız `mode: 'range'` iken okunur ve panelde görünür.",
|
|
368
|
+
minDate: 'Sınırdan önceki günler soluk ve basılamaz, sınırın kendisi seçilebilir; `maxDate` simetrik.',
|
|
369
|
+
markedDates: "İşaretli günler: `[{ date: 'yyyy-MM-dd' }]` (düz tarih metni dizisi de okunur) — günün altında nokta; seçili günde nokta zıt renktedir."
|
|
370
|
+
}
|
|
371
|
+
},
|
|
372
|
+
otpinput: {
|
|
373
|
+
summary: 'Tek kullanımlık kod kutuları; kurallar web ile AYNI modülden (`otp-logic`): temizleme, tamamlanma, ayraç, yeniden gönder sayacı.',
|
|
374
|
+
differences: [
|
|
375
|
+
'Web her kutuyu ayrı alan yapar; mobilde yazıyı kutuların üstündeki TEK görünmez alan alır (`<elementId>__input`): yapıştırma, SMS`ten otomatik doldurma (`oneTimeCode`) ve silme klavyenin kendi davranışıdır, kutular yalnız gösterir. Alan uzunluk sınırı taşımaz — ayraçlı yapıştırma (`123-456`) temizlenip kutu sayısına kesilir, rakam kaybolmaz — ve imleç hep sondadır. `page_screenshot` `set` o alana yazar.',
|
|
376
|
+
'`change` ve `complete` web gibi yalnız GERÇEK değişimde yayılır (`complete` kodu dolduran değişimle birlikte); kabul edilmeyen karakter ve fazlası düşer.',
|
|
377
|
+
'Kilitler web ile aynı: pasif, salt okunur, görünüm ve yükleniyor kipleri yazmayı kapatır; görünüm kipinde kutular düz metne iner ve yeniden gönder çizilmez. Sayaç bağlanınca başlar, `<elementId>__resend` basınca `resend` yayar ve yeniden başlar; tasarım kipinde sayaç koşmaz.',
|
|
378
|
+
'`style` düşer (ham CSS); kutu ölçüsü form yüksekliği, punto form puntosunun 1,2 katı, boşluk puntoya oranlı (web `--otp-gap`).'
|
|
379
|
+
]
|
|
380
|
+
},
|
|
381
|
+
qrcode: {
|
|
382
|
+
summary: 'QR kodu: `data` kodlanır, `quietZone` sessiz bölgedir (modül birimi, varsayılan 1).',
|
|
383
|
+
differences: [
|
|
384
|
+
'Matris `toqr` ile üretilir ve düz görünümlerle çizilir (`react-native-svg` yok); hata düzeltme `M` sabittir ve web\'in `errorCorrectionLevel` prop\'u mobil şemadan düşer; renk web gibi siyah üstüne beyaz — koyu temada da (okuyucular ters kodu her zaman okumaz).',
|
|
385
|
+
'Kare kutunun kenarı: genişliği belli düğümde (`widthType: fill` ya da `fixed`) düğümün genişliği, içerik genişliğinde (`auto` ya da `widthType` hiç yazılmamış) 200 dp; genişlik ölçülemezse de (kanvasta satır kabındaki `fill`) 200 dp — cihaz o düğümü tam genişlik çizer. Sabit px boy kenarı sınırlar. Modül ölçüsü tam sayıya iner, artan birkaç piksel ortalanır. Belirli boy için `appearance.widthType: fixed` + `widthString`.',
|
|
386
|
+
'Veri boşsa ya da QR`a sığmıyorsa (yaklaşık 2,3 KB üstü) yer tutucu çizilir. `quietZone` web ile aynı `common` grubundadır (eski adı `padding` ortak çizim katmanının CSS boşluğuyla çakışıyordu, CQ-272).'
|
|
387
|
+
],
|
|
388
|
+
propNotes: {
|
|
389
|
+
quietZone: 'Sessiz bölge, MODÜL birimiyle (piksel değil); varsayılan 1, panel aralığı web şemasıyla aynı 1–10 (çizer 16\'ya kadar kabul eder). Okuyucular için 2–4 önerilir.'
|
|
390
|
+
}
|
|
391
|
+
},
|
|
392
|
+
stack: {
|
|
393
|
+
summary: 'Çocuklarını üst üste bindiren kap (FlutterFlow Stack). Web`de karşılığı YOKTUR.',
|
|
394
|
+
differences: [
|
|
395
|
+
'İLK çocuk taban katmandır: akışta durur ve yığının boyunu verir. Sonraki her çocuk onun ÜSTÜNE biner; dizi sırası çizim sırasıdır (sonraki üstte).',
|
|
396
|
+
'Üst katmanlar yığının `alignment`ıyla (9 nokta) hizalanır; kaydırmayı çocuğun kendi kenar boşluğu verir (ör. `bottom-right` + sağ/alt margin 8). Hizalama ÇOCUKTA değil yığındadır — `appearance.stackAlign` diye bir alan YOKTUR.',
|
|
397
|
+
'Farklı köşelerde katman için çocuk kap iki eksende `fill` olur (yığını kaplar) ve içeriğini kendi `horizontalAlign`/`verticalAlign`ı ile yerleştirir.',
|
|
398
|
+
'Katmanın boş alanı dokunuşu alttaki katmana geçirir. Çocuklar `blocks` taşımaz (MOB-001 aynen geçerli).'
|
|
399
|
+
],
|
|
400
|
+
propNotes: {
|
|
401
|
+
alignment: "Üst katmanların yeri: `top-left` (varsayılan) · `top-center` · `top-right` · `center-left` · `center` · `center-right` · `bottom-left` · `bottom-center` · `bottom-right`. Yığının boyu kutudan geliyorsa (`fixed`, `fill`, oran) taban da bu noktaya hizalanır."
|
|
402
|
+
}
|
|
403
|
+
},
|
|
404
|
+
'list-item': {
|
|
405
|
+
summary: 'Liste satırı (FlutterFlow ListTile): baş ikon ya da görsel · başlık · alt başlık · son metin ve ikon; basılabilir. Web`de karşılığı YOKTUR.',
|
|
406
|
+
differences: [
|
|
407
|
+
'Satıra dokunuş `click` yayar (yük yok). Pasifken soluk ve basılamaz; tasarım kipinde basış kanvasın seçim jestidir.',
|
|
408
|
+
'Baş tarafta `leadingImage` `leadingIcon`dan önce gelir (40 dp yuvarlak görsel; yüklenmezse başlığın baş harfleri). Boş ikon çizilmez.',
|
|
409
|
+
'Ölçüler Material liste satırı: tek satır 56, alt başlıklı 72; `dense` 48 / 60. Renkler token sınıflarından (başlık `--foreground`, alt başlık ve son taraf `--muted-foreground`, basılıyken `--accent`).',
|
|
410
|
+
'Son tarafta anahtar YOKTUR: anahtarlı satır `container` (satır) + `text` + `switch` ile kurulur. Tekrarlayıcı içinde satır olarak kullanılır — `repeater` satırının akışı tıklanan satırı `<tekrarlayıcı>.selectedItem` ile okur.'
|
|
411
|
+
]
|
|
412
|
+
},
|
|
413
|
+
carousel: {
|
|
414
|
+
summary: 'Parmakla kaydırılan sayfalar (FlutterFlow Carousel ve PageView): çocuk sayfalar ya da web gibi `items` görselleri.',
|
|
415
|
+
differences: [
|
|
416
|
+
'Prop adları ve olaylar web kaydırıcısınınki: `activeIndex` etkin sayfadır, kaydırma/oklar/noktalar/otomatik oynatma yalnız `slideChange { activeIndex }` yayar ve şerit prop değişince kayar (web gibi denetimli).',
|
|
417
|
+
'Mobilde bırakılabilir: çocuğu varsa her ÇOCUK bir sayfadır ve `items` okunmaz (`tabs` gövde modeli); çocuksuz kaydırıcı `items` görsellerini çizer. Kanvasta yalnız `activeIndex` sayfası çizilir — sayfa seçici paneldeki bu alandır.',
|
|
418
|
+
'Görsel sayfaya dokunuş web gibi yalnız bağlantısı ya da akışı olan sayfada `slideClick { currentItem, index }` yayar; dış adres (http(s), mailto, tel, alan adı) sistem tarayıcısında açılır, uygulama içi yol (`/sayfa`) açılmaz — gezinmeyi `slideClick` akışı yapar.',
|
|
419
|
+
'Düşenler: `style`, `pauseOnHover` (sürükleme oynatmayı zaten durdurur), `transition` (sayfalar kayar). Ek: `peek`. Oklar `<elementId>__prev`/`__next`, noktalar `<elementId>__dot-<n>` iç rolleri — `page_screenshot` `click` onlarla basar.',
|
|
420
|
+
'Boy kutudan gelmiyorsa görsel sayfa 16:9, çocuk sayfalar en uzununun boyunda. Genişlik belli değilse (Studio`dan bırakılan düğümün `widthType`ı yok) cihaz genişliği kullanılır; kaydırıcıya `widthType: fill` verin.'
|
|
421
|
+
],
|
|
422
|
+
propNotes: {
|
|
423
|
+
peek: 'Komşu sayfaların kenardan görünen payı (dp); en çok genişliğin dörtte biri, sayfalar araya küçük boşluk alır. 0 (varsayılan) tam genişlik sayfa.'
|
|
424
|
+
}
|
|
425
|
+
},
|
|
426
|
+
fab: {
|
|
427
|
+
summary: 'Yüzen eylem düğmesi (FlutterFlow FloatingActionButton): ekranın alt köşesinde durur, sayfa kaydırılırken yerinde kalır. Web`de karşılığı YOKTUR.',
|
|
428
|
+
differences: [
|
|
429
|
+
'Sayfanın NERESİNE konursa konsun runtime`da barındırıcının ekran katmanına taşınır: kenardan 16 dp, sekme çubuğu varsa onun üstünde, yoksa ev göstergesinin üstünde. Düğümün kendi yeri akışta boş kalır — sayfa kök kabının sonuna koyun.',
|
|
430
|
+
'Dokunuş `click` yayar. `page_screenshot` düğmeyi `<elementId>__press` ile bulur (düğüm kabuğu runtime`da boştur).',
|
|
431
|
+
'Renk `kind`den, `button` ile aynı eşleme (dolu varyant); 56 dp yuvarlak. `extended` açık ve `label` doluysa etiket ikonun yanında yazılır, yoksa etiket yalnız erişilebilirlik adıdır.',
|
|
432
|
+
'Kanvasta yerinde, kesikli bir halka içinde çizilir ve basılamaz.'
|
|
433
|
+
],
|
|
434
|
+
propNotes: {
|
|
435
|
+
position: '`bottom-right` (varsayılan) · `bottom-center` · `bottom-left`.',
|
|
436
|
+
icon: 'Material Symbols adı; boşsa `add`.'
|
|
437
|
+
}
|
|
438
|
+
},
|
|
439
|
+
timer: {
|
|
440
|
+
summary: 'Geri sayım ya da kronometre (FlutterFlow Timer). Web`de karşılığı YOKTUR.',
|
|
441
|
+
differences: [
|
|
442
|
+
'Akış bileşenin yöntemini çağıramaz, yalnız prop yazar: başlat/duraklat `isRunning` (setter), sıfırlama `value` yazmaktır (geri sayımda ör. `duration`, kronometrede 0).',
|
|
443
|
+
'Çalışırken her saniye `tick { value }` yayar ve makine `value`yu yazar; geri sayım 0`a inince `finish { isRunning: false }` yayar. Sayaç duvar saatinden hesaplanır, aralık gecikse de kaymaz.',
|
|
444
|
+
'Gösterim `format`la (`mm:ss` saati dakikaya katar, `HH:mm:ss`, `ss`); punto `text` bileşeninin `h2` ölçeğinden, `typographyStyle` üstüne biner. Tasarım kipinde durur.'
|
|
445
|
+
],
|
|
446
|
+
propNotes: {
|
|
447
|
+
value: 'Gösterilen saniye; boşsa geri sayımda `duration`, kronometrede 0. Sayaç her tikte yazar — akışın yazdığı başka bir değer sayacı o değerden yeniden kurar.',
|
|
448
|
+
duration: 'Geri sayımın başlangıcı (saniye, varsayılan 60); yalnız `mode: countdown`da panelde görünür.'
|
|
449
|
+
}
|
|
450
|
+
},
|
|
451
|
+
rating: {
|
|
452
|
+
summary: 'Yıldızla puanlama; kurallar web ile AYNI modülden (`rating-logic`): yarım yıldız, aynı puana dokununca temizleme, puan metni.',
|
|
453
|
+
differences: [
|
|
454
|
+
'Yıldıza dokunuş `change { value }` yayar; `allowHalf` açıkken yıldızın SOL yarısı ayrı dokunma alanıdır ve yarım puan verir. İç roller: `<elementId>__star-<n>` (1`den; tam puan — yarım açıkken yıldızın sağ yarısı) ve `<elementId>__star-<n>-half` (sol yarı) — `page_screenshot` `click` onlarla basar.',
|
|
455
|
+
'Ekran okuyucuda yıldız şeridi TEK ayarlanabilir öğedir: değeri okunur, yukarı/aşağı kaydırma web`in ok tuşu adımıyla arttırır/azaltır (yarım açıkken 0,5). Pasif (`isDisabled`) soluk çizilir.',
|
|
456
|
+
'Cihazın ikon yazı tipi dolgusuzdur: varsayılan yıldız Unicode ★ ile iki hâlde de dolu çizilir, hâl RENKLE ayrışır (`inactiveColor` `default` kenar rengi, öteki tonlar soluk). Seçilen `icon` glif olarak kalır ve dolu/boş yalnız renkle ayrışır.',
|
|
457
|
+
'`focus`/`blur` şemada kalır ama mobilde yayılmaz (yıldız şeridinin klavye odağı yok). Düşenler: `style`, `autofocus`.'
|
|
458
|
+
]
|
|
459
|
+
},
|
|
460
|
+
'multi-select': {
|
|
461
|
+
summary: 'Çoklu seçim: alanda kaldırılabilir çipler, dokununca alttan açılan onay kutulu liste; değer ve olaylar web ile aynı.',
|
|
462
|
+
differences: [
|
|
463
|
+
'Değer `{ label, value }` DİZİSİDİR (düz değer ve `{ id, text }` de okunur); her dokunuş `change { value }` yayar, yük `id`/`text` ikizlerini taşır — web `multi-select.functions.ts`in kuralları mobilde ikizlendi.',
|
|
464
|
+
'Liste alttan açılır (`dropdown` emsali): gruplu listede (`optionType: grouped`) çocuklu satır `isSelectable` değilse başlıktır, gruplar hep açıktır (`isExpanded` okunmaz). Arama kutusu `search` olayına akış bağlıysa `search { searchText }` yayar ve listeyi akış yazar, değilse yerelde süzer. Liste açılınca `focus`, kapanınca (`Done` ya da perde) `blur`; arama doluyken kapanırsa ve `search` akışa bağlıysa web gibi `search { searchText: "" }` de yayılır (yeniden açılan liste eski sonuçla kalmasın).',
|
|
465
|
+
'Üst sınır web gibi formun `maxItems` doğrulamasıdır, seçim kesilmez. Alanda en çok üç çip, gerisi "+n". İç roller `__trigger`, `__clear`, `__done`; satırlar `role="option"` + `data-value`.'
|
|
466
|
+
]
|
|
467
|
+
},
|
|
468
|
+
toast: {
|
|
469
|
+
summary: 'Geçici bildirim tetikleyicisi; tetikleme sözleşmesi web ile aynı (akış `isOpen`ı açar, bileşen bildirimi gösterip `isOpen`ı kapatır).',
|
|
470
|
+
differences: [
|
|
471
|
+
'Bildirim uygulamanın toast deposuna eklenir ve SAYFADAN BAĞIMSIZ yaşar: "Kaydedildi" gösterip `redirect` yapan akışta hedef sayfada görünmeye devam eder. Düğümün kendisi runtime`da hiçbir şey çizmez; kanvasta örnek balon yerinde çizilir.',
|
|
472
|
+
'Web`in dokuz `position`ı telefonda üçe iner: `top-*`/`top-full` üst, `center` orta, öteki hepsi (varsayılan `bottom-right`) alt; bildirim ekran genişliğindedir. Alttaki bildirim sekme çubuğunun üstünde durur.',
|
|
473
|
+
'Açık `modal`, çekmece ya da `dropdown`/`multi-select` listesi varken bildirim onun ÜSTÜNDE çizilir (modaldaki formun tipli uyarısı, çoklu seçimin her dokunuşunda koşan akışın uyarısı görünür); saydam `tooltip` balonunun altında sayfadaki yerinde kalır. Klavye açıkken alttaki bildirim klavyenin üstüne çıkar.',
|
|
474
|
+
'`dedupeKey` YAZILMIŞSA aynı anahtarlı bildirim görünürken ya da `delay`i dolmamışken yenisi yığılmaz; yazılmamışsa web gibi yığılır. Bir konumda en çok üç bildirim, fazlası en eskisini kapatır. Süre web`in tür varsayılanı (bilgi/başarı 4 sn, uyarı 6, hata 8, yükleniyor kalıcı).',
|
|
475
|
+
'Olaylar web`inki: `open`, `close`, `click` (gövde), `actionClick { text, index }` (eylemin kendi akışıyla). Düşenler: `style`, `pauseOnHover`, `showCopyButton` (pano native modül ister), `allowHtml` (metin olduğu gibi), `priority`.',
|
|
476
|
+
'Akışın `alert` adımındaki tipli uyarılar (success/info/warning/error) cihazda da aynı depo üzerinden toast olur ve beklemez; düz uyarı onay bekleyen diyalogdur.'
|
|
477
|
+
]
|
|
478
|
+
},
|
|
479
|
+
video: {
|
|
480
|
+
summary: 'Video oynatıcı; prop ve olaylar web ikizininki (`src`, `poster`, `autoplay`, `loop`, `muted`, `controls`; `play`/`pause`/`ended`/`click`).',
|
|
481
|
+
differences: [
|
|
482
|
+
'Cihazda `expo-video` (denetimler platformun kendi oynatıcısı), Studio kanvası ve önizlemede HTML5 `<video>`. Kanvasta oynatılmaz ve dokunuş almaz — dokunuş seçim jestidir, denetimler yalnız görünür.',
|
|
483
|
+
'Kutu: boyu kabuktan gelen video (`heightType: fixed` + ölçülebilir `heightString`, ya da `fill`) kabuğu doldurur; genişliği belli video (`widthType: fill`, ya da `fixed` + `widthString`) boyunu orandan alır — panelin `appearance.aspectRatio`su, yoksa 16:9; genişliği belli değilse boy 200 dp. Studio`dan bırakılan video `heightType: fixed` alır ama ölçüsü yoktur: 16:9 için `widthType: fill` verin. Video kutuyu `cover` ile doldurur (web ikizi gibi).',
|
|
484
|
+
'`autoplay` yalnız oynatıcı kurulurken (sayfa açılışı, kaynak değişimi) uygulanır; tarayıcı sesli otomatik oynatmayı engelleyebilir (`muted` açın). `ended` `loop` açıkken yayılmaz. `click` yalnız `controls: false` iken yayılır — denetimler açıkken dokunuş oynatıcınındır.',
|
|
485
|
+
'Cihazda afiş yerel bir özellik değildir: `poster` ilk oynatmaya dek videonun üstünde çizilir ve denetimler açıkken ortasındaki oynat düğmesi oynatmayı başlatır. Düşen: `style`.',
|
|
486
|
+
'Cihazda sayfa odağı kaybedince (yığında arkaya düşünce, başka sekmeye geçince) video durur ve `pause` yayar; dönüşte kendiliğinden sürmez. Döngü sınırındaki ve ara belleğe almadaki kısa duruşlar `pause`/`play` yaymaz (web `<video loop>` gibi).'
|
|
487
|
+
]
|
|
488
|
+
},
|
|
489
|
+
audio: {
|
|
490
|
+
summary: 'Ses oynatıcı (FlutterFlow AudioPlayer): oynat/duraklat düğmesi, başlık, ilerleme izi ve süre. Web`de karşılığı YOKTUR.',
|
|
491
|
+
differences: [
|
|
492
|
+
'Cihazda `expo-audio`, kanvas ve önizlemede HTML5 `<audio>`; denetim iki yerde aynı çizimdir. Cihazda iOS`un sessiz anahtarına uymaz (müzik uygulamalarının davranışı).',
|
|
493
|
+
'Akış yöntem çağıramaz, prop yazar: çalma `isPlaying`dir — açılışta `true` otomatik oynatmadır, akış `true`/`false` yazarak başlatır ve durdurur, bitmiş ses baştan çalar. Kullanıcı denetimle başlatıp durdurunca `play`/`pause` `{ isPlaying }` yayar ve makine prop`u yazar; ses bitince önce `pause`, ardından `ended { isPlaying: false }` (`loop` açıkken `ended` yok). Tarayıcı sesli otomatik oynatmayı reddederse `pause { isPlaying: false }` yayılır.',
|
|
494
|
+
'İzde dokunulan yere atlanır. İç roller `<elementId>__toggle` (oynat/duraklat) ve `<elementId>__track` (iz) — `page_screenshot` `click` onlarla basar.',
|
|
495
|
+
'`showControls: false` bileşeni görünmez yapar ama ses çalar (arka plan sesi, akışla çalınan efekt); kanvasta kesikli yer tutucu çizilir. Tasarım kipinde çalmaz.',
|
|
496
|
+
'Ara belleğe alma (yavaş ağ, izde tamponlanmamış noktaya atlama) duruş sayılmaz, `pause` yaymaz. `ended` akışı aynı turda yeniden `isPlaying: true` yazarsa ses baştan çalar (akışla tekrar). Cihazda sayfa odağı kaybedince (yığında arkaya düşünce) ses durur ve `pause { isPlaying: false }` yayar; dönüşte kendiliğinden sürmez. Kaynak değişince yeni kaynak baştan yüklenir, `isPlaying` açıksa çalar.'
|
|
497
|
+
],
|
|
498
|
+
propNotes: {
|
|
499
|
+
src: 'Ses dosyasının adresi ya da platform dosyası (mp3, m4a, aac, wav). Canlı yayın adresinin süresi bilinmez: iz ilerlemez, süre 0:00 yazar.',
|
|
500
|
+
isPlaying: 'Çalıyor mu: akışın yazdığı `true` çalar, `false` durdurur. Kullanıcının denetimi ve bitiş bu prop`u geri yazar.',
|
|
501
|
+
title: 'Denetimin üstündeki başlık (tek satır); boşsa çizilmez.'
|
|
502
|
+
}
|
|
503
|
+
},
|
|
504
|
+
lottie: {
|
|
505
|
+
summary: 'Lottie animasyonu (FlutterFlow Lottie Animation): Lottie JSON ya da dotLottie (`.lottie`). Web`de karşılığı YOKTUR.',
|
|
506
|
+
differences: [
|
|
507
|
+
'Cihazda `lottie-react-native`, kanvas ve önizlemede `@lottiefiles/dotlottie-react`: çizici ve WASM`ı ayrı parçadır, yalnız `lottie` düğümü olan sayfada yüklenir ve WASM paketin kendisinden sunulur (CDN`e gidilmez). Kanvasta da oynar.',
|
|
508
|
+
'Akış prop yazar: `isPlaying: false` yerinde durdurur, `true` kaldığı yerden sürdürür. Döngüsüz (`loop: false`) animasyon bitince `finish { isPlaying: false }` yayar; akış yeniden `true` yazınca baştan oynar — `finish` akışının kendisi aynı turda `true` yazsa da (akışla tekrar). Tasarım kipinde açık kalan `isPlaying` bitişi tekrar ettirmez.',
|
|
509
|
+
'Kutu `video` ile aynı kuraldan, varsayılan oran olmadan: kabuktan gelen boy ya da (genişlik belliyken) panelin `aspectRatio`su, yoksa 150 dp; animasyon kutuya `contain` ile sığar. Dokunuş almaz, `click` olayı yoktur.'
|
|
510
|
+
],
|
|
511
|
+
propNotes: {
|
|
512
|
+
src: "Animasyonun adresi (`.json` Lottie, `.lottie` dotLottie — cihazda adreste `.lottie` GEÇMELİ, uzantısız dosya JSON sanılır), platform dosyası ya da JSON'un kendisi METİN olarak (yapıştırılan ya da ifadenin ürettiği metin, ör. `{{ JSON.stringify(...) }}`). NESNE olarak bağlanan animasyon kaynak DEĞİLDİR (runtime prop eşleyicisi iç içe düz nesneyi bozuyor) — yer tutucu çizilir. Katman dizisi (`layers`) taşımayan JSON da kaynak sayılmaz.",
|
|
513
|
+
speed: 'Oynatma hızı çarpanı (1 = normal); 0,1–10 aralığına kırpılır, geçersiz değer 1.'
|
|
514
|
+
}
|
|
515
|
+
},
|
|
516
|
+
signature: {
|
|
517
|
+
summary: 'İmza pedi; prop ve olaylar web ikizininki (`value` PNG data URL ya da ham SVG, `penColor`, `penWidth`, `outputFormat`, `clearText`; `change { value }`, `clear`).',
|
|
518
|
+
differences: [
|
|
519
|
+
'Cihazda mürekkep `react-native-svg`, jest `PanResponder`; kanvas ve önizlemede DOM `<svg>`. Her tamamlanan vuruşta değer web gibi `change { value }` ile yazılır: `self.value` de `event.data.value` da dolu gelir. PNG cihazda görünmez bir `Svg`nin anlık görüntüsüdür (ekran ölçeğinde), web`de `<canvas>`ın; ikisi aynı SVG belgesinin çizimidir ve kalem rengi boşsa ekranda tema metin rengi, değerde somut `#111111` olur.',
|
|
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
|
+
'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
|
+
'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 (ARC-116, ölçüldü), `modal` sunumlu sayfada aşağı vuruş sayfayı kapatabilir (ölçülmedi). İmzayı sekme kökündeki ya da itilmemiş sayfaya koyun.'
|
|
524
|
+
]
|
|
525
|
+
},
|
|
526
|
+
webview: {
|
|
527
|
+
summary: 'Uygulama içinde web sayfası (`src`) ya da satır içi HTML (`html`) — FlutterFlow WebView. Web`in `iframe`inin mobil karşılığıdır; web`de bu slug YOKTUR.',
|
|
528
|
+
differences: [
|
|
529
|
+
'Cihazda `react-native-webview`; kanvas ve önizlemede web `iframe`inin korumalı alanıyla `<iframe>` (betik, form, açılır pencere; `allow-same-origin` yok — çerez ya da depolama isteyen site önizlemede eksik çalışabilir, cihazda tam). Kanvasta dokunuş almaz. Android`de görünüm kendi içeriğini sayfanın kaydırma kabı içinde de kaydırır.',
|
|
530
|
+
'Gezinme varsayılan KAPALI (güvenlik kararı): ilk yükleme ve yönlendirmeleri (ilk `load`a kadar), alt çerçeveler ve aynı belgedeki çapalar serbesttir; yüklemeden sonra başka belgeye giden gezinme `navigate { url }` yayar ve ENGELLENİR. Adres sistemde (http(s) tarayıcıda, `mailto:`/`tel:`/`sms:` ilgili uygulamada) YALNIZ kullanıcının dokunduğu bağlantıda açılır — betiğin gezinmesi (`location`, zamanlayıcı, programla tıklama) ve form gönderimi yalnız olay yayar, uygulama şemaları (ör. `whatsapp://`) hiç açılmaz. `allowNavigation: true` gezinmeyi görünümün içinde yapar, `navigate` yine yayılır. Yeni pencere (`target="_blank"`, `window.open`) görünümde açılmaz: `navigate` yayılır, kullanıcının dokunduğu bağlantıysa (izin açıkken de) sistemde açılır.',
|
|
531
|
+
'Kuralın bilinen boşlukları: ilk `load`dan ÖNCE her gezinme serbesttir (betik ya da hızlı dokunuş dahil); aynı adrese yapılan form gönderimi aynı belge sayılır; Android POST isteğini kurala hiç getirmez ve karar 250 ms içinde verilemezse yüklemeye izin verir (olay yine yayılır). Web`de köprü yalnız `html` içeriğinde ve yalnız gerçek bağlantı dokunuşunu görür: betiğin gezinmesi, form gönderimi ve açılır pencere çerçevenin içinde ya da yeni sekmede kalır; başka kökenli `src` sayfasında köprü hiç yoktur.',
|
|
532
|
+
'Sayfadan akışa: `window.ReactNativeWebView.postMessage(metin)` → `message { data }` (metin olduğu gibi; JSON`u akış ayrıştırır). Web`de köprü `html` içeriğinde çalışır, başka kökenli `src` sayfasında YOKTUR.',
|
|
533
|
+
'Kutu `lottie` kuralından: kabuktan gelen boy ya da (genişlik belliyken) panelin `aspectRatio`su, yoksa 300 dp. `load` her tamamlanan yüklemede (izin verilen gezinmeden sonra da) yayılır. Cihazda yüklenemeyen sayfa (ağ hatası) `error` yayar ve yer tutucu çizer; web`de tarayıcı engellenen ya da bulunamayan çerçevede de `load` atar, `error` pratikte gelmez (web `iframe` gibi).'
|
|
534
|
+
],
|
|
535
|
+
propNotes: {
|
|
536
|
+
src: 'Mutlak adres (`https://…`); `javascript:`, `data:`, `vbscript:`, `file:` şemaları boşa düşer (web `iframe` süzgeci). Göreli adres cihazda yüklenmez. `html` doluysa yok sayılır.',
|
|
537
|
+
html: 'Satır içi HTML belgesi; doluysa `src`nin önüne geçer. Cihazda `about:blank` kökeninde, web`de kökensiz korumalı `srcdoc` olarak çizilir; sayfa içi çapa (`#bolum`) yerinde kaydırır.',
|
|
538
|
+
allowNavigation: 'Açıkken bağlantılar görünümün İÇİNDE açılır; kapalıyken (varsayılan) gezinme engellenir ve kullanıcının dokunduğu bağlantı sistemde açılır. İki durumda da `navigate { url }` yayılır.',
|
|
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
|
+
title: 'Erişilebilirlik etiketi (ekran okuyucu; web`de `<iframe title>`).'
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
};
|