@appaflytech/zeyrek-ai-mcp 0.0.36 → 0.0.40

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (210) hide show
  1. package/.env.example +15 -0
  2. package/README.md +5 -5
  3. package/dist/config.js +37 -0
  4. package/dist/index.js +2 -0
  5. package/dist/knowledge/access.js +802 -0
  6. package/dist/knowledge/backendConstraints.js +18 -1
  7. package/dist/knowledge/case.js +41 -0
  8. package/dist/knowledge/componentCatalog.js +524 -53
  9. package/dist/knowledge/componentEvents.js +132 -7
  10. package/dist/knowledge/connectDataBind.js +851 -0
  11. package/dist/knowledge/connectDataDefinition.js +344 -0
  12. package/dist/knowledge/connectDataExecute.js +93 -0
  13. package/dist/knowledge/connectDataRules.js +128 -0
  14. package/dist/knowledge/decision.js +121 -0
  15. package/dist/knowledge/expressionPrelude.js +60 -0
  16. package/dist/knowledge/layoutSummary.js +140 -2
  17. package/dist/knowledge/microserviceParameters.js +58 -0
  18. package/dist/knowledge/mining.js +94 -0
  19. package/dist/knowledge/mobileComponentCatalog.js +876 -0
  20. package/dist/knowledge/mobileComponentEvents.js +259 -0
  21. package/dist/knowledge/mobileStore.js +396 -0
  22. package/dist/knowledge/normalize.js +240 -72
  23. package/dist/knowledge/outlines.js +36 -0
  24. package/dist/knowledge/platform/lint.js +385 -0
  25. package/dist/knowledge/platform/mobile.js +142 -0
  26. package/dist/knowledge/platform/mobileLayoutLint.js +324 -0
  27. package/dist/knowledge/platform/mobileRules.js +231 -0
  28. package/dist/knowledge/platform/mobileSpacing.js +82 -0
  29. package/dist/knowledge/platform/mobileTabs.js +108 -0
  30. package/dist/knowledge/platform/nativeBoxModel.js +44 -0
  31. package/dist/knowledge/platform/profile.js +25 -0
  32. package/dist/knowledge/platform/resolve.js +122 -0
  33. package/dist/knowledge/platform/web.js +39 -0
  34. package/dist/knowledge/policy.js +18 -4
  35. package/dist/knowledge/process.js +510 -0
  36. package/dist/knowledge/reservedTables.js +79 -0
  37. package/dist/knowledge/rowFilter.js +43 -0
  38. package/dist/knowledge/rules.js +485 -22
  39. package/dist/knowledge/schemaGuard.js +11 -0
  40. package/dist/knowledge/styleResolve.js +64 -10
  41. package/dist/knowledge/styleResolveNative.js +529 -0
  42. package/dist/knowledge/themeResolve.js +3 -3
  43. package/dist/observability/trace.js +13 -5
  44. package/dist/platform/argumentAliases.js +128 -0
  45. package/dist/platform/bodyFile.js +103 -0
  46. package/dist/platform/capture/actions.js +398 -0
  47. package/dist/platform/capture/browser.js +1 -0
  48. package/dist/platform/capture/capture.js +683 -0
  49. package/dist/platform/capture/console-log.js +122 -0
  50. package/dist/platform/capture/index.js +11 -0
  51. package/dist/platform/capture/readiness.js +103 -0
  52. package/dist/platform/capture/summary.js +77 -0
  53. package/dist/platform/capture/target.js +5 -0
  54. package/dist/platform/capture/targets/studio-mobile.js +15 -0
  55. package/dist/platform/capture/targets/studio-web.js +5 -0
  56. package/dist/platform/diagnostics.js +10 -4
  57. package/dist/platform/domSummary.js +1 -1
  58. package/dist/platform/errors.js +163 -10
  59. package/dist/platform/http.js +29 -8
  60. package/dist/platform/impersonation.js +45 -0
  61. package/dist/platform/jsonArray.js +24 -0
  62. package/dist/platform/responses.js +39 -5
  63. package/dist/platform/schemaReadMemory.js +60 -0
  64. package/dist/platform/secrets.js +68 -2
  65. package/dist/platform/strictArguments.js +68 -12
  66. package/dist/platform/tokenVault.js +187 -4
  67. package/dist/resources/examples/bpm-gorev-kontrol.json +294 -0
  68. package/dist/resources/examples/bpm-iso-dokuman.json +228 -0
  69. package/dist/resources/examples/bpm-satinalma.json +376 -0
  70. package/dist/resources/examples/connect-data-convert-verify.json +107 -0
  71. package/dist/resources/examples/connect-data-dropdown-roles.json +66 -0
  72. package/dist/resources/examples/connect-data-edit-m2m.json +73 -0
  73. package/dist/resources/examples/connect-data-query-params.json +50 -0
  74. package/dist/resources/examples/connect-data-table-entity.json +147 -0
  75. package/dist/resources/examples/connect-data-workflow-microservice.json +65 -0
  76. package/dist/resources/examples/middleware-authenticate.json +1 -1
  77. package/dist/resources/examples/mobile-app-shell-drawer.json +244 -0
  78. package/dist/resources/examples/mobile-app-shell-stack.json +157 -0
  79. package/dist/resources/examples/mobile-app-shell-tab.json +208 -0
  80. package/dist/resources/examples/mobile-form-screen.json +365 -0
  81. package/dist/resources/examples/mobile-list-detail-form.json +703 -0
  82. package/dist/resources/examples/page-detail-profile.json +2 -1
  83. package/dist/resources/examples/page-dynamic-form.json +3 -2
  84. package/dist/resources/examples/page-flex-sections.json +1 -1
  85. package/dist/resources/examples/page-html-embed.json +1 -1
  86. package/dist/resources/examples/workflow-basic.json +8 -2
  87. package/dist/resources/guides/access.md +810 -0
  88. package/dist/resources/guides/bpm.md +691 -0
  89. package/dist/resources/guides/case.md +153 -0
  90. package/dist/resources/guides/component.md +92 -5
  91. package/dist/resources/guides/decision.md +185 -0
  92. package/dist/resources/guides/entity.md +50 -8
  93. package/dist/resources/guides/expressions.md +14 -5
  94. package/dist/resources/guides/functions.md +1 -1
  95. package/dist/resources/guides/getting-started.md +38 -1
  96. package/dist/resources/guides/layout.md +11 -7
  97. package/dist/resources/guides/merge.md +42 -7
  98. package/dist/resources/guides/microservice.md +88 -3
  99. package/dist/resources/guides/middleware.md +69 -5
  100. package/dist/resources/guides/mobile-layout.md +193 -0
  101. package/dist/resources/guides/mobile-publish.md +148 -0
  102. package/dist/resources/guides/mobile.md +565 -0
  103. package/dist/resources/guides/page.md +469 -82
  104. package/dist/resources/guides/theme.md +8 -2
  105. package/dist/resources/guides/translation.md +1 -1
  106. package/dist/resources/guides/workflow.md +58 -1
  107. package/dist/resources/read.js +41 -0
  108. package/dist/resources/rules.js +11 -5
  109. package/dist/resources/schema-fingerprint.json +7 -5
  110. package/dist/resources/schemas/AccessExplanationDto.json +144 -0
  111. package/dist/resources/schemas/AccessMatrixDto.json +170 -0
  112. package/dist/resources/schemas/AccessPermissionDto.json +57 -0
  113. package/dist/resources/schemas/AccessPolicyDto.json +223 -0
  114. package/dist/resources/schemas/AccessResourceDto.json +86 -0
  115. package/dist/resources/schemas/AppSessionDto.json +53 -0
  116. package/dist/resources/schemas/ConnectDataDescribeDto.json +344 -0
  117. package/dist/resources/schemas/ConnectDataRequestModel.json +202 -0
  118. package/dist/resources/schemas/ConnectDataResultDto.json +421 -0
  119. package/dist/resources/schemas/ConnectorCredentialDto.json +70 -0
  120. package/dist/resources/schemas/ConvertConnectDataToMicroserviceCommand.json +37 -0
  121. package/dist/resources/schemas/CreateAccessPolicyCommand.json +209 -0
  122. package/dist/resources/schemas/CreateDecisionCommand.json +221 -0
  123. package/dist/resources/schemas/CreateEntityCommand.json +118 -0
  124. package/dist/resources/schemas/CreateMicroserviceCommand.json +13 -1
  125. package/dist/resources/schemas/CreateProcessDefinitionCommand.json +1337 -0
  126. package/dist/resources/schemas/CreateQueryCommand.json +4 -0
  127. package/dist/resources/schemas/CreateWorkflowCommand.json +146 -1
  128. package/dist/resources/schemas/DataJobDto.json +6 -1
  129. package/dist/resources/schemas/DecisionDto.json +302 -0
  130. package/dist/resources/schemas/DetachConnectDataMicroserviceCommand.json +28 -0
  131. package/dist/resources/schemas/ExplainAccessQuery.json +33 -0
  132. package/dist/resources/schemas/GenerateProcessDocumentCommand.json +116 -0
  133. package/dist/resources/schemas/GlobalFunctionUpdateResultDto.json +24 -0
  134. package/dist/resources/schemas/MicroserviceDto.json +15 -3
  135. package/dist/resources/schemas/OrganizationProjectDto.json +343 -0
  136. package/dist/resources/schemas/OrganizationSchemaDto.json +196 -0
  137. package/dist/resources/schemas/OrganizationSchemaVersionDto.json +207 -0
  138. package/dist/resources/schemas/PatchProcessDefinitionCommand.json +76 -0
  139. package/dist/resources/schemas/PreviewMicroserviceCommand.json +10 -1
  140. package/dist/resources/schemas/PreviewWorkflowCommand.json +25 -1
  141. package/dist/resources/schemas/ProcessDefinitionDto.json +1480 -0
  142. package/dist/resources/schemas/ProcessSimulationDto.json +96 -0
  143. package/dist/resources/schemas/SaveConnectorCredentialCommand.json +90 -0
  144. package/dist/resources/schemas/SaveProcessEventSourceCommand.json +61 -0
  145. package/dist/resources/schemas/SaveProcessMailSourceCommand.json +89 -0
  146. package/dist/resources/schemas/SignProcessTaskCommand.json +73 -0
  147. package/dist/resources/schemas/SimulateProcessDefinitionQuery.json +92 -0
  148. package/dist/resources/schemas/StartMobileBuildCommand.json +54 -0
  149. package/dist/resources/schemas/StepDto.json +25 -1
  150. package/dist/resources/schemas/UpdateAccessPolicyCommand.json +209 -0
  151. package/dist/resources/schemas/UpdateDecisionCommand.json +216 -0
  152. package/dist/resources/schemas/UpdateEntityCommand.json +118 -0
  153. package/dist/resources/schemas/UpdateMicroserviceCommand.json +13 -1
  154. package/dist/resources/schemas/UpdateProcessDefinitionCommand.json +1357 -0
  155. package/dist/resources/schemas/UpdateQueryCommand.json +4 -0
  156. package/dist/resources/schemas/UpdateViewCommand.json +0 -2
  157. package/dist/resources/schemas/UpdateWorkflowCommand.json +146 -1
  158. package/dist/resources/schemas/UpsertMobileStoreSettingsCommand.json +333 -0
  159. package/dist/resources/schemas/ValidateProcessDefinitionQuery.json +1339 -0
  160. package/dist/server.js +31 -1
  161. package/dist/tools/access.js +369 -2
  162. package/dist/tools/accessOperations.js +135 -0
  163. package/dist/tools/accessPolicies.js +170 -0
  164. package/dist/tools/accessRuntime.js +203 -0
  165. package/dist/tools/applications.js +63 -3
  166. package/dist/tools/bpm.js +343 -0
  167. package/dist/tools/bpmGovernance.js +266 -0
  168. package/dist/tools/bpmOperations.js +230 -0
  169. package/dist/tools/bpmReporting.js +154 -0
  170. package/dist/tools/bpmRouting.js +150 -0
  171. package/dist/tools/bpmRuntime.js +396 -0
  172. package/dist/tools/case.js +178 -0
  173. package/dist/tools/caseRuntime.js +89 -0
  174. package/dist/tools/common.js +19 -6
  175. package/dist/tools/components.js +118 -14
  176. package/dist/tools/connectData.js +450 -0
  177. package/dist/tools/connectors.js +193 -0
  178. package/dist/tools/datasources.js +3 -3
  179. package/dist/tools/decisions.js +206 -0
  180. package/dist/tools/dependencies.js +1 -1
  181. package/dist/tools/deployments.js +38 -3
  182. package/dist/tools/designSchemaPatch.js +34 -9
  183. package/dist/tools/dtos.js +36 -5
  184. package/dist/tools/entities.js +79 -12
  185. package/dist/tools/environments.js +1 -1
  186. package/dist/tools/externalComponents.js +26 -5
  187. package/dist/tools/flows.js +119 -13
  188. package/dist/tools/folders.js +1 -1
  189. package/dist/tools/imports.js +5 -2
  190. package/dist/tools/layouts.js +50 -17
  191. package/dist/tools/merges.js +2 -2
  192. package/dist/tools/microservices.js +77 -25
  193. package/dist/tools/mobile.js +280 -0
  194. package/dist/tools/mobileStore.js +572 -0
  195. package/dist/tools/modules.js +48 -0
  196. package/dist/tools/organizationStructure.js +137 -0
  197. package/dist/tools/pages.js +467 -100
  198. package/dist/tools/platformInfo.js +28 -8
  199. package/dist/tools/profileWrite.js +92 -0
  200. package/dist/tools/projects.js +71 -9
  201. package/dist/tools/rows.js +69 -13
  202. package/dist/tools/schemaOps.js +61 -1
  203. package/dist/tools/screenWrite.js +36 -7
  204. package/dist/tools/screens.js +95 -5
  205. package/dist/tools/templates.js +26 -1
  206. package/dist/tools/translations.js +1 -1
  207. package/dist/tools/variables.js +11 -5
  208. package/dist/tools/workflows.js +10 -5
  209. package/package.json +2 -2
  210. package/dist/platform/screenshot.js +0 -1162
@@ -31,8 +31,20 @@ export const TABLE_COLUMN_TYPE_NOTE = "KOLON TİPİ SÖZLÜĞÜ (bekler → çiz
31
31
  "tag: metin → appearance renginde TEK rozet; renk kolonun appearance prop'undan gelir (satır bazında rows[i]._columns[<indeks>].appearance ile ezilir), serbest hex ALMAZ. " +
32
32
  "tags: [{ value, color }] dizisi ya da metin dizisi → çok rozet, renk SATIR VERİSİNDEN (serbest hex burada geçer), sığmayanlar +N ile toplanır. " +
33
33
  "action: veri kolonu DEĞİL — aksiyon sütunu ayrı çizilir; kolon tanımında seçilirse ham değer metin olarak görünür.";
34
+ /**
35
+ * KORUMALI DEĞER (f-31, kompleks proje) — table · datatable · detailview · text ortak davranışı.
36
+ * Kaynak: `packages/ng-apps-ui/src/shared/protected-value.functions.ts`,
37
+ * `shared/components/protected-value/ProtectedValue.svelte`, `packages/ng-apps-flow/src/access/`.
38
+ */
39
+ export const PROTECTED_VALUE_NOTE = "KORUMALI DEĞER (kompleks proje, f-31): table-source uçtan gelen satır `__protected: { <alanSlug>: 'masked' | 'plain' }` metası taşır; hidden alan satırda HİÇ YOKTUR. " +
40
+ "'masked' alan kilit ikonuyla MASKE METNİNİ ('*******8901') çizer; satırın kimliği bulunursa ve runtime erişim özeti yüklüyse yanında 'Göster' çıkar: gerekçe diyaloğu → POST /{project}/runtime/{app}/reveal → değer 30 SANİYE görünür, sonra kendiliğinden yeniden maskelenir. Değeri BOŞ maskeli hücrede kilit kalır, 'Göster' ÇIKMAZ. " +
41
+ "Tasarımcı kanvasında 'View as user' ile seçilen kullanıcının özeti de yüklenir: 'Göster' o kullanıcıya sunulacağı yerde ETKİSİZ çizilir (tıklama bileşeni seçer, diyalog açılmaz; gerçek açma önizlemede); kullanıcı seçili değilken tasarımcının project.data.reveal izni karar verir. " +
42
+ "'Göster' kuralı moda göre: 'off' (basit proje HEP 'off') ya da özet yüklenemediyse ÇIKMAZ (backend her reveal'i 403 AccessRevealDeniedException ile reddeder); 'shadow'da ÇIKAR (özet her şeyi açık döner, backend reveal'i yine denetler — yetkisiz kullanıcı ret mesajını görür); 'enforce'ta yalnız entity'nin actions'ında reveal varsa. Page.can('reveal', …) bu kuralın yerini tutmaz: 'enforce' dışında hep true'dur. " +
43
+ "Açılan değer prop'a, akışa, olaya, yerel depoya ya da URL'e YAZILMAZ; olay yayılmaz, akış bağlanamaz. 403/404/422/429 mesajları bileşenin dil sözlüğündendir. 'plain' alan düz değerdir, normal çizilir. " +
44
+ "Maskeli değeri forma isMasked'sız BAĞLAMA: güncelleme formunda textinput'un value'su kaydın alanına, isMasked'ı satır metasına birlikte bağlanır (textinput.propNotes.isMasked). Gizleme arayüzdür; yetki backend'de denetlenir. Izgaralarda (bağlı datatable, Studio satır listesi) maskeli hücre politika yazma izni veriyorsa KÖR ÜZERİNE YAZILIR (ADR 0007): editör boş açılır, yalnız yazılan değer gider; table bileşeninde hâlâ düzenlenmez.";
45
+ export const REVEAL_ENTITY_NOTE = "Maskeli değerin açılacağı entity: slug ('musteriler') ya da id. BOŞSA runtime erişim özetinden bulunur — satırın korumalı alanlarını okunur alan olarak taşıyan TEK entity. İki entity aynı alan adını taşıyorsa ya da mod 'shadow' iken (özet alan listesi boş) bulunamaz ve 'Göster' ÇIKMAZ; o durumda doldur. Korumasız veride etkisizdir.";
34
46
  export const STYLE_GROUP_NOTES = {
35
- surfaceStyle: "{ background, radius, borderTop, borderRight, borderBottom, borderLeft, shadow, contentOverflow(visible|hidden|auto), opacity(0–100 yüzde; 100/boş yazılmaz) }. radius: tema kademesi ('var(--ng-radius-md)'; sm/lg 'Border radius'un oranı, md temanın kendisi), tek uzunluk ('18px') YA DA dört köşe ('90px 14px 14px 14px' — sol-üst, sağ-üst, sağ-alt, sol-alt). KENARLIK YÖN BAŞINADIR: her yön kendi CSS kısayolunu taşır ('1px solid var(--ng-border-primary)'), 'none' o kenarı kapatır; eski borderWidth/borderStyle/borderColor üçlüsü EMEKLİ (yalnız hiçbir yön yazılmamışsa okunur). shadow: çok katmanlı `box-shadow` metni ('0px 2px 5px 0px rgba(0,0,0,.2), inset 8px 5px 7px 0px #000'), tema token'ı ('var(--ng-shadow-md)') ya da eski preset anahtarı (none|sm|md|lg).",
47
+ surfaceStyle: "{ background, radius, borderTop, borderRight, borderBottom, borderLeft, shadow, contentOverflow(visible|hidden|auto), opacity(0–100 yüzde; 100/boş yazılmaz), rotate(derece, −360…360), scale(YÜZDE 10–500; 100 aynı boy ve varsayılan — 1.1 değil 110), translateX/translateY(px, −1000…1000) }. radius: tema kademesi ('var(--ng-radius-md)'; sm/lg 'Border radius'un oranı, md temanın kendisi), tek uzunluk ('18px') YA DA dört köşe ('90px 14px 14px 14px' — sol-üst, sağ-üst, sağ-alt, sol-alt). KENARLIK YÖN BAŞINADIR: her yön kendi CSS kısayolunu taşır ('1px solid var(--ng-border-primary)'), 'none' o kenarı kapatır; eski borderWidth/borderStyle/borderColor üçlüsü EMEKLİ (yalnız hiçbir yön yazılmamışsa okunur). shadow: çok katmanlı `box-shadow` metni ('0px 2px 5px 0px rgba(0,0,0,.2), inset 8px 5px 7px 0px #000'), tema token'ı ('var(--ng-shadow-md)') ya da eski preset anahtarı (none|sm|md|lg). DÖNDÜR/ÖLÇEKLE/KAYDIR (ADR 0005): dört alan TEK transform'a derlenir — sıra kaydır → döndür → ölçekle, köken merkez, düğüm çocuklarıyla döner; nötr değer (0°, 100, 0 px) hiçbir şey yazmaz. Değer BİRİMSİZ sayıdır ('15deg', '20px', '110%' yazılmaz) ve aralık dışı yazılmaz — mobilde ikisi de nativeStyle.warnings'e düşer. Transform'lu düğümün İÇİNDEKİ portal açmayan açılır menü/liste düğümün kutusuna hapsolur. hoverStyle.lift düğümün transform'unu ezmez, önüne eklenir. Katmanlar (modal, drawer, popover) ve uygulama kabukları (layout, layout-region, layout-shell, auth-layout, qm-content, qm-sidebar) bu dört alanı TAŞIMAZ: transform'lu ata position:fixed katmanı ekrandan koparır. Döndürmeyi serbest style.transform'a yazma — mobil yalnız tipli alanı çizer (MOB-002).",
36
48
  typographyStyle: "{ textColor, fontFamily('var(--ng-font)' tema gövde | 'var(--ng-font-heading)' tema başlık | 'monospace' — token tema fontunu izler; SİSTEM fontları ('Georgia, serif', 'Courier New, monospace') olduğu gibi uygulanır, serbest WEB fontu (Google) ise YÜKLENMEZ: tema yüklemediği için tarayıcı yedek yazı tipine düşer), fontSize(CSS uzunluğu: '15px'|'1.1em'; çıplak sayı px sayılır), fontWeight(400|500|600|700), fontStyle(normal|italic), textDecoration(none|underline|line-through), lineHeight(TEK alan, üç yazım: oran '1.4' | yüzde '140%' | uzunluk '24px'; eski kayıtlardaki çıplak 140 yüzde sayılır), letterSpacing(CSS uzunluğu, negatif meşru: '-0.4px'), textAlign(left|center|right|justify|start|end — left/right FİZİKSELDİR, dir=rtl'de de aynı yöne yazar; start/end MANTIKSALDIR, yazı yönüne göre döner (LTR'de sol/sağ, RTL'de sağ/sol): çok dilli ya da ar/RTL uygulamada start/end yaz) }. Komponentin içeriğine miras kalır.",
37
49
  hoverStyle: "{ background, borderColor, shadow(none|sm|md|lg), lift(CSS uzunluğu: '2px' — POZİTİF değer öğeyi yukarı kaldırır, '-2px' aşağı iter), transitionMs }. Hiçbir alan dolu değilse hover bloğu ve geçiş HİÇ yazılmaz.",
38
50
  colorTokens: "RENK ALANLARI (background, textColor, borderColor, hover.background/borderColor) hex kadar tema token'ı da alır: 'var(--ng-accent-primary)', 'var(--ng-status-error)', 'var(--ng-background-inverse)'. Token yazılan alan tema değişince izler, hex yazılan kopar; tasarım sistemi renklerinde ÖNCE token'ı tercih et (studio panelinde aynı seçim tema chip'iyle yapılır).",
@@ -85,7 +97,7 @@ export const componentKnowledge = {
85
97
  }
86
98
  },
87
99
  table: {
88
- summary: 'Etkileşimli veri ızgarası: satır seçimi, çift tık, hücre içi düzenleme, kolon filtreleme/sıralama, araç çubuğunda arama — her etkileşim AYRI olay olarak akışa bağlanır.',
100
+ summary: 'LEGACY (2026-09-18): paletten kaldırıldı, yeni ekranlarda datatable kullan; mevcut sayfalardaki table çizilmeye devam eder. Etkileşimli veri ızgarası: satır seçimi, çift tık, hücre içi düzenleme, kolon filtreleme/sıralama, araç çubuğunda arama — her etkileşim AYRI olay olarak akışa bağlanır.',
89
101
  behavior: [
90
102
  'Süzme/sıralama/arama/sayfalama sunucu taraflıdır: filters/sortField/searchText/offset akışla uca gider, dönen satırlar rows prop’una setter ile yazılır.',
91
103
  'AKIŞ BAĞLANMAZSA KONTROL ÇİZİLİR AMA SATIR DEĞİŞMEZ: showSort başlığa ok, filterMode filtre satırı/paneli, isSearchable arama kutusu koyar; tablo rows’u KENDİSİ sıralamaz, süzmez, aramaz, sayfalamaz. İlgili olay (sort · filter · search · pagination) mount akışıyla aynı sorguya bağlanmadıysa ok döner, kutu dolar, satırlar yerinde kalır. Üçünün de yazdığı offset 0’a döner.',
@@ -95,11 +107,13 @@ export const componentKnowledge = {
95
107
  "totalRows yazılmazsa (0/boş) tablo elindeki satırlardan fazlasını bilemez: sayfalayıcı TEK SAYFA kalır ve gösterge o satırları sayar ('12 / 12'); ileri oku pasiftir. limit sayfa boyu listesinde (10·20·30·40·50) yoksa (25, 100) listeye eklenir. rows/filters/selectedRows akıştan null ya da dizi olmayan bir değerle gelirse boş liste sayılır, tablo çökmez (selectedRows'a tek satır nesnesi yazma — dizi yaz).",
96
108
  "isPaginated:true + akışta limit/offset parametreleri + pagination olayı üçlüsü birlikte kurulmalı; biri eksikse tablo tek sayfa kalır (platform_guide('page') Kural 1c).",
97
109
  "SATIR BAZLI GÖRÜNÜM EZMESİ: bir satır kendi _columns DİZİSİNİ taşıyabilir — rows[i]._columns[<kolonun columns dizisindeki İNDEKSİ>] = { appearance:'error', isBold:true, options:[...] } kolon tanımıyla birleşir (column-view.ts resolveColumn → Table.svelte <TableCell {column}>). İndeks TANIM sırasıdır: buildViewColumns index'i isHidden kolonlar elenmeden ÖNCE atar, görünür sıra değil. Kullanıcı kolon menüsünden kolon gizlese bile indeksler kaymaz (hideColumns buildViewColumns'dan SONRA uygulanır). Ezilebilen alanlar appearance · options · isBold; CSV export'u da ezmeyi uygular. Aynı kalıp _actions[i] ile satır bazlı aksiyon ezmesinde de çalışır (rowActions). ŞEMA PROP'U DEĞİLDİR — component_get prop listesinde görünmez, satır verisinin içinde taşınır.",
98
- "Koşullu/satır bazlı renk table'da _columns ile kurulur ve style prop'unu KAYBETTİRMEZ — datatable'ın colorMap'i statiktir. Hem CSS hem satıra göre renk isteyen tablo table'dır; renk için datatable'a mecbur değilsin."
110
+ "Koşullu/satır bazlı renk table'da _columns ile kurulur ve style prop'unu KAYBETTİRMEZ — datatable'ın colorMap'i statiktir. Hem CSS hem satıra göre renk isteyen tablo table'dır; renk için datatable'a mecbur değilsin.",
111
+ PROTECTED_VALUE_NOTE + " Tabloda: maskeli hücre DÜZENLENMEZ (çift tık/Enter editör açmaz) ve hover ipucu vermez; satır kimliği `id`, yoksa isKey kolonu."
99
112
  ],
100
113
  propNotes: {
101
114
  surfaceStyle: NODE_SURFACE_NOTE,
102
115
  rows: 'Satır dizisi; mount/filter/sort/pagination akışlarının setter adımıyla doldurulur.',
116
+ revealEntity: REVEAL_ENTITY_NOTE,
103
117
  appearance: "YÜKSEKLİK/GENİŞLİK ELLE HESAPLANMAZ (ölçüldü 2026-09-05, f11-repro). heightType:'auto' tablo içeriği kadar uzar — satır sayısı × satır yüksekliği hesabı gerekmez. heightType:'fixed' gövdeyi KAYDIRIR (grid-container overflow:auto), satır kaybolmaz; kare'de görünmeyen satır kırpılmış değil kaydırılmıştır. KOLONLAR KARTI TAŞIRMAZ: genişlik toplamı kabı aşarsa tablo kendi içinde YATAY kaydırır; kabın scrollWidth'i değişmez. KAYDIRMA ÇUBUKLARI VARSAYILAN GİZLİDİR (kaydırma Shift+tekerlek, trackpad, dokunma ve klavyeyle çalışır) ve sağda gizli kolon olduğunu gösteren tek işaret sabitlenmiş aksiyon kolonunun (actionsPinned) sol çizgisidir — kolonları sağa taşan tabloda kullanıcının görmesi için showScrollbar:true yaz. Toplam kaptan KÜÇÜKSE kolonlar orantılı büyütülüp kap tam doldurulur (stretchColumns) — bu yüzden 'kolonu daraltayım da sığsın' yamalarına gerek yok. Tek gerçek tuzak yerleşim tarafındadır: FLEX ebeveynde blocks[].size yok sayılır, ölçü appearance'tan gelir; IZGARA ebeveynde tersi (gateway PAGE-019 ile uyarır).",
104
118
  totalRows: "Toplam kayıt: Number(Steps.<adım>?.headers?.[\"total-count\"] ?? 0) guard'lı ifadesiyle yazılır. Yazılmazsa sayfalayıcı tek sayfa kalır ve gösterge eldeki satırları sayar.",
105
119
  rowSelection: "none | single | multi — seçim self.selectedRow / self.selectedRows prop'larından okunur. none 'satır seçilemez' DEMEK DEĞİL: satır tıklaması yine selectedRow'a yazar ve select'i çalıştırır, yalnız vurgu yoktur.",
@@ -122,17 +136,53 @@ export const componentKnowledge = {
122
136
  "Liste→form geçişi satır AKSİYONUYLA kurulur: actions:[{ text, kind, icon, flow:{ type:'flow', ref:<flowId> } }]. doubleClick/select bağlamak 200 döner ama bağ ölüdür (gateway PAGE-008 keser).",
123
137
  "Aksiyona tıklanınca komponent ÖNCE tıklanan satırı kendi selectedRow prop'una yazar, SONRA akışı çalıştırır (Table.svelte:72 setNode + onEmit) — akışta satır '<elementId>.selectedRow.<alan>' ile okunur. selectedRow katalogda hidden'dır; setter ile yazılmaz, komponent doldurur.",
124
138
  "style prop'u 2026-08-27'de EKLENDİ: parçalar &__toolbar · &__title · &__head · &__th · &__body · &__row · &__td. table'ın aksine tek yazım kuralı vardır — hepsi designerCss'ten geçer, yani camelCase yazılır ve iç seçici alır. (Bu tarihten önce datatable stillendirilemiyordu; eski notlar 'style YOKTUR' diyorsa güncel değildir.)",
125
- "Satır bazlı görünüm ezmesi (_columns / _actions) da YOKTUR — o table'a özgüdür. Renklendirme burada yalnız kolonun colorMap/autoColor sözlüğüyle, yani satırdan bağımsız kurulur."
126
- ],
127
- propNotes: {
128
- surfaceStyle: NODE_SURFACE_NOTE,
129
- columns: "Kolon tipleri: text · number · date · datetime · time · switch · tag · email · url · link · image · file · progress. Her tipin ne beklediği/ne çizdiği table'ın kolon sözlüğüyle AYNIDIR (component_get('table') → knowledge.propNotes.columns), İKİ İSTİSNA dışında: burada image/file düz URL kabul etmez (aşağıdaki image notu) ve renk satır bazında değil colorMap ile kurulur. PROGRESS (2026-08-27) hücrenin içine çubuk ya da halka çizer: progressVariant bar|circle · max (varsayılan 100) · progressLabel none|percent|fraction|value · progressColor + customProgressColor · thresholds [{from,color}] (yüzdeyi geçmeyen en yüksek eşik kazanır) · captionField BAŞKA bir satır alanının metnini çubuğun ÜSTÜNE yazar, yani ad ve çubuk tek hücrede durur. Sıralama/dışa aktarım ham sayıyı görür, çizimi değil.",
139
+ "Satır bazlı _columns görünüm ezmesi YOKTUR — o table'a özgüdür; renklendirme yalnız kolonun colorMap/autoColor sözlüğüyle, satırdan bağımsız kurulur. Aksiyon ise satıra göre değişebilir: rows[i]._actions[<aksiyon index>] = { isHidden, isDisabled, text … } o satırda aksiyonun üstüne biner (rowActions).",
140
+ "SATIR KOŞULLU AKSİYON (2026-09-25): actions[i].isHidden / isDisabled bir kod ifadesi olabilir — { type:'code', ref:'{{ !item.isCustomizable }}' }; tablo onu HER SATIR için item = o satır ile çözer (machine.evaluateExpression). Connect Data'ya bağlı tabloda satırlar _actions taşıyamadığı için tek yol budur. Sıra: tanım → ifade → satırın _actions'ı. Sütun çizilen satırlardan hesaplanır: aksiyon en az bir satırda görünüyorsa sayılır, her satırda gizliyse (koşul ya da _actions) sütun hiç çizilmez (2026-10-02); satır yokken koşullu aksiyon aday sayılır. Kanvasta ifade çözülmez, aksiyon her satırda görünür.",
141
+ "HÜCRE ŞABLONU (2026-09-21): bir kolonun hücresi serbest tasarlanabilir — tablonun ÇOCUĞU olarak bir datatable-cell düğümü (props.column = o kolonun name'i) eklenir, içine bırakılan bileşenler o kolonda her satırda çizilir ve satırı item olarak okur ({{ item.title }}). Tablonun başka türde çocuğu olmaz. Ayrıntı: datatable-cell kaydı.",
142
+ "keepSampleData (gizli switch, 2026-09-21) bir TASARIMCI kararıdır: true iken studio kanvasında bağlı olmayan tablonun üstündeki 'Örnek veri gösteriliyor · Connect data' çağrısı ve perdesi çizilmez. Runtime okumaz, veriyi etkilemez; örnek satırlarla bırakılacak bir tabloda true yazılabilir, rows bağlanınca anlamı kalmaz. Kanvasta tablo kendi içinde yatay kayar ve kolon başlığı tıklaması o kolonun panelini açar (designer.interactive) — bu da yalnız studio davranışıdır.",
143
+ "KOLON GENİŞLİĞİ (2026-09-22): başlığın sağ kenarı sürüklenerek (ya da tutamaç odaktayken ←/→, 10px) kolon daraltılıp genişletilir; en dar 60px. Kanvasta bu kolonun columns[i].width değerini yazar — paneldeki Width alanıyla aynı değer, tek geri alma adımı. Runtime'da tanıma YAZILMAZ: ziyaretçinin seçimi tarayıcıda kolon tercihiyle (localStorage ZY_DataTableColumns_<elementId>.widths) saklanır, kolon menüsündeki Sıfırla onu da siler. Genişliği kalıcı vermek için width yaz.",
144
+ PROTECTED_VALUE_NOTE + " Datatable'da satır kimliği keyField alanıdır (varsayılan `id`; bağlı tabloda runtime kaynağın birincil anahtarını yazar, isKey yok); maskeli hücre biçimlendirilmez, kolon tipinden bağımsız kilitli maske çizilir. KÖR ÜZERİNE YAZMA (2026-09-26, ADR 0007): BAĞLI tabloda kolonun capability.canWrite'ı açıksa (politika canWrite ∧ tanımın editable listesi — maskeli okumak yazmayı kapatmaz) maskeli hücre satır/hücre düzenlemesinde BOŞ editörle açılır, yer tutucu 'Değiştirmek için yeni değer girin'; yalnız YAZILAN değer taslağa ve update isteğine girer, boş bırakılan ya da yazılıp silinen maske hiç gitmez. Maskeli hücre hücre seçimine girmez (yazılan değer başka satırlara yayılmaz) ve toplu düzenleme maskeli kolonu SUNMAZ. Bağlı OLMAYAN tabloda maskeli hücre düzenlenmez (değişiklik elle yazılan save akışına gider). Eski değeri görerek düzeltmek için önce 'Göster' (açılan değer editöre ön doldurulmaz).",
145
+ "DÜZENLEME (2026-09-17, f-21; satır bazlı): editMode none|row|batch. Satır ✏ düğmesi ya da çift tıkla düzenlemeye açılır ve YAZILABİLİR HÜCRELERİNİN HEPSİ aynı anda editör olur (tek hücre editörü yok); ilişki hücresi lookup panelini açar. Enter satırı bitirir, Escape vazgeçer. row kipinde satır sonundaki ✓ o satırı kaydeder (hatasızsa satır kapanır), batch'te ✓ yalnız satırı kapatır ve üst çubukta 'N değişiklik · Kaydet · Vazgeç' kalır; kapanmış ama kaydedilmemiş satırda ✓/✕ görünür. canAddRow yeni satırı açar (newRowDefaults ile dolu, düzenlemede açılır; üstteki '+ Satır' düğmesi 2026-09-18'de KALKTI — yerine addRowButton ile satırların altında/üstünde mavi '+ Satır ekle' satırı ve addRowShortcut açıkken tablo odaktayken Ctrl/Cmd+Enter; buton alttayken yeni satır da en alta eklenir), canDeleteRow satır sonunda onaylı Sil. Kaydet 'save' olayı yayar ve changeset'i self.changeset'e yazar. BAĞLI TABLODA (rows connectData, behavior.edit açık) editMode/canEditRow/canAddRow/canDeleteRow/newRowDefaults/keyField'ı runtime tanım ∧ yazma kabiliyetinden YAZAR, yazmayı connect-data ucuna kendisi yapar (create → update → delete; hatalar self.rowErrors, satır taslakta kalır) — save için AKIŞ YAZILMAZ. Hücre yalnız capability.canWrite (policy ∧ editable) açıksa düzenlenir; bağlı olmayan tabloda kolonun editable işareti (columns[].editable). image/file/progress/link hücresi, bağlı olmayan tablonun maskeli hücresi ve anahtarı (keyField; bağlı tabloda kaynağın birincil anahtarı, yoksa id) olmayan ya da sayfada tekrar eden satır düzenlenmez/silinmez. Kaydı süren satırın ✓/Sil/Kaydet düğmesi pasiftir (çift kayıt yok); atomic tanımda toplu yazmada düşen satırın komşuları 'Kaydedilmedi' işaretiyle taslakta kalır (hiçbiri yazılmadı; writeMode partial'da komşular yazılır, yalnız düşen satır kırmızı kalır); ✕ satırın hatasını da siler. Hücre seçimi (selectedCells, cellSelectionChange) yalnız düzenleme kipinde. Kanvasta düzenleme pasiftir. GÜNCELLEME (2026-09-18): tasarımcıda batch seçeneğinin etiketi 'Cell'dir (değer batch kalır). Yazılabilir ilişki hücresi TEK tıkta yalnız seçilir; ÇİFT tık düzenler: row kipinde satırın bütün yazılabilir hücreleri açılır, Cell (batch) kipinde kayıtlı satırın YALNIZ çift tıklanan hücresi editör olur (Enter ya da alandan çıkmak değeri taslakta bırakıp kapatır, Escape yalnız editörü kapatır; ✏ ve yeni satır iki kipte de bütün satırı açar); ilişki hücresinde seçim paneli açılır; düzenlenen satırda ilişki hücresi bir seçici düğmedir (değer + ok). batch kipinde çift tıklanan hücre aynı kolondaki çoklu hücre seçiminin içindeyse yazılan değer seçili BÜTÜN hücrelere gider (row kipinde yalnız o satır). batch kipinde Sil onaysızdır ve satırı 'SİL' rozetiyle, üstü çizili olarak silinecek diye İŞARETLER (↶ ile geri alınır); silme kayıtta changeset.deleted'a girer. Yeni satır 'YENİ' rozeti ve yeşil zemin alır; değişen hücrede köşe işareti ve altında üstü çizili eski değer vardır. Üst çubuk KALKTI: tablonun altında 'N değişiklik · N yeni · N silinecek · N hata' özeti, 'Tümünü geri al' ve 'Değişiklikleri kaydet (N)' durur. Filtre özetinde ve filtre çubuğunda lookup'tan seçilen ilişki değeri kimliğiyle değil görünen alanıyla yazılır; filtre çubuğunda ilişki kolonu doğrudan seçim paneliyle açılır ve seçim hemen uygulanır. GÜNCELLEME (2026-09-19): editMode'a cell (hücre başına kayıt; tanımda saveMode 'cell') eklendi; tasarımcıda batch'in etiketi artık 'Batch', 'Cell' etiketi yeni cell kipidir. cell kipinde kayıtlı satırın çift tıklanan hücresi tek başına açılır ve ✓/✕ editörün kendi çerçevesinin sağ ucunda, ayraçtan sonra iki ikon düğmedir (arama kutusunun temizle düğmesi gibi) (satır ✏ düğmesi yoktur): ✓ ya da Enter yalnız o alanı hemen kaydeder (update patch'inde tek alan), ✕ ya da Escape vazgeçer; alandan çıkmak editörü kapatmaz. Aynı anda tek hücre açıktır, başka hücreye geçmek açık hücrenin kaydedilmemiş değerini atar; kayıt hata verirse hücre açık kalır ve hata altında görünür. İlişki hücresinde panel kapanınca hücre açık kalır, seçim ✓ ile yazılır. Yeni satır, Sil (onaylı) ve toplu düzenleme row kipindeki gibi hemen kaydedilir; edit kolonu yalnız canAddRow ya da canDeleteRow açıksa görünür. Çoklu hücre seçiminin içindeki hücre açılırsa (batch ve cell) değer seçili bütün hücrelere yazılır; cell kipinde ✓ hepsini tek changeset'te kaydeder, ✕ hepsinden vazgeçer. Edit kolonu (✏ 🗑) sağa yapışıktır (sticky), genişliği boştaki düğmelere göredir; ✏/🗑 hover'da görünür. Çakışan işlemler kilitlidir: toplu satır seçimi varken çift tık/✏ düzenleme açmaz, Satır ekle (ve Ctrl+Enter) gizlenir, ✏/🗑 görünmez; düzenleme açıkken satır seçim kutuları devre dışıdır ve ✏/🗑 görünmez. Escape ilişki hücresinde (lookup paneli açıkken de) düzenlemeyi kapatır.",
146
+ "LOOKUP (2026-09-17, f-23): bağlı tabloda YAZILABİLİR relation hücresi lookup panelini açar (hedef tablo op:lookup ile, arama + 'Daha fazla'), seçim yalnız düzenlenen satırda; salt okunur tabloda, editable dışı alanda ya da güncellenemeyen satırda hücre HİÇBİR ŞEY açmaz (2026-09-21 — eski gezinme paneli kaldırıldı). Panelin 'Detaylı ara…' bağlantısı tanımın lookup.mode'una göre pencere ya da sağ çekmece açar (mode yazılmamışsa pencere, 2026-09-19) ve paneldeki arama metniyle başlar: kolonlar lookup.fields (türetilmişte anahtar dışı alanlar), arama, lookup.behavior.filterable alanlarında VE koşulları, başlıktan sıralama, sayfalar; o2m/self tekil seçim ('Seç' ya da çift tık), m2m onay kutuları + 'Uygula'; 'Temizle' alan zorunluysa (describe isRequired) gizli; yazma yetkisi yoksa panel yalnız gezinme. Seçilen hedef hücreye yerel yazılır, kayıt { alan: '<id>' } / m2m ['<id>', …] olarak gider. Filtre panelinde relation kolonunun değeri 'Seç…' ile aynı panelden seçilir (in/notin çoklu), chip'te görünen ad. Hedefin görünen alanı metin (ve korumasız) ise sunucu ilişkiye contains/icontains da sunar (2026-09-21): bu işleçte değer seçilmez, YAZILIR ve hedefin görünen alanında aranır ({ field:'city', operator:'icontains', value:'ist' } → EXISTS … title ILIKE '%ist%'); gelişmiş panelde, column modundaki işleç düğmesinde ve bar hapının editöründe (işleç seçimi + kayıt seçimi ya da metin) çıkar; bar ile gelişmiş panel birlikteyken panel çubuğun ÜSTÜNDE açılır, çubuk hep tablonun hemen üstündedir. Hedef tabloyu okuyamayan (targetReadable:false) hücre gri “—” + kilit çizer ve panel açmaz. Hedefin maskeli alanı ayrıntılı aramada maske olarak (Göster ile) çizilir.",
147
+ "TOPLU (2026-09-17, f-22): bulkActions none|edit|delete|both açık ve editMode none değilken başa onay kutusu kolonu gelir (başlıkta sayfadaki satırları seç); anahtarlı sunucu satırları seçilir, seçim self.selectedRows'a yazılır ve rowSelectionChange yayılır. Seçim çubuğu: 'N seçili · Toplu düzenle · Sil · Temizle'. Toplu düzenle bir FORMDUR ve sağdan açılan bir ÇEKMECEDE (drawer, 2026-09-19) alanlar alt alta listelenir; altta Vazgeç · Uygula, arka plan/×/Escape uygulamadan kapatır: yazılabilen her kolon için editör (anahtar üçlü seçim, ilişki alanında lookup paneli); yalnız doldurulan alanlar uygulanır, boş bırakılan değişmez; ilişki alanının ×'i temizler (o2m null, m2m boş liste — hücre editörüyle aynı); row kipinde bütün doldurulan alanlar tek save (tek update isteği, bulk), batch'te taslağa girer. Sil onaylı, tek delete. Hatasız yazılan satırlar seçimden düşer, hatalılar kırmızı ve seçili kalır; 1000 satır üstünde toplu eylem kapanır. BAĞLI TABLODA bulkActions'ı runtime yazar: tanım edit.bulk ∧ meta.write.bulk, update → edit, delete → delete. Hücre seçimi (Shift/Ctrl/Alt, selectedCells, cellSelectionChange) tek başına değer doldurmaz; batch kipinde seçimin içindeki bir hücre çift tıkla düzenlenirse değer seçili hücrelerin hepsine yazılır (2026-09-18), çok alanı birlikte değiştirmek toplu düzenle formuyla yapılır. Kilitli (yazılamayan) hücre seçime girmez.",
148
+ "YERLEŞİM VE FİLTRE MODLARI (2026-09-18; 2026-09-21'den beri gelişmiş oluşturucu filterMode değil advancedFilter anahtarıdır ve column/bar ile birlikte açılabilir): advancedFilter (koşul oluşturucu: tümü/herhangi biri, VE/VEYA, grup; kurallar tutamaçtan sürüklenip grubun içine/dışına taşınır; Uygula yalnız her kuralın kolonu ve değeri doluyken görünür, Sıfırla yalnız uygulanmış filtre ya da taslakta kural varken; ziyaretçi filtreyi adıyla kaydedebilir — tanıma yazılmaz, tarayıcıda element id'siyle saklanır (localStorage ZY_DataTableFilters_<elementId>), üst çubukta Filtre düğmesinin yanındaki 'Kayıtlı filtreler' açılır menüsünden (filterPosition left'te sağında, right'ta solunda) panel açılmadan seçilip uygulanır, kanvasta yoktur; filtre yokken panel boş bir kuralla açılır; 'Filtre (n)' düğmesiyle açılır, Ctrl+Enter uygular — düğme ARAÇ GRUBUNUN PARÇASI DEĞİLDİR (2026-09-18): araçlar nerede olursa olsun tablonun üstündeki çubukta durur, filterPosition left'te başlığın hemen ardına, right'ta sağ kenara) · column (başlığın altında kolon başına filtre satırı: metinde işleç menüsü, sayı/tarihte min–max (bağlı tablonun birincil anahtarı hariç: tek değer, eşittir; date ve datetime kolonda gün seçilir ve gte 'GÜNT00:00:00' · lte 'GÜNT23:59:59' gider — bitiş günü dahildir, 2026-10-02), boolean Tümü/Evet/Hayır, enum/tag'de çoklu seçim, relation'da lookup) · bar (tablo üstünde kolon başına açılır düğme + panel) · none. ÜÇ MOD DA AYNI filters sözleşmesini yazar ve mount'u tetikler — bağlı tabloda işleçler capability.operators'tan gelir (aralık yalnız gte+lte sunulursa), enabled:false kolon hiçbir modda çıkmaz; column/bar ekranı her zaman filters prop'undan kurulur (sunucu 422 ile reddedince geri yazılan filtre görünür). showFilterSummary aktif filtre + sıralamayı kaldırılabilir chip'ler olarak gösterir; bar modunda çizilmez (aktif filtreler barın haplarında durur ve oradan düzenlenir), sonuç sayısı ne barda ne özette yazılır — footer'daki kayıt özeti taşır. Başlık (title) boşsa üst çubuk yalnız araçlar üstteyse ya da advanced filtre düğmesi varsa çizilir; başlıksız tabloda filterMode bar iken üst köşedeki araçlar ayrı çubuk açmaz, filtre çubuğunun ucuna oturur. Araçlar (showRefresh · showExport: bu sayfanın CSV'si · showColumnManager: 'Column settings' menüsü — kolon gizle/göster ve sürükleyerek (ya da tutamaçta ↑/↓) sırala, tanıma yazılmaz; seçim tarayıcıda element id'siyle saklanır (localStorage ZY_DataTableColumns_<elementId>) ve tablo aynı kolonlarla açılır, Reset kaydı siler, kanvas okumaz; üçü de yalnız ikon + tooltip) toolsPosition ile dört köşeden birine oturur; footer (sol altta kayıt özeti '1–10 / 24 kayıt · 1 seçili' — showRecordSummary ile kapatılır —, sayfa başına, «ilk ‹önceki sayfa numaraları sonraki› son» düğmeleri) footerPosition ile tablonun altında ya da üstündedir; sayfalama paginationPosition ile kayıt sayısının ardında (left) ya da sağ kenardadır, stickyFooter footer'ı sayfa kaydırmasında görünür kenara yapıştırır. stickyHeader başlığı tablonun KENDİ kaydırmasında üstte tutar (sabit yükseklikli tablo); kolonun isPinned'i kolonu başa alıp yatay kaydırmada solda sabitler. size sm|md|lg satır yüksekliğini, hücre boşluğunu ve yazı boyunu değiştirir. YENİ BIRAKILAN TABLO (2026-09-18): başlıksız, filterMode bar, araçlar sağ üstte (filtre çubuğunun ucunda), isPaginated açık, sayfalama sağ altta, kayıt özeti sol altta, stickyHeader açık, size md, Status kolonu solid tag; bu değerler yalnız şema varsayılanıdır — prop'u hiç yazılmamış eski düğüm eski görünüşünü korur (advanced, sağ üst araçlar, sağda sayfalama, yapışkan başlık kapalı). paginationMode pages (numaralı) | infinite (gövde sona kaydırıldıkça sonraki sayfa offset=yüklenen satır sayısıyla istenir ve satırlar birikir; kendi yüksekliğiyle uzayan tabloda footer'da 'Daha fazla' düğmesi). Gövde durumları: yükleniyor (iskelet), kayıt yok, filtre sonucu boş (Filtreleri kaldır), hata (loadError; Tekrar dene mount'u yeniden çalıştırır, satır varken tablo üstünde şerit).",
149
+ "TİPE BAĞLI İLİŞKİ (2026-10-01, ADR 0012): 'Kime' gibi bir hücre satırın türüne göre farklı tabloya bağlanıyorsa (hedef başına ayrı nullable FK: hedef_user_id, hedef_pozisyon_id, hedef_birim_id) kolonu görünen adı tutan METİN alanına bağla ve columns[i].relationTypeField = türü tutan alan (ör. hedef_tipi), relationTargets = [{ value:'kullanici', field:'hedef_user_id' }, …] yaz. Hedef FK kolonları columns'ta isHidden:true durmalı ve tanımın editable listesinde olmalı (tür, ad ve üç FK). Satır düzenlemesinde hücre o satırın (taslaktaki) türünün gizli ilişki kolonunun lookup'ını açar; seçim TEK YAMAYLA seçilen FK'yi, öbür FK'leri null'u ve görünen adı (hedefin görünen alanı) yazar; tür değişince FK'ler ve ad boşalır. Tür boşken hücre salt okunurdur. Toplu düzenleme bu kolonu sunmaz. Birden çok türün paylaştığı hedef tabloda (birimler: departman/firma/grup) relationTargets öğesine filterField + filterValues ('holding, company') ve isteğe bağlı excludeField + excludeValues yazılır; alanlar tanımda o FK'nin lookup.behavior.filterable listesinde olmalı. Tür değişince Kime seçicisi hemen açılır; seçimsiz kapanırsa tür ve Kime eski hâline döner. Kayıt satırın kaydıdır — editMode row önerilir.",
150
+ "SÜRÜKLE-SIRALA (2026-10-01, ADR 0012): canReorderRows:true + orderField:'<sayı alanı>' (editMode none değilken ve sıra kolonu yazılabilirken) satır başına tutamaç kolonu açar; satırlar orderField'a göre çizilir (boşlar sonda). Sürükle ya da tutamaç odaktayken ↑/↓. Bırakılan satır kendi adımı olur, aynı sıradaki satırlar grup kalır (iki eş sıralı satırın arasına bırakılan o gruba katılır), adımlar 1..n yeniden numaralanır; yalnız değeri değişen satırlar yazılır. row/cell kipinde hemen tek save (operation rowReorder), batch'te taslakta bekler. Yeni ve anahtarsız satır taşınmaz; açık düzenleme, toplu seçim ya da süren kayıt varken tutamaç pasiftir. Eş sıra vermek için sıra hücresi elle düzenlenir.",
151
+ ],
152
+ propNotes: {
153
+ searchText: "Gizli, AKIŞIN yazdığı arama metni (2026-10-02, web ve mobil). Tablonun kendi arama kutusu yoktur; ayrı bir textinput'un değeri setter ile <tablo>.searchText'e yazılır. Bağlı tabloda setter bu yazımdan sonra listeyi YENİDEN OKUR (sayfa başa döner) ve istek search taşır: sunucu tanımın behavior.searchable alanlarında içerir (icontains) koşuluyla arar — entity kaynağında ve dinamik filtreli Table kaynaklı microservice'te. Searchable boşsa istek 422 ConnectDataFilterNotAllowed. Aynı yol filters / sortField / sortType / offset / limit için de geçerlidir: setter bunlardan birini yazınca bağlı liste yeniden okunur.",
154
+ canReorderRows: 'boolean (varsayılan false) — satırları tutamaçtan sürükleyerek sıralama; orderField olmadan ya da editMode none iken etkisiz.',
155
+ orderField: "Sırayı tutan sayı alanının adı (ör. 'sira'); canReorderRows açıkken satırlar buna göre çizilir ve sürükleme buraya yazar.",
156
+ surfaceStyle: NODE_SURFACE_NOTE + " Datatable'ın kabı VARSAYILAN olarak kendi 1px çerçevesini, 6px köşesini ve yüzey zeminini çizer (filtre çubuğu + ızgara + footer'ı saran çerçeve). Grupta bir kenarlık yazılınca (borderTop/Right/Bottom/Left — 'none' dahil) kap KENDİ çerçevesini bırakır: çerçeveyi kaldırmak için dört yöne 'none' yaz; düz çizgi yazmak ikinci çerçeve eklemez. radius yazılınca kap köşeyi düğüm kutusundan alır, background yazılınca kabın zemini saydamlaşır (2026-09-18).",
157
+ editMode: "none | row | cell | batch (tasarımcı etiketleri Row / Cell / Batch). Bağlı tabloda runtime tanımın behavior.edit.saveMode'undan yazar; elle yazmak bağlı tabloda etkisizdir. Bağlı olmayan tabloda save olayındaki self.changeset'i akış yazar.",
158
+ operation: "Salt okunur, save'den ÖNCE yazılır (2026-09-21): kaydı doğuran işlem — rowAdd · rowEdit · cellEdit · rowDelete · bulkEdit · bulkDelete · batchSave (batch kipinin 'Değişiklikleri kaydet'i, karışık changeset) · rowReorder (sürükle-sırala). Ayrı olay YOKTUR: tek save akışı Condition'da self.operation ile ayırır.",
159
+ editedRows: "Salt okunur, save'den önce yazılır: eklenen/düzenlenen satırların TAM hâli (sunucu satırı + yama; yeni satırda girilen değerler) — changeset.updated yalnız yamayı taşır. Kolonlara bağlıdır: akış editörü self.editedRows[0].<kolon> önerir.",
160
+ deletedRows: "Salt okunur, save'den önce yazılır: silinen satırların TAM hâli (tek silmede bir öğe) — changeset.deleted yalnız { rowId, id } taşır.",
161
+ editedCell: "Salt okunur, save'den önce yazılır: yalnız operation cellEdit iken { rowId, field, value, previousValue }, diğer işlemlerde null.",
162
+ bulkPatch: "Salt okunur, save'den önce yazılır: yalnız operation bulkEdit iken toplu formun seçili satırlara yazdığı { <kolon>: değer }, diğerlerinde null.",
163
+ rowErrors: "Salt okunur: [{ rowId, field?, message }] — bağlantı son kaydın satır hatalarını yazar; field varsa o hücre kırmızı çerçeve + mesaj.",
164
+ selectedCells: "Salt okunur: { column, rowIds[], anchorRowId } — aynı kolonda çoklu hücre seçimi (D-25); farklı kolona tıklamak seçimi sıfırlar. Doldurma f-22.",
165
+ revealEntity: REVEAL_ENTITY_NOTE,
166
+ columns: "Kolon tipleri: text · number · date · datetime · time · switch · tag · email · url · link · image · file · progress · relation · html. HTML (2026-09-18) html bileşeninin modelini hücreye taşır: satır değeri { content, style } — content ham HTML'dir ve SATIRIN alanlarıyla Mustache'ten geçer ('<b>{{name}}</b>'), style o hücreye scoped CSS bloğudur (emotion; 'color:red; b { … }' iç seçici alır, designerCss/!important YOK); bağlı kaynaktan düz metin gelirse content sayılır. İşaretleme TEMİZLENMEDEN basılır (html bileşeniyle aynı güven modeli; <script> hücrede ÇALIŞMAZ, satır içi on* handler'lar çalışır) — son kullanıcının yazdığı bir alanı html kolonuna eşleme. Satır içi düzenlenmez (editable gizli); sıralama/filtre/CSV etiketsiz metni görür. Studio Rows editöründe html kolonu için 'HTML content' + 'Style' iki metin alanı çıkar. RELATION (Connect Data) ilişki alanının hedef nesnesini ({ id, ad }) görünen alanıyla metin olarak, m2m dizisini ilk 3 chip + “+N” olarak çizer; hedef tabloyu okuyamayan kullanıcıya gri “—” + kilit basar. BAĞLI TABLO: rows connectData ile bağlıysa runtime her kolona gizli capability yazar (işleçler, sortable, enabled, relation, enum) — sıralama/filtre anahtarını ve filtre işleç listesini sunucu belirler, enum değerleri etiket+renkle çizilir; capability elle yazılmaz. Her tipin ne beklediği/ne çizdiği table'ın kolon sözlüğüyle AYNIDIR (component_get('table') → knowledge.propNotes.columns), İKİ İSTİSNA dışında: burada image/file düz URL kabul etmez (aşağıdaki image notu) ve renk satır bazında değil colorMap ile kurulur. PROGRESS (2026-08-27) hücrenin içine çubuk ya da halka çizer: progressVariant bar|circle · max (varsayılan 100) · progressLabel none|percent|fraction|value · progressColor + customProgressColor · thresholds [{from,color}] (yüzdeyi geçmeyen en yüksek eşik kazanır) · captionField BAŞKA bir satır alanının metnini çubuğun ÜSTÜNE yazar, yani ad ve çubuk tek hücrede durur. Sıralama/dışa aktarım ham sayıyı görür, çizimi değil. KİŞİ HÜCRESİ (2026-09-18): text kolonunda showAvatar metnin önüne baş harfli renkli daire çizer (renk addan türer, aynı ad hep aynı renk); avatarField BAŞKA bir satır alanından görsel okur (dosya nesnesi ya da URL; yüklenemezse baş harfe düşer) — ayrı image kolonu açmadan 'avatar + ad' tek hücrede durur. TAG appearance subtle: açık zemin + koyu yazı + renkli nokta (durum rozeti); colorMap'te semantik ad (success/warning/info) tema token'ına çözülür — DİKKAT: temalarda info neredeyse beyazdır (#F8F8F8), mavi için primary kullan; çok açık bir renk subtle'da gri rozete sınırlanır; colorMap satırının mode'u solid ise o değer kolonun görünümünden bağımsız renkli zemin + beyaz yazıyla çizilir (varsayılan soft = kolonun appearance'ı). SWITCH kolonu (2026-09-18) kontrol değil durum işaretidir: booleanStyle icon (varsayılan; true yeşil dolu daire + ✓, false kırmızı dolu daire + ×) · text (dile göre Evet/Hayır, Hayır kırmızı) · switch (eski toggle görünümü); booleanFalseColor muted false'u sönük griye çeker (varsayılan error/kırmızı — false'un sorun olmadığı alanlarda muted kullan). number kolonu eşit genişlikli rakamla çizilir; url kolonu adresi protokolsüz gösterir. HİZA (2026-09-18): kolonun align alanı left|center|right başlığı ve hücreyi birlikte hizalar (avatar+metin ve halka progress da kayar); boş = her tipte solda (number dahil — tutarları sağa yaslamak için align:right yaz); bağlı tablonun birincil anahtar kolonu (capability.isKey) yeni bağlamada 80px dar gelir.",
130
167
  image: "IMAGE/FILE kolonu düz URL string'i KABUL ETMEZ: hücre `{ absolute_path, display_name }` (ya da `fileName`) alanlarını taşıyan bir DOSYA NESNESİ (veya nesne dizisi) bekler — `DisplayCellView.svelte:10` `file.absolute_path ?? ''` okur, düz string verilince kaynak boş kalır ve hücre SESSİZCE boş çizilir (09-04 Y-21). Satır verisi bir metin kolonunda URL taşıyorsa kolonu 'url'/'link' yap ya da veriyi { absolute_path: '<url>', display_name: '<ad>' } biçimine çevir; entity'nin FILE alanı zaten bu şekli döner.",
131
168
  actions: "Satır aksiyonları. kind sözlüğü BUTON'unkinden farklıdır: error · information · solid · transparent · dark · danger · warning (butonda success/error/info/primary/warning). Yanlış sözlükten değer invalid-enum-value verir.",
132
169
  selectedRow: "Salt okunur: satır aksiyonu tıklanınca komponentin kendisi doldurur; akış ifadesinde '<elementId>.selectedRow' ile okunur.",
133
- colorMap: "Kolon içi değer→renk sözlüğü: [{ value:'Active', color:'#16a34a' }]. STATİKTİR — hücrenin kendi değerine bakar, satırın başka alanına göre hesaplanamaz. Satıra göre koşullu renk gerekiyorsa ya table + _columns ezmesi kullan ya da satır verisinde rengi taşı ({ label, color }) — render sırası: veri objesindeki color → colorMap[etiket] → autoColor. TAG HÜCRE ŞEKLİ: metin, { label, color? } ya da { value, color? } (label yoksa value okunur; ikisi de yoksa obje ham JSON basılır) veya bunların dizisi. RENK (veri objesinde de colorMap'te de): semantik ad primary · info · success · warning · error TEMA TOKEN'INA çözülür (tema değişince izler, ham hex yazmaya gerek yok); hex/rgb/'var(--ng-…)'/CSS renk adı olduğu gibi geçer; başka bir değer (yazım hatası, çözülmemiş '{{ }}') o kademeyi ATLAR ve sıradakine düşer. Veri objesindeki variant OKUNMAZ — outline/solid kolonun appearance'ından gelir. Solid rozetin yazı rengi token'da CSS ile siyah/beyaz seçilir.",
170
+ colorMap: "Kolon içi değer→renk sözlüğü: [{ value:'Active', color:'#16a34a' }]. ETİKET (2026-10-01): satıra label yazılırsa hücre ham değer yerine onu çizer — [{ value:'Approved', label:'Onaylandı', color:'success' }] veritabanındaki İngilizce durumu Türkçe rozetle gösterir; filtre seçenekleri de etiketi gösterir, sıralama/filtre ham değerle çalışır. Bağlı kolonda aynı değerin enum etiketini EZER. Etiketli değerin solid modu etikete göre uygulanır. STATİKTİR — hücrenin kendi değerine bakar, satırın başka alanına göre hesaplanamaz. Satıra göre koşullu renk gerekiyorsa ya table + _columns ezmesi kullan ya da satır verisinde rengi taşı ({ label, color }) — render sırası: veri objesindeki color → colorMap[etiket] → autoColor. TAG HÜCRE ŞEKLİ: metin, { label, color? } ya da { value, color? } (label yoksa value okunur; ikisi de yoksa obje ham JSON basılır) veya bunların dizisi. RENK (veri objesinde de colorMap'te de): semantik ad primary · info · success · warning · error TEMA TOKEN'INA çözülür (tema değişince izler, ham hex yazmaya gerek yok); hex/rgb/'var(--ng-…)'/CSS renk adı olduğu gibi geçer; başka bir değer (yazım hatası, çözülmemiş '{{ }}') o kademeyi ATLAR ve sıradakine düşer. Veri objesindeki variant OKUNMAZ — outline/solid kolonun appearance'ından gelir. Solid rozetin yazısı BEYAZDIR, yalnız gerçekten açık zeminde (sarı/amber, açık gri; LCH açıklığı > 70) siyah seçilir — token'da CSS ile, hex'te ölçülerek. SATIR MODU (2026-09-18): [{ value, color, mode:'solid' }] o değeri kolonun appearance'ı (subtle/outline) ne olursa olsun dolu zemin + BEYAZ yazıyla çizer; mode yazılmazsa ya da 'soft' ise kolonun görünümü geçerlidir. Renksiz satırın solid modu yok sayılır.",
134
171
  tableStyle: "zebra | plain — satır zemini varyantı; CSS DEĞİL. Serbest CSS için ayrı `style` prop'u vardır (parça bazlı).",
135
- style: "Parça bazlı CSS: &__toolbar · &__title · &__head · &__th · &__body · &__row · &__td. designerCss her bildirime !important ekler, yani komponentin kendi çerçeve/ayraç varsayılanlarını ezer — Figma tipi düz tablo bununla kurulur."
172
+ style: "Parça bazlı CSS: &__toolbar · &__title · &__footer · &__summary · &__filter-bar · &__filter-panel · &__head · &__th · &__body · &__row · &__td. designerCss her bildirime !important ekler, yani komponentin kendi çerçeve/ayraç varsayılanlarını ezer — Figma tipi düz tablo bununla kurulur.",
173
+ filterMode: "column | bar | none — satır içi filtre arayüzü; gelişmiş koşul oluşturucu ondan bağımsız advancedFilter anahtarıdır, ikisi birlikte açılabilir. Hepsi aynı filters dizisini yazar, akış/bağlantı farkı görmez. column/bar modunda VE/VEYA ve grup kurulamaz (kök kurallar and ile bağlanır); oradan uygulanan filtre yalnız o kolonun kök kurallarını değiştirir, gelişmiş paneldeki grup/or kuralları KORUNUR ve kolon/bar kuralları panelde kural olarak görünür. Bar'ın 'Filtreleri temizle'si yalnız bar kurallarını kaldırır. Eski düğümdeki filterMode=advanced (advancedFilter yazılmamışken) gelişmiş oluşturucu olarak okunur.",
174
+ advancedFilter: "boolean (şema varsayılanı false) — gelişmiş koşul oluşturucu ('Filtre (n)' düğmesi + panel), filterMode'dan bağımsız. Yazılmamış eski düğümde filterMode=advanced ya da boşsa açık sayılır.",
175
+ paginationMode: "pages | infinite — yalnız isPaginated açıkken. infinite'te akış/bağlantı yine TEK sayfa döner; birikimi komponent yapar (offset 0 sıfırlar). totalRows yazılmazsa 'daha var mı' bilinemez ve yükleme durur.",
176
+ toolsPosition: "top-right | top-left | bottom-right | bottom-left — yenile/dışa aktar/kolon menüsü grubunun köşesi (advanced Filtre düğmesi bu grupta DEĞİLDİR, bkz. filterPosition). Alt köşede footer alttaysa onun içine, üstteyse tablonun altındaki ayrı çubuğa oturur.",
177
+ filterPosition: "left | right — yalnız advancedFilter açıkken: 'Filtre (n)' düğmesi hep tablonun üstündeki çubuktadır; left'te başlığın hemen sağına (başlık yoksa sol kenara), right'ta sağ kenara (üstteki araçlardan önce) oturur.",
178
+ paginationPosition: "left | right — footer'da sayfa başına + sayfa numaralarının yeri: left kayıt sayısının ardı (yeni tablonun varsayılanı), right sağ kenar (prop yazılmamış eski düğüm).",
179
+ stickyHeader: "Başlık satırı (ve column modundaki filtre satırı) tablonun KENDİ dikey kaydırmasında üstte kalır — tablo sabit yükseklikliyken anlamlıdır; kendi yüksekliğiyle uzayan tablo sayfayla kaydığından etkisizdir.",
180
+ stickyFooter: "Footer sayfa kaydırmasında görünür kenara yapışır (footerPosition top'ta üste, bottom'da alta) — kendi yüksekliğiyle uzayan uzun tabloda sayfalamayı erişilir tutar.",
181
+ size: "sm | md | lg — satır yüksekliği (hücre dikey boşluğu 6/12/16px), gövde yazısı (12/13/14px) ve başlık yüksekliği (32/40/48px). Varsayılan md.",
182
+ footerPosition: "bottom | top — toplam kayıt + sayfalama çubuğu; üstteyken stickyFooter ile sayfa kaydırmasında üstte kalabilir.",
183
+ addRowButton: "bottom | top | none — canAddRow açıkken '+ Satır ekle' satırının yeri; none'da yeni satır yalnız Ctrl/Cmd+Enter (addRowShortcut) ile açılır.",
184
+ showExport: "Görünen kolonlar × eldeki satırlar CSV'si (bu sayfa; infinite'te o ana kadar yüklenenler) — sunucudaki tüm sonuç DEĞİL.",
185
+ loadError: "Salt okunur: Connect Data bağlantısının son okuma hatası (başarılı okuma temizler). Satır yoksa gövde hata durumu + 'Tekrar dene', satır varsa üstte şerit. Bağlı olmayan tabloda akış yazabilir."
136
186
  }
137
187
  },
138
188
  form: {
@@ -144,6 +194,7 @@ export const componentKnowledge = {
144
194
  "Düzen prop grubunun TAMAMINI taşır (2026-09-01): layout ('flex' | 'grid') + direction/horizontalAlign/verticalAlign/size/gap/wrap, varsayılanları container ile aynı (flex · row · left · top · shrink · medium · wrap açık). 'Form'a layout yazılmaz' eski bilgidir. layout prop'u hiç yazılmamış eski form kayıtları ızgara koordinatıyla (blocks[].position + size.w) dizilmeye devam eder. Platform kataloğu component_get'te hâlâ eski şemayı gösteriyorsa kayıt yenilenmemiştir (ARC-024).",
145
195
  "Alan doğrulaması komponentin kendi validations dizisindedir: [{ type: 'required'|'email'|'max-length'…, message, value, isActive }] — dördü de zorunlu, eski 'maxLength' yazımı kaydedilir ama runtime doğrulayıcı onu TANIMAZ ve sessizce hiçbir şey doğrulamaz. min-value/max-value tarih kuralının çıplak 'yyyy-MM-dd' değeri YEREL gün okunur (2026-09-18): sınır gününe eşit bir alan değeri her saat diliminde geçer (eskiden UTC okunup Türkiye'de 3 saat kayıyordu, CQ-252).",
146
196
  "message bir ÇEVİRİ ANAHTARI olabilir: 't:' önekiyle yazılan mesaj (ör. 't:form.required') uygulamanın çeviri sözlüğünden çözülür — hem alanın kendi hata metninde hem form-validation-errors listesinde. Öneksiz mesaj yazarın kendi cümlesidir ve iki nokta içerse bile aynen gösterilir. Çözüm form MOUNT olurken bir kez yapılır: ekranda hata dururken dil değiştirilirse metin sayfa yenilenene kadar eski dilde kalır.",
197
+ "KORUMALI ALAN (f-31): maskeli değer forma ASLA isMasked'sız value olarak bağlanmaz — güncelleme formunda korumalı alanın textinput'u value'yu kaydın alanına, isMasked'ı satır metasına birlikte bağlar (textinput.propNotes.isMasked). isMasked:true iken BOŞ bırakılan alan required doğrulamasına TAKILMAZ; kullanıcı yazarsa sıradan alan gibi doğrulanır. Boş değerin GÖNDERİLMEMESİ submit akışının isteği nasıl kurduğuna bağlıdır: microservice çağrısının parametre bağı null/'' değeri gövdeye koymaz (saklı değer korunur); gövde akış kodunda ya da setter göreviyle elle kuruluyorsa null GİDER — canWrite yoksa 403 AccessFieldWriteDeniedException, varsa saklı değer SİLİNİR. O durumda boş maskeli alanı gövdeden çıkar.",
147
198
  "Formu temizlemek için akış kodunda resetForm('<form adı>') çağrılır (2026-09-15): alanlar başlangıç değerine döner, form gönderilmemiş hâline geçer, hata işaretleri ve form-validation-errors listesi silinir. Alanları setter ile tek tek null'a çekmek YANLIŞ yoldur: form bir kez gönderildiyse her change doğrulamayı yeniden koşturur ve boş form 'zorunlu alan' mesajlarıyla açılır. Gönderim sonrası otomatik temizlik isteniyorsa isClearFormInputsAfterSubmit aynı sıfırlamayı yapar.",
148
199
  "isLoading AÇIKKEN alanlar DOM'dan kalkar, yerine yükleme animasyonu çizilir: kapanınca çocuklar yeniden mount olur ve onların mount olayları İKİNCİ kez çalışır; makinedeki değerler korunur. title boş bırakılırsa başlık bandı hiç çizilmez. Kanvas toolbar'ı (2026-09-18): isClearFormInputsAfterSubmit · isLoading · isHidden — yerleşim grubunu container toolbar'ı zaten çizer."
149
200
  ],
@@ -159,7 +210,7 @@ export const componentKnowledge = {
159
210
  }
160
211
  },
161
212
  box: {
162
- summary: "Evrensel bırakma kutusu: container'dan farkı kutu modelinin border-box olması ve isteğe bağlı başlık/altlık bölgeleridir; yerleşim değer kümesi 2026-09-02'den beri container'ınkiyle aynıdır.",
213
+ summary: "Evrensel bırakma kutusu: container'dan farkı kutu modelinin border-box olması, tabanında ÇERÇEVE OLMAMASI ve isteğe bağlı başlık/altlık bölgeleridir; yerleşim değer kümesi 2026-09-02'den beri container'ınkiyle aynıdır. Tasarımda çerçevesi olmayan her düzen kutusu (satır, sütun, şerit, buton grubu) box ile kurulur.",
163
214
  behavior: [
164
215
  LAYOUT_ABSENT_NOTE,
165
216
  "layout iki değer alır: 'flex' (akış) ve 'grid' — ve 'grid' container'ınkiyle AYNI ŞEYDİR: mutlak koordinatlı 12 kolon canvas (kullanıcı kararı 2026-09-02, tek grid kavramı). Şemadaki eski 'cssgrid' değeri (akan GERÇEK display:grid) seçenek olmaktan çıktı: yeni yazımda geçmez (invalid-enum-value), yalnız o değerle KAYITLI eski düğümler çizilmeye devam eder (screen-builder/grid-layout.ts isCssGridLayout yalnız 'cssgrid'e bakar).",
@@ -200,7 +251,7 @@ export const componentKnowledge = {
200
251
  'Yüzeysiz sarmalayıcıdır: kendi zemini/kenarlığı yoktur, yalnız bölge ayracını çizer (header altına, footer üstüne).',
201
252
  "Palette GÖRÜNMEZ (isHide) ve SİLİNEMEZ (isDeletable:false) — kaldırmanın tek yolu box'ın ilgili anahtarını kapatmaktır.",
202
253
  "isLoading prop'u YOKTUR: yükleniyor durumu kutunun kendisindedir, bölge onu hiç görmez — dolayısıyla CQ-308'in bırakma alanını öldüren kalıbı bu düğümde hiç oluşmaz.",
203
- "Kendi yerleşimini panelden değil ELEMENT AĞACINDAN seçilerek düzenler (palette gizli, ağaçta görünür); gap alanı hâlâ eski gap+gapCustom ikilisini taşır (box'ta tek alan allowCustom ile birleşti).",
254
+ "Kendi yerleşimini panelden değil ELEMENT AĞACINDAN seçilerek düzenler (palette gizli, ağaçta görünür); gap alanı hâlâ eski gap+gapCustom ikilisini taşır (box'ta tek preset alanına indi; liste dışı değer platformda 422).",
204
255
  "role prop'u ('header' | 'footer') bölgenin kimliğidir ve gizlidir; elle değiştirmek yerleşimi bozar.",
205
256
  "Ayraç rengi ve bölge dolgusu artık kutunun 'sectionStyle' grubundan yönetilir (bölge düğümünün kendi şemasından değil): headerDivider/footerDivider/dividerColor/sectionPadding."
206
257
  ],
@@ -323,13 +374,18 @@ export const componentKnowledge = {
323
374
  'createdAt çözülemezse (dün, 2026-13-45, 2026-02-30, 2026-02-30T10:00:00, tek başına 0 ya da 12345) tarih HAM metin olarak görünür; yeni bir gün uydurulmaz. Tarih biçimi seçilemez, yerele göre sabittir.',
324
375
  'Kök yazı tipi/rengi içe iner: style.fontSize, fontFamily ve color yazar adı, metin, tarih ve yazma kutusuna ulaşır (iç boyutlar kökün oranıdır; tarih rengi yazı renginin %72’sidir). Bağlantı gibi çizilen eylem düğmeleri ve @bahsetme vurgusu vurgu rengini korur.',
325
376
  'Klavye: yazma kutusunda @ ile açılan öneri ↑/↓ ile gezilir, Enter seçer (liste kapalıysa gönderir), Esc listeyi kapatır (IME bileşimi sırasındaki Esc de üst katmanı kapatmaz); gezilen satır kaydırılan listenin görünür bölümünde kalır; yanıt/düzenleme kutusu Esc ile kapanır ve çekmece/modal gibi üst katmanı KAPATMAZ. Yanıt ve düzenleme kutusu açılınca odak kutuya gelir, kapanınca açan düğmeye döner. IME bileşimi sırasında Enter göndermez. Öneri listesi altta sığmıyorsa kutunun üstüne açılır.',
326
- 'Yorumlar liste yapısındadır (role="list", her konu listitem); yazma kutusunun adı "Yorum yaz", yanıt kutusunun "Yanıt yaz", düzenleme kutusunun "Yorumu düzenle" (dile göre). Avatar süs görseldir; kırık ya da yüklenemeyen avatar adın baş harflerine düşer.'
377
+ 'Yorumlar liste yapısındadır (role="list", her konu listitem); yazma kutusunun adı "Yorum yaz", yanıt kutusunun "Yanıt yaz", düzenleme kutusunun "Yorumu düzenle" (dile göre). Avatar süs görseldir; kırık ya da yüklenemeyen avatar adın baş harflerine düşer.',
378
+ "Süreç kapsamı (scope task | instance, targetId): rows platform yorumlarıdır (Page.bpm.instance(id).comments() — { id, body, authorUserId, postedAt }) ve users listesiyle adlara çevrilir. submit yükündeki process alanı { scope, targetId, visibility, body, mentionUserIds } taşır: @Ad metinde @<kullanıcı id>'sine çevrilmiştir — bahsetme metnin başında ya da boşluktan sonra başlar, ad tam kelime olarak eşleşir (@Alican, Ali değildir), büyük/küçük harf Türkçe kuralla yok sayılır, uzun ad önce; iki kullanıcının paylaştığı ad çevrilmez. Akış Page.bpm.instance(targetId).comment(process.body, process.visibility) ya da Page.bpm.task(targetId).comment(...) çağırır. Bahsedilen kişiye platform metinsiz bildirim yollar (iç yorumda yalnız dış katılımcı olan kişiye hiç). visibility boşsa sürecin commentVisibility'si uygulanır; internal dış katılımcıdan gizler. Süreç kapsamında yanıt, beğeni, düzenleme ve silme kapalıdır (platformda karşılığı yok)."
327
379
  ],
328
380
  propNotes: {
329
381
  rows: '[{ id, author, text, createdAt, parentId, avatar, likeCount, likedByMe }] — parentId dolu olan satır yanıttır. createdAt ISO metni, "YYYY-AA-GG" ya da Unix zaman damgası (10 hane saniye / 13 hane milisaniye) olabilir; boş author+text satırı atlanır.',
330
382
  currentUser: 'Yorum sahipliğini ve ownOnly filtresini belirleyen ad; tüm olay yüklerindeki author budur (yorumun sahibi DEĞİL, işlemi yapan). Boşsa düzenleme/silme ownOnly açıkken gizlenir.',
331
383
  people: '@bahsetme önerileri: virgülle ayrılmış metin ya da ad dizisi ({{ users.map((u) => u.name) }}).',
332
384
  placeholder: 'Boşsa dile göre "Yorum yaz… (@ ile birini an)" gösterilir; yanıt kutusu da aynı metni kullanır. Erişilebilir ad ayrıdır ve dile göre sabittir.',
385
+ users: "[{ id, name }] — süreç yorumunda bahsedilebilecek kullanıcılar; öneriler people ile birleşir.",
386
+ scope: "'' (serbest) | task | instance — süreç görevine ya da örneğine yorum.",
387
+ targetId: 'Süreç kapsamında görev ya da örnek kimliği; submit yükünün process.targetId alanına geçer.',
388
+ visibility: "'' (sürecin commentVisibility'si, varsayılan) | all | internal — süreç yorumunun görünürlüğü.",
333
389
  style: STYLE_GROUP_NOTES.styleEscape + " PARÇALAR (19): '&__list' · '&__thread' (bir kök yorum + yanıtları) · '&__comment' · '&__avatar' · '&__body' · '&__meta' · '&__author' · '&__date' · '&__text' · '&__mention' · '&__actions' · '&__action' · '&__reply-composer' · '&__composer' · '&__textarea' · '&__button' · '&__suggestions' · '&__suggestion' · '&__empty'. Durum hedefleri parçaya EK olarak yazılır: '&__comment--reply' (yanıt) · '&__comment--pending' (gönderiliyor) · '&__action--danger' (Sil) · '&__button--ghost' (Vazgeç); beğeni düğmesi için '&__action[aria-pressed=\"true\"]'; '&__textarea:focus-visible', '&__action:hover', '&__suggestion:hover', '::before/::after' ve '@media' çalışır. Hepsi ilk adayda tutar. Yanıt girintisi mantıksaldır (margin-inline-start): RTL'de sağdan gelir; özelleştirirken marginLeft değil marginInlineStart yaz."
334
390
  }
335
391
  },
@@ -358,6 +414,7 @@ export const componentKnowledge = {
358
414
  container: {
359
415
  summary: "Genel kapsayıcı (TİPLİ stil modeli: surfaceStyle · typographyStyle · hoverStyle · headerStyle); children'ını ya FLEX akışıyla (yeni kapsayıcıların varsayılanı) ya da 12 kolonluk IZGARA ile dizer. Her sayfanın kökünde silinemeyen page_container bundandır ve o da aynı düzen prop'larını alır.",
360
416
  behavior: [
417
+ "ÇERÇEVE TABANDA VARDIR: tema her container'a kart yüzeyi (1px --ng-border-primary çerçeve) verir. Tasarımda çerçevesi olmayan kutu için container DEĞİL box kullan. container zorunluysa çerçeveyi surfaceStyle ile kapat — { borderTop:'none', borderRight:'none', borderBottom:'none', borderLeft:'none' } (zemin de istenmiyorsa background:'transparent'); style'a ham border yazma. Düzen kaplarında bu yapılmazsa ekran iç içe çerçevelerle çizilir (kullanıcı bildirimi, qm qms-dokumanlar 2026-09-30; platform_guide('page') §Kap seçimi).",
361
418
  "states.isWrapper:true iken salt düzen elemanıdır: title ve __header bloğu ÇİZİLMEZ, zemin/çerçeve taşımaz ve gövdesi dolgusuzdur — kart başlığı gerekiyorsa içine text komponenti koy (platform_guide('page') Bilinen sınırlar). Bu kip artık bileşenin kendi CSS'inde: tipli alanlar (surfaceStyle) sayfa köküne de zemin/çerçeve verebilir.",
362
419
  "KATMAN SIRASI (K4): tema componentStyles → $preset TABANDIR; tipli grup alanları temayı alan alan EZER; düğümün serbest style'ı SON SÖZDÜR. Yüzey/tipografi/hover/başlık kararlarını style'a ham CSS olarak yazma — alanı varsa gruba yaz.",
363
420
  "BAŞLIK BANDI title YA DA description doluyken çizilir (2026-09-18): description başlığın altındaki ikinci satırdır (ikincil metin rengi, küçük punto) ve yalnız açıklama yazmak da bandı açar. İki alan da KIRPILIR: yalnız boşluktan ibaret bir başlık/açıklama doldurulmamış sayılır ve bant açılmaz. states.isWrapper:true iken ikisi de çizilmez.",
@@ -371,7 +428,7 @@ export const componentKnowledge = {
371
428
  "layout:'grid' iken diğer altı prop okunmaz — Studio panelinde de gizlenir. Katalogda tanımlı oldukları için doğrulama duvarı susar: ızgara kapsayıcıya direction yazmak sessizce hiçbir şey yapmaz (gateway PAGE-015 ile uyarır).",
372
429
  "Katalog varsayılanı 2026-08-25'te grid → FLEX oldu ama varsayılan düğüm KURULURKEN props'a yazılır (Studio bırakma yolu definition.defaults'u kopyalar), renderer'da geriye dönük bir etkisi YOKTUR: layout prop'u hiç olmayan düğüm — bütün eski kayıtlar — ızgara çizilmeye devam eder. Yani şemayı sen kuruyorsan varsayılana güvenme, layout'u açıkça yaz.",
373
430
  "YERLEŞİM (layout) KURARKEN DE TERCİH EDİLEN KAPTIR: layout views'ü sıradan bir komponent ağacıdır ve kökü container'dır — Studio'nun VARSAYILAN layout iskeleti (getDefaultLayout, 2026-09-29) kökü böyle kurar: states.isWrapper:true + appearance.heightType:'fill' + block x0/w12 (sayfanın page_container'ının yerleşim ikizi: çerçevesiz, başlıksız, ekranı dolduran); içinde navigations sol menü, menünün İÇİNDE ana sütun container'ı (column) → üst şerit container'ı + içerik container'ı → slot. Yeni kabukta önce ngapps://examples/layout-app-shell'i kullan, sonra özelleştir. layout monoliti ve layout-shell/layout-region ikilisi emekliye ayrıldı (platform_guide('layout')).",
374
- "MOBİL TUZAĞI — flex çocukları telefonda ALT ALTA DÜŞMEZ: runtime'ın mobil kuralı yalnız ızgara özelliklerini ezer (RenderComponent.svelte, @media max-width:767px → grid-row/grid-column/height), flex çocuğu genişliğini getFlexChildStyle'ın flex-basis'inden alır ve flex-wrap:nowrap altında satır bozulmaz. 375px'te ölçüldü: aynı span'lerle ızgara kabın çocukları 375/375px alt alta, flex kabınkiler 49/310px yan yana. Telefonda yığılması gereken satır için layout:'grid' kullan; wrap artık varsayılan açık (2026-09-01) ama sarma yalnız sığmayan çocuğu alta atar, ızgara yığılmasının yerini tutmaz (zeyrek-frontend docs/issues.md ARC-031)."
431
+ "DAR EKRAN TUZAĞI — flex çocukları telefon genişliğinde ALT ALTA DÜŞMEZ: runtime'ın dar ekran kuralı yalnız ızgara özelliklerini ezer (RenderComponent.svelte, @media max-width:767px → grid-row/grid-column/height), flex çocuğu genişliğini getFlexChildStyle'ın flex-basis'inden alır ve flex-wrap:nowrap altında satır bozulmaz. 375px'te ölçüldü: aynı span'lerle ızgara kabın çocukları 375/375px alt alta, flex kabınkiler 49/310px yan yana. Telefonda yığılması gereken satır için layout:'grid' kullan; wrap artık varsayılan açık (2026-09-01) ama sarma yalnız sığmayan çocuğu alta atar, ızgara yığılmasının yerini tutmaz (zeyrek-frontend docs/issues.md ARC-031)."
375
432
  ],
376
433
  propNotes: {
377
434
  surfaceStyle: STYLE_GROUP_NOTES.surfaceStyle + ' ' + STYLE_GROUP_NOTES.colorTokens + " Kapsayıcının TABANI tema token'larıdır (--ng-background-surface zemin, 1px --ng-border-primary çerçeve, --ng-rounded köşe); alan boş bırakılırsa tema izlenir. contentOverflow gövdeye ('&__body') yazılır.",
@@ -470,49 +527,55 @@ export const componentKnowledge = {
470
527
  behavior: [
471
528
  "Alan SEÇİLİ METNİ options'tan çözer: value dolu ama o value'lu bir option listede YOKSA kutu BOŞ görünür (hata vermez). Uzaktan dolan listede sırayı koru — önce options'ı yaz, sonra value'yu; ikisi ayrı akışlarda yazılıyorsa alan bir an boş kalır.",
472
529
  "Eşleşme TİPE DUYARLIDIR (katı ===): options'tan gelen { id: 34 } sayı kalır, alanın value'su ise metindir ('34'), yani bu ikisi EŞLEŞMEZ ve kutu boş görünür. Bu, 'value var ama görünmüyor' vakalarının en sık sebebidir — eşlemeyi akış katmanında aynı tipe getir.",
473
- "change yükü { value, selectedLabel } taşır ve ikisi de düğümün prop'una yazılır: akışta self.value ve self.selectedLabel ile okunur. selectedLabel 2026-09-11'de eklendi — etiketi göstermek için options'ta arama yapmaya gerek yok. Temizleme (X) de change yayar, ikisi de boş metin olur.",
530
+ "change yükü { value, selectedLabel } taşır ve ikisi de düğümün prop'una yazılır: akışta self.value ve self.selectedLabel ile okunur. selectedLabel 2026-09-11'de eklendi — etiketi göstermek için options'ta arama yapmaya gerek yok. Temizleme (panelin 'Seçimi temizle' düğmesi) de change yayar, ikisi de boş metin olur.",
474
531
  "Arama VARSAYILAN OLARAK YERELDİR (label üzerinde bulanık eşleme). Sayfa bu bileşene bir `search` olayı bağlarsa yerel süzme KAPANIR ve tamamen akışın sorumluluğuna geçer: bileşen searchText'i yazıp olayı atar, akış options'ı yeniden yazmazsa liste değişmez. Uzak aramada isLoading'i akıştan aç/kapa.",
475
- "isLoading KİLİT DEĞİLDİR (2026-09-11): alan odaklanabilir kalır, açık liste yükleniyor satırını gösterir ve kullanıcı yazmayı sürdürebilir. Öncesinde isLoading alanı disabled yapıyordu, yani uzak arama her tuşta odağı düşürüyordu. Tek şart: liste KAPALIYKEN isLoading açıksa chevron'a tıklamak listeyi açmaz (metin alanına tıklamak ve klavye açar) — ortak Select'in kuralı.",
532
+ "isLoading KİLİT DEĞİLDİR (2026-09-11): alan odaklanabilir kalır, açık liste yükleniyor satırını gösterir ve kullanıcı yazmayı sürdürebilir. Öncesinde isLoading alanı disabled yapıyordu, yani uzak arama her tuşta odağı düşürüyordu. 2026-10-05'ten beri liste kapalıyken de tıklama ya da tuş paneli açar ve yükleniyor satırı görünür.",
476
533
  'Olaylar: mount (render katmanı atar) · change · search · focus · blur. blur 2026-09-11’de eklendi ve odak alanın TAMAMINI terk edince yayılır — liste açılırken odak arama kutusuna geçtiğinde yayılmaz, yani blur’a bağlanan doğrulama liste içinde tetiklenmez.',
477
- "optionType='grouped' iken option'ın children'ı alt satırları çizer; çocuğu olan satır VARSAYILAN OLARAK SEÇİLEMEZ, yalnız açılır/kapanır — başlığın kendisi de seçilebilsin isteniyorsa o option'a isSelectable ver. optionType='single' iken children/isExpanded/isSelectable okunmaz.",
478
- "Tek doğrulama kuralı `required`'dır (2026-09-11; `pattern` bildirimi kaldırıldı, panelde hiç çizilemiyordu)."
534
+ "ALAN VE PANEL (2026-10-05, datatable'ın Connect Data ilişki alanıyla aynı görünüm): alan yazılan bir girdi DEĞİL, odaklanabilir bir kutudur — Tab ile gelinir, Enter/Space/↓/↑ paneli açar. Arama kutusu açılan panelin ÜSTÜNDEDİR ve açılınca odaklanır; 'Seçimi temizle' panelin altındadır (değer varken ve clearable açıkken). Seçim, Escape ve temizleme paneli kapatıp odağı alana geri verir; odak alandan (panel dahil) çıkınca panel kapanır. Alanda X yoktur ve Backspace değeri silmez. Tab ile alana gelmek focus yayar (bir kez); panelde Tab seçeneklerden geçmez (ok tuşları gezer); dışarı tıklamak paneli kapatır ve blur yayar. Salt okunur, görüntüleme ve devre dışı alan odak almaz.",
535
+ "optionType='grouped' iken option'ın children'ı alt satırları çizer; çocuğu olan satır VARSAYILAN OLARAK SEÇİLEMEZ, yalnız açılır/kapanır — başlığın kendisi de seçilebilsin isteniyorsa o option'a isSelectable ver. optionType='single' iken children/isExpanded/isSelectable okunmaz. Connect Data ile kurulan ağaçta (children rolü) her satır kaynağın kaydıdır: isExpanded / isSelectable rolü bir alana eşlenmediyse satırlar AÇIK ve SEÇİLEBİLİR gelir (2026-10-05).",
536
+ "Tek doğrulama kuralı `required`'dır (2026-09-11; `pattern` bildirimi kaldırıldı, panelde hiç çizilemiyordu).",
537
+ "LOOKUP (2026-10-05, ADR 0007): Connect Data ile entity'ye bağlı ve tanımın kök `lookup`'ı açıkken (bağlama `lookupMode` yazar) alanın sağında, chevron'un solunda ↗ çizilir; tıklayınca bileşenin KENDİ kaynağı lookup penceresinde (modal ya da sağ çekmece, `lookup.mode`) kolonlar, filtre çipleri, başlık sıralaması ve sayfalarla açılır. Satıra tıklamak seçer ve kapatır; yük normal seçimle aynı change { value, selectedLabel } (value, değer rolünün HAM değeri). Seçilen kayıt yüklü options'ta yoksa kutu etiketini yine gösterir. Ana tanımın filtresi pencerede de geçerlidir. Kanvasta, salt okunur/görüntüleme/devre dışı kipte ↗ yoktur; pencere açıkken blur yayılmaz, kapanınca odak ↗'ye döner. Açmak/kapatmak: connect_data_bind { lookup } ya da studio çekmecesi; yeni bağlamada açık gelir."
479
538
  ],
480
539
  propNotes: {
481
540
  value: "Seçilen option'ın value'su — ilişki alanlarında etiket değil id yazılır/okunur. Kutuda ancak aynı value'lu bir option listede varken metin görünür ve karşılaştırma tipe duyarlıdır (sayı 34 ile metin '34' eşleşmez).",
482
541
  options: '[{ label, value }] dizisi; akışla doldurulacaksa setter hedefi budur. Ek alanlar: caption, icon/prefixImage/prefixText, color, tooltip, isDisabled, isHidden ve grouped modda children/isSelectable/isExpanded.',
483
542
  optionType: "'single' düz liste, 'grouped' children ile ağaç. single'da children ve yanındaki iki bayrak hiç okunmaz.",
484
- clearable: 'Seçimi temizleyen X düğmesi (varsayılan açık). Temizleme change yayar, ayrı bir olay yoktur.',
543
+ clearable: "Panelin altındaki 'Seçimi temizle' düğmesi (varsayılan açık, yalnız değer varken çizilir). Temizleme change yayar, ayrı bir olay yoktur.",
485
544
  emptyText: 'Liste boşken gösterilen metin; boş bırakılırsa arayüz dilinden gelen "sonuç yok" metni kullanılır.',
486
545
  placeholder: 'Seçim yokken kutuda duran metin; aynı zamanda yükleniyor satırının metnidir.',
487
546
  searchText: "Gizli durum prop'u: bileşen OKUMAZ, `search` olayıyla yazar. Uzak aramada sorguyu akışta self.searchText ile oku.",
488
547
  selectedLabel: "Gizli durum prop'u: `change` seçilen option'ın label metnini buraya yazar (temizlemede boş metin). Yalnız kullanıcı seçimiyle dolar — value'yu akıştan yazmak burayı GÜNCELLEMEZ.",
489
- isLoading: 'Uzak arama/doldurma sürerken akıştan açılır; alan kilitlenmez, yalnız spinner ve yükleniyor satırı çizilir.'
548
+ lookupMode: "Gizli durum prop'u: Connect Data bağlaması her okumada yazar — tanımın kök `lookup`'ı açıksa 'modal' ya da 'drawer', kapalıysa 'none'. Bileşen alanın sağındaki ↗ lookup düğmesini yalnız bu 'none' değilken çizer; elle yazılmaz, lookup'ı tanımdaki kök `lookup` açar/kapatır.",
549
+ isLoading: 'Uzak arama/doldurma sürerken akıştan açılır; alan kilitlenmez, yalnız spinner ve yükleniyor satırı çizilir.',
550
+ loadError: "Salt okunur: Connect Data bağlantısının son okuma hatası (başarılı okuma temizler). Doluyken açılan liste 'sonuç yok' yerine bu metni gösterir — okuma izni yoksa (403) platformun yerelleştirilmiş 'Bu kaynağa erişim izniniz yok.' metni (39/02 U-2). Bağlı olmayan dropdown'da akış yazabilir."
490
551
  }
491
552
  },
492
553
  'multi-select': {
493
554
  summary: 'Aranabilir çoklu seçim; value bir değer dizisidir, seçilenler etiket (chip) olarak görünür, search olayı sunucu taraflı arama kurmaya yarar.',
494
555
  behavior: [
495
- "value bir DİZİDİR ve üç biçimi de okunur: düz değer (['policies', 7]), şemanın biçimi ([{ value, label }]) ve eski ikizler ([{ id, text }]). Düz değer yazmak 2026-09-11'e kadar etiketi 'undefined' gösteriyordu; artık değer etiketin kendisi olur ve doğru metin options yüklenince gelir.",
556
+ "value bir DİZİDİR ve üç biçimi de okunur: düz değer (['policies', 7]), şemanın biçimi ([{ value, label }]) ve eski ikizler ([{ id, text }]). Düz değer yazmak 2026-09-11'e kadar etiketi 'undefined' gösteriyordu; artık değer etiketin kendisi olur ve doğru metin options yüklenince gelir (2026-10-01'e kadar gelmiyordu: akışın yazdığı id dizisi seçenekler yüklense de çipte id olarak kalıyordu).",
496
557
  "Etiketin metni options'tan tazelenir: aynı value'lu option listede varsa onun label'ı yazılır. Bu arama METİNLEŞTİREREK karşılaştırır (String(a) === String(b)), AMA yalnız etiket metni için: satırın işaretli görünmesi ve seçimin kaldırılması KATI karşılaştırma kullanır. Yani value'da metin '34', options'ta sayı 34 varsa çip doğru etiketle çizilir ama liste satırı işaretsiz kalır ve tıklamak hiçbir şey yapmaz — eşlemeyi akış katmanında aynı tipe getir (CQ-208).",
497
558
  "change yükü { value: [{ value, label, id, text }] } taşır ve düğümün value prop'una yazılır: akışta self.value ile okunur. id/text, value/label'ın eski adlı ikizleridir — kayıtlı sayfalar onlarla okuduğu için bilerek korunuyor.",
498
559
  'Her seçimden sonra arama kutusu TEMİZLENİR ve tam liste geri gelir (bilinçli davranış); liste kapanınca da temizlenir ve bir kez boş search yayılır.',
499
560
  "Arama VARSAYILAN OLARAK YERELDİR (label üzerinde bulanık eşleme). Sayfa bu bileşene bir `search` olayı bağlarsa yerel süzme KAPANIR ve tamamen akışın sorumluluğuna geçer: bileşen searchText'i yazıp olayı atar, akış options'ı yeniden yazmazsa liste değişmez. Uzak aramada isLoading'i akıştan aç/kapa.",
500
- 'isLoading KİLİT DEĞİLDİR (2026-09-11): alan odaklanabilir kalır, açık liste yükleniyor satırını gösterir ve kullanıcı yazmayı sürdürebilir. Öncesinde isLoading alanı disabled yapıyordu, yani uzak arama her tuşta odağı düşürüyordu. Tek şart: liste KAPALIYKEN isLoading açıksa kutuya tıklamak listeyi açmaz (arama kutusuna odaklanmak açar).',
501
- 'Olaylar: mount (render katmanı atar) · change · search · focus · blur. blur 2026-09-11’de eklendi ve odak alanın TAMAMINI terk edince yayılır: etikete, X’e ya da chevron’a basmak odağı alandan çıkarmaz ve liste içinde gezinmek blur yaymaz. Alan terk edilince açık liste de kapanır.',
561
+ 'isLoading KİLİT DEĞİLDİR (2026-09-11): alan odaklanabilir kalır, açık liste yükleniyor satırını gösterir ve kullanıcı yazmayı sürdürebilir. Öncesinde isLoading alanı disabled yapıyordu, yani uzak arama her tuşta odağı düşürüyordu. 2026-10-05’ten beri liste kapalıyken de tıklama ya da tuş paneli açar ve yükleniyor satırı görünür.',
562
+ 'Olaylar: mount (render katmanı atar) · change · search · focus · blur. blur 2026-09-11’de eklendi ve odak alanın TAMAMINI terk edince yayılır: çipe ya da chevron’a basmak odağı alandan çıkarmaz ve liste içinde gezinmek blur yaymaz. Alan terk edilince açık liste de kapanır.',
502
563
  'Liste açıldığında seçili olanlar (ve seçili çocuğu olan başlıklar) başa alınır; sıra liste AÇILDIĞI ANDA dondurulur, seçim değiştikçe satırlar zıplamaz.',
503
- "optionType='grouped' iken children alt satırları çizer; çocuğu olan satır VARSAYILAN OLARAK SEÇİLEMEZ: kutusu çizilmez ve satırın kendisi disabled'dır, açıp kapatmak yalnız sağdaki ok düğmesiyle (ya da klavyede Enter/ok tuşlarıyla) olur — başlık da seçilebilsin isteniyorsa o option'a isSelectable ver. optionType='single' iken children/isExpanded/isSelectable okunmaz.",
504
- 'Arama kutusu boşken Backspace son etiketi siler; etiketler tek satıra sığmazsa fazlası "+n" rozetinde toplanır (kilitli/viewmode alanda rozet tıklanınca kalanları listeler).',
505
- "Doğrulama kuralları: required · minItems · maxItems (2026-09-11; `pattern` bildirimi kaldırıldı — değeri dizi olan alanda uygulanacak metin yok ve panelde hiç çizilemiyordu). Panel bu iki sayı kuralını 'Min length' / 'Max length' adıyla çizer; dizide uzunluk = SEÇİLİ ELEMAN SAYISI. minItems/maxItems yazılırsa gateway min-length/max-length'e çevirir."
564
+ "optionType='grouped' iken children alt satırları çizer; çocuğu olan satır VARSAYILAN OLARAK SEÇİLEMEZ: kutusu çizilmez ve satırın kendisi disabled'dır, açıp kapatmak yalnız sağdaki ok düğmesiyle (ya da klavyede Enter/ok tuşlarıyla) olur — başlık da seçilebilsin isteniyorsa o option'a isSelectable ver. optionType='single' iken children/isExpanded/isSelectable okunmaz. Connect Data ile kurulan ağaçta (children rolü) her satır kaynağın kaydıdır: isExpanded / isSelectable rolü bir alana eşlenmediyse satırlar AÇIK ve SEÇİLEBİLİR gelir (2026-10-05).",
565
+ "ÇİPLER SARAR (2026-10-05, datatable'ın Connect Data ilişki alanıyla aynı görünüm): etiketin tamamı görünür, sığmayan çip alt satıra geçer ve alan büyür; '+n' rozeti, çipte X ve alanda X YOKTUR, Backspace bir şey silmez. Seçim panelde kutunun işareti kaldırılarak ya da panelin altındaki 'Seçimi temizle' ile kaldırılır. Arama kutusu panelin üstündedir ve açılınca odaklanır; her tıklama hemen yazar ve panel açık kalır (Uygula yok). Escape ve temizleme paneli kapatıp odağı alana verir. Tab ile alana gelmek focus yayar (bir kez); panelde Tab seçeneklerden geçmez (ok tuşları gezer); dışarı tıklamak paneli kapatır ve blur yayar. Salt okunur, görüntüleme ve devre dışı alan odak almaz.",
566
+ "Doğrulama kuralları: required · minItems · maxItems (2026-09-11; `pattern` bildirimi kaldırıldı — değeri dizi olan alanda uygulanacak metin yok ve panelde hiç çizilemiyordu). Panel bu iki sayı kuralını 'Min length' / 'Max length' adıyla çizer; dizide uzunluk = SEÇİLİ ELEMAN SAYISI. minItems/maxItems yazılırsa gateway min-length/max-length'e çevirir.",
567
+ "LOOKUP (2026-10-05, ADR 0007): kök `lookup`'ı açık bağlı multi-select'te ↗ pencereyi ÇOKLU kipte açar — satıra tıklamak soldaki kutuyu işaretler, pencere açık kalır, Uygula tüm seçimi change { value: [{ value, label, id, text }] } olarak yazar (işaretlenme sırasıyla). Önceden seçilenler işaretli gelir ve ilk açılışta (süzülmeden, sıralanmadan, ilk sayfada) `ids` ile ayrıca okunup EN ÜSTTE durur. Escape değişikliği yazmadan kapatır. Kanvasta, salt okunur/görüntüleme/devre dışı kipte ↗ yoktur."
506
568
  ],
507
569
  propNotes: {
508
570
  value: "Seçili değerlerin dizisi — ilişki alanlarında etiket değil id yazılır/okunur. Düz değer dizisi de (['a', 'b']) geçerlidir; etiketler options yüklendiğinde tazelenir.",
509
571
  options: '[{ label, value }] dizisi; akışla doldurulacaksa setter hedefi budur. Ek alanlar: caption, icon/prefixImage/prefixText, color, tooltip, isDisabled, isHidden ve grouped modda children/isSelectable/isExpanded.',
510
572
  optionType: "'single' düz liste, 'grouped' children ile ağaç. single'da children ve yanındaki iki bayrak hiç okunmaz.",
511
- clearable: 'Tüm seçimi temizleyen X düğmesi (varsayılan açık, yalnız seçim varken çizilir). Temizleme change yayar, ayrı bir olay yoktur.',
573
+ clearable: "Tüm seçimi temizleyen, panelin altındaki 'Seçimi temizle' düğmesi (varsayılan açık, yalnız seçim varken çizilir). Temizleme change yayar, ayrı bir olay yoktur.",
512
574
  emptyText: 'Liste boşken gösterilen metin; boş bırakılırsa arayüz dilinden gelen "sonuç yok" metni kullanılır.',
513
575
  placeholder: 'Hiç seçim yokken kutuda duran metin; aynı zamanda yükleniyor satırının metnidir.',
514
576
  searchText: "Gizli durum prop'u: bileşen OKUMAZ, `search` olayıyla yazar. Uzak aramada sorguyu akışta self.searchText ile oku.",
515
- isLoading: 'Uzak arama/doldurma sürerken akıştan açılır; alan kilitlenmez, yalnız spinner ve yükleniyor satırı çizilir.'
577
+ isLoading: 'Uzak arama/doldurma sürerken akıştan açılır; alan kilitlenmez, yalnız spinner ve yükleniyor satırı çizilir.',
578
+ lookupMode: "Gizli durum prop'u: Connect Data bağlaması her okumada yazar — tanımın kök `lookup`'ı açıksa 'modal' ya da 'drawer', kapalıysa 'none'. Bileşen alanın sağındaki ↗ lookup düğmesini yalnız bu 'none' değilken çizer; elle yazılmaz, lookup'ı tanımdaki kök `lookup` açar/kapatır."
516
579
  }
517
580
  },
518
581
  'tag-input': {
@@ -545,6 +608,7 @@ export const componentKnowledge = {
545
608
  "inputMask seçiliyse KULLANICININ yazdığı metin anında maskeye biçimlenir ve value biçimli hâlidir ('0(555) 123 45 67'); kullanıcı yazarken maske dışı karakterler sessizce düşer. Akıştan/kayıttan yazılan değer ise OLDUĞU GİBİ kalır (ekranda biçimli görünür). Form, biçimlenince hiçbir karakter kaybetmeyen ham değeri ('5551234567') kabul eder ve akışa HAM gönderir; karakter kaybettiren değer ('+905551234567', fazla hane, küçük harf) ile tarih/saat/son kullanma maskelerindeki ayraçsız değer 'Value does not match the selected input mask.' ile formu kilitler — o maskelere akıştan biçimli yaz. Ham rakam istiyorsan akışta ayıkla (2026-10-03)."
546
609
  ],
547
610
  propNotes: {
611
+ isMasked: "KORUMALI ALAN (f-31): value her zamanki gibi kaydın alanına bağlanır, isMasked yanına satır metasına: {{ Steps.<satırıOkuyanAdım>.data.__protected?.<alan> === 'masked' }}. true iken bağlı value maske metni sayılır ve GÖSTERİLMEZ: alan BOŞ başlar, yer tutucu uygulama dilinde 'Değiştirmek için yeni değer girin' olur (placeholder prop'u o sürece gösterilmez) ve mount SONRASI value null'a yazılır, maske metni düğümde kalmaz (tasarım kanvasında yazılmaz). Bu yazım şemada OLMAYAN 'maskCleared' emit'iyle yapılır — akış bağlanamaz, change/changed ÇALIŞMAZ. Kullanıcı yazınca sıradan girdidir; value girdinin yazmadığı bir değere dönerse (forma başka satır seçildi, akış alanı sıfırladı) yeni kaydın maskesi yine gizlenir ve null'a çekilir. Yalnız isMasked bağlamak da çalışır ama plain satırda da alan boş kalır. Boş değer yalnız microservice parametre bağında gövdeden DÜŞER (saklı değer korunur); akış kodunda ya da setter göreviyle elle kurulan gövdede null GİDER — canWrite yoksa 403 AccessFieldWriteDeniedException, varsa saklı değer SİLİNİR. Formda boş bırakılan maskeli alan required'a takılmaz. value'yu maskeli kayda bağlayıp isMasked vermemek maskeyi geri gönderir — yapma.",
548
612
  clearable: 'Değer varken alanın sağında × düğmesi çizer; tıklanınca value boşalır ve change + changed yayılır. Kilitli (disabled/readonly/viewmode/loading) alanda çizilmez.',
549
613
  inputMask: "Hazır maske anahtarı (pattern:/date:/time:/regex:…); serbest desen için 'custom:' öneki ('custom:(###) ###-####'). IBAN anahtarı 'iban:TR## #### #### #### #### #### #### ##' dizesi 28 # okunur ama deseni TR + 24 rakamdır (26 karakter); geçerli TR IBAN biçimlenir ve Form maske denetiminden geçer (2026-10-03).",
550
614
  prefixIcon: "Alanın İÇİNDE solda çizilen salt görsel ikon ({ name: 'search' }); value'ya karışmaz. Renk verilmezse ikincil metin rengi. Viewmode'da hiç çizilmez: alan düz metne döner ve ikon yuvası kadar girinti bırakmaz.",
@@ -858,7 +922,7 @@ export const componentKnowledge = {
858
922
  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. Tasarımda value'ya drive dosyası BAĞLAMA ({ type:'file', ref:<fileId> } — Studio panelinin dosya seçicisi de bunu yazar): çalışma anı değeri { type:'file', ref, data:<URL> } olur, çip dosya adı yerine URL yazar ve kullanıcı dokunmadan kaydederse backend type:'file' kaydında yalnız value'yu okuduğu için tekil alan sessizce NULL'lanır (200 döner, mevcut dosya silinir; NOT NULL alanda 400 InvalidParameterException). Varsayılan dosya gerekiyorsa value'yu static ref nesnesi olarak ver: { type:'static', data:{ type:'ref', value:'<fileId>', fileName, absolute_path } } — çip adıyla çizilir, dokunmadan kayıt dosyayı yazar (ölçüldü 2026-10-02).",
859
923
  text: 'Butonun üzerindeki metin (varsayılan "Attach File"); ikon sabittir. Alanın başlığı ayrı bir prop\'tur: label.',
860
924
  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).',
861
- 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.',
925
+ 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).',
862
926
  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.',
863
927
  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.',
864
928
  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ı).",
@@ -900,7 +964,7 @@ export const componentKnowledge = {
900
964
  "href ve isNewTabLink YALNIZ type:'link' iken okunur — href doldurmak butonu link yapmaz. İç sayfaya link için href'e URL değil { type:'page', ref:<pageId> } Prop'u yaz. Link kilitliyken (isDisabled/isLoading) ya da href boşken hiçbir yere gitmez ve odak almaz; kilit kalkınca ya da href akışla değişince adres anında güncellenir (2026-09-11 öncesi ilk çizimdeki adreste donuyordu: kilitli açılan link hep ölü kalıyordu).",
901
965
  "YATAY DOLGU ikon + metinde MÜREKKEBE göre dengelenir (2026-09-29): Material glifinin ~0.2em yan boşluğu yüzünden eşit kutu dolgusunda ikon tarafı 3px geniş görünüyordu ('Save Order': glif 16px, metin 13px). Bileşen ikon tarafını o kadar daraltır (ikon sağdaysa sağı). Dolguyu büyütmek/küçültmek için style.padding YAZMA — !important ile dengeyi ezer; style: { '--ng-btn-pad-x': '18px' } yaz, iki taraf ondan türetilir. Pill (radius-pill) düğmede 16-18px, lg'nin 12px tabanı dar görünür.",
902
966
  "METİN RENGİ zeminin ölçülen parlaklığından seçilir (2026-09-29, shared/utils getContrastTextColor): açık zemine koyu, koyu zemine açık metin; temanın onPrimary'si (--ng-text-on-accent) o polaritedeyse o kullanılır, değilse #000000/#ffffff. Tema metin token'ı (--ng-text-primary) YEDEK DEĞİLDİR: koyu modda açığa döner ve açık accent'li butonda (Rexora #B8F06C) metni okunmaz yapıyordu. Tema modu değişince (theme-toggle) renk yeniden hesaplanır; aynı kural icon çipinde ve tablo etiketlerinde de geçerlidir.",
903
- "Kayıtlı sayfalardaki eski kind:'custom' + customColor ikilisi VERİ GÖÇÜ OLMADAN aynen çizilir (render-anı takma adı, text emsali): surfaceStyle.background boşsa eski renk `--ng-btn-custom-color` değişkeniyle solid/outline/text varyantına eskisi gibi iner; Background doldurulunca takma ad susar. page_runtime_get(resolveStyles:true) bu değişkeni resolvedStyle'da gösterir. DİKKAT: platformun doğrulama duvarı sayfanın TAMAMINI okur — böyle bir düğüm taşıyan sayfaya yapılan her page_schema_patch, dokunulmayan düğüm yüzünden invalid-enum-value/unknown-prop ile reddedilir (ARC-036). Sayfayı yeniden yazmadan önce o butonu kind: semantik değer + surfaceStyle.background'a çevir (aynı çağrıda replace_prop ile).",
967
+ "Kayıtlı sayfalardaki eski kind:'custom' + customColor ikilisi VERİ GÖÇÜ OLMADAN aynen çizilir (render-anı takma adı, text emsali): surfaceStyle.background boşsa eski renk `--ng-btn-custom-color` değişkeniyle solid/outline/text varyantına eskisi gibi iner; Background doldurulunca takma ad susar. page_runtime_get(resolveStyles:true) bu değişkeni resolvedStyle'da gösterir. DİKKAT: platformun doğrulama duvarı sayfanın TAMAMINI okur — böyle bir düğüm taşıyan sayfaya yapılan her page_schema_patch, dokunulmayan düğüm yüzünden invalid-enum-value/unknown-prop ile reddedilir (ARC-252). Sayfayı yeniden yazmadan önce o butonu kind: semantik değer + surfaceStyle.background'a çevir (aynı çağrıda replace_prop ile).",
904
968
  "İpucu (tooltip) prop'u YOKTUR: düğümün ortak appearance.tooltip alanı (+ tooltipPosition: top · bottom · left · right) her komponentte ipucu çizer. Tıklamadan önce onay istemek de butonun değil akışın işidir: click akışının başına confirm adımı koy (yalnız web — mobil barındırıcıda confirm adımı yok)."
905
969
  ],
906
970
  propNotes: {
@@ -1070,9 +1134,10 @@ export const componentKnowledge = {
1070
1134
  "key satırın kimliğidir ve METİN olarak karşılaştırılır (selected '7' ile data key 7 eşleşir). key'i boş/eksik satır hiç seçili çizilmez ve onay kutusu kilitlidir (yalnız ebeveyninden durum alır); aynı seviyede key tekrar ederse ya da eksikse ağaç kırılmaz ama selected/checkedKeys o satırları ayırt edemez — sorgudan kurarken benzersiz id'yi key'e eşle.",
1071
1135
  'selected akıştan yazıldığında o düğüme giden dallar KENDİLİĞİNDEN açılır (yalnız açar; kullanıcının elle açtıklarını kapatmaz). Satır verisindeki isExpanded:true de kendi başına açar.',
1072
1136
  "isCheckable:true her satırın soluna onay kutusu koyar; işaretli key'ler checkedKeys dizisidir. Bir üst satırın key'i TÜM dalı temsil eder: checkedKeys'e yalnız ebeveyn yazmak altındaki bütün etkin satırları işaretler; etkin çocuklarının hepsi işaretli ebeveyn işaretli, bir kısmı işaretliyse yarım (—) çizilir. Kutuya tıklamak dalı birlikte işaretler/kaldırır. isDisabled satırın kutusu kilitlidir ve zincir onda durur: ebeveynin işareti ona ve altına inmez, o da ebeveynin durumuna sayılmaz (altındaki etkin satırlar tek tek işaretlenebilir).",
1073
- "change yalnız kullanıcı kutuya tıklayınca yayılır (akışın checkedKeys yazması yaymaz). Yazılan checkedKeys normalize edilmiştir: tam işaretli her satır belge sırasıyla (tamamlanan ebeveyn dahil); ağaçta çizilmeyen key'ler (gizli satır, henüz yüklenmemiş veri) sona olduğu gibi eklenir. Satır tıklaması (click/selected) ile kutu (change/checkedKeys) birbirinden bağımsızdır. checkedKeys'i (ve selected'ı) {{ }} İFADESİNE BAĞLAMA: kullanıcı yazması ifadeli prop'u bozar ve değişiklik kaybolur (platform kusuru CQ-247) — başlangıç listesi STATİK yazılamaz (skaler dizi 500 verir, ARC-157): tree'nin mount akışında self.checkedKeys = [...] ile ver.",
1137
+ "change yalnız kullanıcı kutuya tıklayınca yayılır (akışın checkedKeys yazması yaymaz). Yazılan checkedKeys normalize edilmiştir: tam işaretli her satır belge sırasıyla (tamamlanan ebeveyn dahil); ağaçta çizilmeyen key'ler (gizli satır, henüz yüklenmemiş veri) sona olduğu gibi eklenir. Satır tıklaması (click/selected) ile kutu (change/checkedKeys) birbirinden bağımsızdır. checkedKeys (ya da selected) {{ }} ifadesine bağlıysa kullanıcının tıklaması ifadeyi o düğümde ezer ve kalır; ifadede adı geçen bir düğüm değişince bağ yeniden koşar ve seçimi ifadenin sonucuyla değiştirir (ARC-147, 2026-09-29'dan önce prop bozuluyordu). Seçimin kalıcı olması gerekiyorsa akıştan self.checkedKeys = [...] ile ver — başlangıç listesi STATİK yazılamaz (skaler dizi 500 verir, ARC-157): tree'nin mount akışında yaz.",
1074
1138
  "actions komponent düzeyinde BİR KEZ tanımlanır, her satır aynı menüyü çizer; bir satır farklılaşacaksa veri öğesine _actions dizisi konur ve SIRA numarasıyla şablonun üstüne biner (o satırda gizleme / etiket değiştirme).",
1075
1139
  "Aksiyonlar set_event ile DEĞİL her aksiyonun kendi flow prop'uyla bağlanır; şema olayı yayılmaz. Aksiyonun akışında satır self.currentItem'da, event.data'da { currentItem, actionKey } (actionKey: aksiyonun key'i) gelir. flow'u boş aksiyon hiçbir şey yapmaz.",
1140
+ "BAĞLI VERİ (2026-09-17, f-32): data connectData'ya bağlanabilir; children rolü ÜST KAYIT alanıdır (parent_id ya da self ilişki). Runtime satırları toTree ile iç içe children'a çevirir (üstü boş/listede yok → kök, döngüdeki satır köke, derinlik 10), sayfalamayı kapatır ve ilk 1000 satırı okur (CD-009). Anahtar kaynağın birincil anahtarıdır; query/workflow kaynağında yoktur, o zaman key (yoksa value) rolünün alanı kullanılır — anahtarsız satırlar köke düşer. Bağlantı yazmaz; seçim yine click olayıdır.",
1076
1141
  'isSearchable:true arama kutusunu + tümünü aç/kapat düğmelerini açar. Süzme text ve subtle alanlarında geçer, eşleşenin ataları yerinde kalır, eşleşenin alt ağacı bütün görünür ve süzme sürerken dallar açık çizilir (chevron o sırada etkisizdir). Süzme İSTEMCİ tarafındadır: sunucuda arama gerekiyorsa kutuyu kapatıp kendi textinput + akış çiftini kur. Arama sürerken onay durumu TAM ağaçtan hesaplanır ve bir ebeveyni işaretlemek aramanın gizlediği çocuklarını da işaretler.',
1077
1142
  'isLoading iskelet satır çizer; veri (ya da arama sonucu) boşsa emptyText basılır. data içindeki null / düz değer öğeler atlanır.',
1078
1143
  'Satır ikonu icon > image > varsayılan klasör ikonu sırasıyla seçilir; satırdaki isHidden satırı hiç çizmez, isDisabled satır tıklamasını ve kutusunu kilitler (dalı yine açılıp gezilebilir).',
@@ -1110,7 +1175,8 @@ export const componentKnowledge = {
1110
1175
  "EMEKLİ prop'lar: isBold, align, color, customColor şemada YOK — yazılırsa unknown-prop ile reddedilir. Karşılıkları: typographyStyle.fontWeight ('600'), textAlign, textColor (semantik renk için tema token'ı: var(--ng-status-success) gibi). Kayıtlı eski sayfalarda bu prop'lar render anında takma adla çözülür (resolvedStyle bunu gösterir), yeni yazımda kullanılmaz.",
1111
1176
  "Hover grubu yok (metnin hover semantiği yok); surfaceStyle etiket/vurgulu paragraf içindir (zemin, köşe, çerçeve, gölge) ve contentOverflow alanı yoktur (taşma hedefi yok). METNİN taşması surfaceStyle'ın işi değildir, lineClamp prop'unundur.",
1112
1177
  "Olay YOKTUR: şema events sözlüğü boştur, componentEvents kaydı da yoktur. Metne tıklamayı akışa bağlamak isteyen düğümü button ya da bir kaba sarar.",
1113
- "KATMAN SIRASI (K4): tema componentStyles → $preset TABANDIR; tipli grup alanları temayı alan alan EZER; düğümün serbest style'ı SON SÖZDÜR. Grubun karşılamadığı kararı style kanalına (custom properties) yaz."
1178
+ "KATMAN SIRASI (K4): tema componentStyles → $preset TABANDIR; tipli grup alanları temayı alan alan EZER; düğümün serbest style'ı SON SÖZDÜR. Grubun karşılamadığı kararı style kanalına (custom properties) yaz.",
1179
+ PROTECTED_VALUE_NOTE + " Metinde: yalnız record + recordField birlikte verilince devreye girer; maskeliyken content YOK SAYILIR ve record[recordField] (maske metni) çizilir."
1114
1180
  ],
1115
1181
  propNotes: {
1116
1182
  content: "Düz metin; {{ }} ile ifadeye bağlanır. 0 ve false BASILIR (bkz. behavior). Biçimli içerik (kalın parça, liste, link) metnin içinde DEĞİL ayrı komponentte kurulur: html ya da texteditor.",
@@ -1119,7 +1185,10 @@ export const componentKnowledge = {
1119
1185
  surfaceStyle: STYLE_GROUP_NOTES.surfaceStyle + ' ' + STYLE_GROUP_NOTES.colorTokens,
1120
1186
  typographyStyle: STYLE_GROUP_NOTES.typographyStyle + ' ' + STYLE_GROUP_NOTES.colorTokens,
1121
1187
  style: STYLE_GROUP_NOTES.styleEscape +
1122
- " text'in TEK iç parçası yükleniyor çubuğudur: &__skeleton (isLoading açıkken). Başka &__parça YOKTUR; &__text, &__content gibi adaylar sessizce etkisizdir (kök tek bir etikettir: kök özellikleri, :hover, :active, ::before/::after, ::first-letter, ::first-line, ::selection, @media ve @supports kökte çalışır). Text odaklanamaz (tabindex yok), yani &:focus-visible hedefi hiç tetiklenmez. @keyframes style içinde ÇALIŞIR (2026-10-02'den beri; animation adı + keyframe gövdesi birlikte yazılır), PascalCase 'Webkit*' anahtarlarını platform kayıtta DÜŞÜRÜR (yanıttaki silentlyDropped bildirir; ölçüldü): kebab yaz ('-webkit-text-fill-color', '-webkit-background-clip')."
1188
+ " text'in TEK iç parçası yükleniyor çubuğudur: &__skeleton (isLoading açıkken). Başka &__parça YOKTUR; &__text, &__content gibi adaylar sessizce etkisizdir (kök tek bir etikettir: kök özellikleri, :hover, :active, ::before/::after, ::first-letter, ::first-line, ::selection, @media ve @supports kökte çalışır). Text odaklanamaz (tabindex yok), yani &:focus-visible hedefi hiç tetiklenmez. @keyframes style içinde ÇALIŞIR (2026-10-02'den beri; animation adı + keyframe gövdesi birlikte yazılır), PascalCase 'Webkit*' anahtarlarını platform kayıtta DÜŞÜRÜR (yanıttaki silentlyDropped bildirir; ölçüldü): kebab yaz ('-webkit-text-fill-color', '-webkit-background-clip').",
1189
+ record: "KORUMALI DEĞER İÇİN: content'in bağlandığı SATIR nesnesi ({{ musteriTablosu.selectedRow }}); recordField ile birlikte verilir. Korumasız metinde boş bırak.",
1190
+ recordField: "record içindeki alan slug'ı ('tckn'). Satırın __protected metası bu alanı 'masked' işaretlerse metin kilitli maske olarak çizilir.",
1191
+ revealEntity: REVEAL_ENTITY_NOTE
1123
1192
  }
1124
1193
  },
1125
1194
  image: {
@@ -1184,7 +1253,7 @@ export const componentKnowledge = {
1184
1253
  propNotes: {
1185
1254
  data: "Koda gömülecek metin ya da adres; {{ }} ile bağlanabilir. Sayı ve null kabul edilir (metne çevrilir / boş sayılır). KIRPILMAZ — baştaki ve sondaki boşluk da kodlanır, ama yalnız boşluktan oluşan değer 'boş' sayılır. Şemadaki 'https://zeyrek.glomil.app/' varsayılanı TASARIM ANI değeridir: paletten bırakılan düğüme yazılır, ama data taşımayan bir düğümde (MCP'den yazılan sayfa) runtime varsayılanı boş stringtir ve yer tutucu çizilir — MCP'den kurarken data'yı AÇIKÇA yaz (CQ-265).",
1186
1255
  errorCorrectionLevel: "L | M | Q | H (varsayılan M). Tanınmayan değer (yanlış yazılmış bir seviye, boş metin, sayı) sessizce M’ye düşer — kütüphane onda Error atıp kodu tamamen kaybettirirdi. Kapasite ilişkisi için behavior.",
1187
- quietZone: 'Kodun çevresindeki sessiz alan, MODÜL sayısı olarak (piksel DEĞİL), 1–10, varsayılan 1. Adı padding DEĞİL: düğümün padding adlı bir prop’u ortak render katmanınca CSS boşluğu sayılır ve tasarımcının Spacing ayarını ezer (CQ-272).',
1256
+ quietZone: 'Kodun çevresindeki sessiz alan, MODÜL sayısı olarak (piksel DEĞİL), 1–10, varsayılan 1. Adı padding DEĞİL: düğümün padding adlı bir prop’u ortak render katmanınca CSS boşluğu sayılır ve tasarımcının Spacing ayarını ezer (CQ-416).',
1188
1257
  isLoading: 'Kodun yerine nabız atan gri kare çizer; veriyi üreten sorgu koşarken akıştan açılır. Açıkken kod HİÇ çizilmez — bekleyen bir QR eski değeriyle taranmasın diye.',
1189
1258
  style: 'Tasarımcı stil nesnesi; SARMALAYICIYA uygulanır, kodun kendi renklerini ya da modüllerini değiştirmez.',
1190
1259
  isHidden: 'Ortak katman görünürlüğü (RenderComponent okur).'
@@ -1201,10 +1270,11 @@ export const componentKnowledge = {
1201
1270
  "UZUN METİN: boşluksuz 300 karakterlik etiket de kabın içinde satır kırar; etiket en çok kabın genişliği kadar olur — &__tag'a maxWidth/overflowWrap yazmak GEREKMEZ. Etiketler satır sonunda alt satıra sarar; kökte flexWrap:'nowrap' verirsen etiketler yine sözcüğün genişliğine kadar daralır (sözcük ortasından kırılmaz, yalnız kabı aşan tek etiket kırılır).",
1202
1271
  "ERİŞİLEBİLİRLİK: isActive olan etiket aria-current='true' taşır; seçili durumu ekran okuyucuya iletmesi tıklanabilir (button) etikette güvenilirdir, salt metin (span) etikette öznitelik taşınır ama okunması ekran okuyucuya bağlıdır — durumu başka bir yolla da anlatmak istersen etiket metnine yaz. Tıklanabilir etiket kendi metniyle adlanan bir button'dır; basılı tutulan Enter olayı BİR kez tetikler. Kök bir liste değildir (rolsüz div).",
1203
1272
  "VERİ YAZIMI: values'a statik düz metin/sayı dizisi (['billing','critical']) ve karışık dizi KAYDEDİLEMEZ (500) — values'u kod tipinde bağla: {{ ['billing','critical'] }}. Statik öğenin label'ında {{ }} yorumlanmaz, ham basılır; ifade gerekiyorsa values'un kendisini ifade olarak yaz ({{ [{ label: state.page.x }] }}). Akış values'ı okuyup geri yazarsa label'daki çeviri sarmalı boşalır: akışta t(anahtar) ile çözülmüş metni yaz.",
1204
- "STİL HEDEFLERİ: kök CSS (gap, justifyContent, flexDirection, padding, border, fontSize, fontFamily, color…) çalışır; kökün fontSize/fontFamily'si etiketlere iner, color'ı yalnız renksiz (nötr) etikete iner — durum renkleri kendi rengini korur. '&__tag' HER etiketi hedefler (backgroundColor, color, border, borderRadius, padding, fontFamily, fontSize, fontWeight, textTransform, letterSpacing, boxShadow, textShadow, maxWidth ve linear-gradient çalışır; varyantın ve rengin zeminini ezer). Etiketin öznitelikleri durum hedefidir: &__tag[data-active='true'] (seçili), &__tag[data-color='success'] (renk), &__tag[data-variant='outline'] (varyant); bunlarla :hover, :focus-visible, ::before, :nth-child(n) ve @media birlikte yazılır. '&__tag:hover' salt metin (span) etiketine de uygulanır; YALNIZ tıklanabilirleri hedeflemek için '&__tag.ng-tag--clickable:hover'. Çakışan durum kuralları (aktif + hover aynı özellik) için kazanan anahtar sırasına bağlıdır: aynı özelliği tek seçicide ver. Etiket başına simge icon, etiket başına renk customColor/color ile verilir; renkli nokta isteniyorsa '&__tag[data-custom]::before' ile content:'', display:inline-block, width/height:8px, borderRadius:50%, marginInlineEnd:6px ve background:'var(--ng-tag-color)' yazılır (serbest renkli etiket CSS değişkeni --ng-tag-color taşır, data-custom='true' alır). Etiket başına GRADYAN özelliği YOKTUR: ':nth-child' ile yazılır (veriye bağlı değil)."
1273
+ "STİL HEDEFLERİ: kök CSS (gap, justifyContent, flexDirection, padding, border, fontSize, fontFamily, color…) çalışır; kökün fontSize/fontFamily'si etiketlere iner, color'ı yalnız renksiz (nötr) etikete iner — durum renkleri kendi rengini korur. '&__tag' HER etiketi hedefler (backgroundColor, color, border, borderRadius, padding, fontFamily, fontSize, fontWeight, textTransform, letterSpacing, boxShadow, textShadow, maxWidth ve linear-gradient çalışır; varyantın ve rengin zeminini ezer). Etiketin öznitelikleri durum hedefidir: &__tag[data-active='true'] (seçili), &__tag[data-color='success'] (renk), &__tag[data-variant='outline'] (varyant); bunlarla :hover, :focus-visible, ::before, :nth-child(n) ve @media birlikte yazılır. '&__tag:hover' salt metin (span) etiketine de uygulanır; YALNIZ tıklanabilirleri hedeflemek için '&__tag.ng-tag--clickable:hover'. Çakışan durum kuralları (aktif + hover aynı özellik) için kazanan anahtar sırasına bağlıdır: aynı özelliği tek seçicide ver. Etiket başına simge icon, etiket başına renk customColor/color ile verilir; renkli nokta isteniyorsa '&__tag[data-custom]::before' ile content:'', display:inline-block, width/height:8px, borderRadius:50%, marginInlineEnd:6px ve background:'var(--ng-tag-color)' yazılır (serbest renkli etiket CSS değişkeni --ng-tag-color taşır, data-custom='true' alır). Etiket başına GRADYAN özelliği YOKTUR: ':nth-child' ile yazılır (veriye bağlı değil).",
1274
+ "isDisabled:true (yalnız boolean true) etiketi soluk çizer ve tıklanamaz yapar: düğme disabled olur, clickItem çalışmaz. Sayısı 0 olan süzgeç çipi için akıştan yaz (2026-09-30)."
1205
1275
  ],
1206
1276
  propNotes: {
1207
- values: "[{ label, icon?, color?, customColor?, variant?, isActive? }] ya da düz metin dizisi (kod tipinde bağla). color: primary|info|success|warning|error ya da doğrudan CSS rengi (#hex, rgb(), var(--token), renk adı); customColor (CSS rengi) doluysa color'ı ezer; çizilemeyen renk nötr. icon: Material Symbols adı ya da { name }. variant: solid|outline.",
1277
+ values: "[{ label, icon?, color?, customColor?, variant?, isActive?, isDisabled? }] ya da düz metin dizisi (kod tipinde bağla). color: primary|info|success|warning|error ya da doğrudan CSS rengi (#hex, rgb(), var(--token), renk adı); customColor (CSS rengi) doluysa color'ı ezer; çizilemeyen renk nötr. icon: Material Symbols adı ya da { name }. variant: solid|outline.",
1208
1278
  currentItem: "Gizli prop: son tıklanan öğe (values'taki nesnenin tamamı, düz metin dizisinde metnin kendisi). index yalnız event.data'da.",
1209
1279
  style: "Kök düğüm ve '&__tag' alt anahtarı (her etiket). Durum hedefleri etiketin data-active / data-color / data-variant öznitelikleridir; tıklanabilir etiketin ek sınıfı ng-tag--clickable (davranış maddesi STİL HEDEFLERİ)."
1210
1280
  }
@@ -1427,7 +1497,7 @@ export const componentKnowledge = {
1427
1497
  sidebarSide: "Panelin ekranın hangi kenarında duracağı: 'left' | 'right'. sidebar, hybrid ve dual düzenlerinde anlamlı; diğerlerinde panel yoktur.",
1428
1498
  sidebarStyle: "'docked' panel kenara yapışır ve tek kenarlık taşır; 'floating' onu dört yanı boşluklu, köşeli ve gölgeli bir karta çevirir. sidebar, hybrid ve dual düzenlerinde anlamlı.",
1429
1499
  width: "Panel genişliği (px, 160–480). Rail modunda YOK SAYILIR — orada genişlik satır yüksekliği ve ikon kutusundan hesaplanır (navigation-tokens.ts railWidth). Drawer menü tipinde de okunmaz; onun genişliği drawerWidth’tir.",
1430
- collapsible: "Panelin başlığına daraltma düğmesi koyar; ziyaretçi menüyü rail’e indirip geri açabilir. Rail zaten daraltılmış olduğu için orada, drawer’da da anlamsızdır.",
1500
+ collapsible: "Panelin başlığına daraltma düğmesi koyar; ziyaretçi menüyü rail’e indirip geri açabilir; drawer’da anlamsızdır. KAPALI BAŞLAYAN MENÜ (2026-09-30): collapsible:true + displayMode:'rail' birlikte yazılırsa menü ŞERİT olarak açılır ve kenardaki chevron'la tam görünüme (width genişliğinde ikon + metin ağaç) açılır — ayrı bir 'kapalı başla' prop'u yoktur. Ziyaretçinin tercihi tarayıcıda düğüm başına saklanır (localStorage ng-nav-collapsed:<elementId>, '1' kapalı / '0' açık); kayıt yoksa bu varsayılan okunur. Tasarımcı tuvali menüyü her zaman açık çizer.",
1431
1501
  levelStyle: "Derin seviyelerin TİPOGRAFİSİ: 'uniform' her seviye aynı punto; 'tapered' 2. seviyeden itibaren satır kısalır ve yazı bir tık küçülüp soluklaşır, böylece derinlik göz kararıyla okunur. Girintiyi DEĞİŞTİRMEZ (o indent/maxIndent’in işi). Rail’de karşılığı yoktur.",
1432
1502
  nestedStyle: "Çocuğu olan satır nasıl çizilsin: 'indent' normal bir satırdır (açılır/kapanır); 'subheader' küçük bir BÖLÜM BAŞLIĞI olur ve çocukları hep açık durur. Düz menüde her dal böyledir. Akordiyonda (2026-09-25) yalnız ADRESSİZ ve isExpandable İŞARETLENMEMİŞ iç öğe başlığa döner, çocukları başlıkla aynı hizada çizilir — «Yetki yönetimi» (isExpandable: true) açılır modül kalır, içindeki «Organizasyon» etikettir. Varsayılan 'indent' kayıtlı menüleri değiştirmez.",
1433
1503
  hMenuStyle: "Header’da bir üst öğenin alt menüsü nasıl açılır: 'dropdown' altında küçük panel; 'mega' çubuğun tamamı boyunca çok kolonlu panel; 'tabs' alt öğeler ikinci bir satırda sekme çubuğu olur (açılır panel yok). Yalnız header düzeninde geçerlidir.",
@@ -1522,16 +1592,16 @@ export const componentKnowledge = {
1522
1592
  behavior: [
1523
1593
  "Gövdesi BLOK akışındadır ve çocukları 12 kolonluk IZGARA yerleştirir — hem runtime'da hem Studio tuvalinde. Gövde satır flex'i olsaydı renderer'ın çocuk sarmalayıcısı içerik genişliğine çökerdi (ölçüldü: runtime'da 1200px yerine 213px, tuvalde 0). Yani bölgelerin konumu dock prop'undan DEĞİL, blocks[]'ten gelir.",
1524
1594
  "RUNTIME'DA İZLER KABUKTAN GELİR (SHELL-002/003, 2026-09-29): çocukların blocks[] çizgilerine dokunulmaz, yalnız satır/kolon ölçüleri değişir — fill bölgesinin kapladığı satırlar kabuğun kalan yüksekliğini paylaşır (üst/alt şerit satırları sabit kalır), yalnız KAPALI bölgelerin kapladığı kolonlar 0'a iner ve fill o alanı devralır. Fill bölgesi yoksa ızgara olduğu gibi kalır. Studio tuvali bu kuralı UYGULAMAZ: tuvalde tasarımcının ızgarası görünür.",
1525
- "Mobilde (≤767px) kabuk en az ekran yüksekliğindedir; drawer bölgesi ve overlay ekrana SABİTTİR (position: fixed, çekmece min(300px, 85vw) genişlikte) — 2026-09-29'a kadar kabuk 0px'e çöküp çekmeceyi görünmez kılıyordu (SHELL-001). Açık çekmece role=dialog + aria-modal taşır; Escape kapatır.",
1526
- "sidebarOpen CANLI DURUMDUR: prop'un kendisi durumdur, toggle onu doğrudan yazar (qm-sidebar'ın isCollapsed deseni). Bir Durum değişkenine bağlanabilir ya da change-property akışıyla çevrilebilir. Mobil drawer'ın kapalı açılışı motora da yazılır (SHELL-005, 2026-09-29): ilk '!sidebarOpen' akışı artık çekmeceyi açar.",
1595
+ "Dar ekranda (≤767px) kabuk en az ekran yüksekliğindedir; drawer bölgesi ve overlay ekrana SABİTTİR (position: fixed, çekmece min(300px, 85vw) genişlikte) — 2026-09-29'a kadar kabuk 0px'e çöküp çekmeceyi görünmez kılıyordu (SHELL-001). Açık çekmece role=dialog + aria-modal taşır; Escape kapatır.",
1596
+ "sidebarOpen CANLI DURUMDUR: prop'un kendisi durumdur, toggle onu doğrudan yazar (qm-sidebar'ın isCollapsed deseni). Bir Durum değişkenine bağlanabilir ya da change-property akışıyla çevrilebilir. Dar ekranda drawer'ın kapalı açılışı motora da yazılır (SHELL-005, 2026-09-29): ilk '!sidebarOpen' akışı artık çekmeceyi açar.",
1527
1597
  "toggle olayı DURUM DEĞİŞİKLİĞİNİ bildirir (SHELL-009, 2026-09-29): overlay, Escape, bir akışın ya da Durum bağlamasının yazdığı yeni değer aynı olayı doğurur; açılıştaki çözümleme olay sayılmaz. toggle'a bağlı bir akış sidebarOpen'ı çevirirse sonsuz döngü kurar — yapmayın.",
1528
- "mobileBehavior yalnız yan panelin mobilde AÇIK BAŞLAYIP başlamayacağını belirler (resolveInitialSidebarOpen: drawer → kapalı, stack → açık). 2026-08-28'e kadar var olan 'stack ise gövdeyi column yap' CSS kuralı, gövde blok akışına geçtiği için KALDIRILDI — artık yerleşimi ızgara belirliyor.",
1598
+ "mobileBehavior yalnız yan panelin dar ekranda AÇIK BAŞLAYIP başlamayacağını belirler (resolveInitialSidebarOpen: drawer → kapalı, stack → açık). 2026-08-28'e kadar var olan 'stack ise gövdeyi column yap' CSS kuralı, gövde blok akışına geçtiği için KALDIRILDI — artık yerleşimi ızgara belirliyor.",
1529
1599
  "isViewportFilling / isShellRoot yetenekleri ve states.isShell bayrağı BACKEND'DE SAKLANMAZ (components tablosunda sütun yok, States kaydında isShell yok — zeyrek-frontend docs/issues.md BE-002). Davranışı tip adına düşen yedek listeler taşır; şema yazarken bu bayraklara güvenme."
1530
1600
  ],
1531
1601
  propNotes: {
1532
1602
  surfaceStyle: STYLE_GROUP_NOTES.surfaceStyle + ' ' + STYLE_GROUP_NOTES.colorTokens + ' Kabuk KENDİ derler (SHELL-006, 2026-09-29): değer .ng-layout-shell KÖKÜNE iner, contentOverflow da köke.',
1533
1603
  sidebarOpen: 'Yan panelin açık olup olmadığı; canlı durumdur, bağlanabilir.',
1534
- mobileBehavior: "'drawer' (varsayılan; mobilde kapalı başlar) | 'stack' (mobilde açık başlar).",
1604
+ mobileBehavior: "'drawer' (varsayılan; dar ekranda kapalı başlar) | 'stack' (dar ekranda açık başlar).",
1535
1605
  style: "&__body ve &__overlay parçaları uygulanır."
1536
1606
  }
1537
1607
  },
@@ -1565,6 +1635,20 @@ export const componentKnowledge = {
1565
1635
  ]
1566
1636
  },
1567
1637
  view: { summary: 'Tabs/switcher altındaki görünüm kapsayıcısı; children gruplamaya yarar.' },
1638
+ 'datatable-cell': {
1639
+ summary: 'datatable kolonunun HÜCRE ŞABLONU: tablonun çocuğu olan çerçevesiz kapsayıcı; içindeki bileşenler o kolonun hücresine HER SATIRDA çizilir ve satırı item olarak okur.',
1640
+ behavior: [
1641
+ "YALNIZ bir datatable'ın DOĞRUDAN çocuğu olarak anlamlıdır ve toolbox'ta yoktur (isHide). column prop'u tablonun columns[].name değerlerinden biri olmalıdır; eşleşmeyen ya da boş column ile düğüm hiçbir yerde çizilmez. Aynı column ile iki şablon varsa yalnız İLKİ çizilir.",
1642
+ "Şablonu olan kolonun hücresinde kolonun type/format ayarları (tag, progress, tarih biçimi…) ÇİZİLMEZ — hücreyi şablon doldurur; sıralama, filtre ve CSV yine satırın ham değerini kullanır. O hücre satır içi düzenlemeye açılmaz; maskeli (korumalı) hücrede şablon değil kilitli maske çizilir.",
1643
+ "İçindeki düğümlerin KOD bağlamalarında item o satırdır: {{ item.title }}. item SALT OKUNURDUR (repeater'daki gibi satıra geri yazmaz). Bağlı (connectData) tabloda item sunucudan gelen satırdır; ilişki alanı nesnedir ({{ item.kategori.ad }}).",
1644
+ 'Kapsayıcıdır (isDroppable): içine text, image, tag, button, container… bırakılır. Satır başına bir kopya çizildiği için ağır bileşen (chart, iç içe tablo) koyma; sayfa boyu × kolon sayısı kadar örnek oluşur.',
1645
+ "HÜCRENİN KAPSAYICISIDIR (2026-09-21): container'ın yerleşim prop'larını taşır — layout flex (varsayılan, 2026-09-22; direction row) | grid (12 kolonluk ızgara); flex'te direction/horizontalAlign/verticalAlign/gap/wrap. Kapsayıcısı çerçevesiz ve SAYDAMDIR (satırın zemini görünür; style.background ezer). Tasarımcı yarattığında iç/dış boşluğu yoktur (appearance paddingType/marginType none) ve element id'si kolon adıyla başlar (<kolon>-cell…). Tek başına silinemez (isDeletable false); şablonu kaldırmak kolonu kendi biçimine (tag, progress…) döndürür. Tasarımcı yeni hücreye kolonun değerine kodla bağlı bir text koyar ({{ item.<kolon> }}, ilişkide {{ item.<kolon>.<görünen alan> }})."
1646
+ ],
1647
+ propNotes: {
1648
+ column: "Şablonun ait olduğu kolonun name'i (columns[].name). Zorunlu; tasarımcıda kolon başlığındaki tasarım düğmesi yazar.",
1649
+ layout: "flex (varsayılan, direction row) | grid — container'ınkiyle aynı anlam; flex'te direction, horizontalAlign, verticalAlign, gap ve wrap açıktır, grid'de gizlenir."
1650
+ }
1651
+ },
1568
1652
  'widget-area': {
1569
1653
  summary: 'Widget’ların yerleştirildiği alan: widget şemasının KÖK düğümü (widgetType: container).',
1570
1654
  behavior: [
@@ -1605,6 +1689,7 @@ export const componentKnowledge = {
1605
1689
  "histories iki kayıt biçimini aynı kuralla okur. (1) Backend geçmişi — kaydı getiren get servisi adımının data.meta.history'si: { id, occurredAt, userId, userEmail, userFirstName, userLastName, action: CREATE|UPDATE|DELETE, ipAddress, changedFields: [{ fieldId, fieldSlug, fieldName, previousValue, currentValue }] }. (2) Kart alanları — { type, title, username, createdAt, status, statusLabel, icon, previousValue, currentValue }. Kart alanı doluysa kazanır, boşsa backend alanından türetilir: username ← userFirstName + userLastName ← userEmail; createdAt ← occurredAt; status/statusLabel/title/icon ← action (CREATE success 'Oluşturuldu'/'kaydı oluşturdu.', UPDATE primary 'Güncellendi', DELETE danger 'Silindi'; dil bileşenin dili).",
1606
1690
  'changedFields’ın her satırı kartta "fieldName: önceki → şimdiki" satırı olur (fieldName yoksa fieldSlug); iki değeri de boş satır çizilmez. Değer nesneyse JSON basılır. Üst düzey previousValue/currentValue etiketsiz tek satırdır.',
1607
1691
  'meta.history İKİ şartla gelir: (1) kaydı getiren get servisi adımının kaynak ayarında includeHistory: true (microservice kaydında sourceParameters.includeHistory; kapalıysa data.meta hiç oluşmaz), (2) entity’de denetim izi: isAuditTrailActive true ve auditTrailType (Basic ya da Detailed) (ya da adımın requestedHistoryType’ı; entity türünü aşarsa istek hata verir). Simple’da history null’dır; changedFields yalnız Detailed’da dolar. Tek ya da liste getirmede kayıt başına EN YENİ 5 işlem gelir ve eskisini sayfa sayfa getiren bir akış yolu yoktur (meta.historyTotalCount toplamı söyler).',
1692
+ 'Her kayıt tek satırdır: saat · avatar (username’in baş harfleri; username yoksa kaydın ikonu) · username + title · durum rozeti (ikon + statusLabel, status renginde). type metin olarak ÇİZİLMEZ, yalnız rozetin ipucudur (title) — statusLabel boşsa hiç görünmez; görünmesi gereken bilgiyi title ya da statusLabel’a yaz. dateFormat absolute iken ardışık aynı günün kayıtları tek gün başlığı altında toplanır ("11 Mart 2026") ve satırda yalnız saat kalır; relative’de başlık yoktur. createdAt hazır metinse ve saatle bitiyorsa ("5 Ekim 2026 13:17") aynı kural işler: saatten önceki kısım gün başlığı, saat satırda kalır. icon verilmemiş kayıtta rozet ikonu status’tan gelir: success check, warning play_arrow, danger close, diğerleri flag_check — başka ikon (ör. güncelleme için edit, oluşturma için add) isteniyorsa kayda icon yaz.',
1608
1693
  'Sıralama yapılmaz: dizi geldiği sırayla çizilir (backend en yeniyi başa koyar). Nesne olmayan öğe (null, metin) atlanır; histories dizi değilse boş durum çizilir.',
1609
1694
  'visibleLogCount üstü kayıtlar atılmaz: altta "Daha fazla göster (N)" çıkar, her basış sınırı visibleLogCount kadar büyütür ve showMore yayar. Boş/0 = hepsi görünür. Backend en fazla 5 işlem verdiği için meta.history bağlıyken düğme ancak visibleLogCount 5’ten küçükken görünür; showMore veri çekmez. Açılan sınır, listenin EN YENİ (ilk) girdisi değişince (başka kayda geçince ya da yeni işlem gelince) başa döner; aynı veri yeniden gelince, yalnız eski girdiler değişince ya da dil değişince açık kalır. İlk girdinin en yeni olduğu varsayılır (backend böyle verir; dizi tersse yeni işlem sınırı sıfırlamaz) ve aynı saniyede, aynı tür ve kullanıcıyla başlayan iki kayıt aynı kimlik sayılır.',
1610
1695
  'Şema varsayılanı 5 demo kayıttır (James Anderson…): gerçek sayfada histories’i akışa bağla; kayıt gelene dek demo görünmesin istiyorsan başlangıçta isLoading true ya da histories [] yaz.',
@@ -1620,12 +1705,12 @@ export const componentKnowledge = {
1620
1705
  visibleLogCount: 'İlk görünen kayıt sayısı (varsayılan 15); aşılınca "Daha fazla göster" çıkar. Boş/0 = hepsi.',
1621
1706
  showMoreText: 'Düğme metni; boşsa dilde "Daha fazla göster"/"Show more". Yanına gizli kayıt sayısı eklenir. Panelde yalnız visibleLogCount doluyken görünür.',
1622
1707
  emptyText: 'Liste boşken başlık; boşsa dilde "Geçmiş kaydı bulunmuyor" + açıklama. Doluysa açıklama çizilmez.',
1623
- dateFormat: 'absolute (varsayılan; "11 Mart 2026 09:24") | relative ("3 gün önce", canlı güncellenmez, gelecek zaman şimdi sayılır). ISO olmayan metin ve takvimde olmayan gün (2026-02-30) olduğu gibi basılır.',
1708
+ dateFormat: 'absolute (varsayılan; gün başlığı "11 Mart 2026" + satırda saat "09:24") | relative ("3 gün önce", canlı güncellenmez, gelecek zaman şimdi sayılır). ISO olmayan metin ve takvimde olmayan gün (2026-02-30) olduğu gibi basılır.',
1624
1709
  connector: 'Kartlar arası dikey çizgi: stub (varsayılan; ikon daireleri arasında kısa çizgi, eski görünüm) | rail (ikonun üstünden ve altından kartın kenarına, komşu kartlarla kesintisiz birleşen çizgi; her kart yüksekliğinde ve ikon boyutunda çalışır) | none (çizgisiz). Tanınmayan değer stub okunur. İkonu küçültüp nokta yapmak için ikon boyutunu &__item { "--audit-hst-icon": "14px" } ile ver (daire ve çizgi birlikte uyar); &__icon width/height çizgiyi taşımaz. rail çizgisi &__connector ile boyanır (width, background; her kartta iki parça olduğu için gradyan her kartta yeniden başlar, tek parça gradyan olmaz). Kartı start tarafında kaydıracaksan padding yerine border-inline-start ya da margin ver: çizgi kartın kenarından ikonun yarısı kadar içeride durur, padding ikonu iter ama çizgiyi itmez. Kartlar bitişik olmalı ve ikon kartın dikey ortasında durmalı: &__list ya da &__item ile dikey margin/gap ve asimetrik padding-top/bottom rail çizgisini böler.',
1625
1710
  locale: 'Tarih, işlem etiketi, düğme ve boş durum dili; boşsa uygulama dili (ar dahil). Listede tr, en ve ar var; başka dil için boş bırak ve uygulama dilini o yap (metinler İngilizce okunur).',
1626
1711
  iconStyle: 'Kartın işaretçisi: icon (varsayılan; durum ikonu) | dot (ikonsuz dolu nokta, durumun renginde, çevresinde 3 px açık halka; zaman çizgisi görünümü). dot boyutunu &__item { "--audit-hst-icon": "18px" } ile ayarla; connector rail ile birlikte nokta ve çizgi aynı eksende durur. Tanınmayan değer icon okunur. Noktayı &__icon ile boya (background, border); glifi gizlemek için fontSize: 0 numarasına gerek kalmaz.',
1627
1712
  isLoading: 'true iken içerik yerine iskelet.',
1628
- style: 'Kök + parçalar: &__title (başlık), &__list (kartların kabı), &__connector (yalnız connector rail: ikonun üstündeki ve altındaki çizgi parçaları), &__item (her kart; ayrıca data-status="primary|success|danger|warning|info" — durum başına farklı boyamak için [data-status="danger"] hedefle, :nth-child yerine), &__icon (yuvarlak ikon kutusu ya da iconStyle dot noktası; boyut --audit-hst-icon, glif fontSize ile ölçeklenir), &__type (tür etiketi), &__name (kullanıcı adı + mesaj satırı), &__message (yalnız mesaj), &__date, &__diff (her alan değişikliği satırı), &__status (durum rozeti), &__more (Daha fazla göster düğmesi; :hover ve :focus-visible alır), &__empty (boş durum kutusu). Durumlar: &__item:hover, &__item:last-child, &__item:nth-child(odd), @media. &__item::before (yatay ayırıcı) ve &__item::after (kısa çizgi) bileşenin kendi çizgileridir: display, background, width, height, border yazılır (connector none ya da rail ile kapatılır), content YAZILAMAZ (bileşenin kendi content kuralı kazanır, yazdığın sessizce etkisiz kalır). Kök fontSize, color ve fontFamily içe iner: parçalar boyutlarını em ile kökten alır, ikincil metin (tarih, tür, önceki değer) kökün renginin %72 oranındadır; kökte color verince durum rozetinin metni yine durumun rengine karışır (okunur kalır). Üst kabın yazı tipi kartlara geçmez (tema jetonu), gerekirse bu bileşenin kendi style kökünde ver.'
1713
+ style: 'Kök + parçalar: &__title (başlık), &__list (kartların kabı), &__connector (yalnız connector rail: ikonun üstündeki ve altındaki çizgi parçaları), &__item (her kayıt satırı; ayrıca data-status="primary|success|danger|warning|info" — durum başına farklı boyamak için [data-status="danger"] hedefle, :nth-child yerine), &__icon (yuvarlak avatar/ikon kutusu ya da iconStyle dot noktası; boyut --audit-hst-icon, glif fontSize ile ölçeklenir), &__name (kullanıcı adı + mesaj satırı), &__message (yalnız mesaj), &__date, &__diff (her alan değişikliği satırı), &__status (durum rozeti), &__more (Daha fazla göster düğmesi; :hover ve :focus-visible alır), &__empty (boş durum kutusu). Durumlar: &__item:hover, &__item:last-child, &__item:nth-child(odd), @media. &__item::before (yatay ayırıcı) ve &__item::after (kısa çizgi) bileşenin kendi çizgileridir: display, background, width, height, border yazılır (connector none ya da rail ile kapatılır), content YAZILAMAZ (bileşenin kendi content kuralı kazanır, yazdığın sessizce etkisiz kalır). Kök fontSize, color ve fontFamily içe iner: parçalar boyutlarını em ile kökten alır, ikincil metin (tarih, önceki değer) kökün renginin %72 oranındadır; kökte color verince durum rozetinin metni yine durumun rengine karışır (okunur kalır). Üst kabın yazı tipi kartlara geçmez (tema jetonu), gerekirse bu bileşenin kendi style kökünde ver.'
1629
1714
  }
1630
1715
  },
1631
1716
  'document-editor': {
@@ -1730,7 +1815,7 @@ export const componentKnowledge = {
1730
1815
  "click yalnız şemada bağlıysa yayılır (avatar/image deseni): bağlıyken rozet <button> olur, tıklanabilir görünür ve odak sırasına girer; bağlı değilken salt görsel <span>'dir.",
1731
1816
  'TIKLANABİLİR NOKTA İÇİN dotLabel ZORUNLU: nokta kipinde rozetin metni yoktur, click bağlıyken aria-hidden da basılmaz — dotLabel boşsa ekranda adsız bir düğme kalır ve ekran okuyucu onu "düğme" diye okur.',
1732
1817
  'Rozet kendi başına durur; başka bir bileşenin köşesine yapışmaz — saydığı şeyin yanına yerleştirilir (button ve icon kendi köşe rozetlerini kendileri çizer).',
1733
- 'Rozetin kendi ipucu prop’u YOKTUR ve gerekmez: 99+ ve kesilen metin title\'a kendiliğinden yazılır (nokta kipinde dotLabel title olur). Düğümün ortak appearance.tooltip kanalı rozet için BAĞLANAMAZ ("{{ item.count }}" harfi harfine basılır) ve ekran okuyucuya ulaşmaz (yalnız data-tooltip + CSS) — kullanma (CQ-249).',
1818
+ 'Rozetin kendi ipucu prop’u YOKTUR ve gerekmez: 99+ ve kesilen metin title\'a kendiliğinden yazılır (nokta kipinde dotLabel title olur). Düğümün ortak appearance.tooltip kanalı rozet için BAĞLANAMAZ ("{{ item.count }}" harfi harfine basılır) ve ekran okuyucuya ulaşmaz (yalnız data-tooltip + CSS) — kullanma (CQ-427).',
1734
1819
  'Erişilebilir ad: ariaLabel doluysa rozetin okunan adı odur ("3 okunmamış mesaj"). Tıklanamayan chip tek bir görsel (role=img) olarak okunur ve içindeki sayı ayrıca okunmaz; tıklanabilir chip düğme kalır ve adı etiket olur (etiketsiz tıklanabilir sayaç yalnız "99+" gibi bir sayıyı okur ve ne yaptığını söylemez — sayaca tıklama bağlıyorsan ariaLabel yaz). Nokta kipinde dotLabel etiketin yedeğidir, ariaLabel onu ezer; etiketsiz tıklanabilir nokta adsız düğme kalır.',
1735
1820
  'Tıklanabilir NOKTANIN tıklama alanı görünmez bir 24×24 px\'e genişler (WCAG 2.5.8; nokta ve yerleşim aynı); bunu ::after kurar, noktada style\'a &::after yazma. Nokta başka bir tıklanabilir öğenin ~7 px yanındaysa o bölgedeki tıklamaları nokta alır: yan yana tıklanabilir nokta/düğme koyacaksan aralarını 14 px üstü bırak. Kendi başına hâlâ adsız bir düğme olabilir: dotLabel yaz.',
1736
1821
  'Köşe rozeti (bir düğme ya da avatarın köşesinde sayaç) için bileşen yok, style var: kabın style\'ına position: relative, rozetin style\'ına position: absolute; top: -4px; inset-inline-end: -6px (RTL\'de kendiliğinden aynalanır) ve kabın surfaceStyle\'ında contentOverflow: visible yaz — yoksa kap rozeti kırpar. Tıklanabilir köşe rozeti için rozetin kendisi click\'i taşır.',
@@ -1815,13 +1900,16 @@ export const componentKnowledge = {
1815
1900
  }
1816
1901
  },
1817
1902
  chart: {
1818
- summary: 'ECharts tabanlı grafik (bar/line/area/pie/donut + waterfall, histogram, pareto, bullet, tornado, radial, funnel, gauge, radar, funnelflow, scatter). VERİ ÇEKMEZ: satırlar rows prop’una akışla yazılır.',
1903
+ summary: 'ECharts tabanlı grafik (bar/line/area/pie/donut + waterfall, histogram, pareto, bullet, tornado, radial, funnel, gauge, radar, funnelflow, scatter). Satırlar ya tabloya/query’ye/workflow’a/uca BAĞLANIR (rows ya da series.N.data → connect_data_bind, akışsız; kategori/değer rolleri, CD-015 aggregate) ya da akışla rows prop’una yazılır (bağlı prop’a setter yazılmaz, CD-005).',
1819
1904
  behavior: [
1820
1905
  "Veri prop'u data DEĞİL rows'tur (data eski adıdır, yalnız geriye uyumluluk için duruyor). Kategori categoryField, değerler series[].valueField ile çözülür.",
1821
1906
  'seriesField + valueField birlikte verilirse satırlar "kategori+seri başına bir satır" sayılıp geniş biçime pivotlanır; series dizisi o zaman prop’tan değil veriden türetilir.',
1822
1907
  'aggregate/sort/topN/nullMode veriyi çizimden ÖNCE dönüştürür — aynı işi akışta yapmana gerek yok.',
1823
1908
  '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.',
1824
1909
  'isExportable "tablo olarak gör" + dışa aktarma araç çubuğunu açar; showRefresh refresh olayını yayan bir yenile düğmesi ekler.',
1910
+ "BAĞLI VERİ (2026-09-17, f-31): rows birincil bağlanabilir prop (fieldProps: rol seçimi categoryField/seriesField/valueField'a da yazılır). Ham tablo satırlarında seriesField + valueField + aggregate: toplama pivottan ÖNCE kategori+seri çifti başına yapılır (yığın grafik doğru toplam). funnelSources ikinci yuva (name, count). SERİ BAŞINA KAYNAK: series[i].data kendi başına bağlanır (prop yolu series.<i>.data, roller category + value); noktalar kategoriye göre rows'a birleşir, değer serinin valueField'ına (boşsa series_<i>). aggregate birleşmeden önce BİR kez uygulanır (count nokta sayısı); aggregate yoksa aynı kategorinin son noktası kazanır. Seri öğesi bağlanınca statik örnek rows aynı commit'te boşalır. rows da bağlıysa iki kaynak birleşir, uyarı yok; ilk bağlantı (rows) birincildir, series okumaları yükleniyor durumuna dokunmaz.",
1911
+ "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).",
1912
+ '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) eksenin ortasına, etiketlerin dışına yazılır; ızgara etiket + başlığa yer ayırır (2026-09-29). title/subtitle doluyken çizim alanı başlığın altına iner (radar/radyalde merkez aşağı kayar).',
1825
1913
  "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.",
1826
1914
  '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.',
1827
1915
  '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.',
@@ -1841,7 +1929,7 @@ export const componentKnowledge = {
1841
1929
  'DURUM KUTULARI (2026-09-30): isLoading bir iskelet çizer (öncesinde alan boş kalıyordu); hata kutusu role="alert", boş kutu role="status" taşır; emptyText/errorText yalnız boşluktan oluşuyorsa varsayılan metin yazılır. Tam ekran (isExportable) bir kaplamadır: Esc kapatır, Tab kaplamanın dışına kaçmaz.'
1842
1930
  ],
1843
1931
  propNotes: {
1844
- rows: 'Satır dizisi; mount/filter akışlarının setter hedefi.',
1932
+ rows: 'Satır dizisi. Bağlanabilir prop (connectData.props.rows): veri kaynağından okunuyorsa connect_data_bind; akışla doldurulacaksa mount/filter akışlarının setter hedefi — ikisi birden değil (CD-005).',
1845
1933
  legend: "{ show, position, orient, showValues }. position artık DÖRT yön: top | bottom | left | right (2026-08-27). Yana yaslanan legend her zaman dikey çizilir — yatay seçilse bile ezilir, çünkü yandaki yatay legend grafiğin üstüne biner. showValues YALNIZ pasta/halkada iş görür: seri adının yanına dilim değerini yazar.",
1846
1934
  centerLabel: "{ show, text, subtext } — YALNIZ donut. text boş bırakılırsa dilim değerlerinin TOPLAMI yazılır (valueFormat uygulanır), yani 'ortadaki toplam' için ayrı bir setter gerekmez. Pastada delik olmadığı için görünmez ve panelde gizlidir.",
1847
1935
  categoryField: 'Kategori ekseni alan adı (varsayılan "label"). SCATTER’DA x ekseninin SAYISAL kolonudur (y = series[0].valueField) — eski xField adı geriye uyumluluk için ayrılmış durumda, onu kullanma.',
@@ -2166,9 +2254,12 @@ export const componentKnowledge = {
2166
2254
  'Uzun başlık, altyazı, trend etiketi ve alt satır metni satır kırar, kırpılmaz; değer tek satırdır ve sığmazsa "…" ile biter (title tam metni taşır). 999px gibi büyük köşe yarıçapı alt satırın köşesini kırpar.'
2167
2255
  ],
2168
2256
  propNotes: {
2169
- value: 'Sayı ya da metin; sayıysa valueFormat uygulanır.',
2257
+ value: 'Sayı ya da metin; sayıysa valueFormat uygulanır. rows Connect Data ile bağlıyken basılmaz — yerine rows özeti gelir.',
2170
2258
  valueFormat: 'decimals yazılmazsa sayının kendi ondalığı (en çok 2; 3.1 → "3,1"), abbreviate açıkken 0; thousandsSep kapalıyken ondalık ayracı DEĞİŞMEZ (1250,00); abbreviate basamaktan önce yuvarlar (1500 → "2K", decimals:1 ile "1,5K").',
2171
- sparkline: 'Sayı dizisi; kendi min/max’ına göre ölçeklenir (sıfır tabanlı değil).',
2259
+ rows: "Ana değerin Connect Data kaynağı (39/03 U-13, 2026-09-21): birincil bağlanabilir prop (connectData.primary: rows, rol value: number zorunlu); connect_data_bind { prop: 'rows', roles: { value: '<sayı alanı>' } }. Bağlıyken kart value yerine valueAggregate özetini basar. Sayfalamaz: tanımın sayfa boyu 1000 yazılır (connect_data_bind pageSize vermezseniz) — kaynak 1000'i aşarsa sum/avg/min/max kesiktir ve runtimeErrors'a ConnectDataRowsTruncated düşer.",
2260
+ valueAggregate: "Bağlı rows'tan ana değer: first (varsayılan; ilk satırın value'su — tek değer döndüren query/microservice), count (kaynağın meta.total'ı → totalRows, 1000'i aşan kaynakta da tam), sum · avg · min · max (okunan satırlar). Bağlama bu prop'u yazmaz; page_schema_patch set_prop ile seçilir.",
2261
+ totalRows: 'Gizli; runtime bağlantısı yazar (count özeti okur). Elle yazılmaz.',
2262
+ sparkline: 'Sayı dizisi; kendi min/max’ına göre ölçeklenir (sıfır tabanlı değil). Connect Data ile de bağlanır (ikincil prop, prop: sparkline) — araç çubuğundaki Connect data artık ana değeri (rows) bağlar.',
2172
2263
  trend: 'Değişim miktarı; işareti yönü ve rengi belirler, birimini trendFormat söyler. 0 nötrdür ve panelden temizlenemez.',
2173
2264
  trendFormat: 'percent (varsayılan) yüzde işaretiyle yazar; value işareti korur, birim yazmaz — mutlak değişim gösteren KPI için.',
2174
2265
  isNewTabLink: 'Yalnız footerHref doluyken anlamlı: target="_blank" + rel="noreferrer noopener". Yeni sekmede footerFlow akışı da tamamlanır.',
@@ -2249,8 +2340,8 @@ export const componentKnowledge = {
2249
2340
  behavior: [
2250
2341
  'minTime/maxTime dışındaki seçenekler listeden ATILMAZ, pasifleştirilir; minutesStep seçenek adımını belirler.',
2251
2342
  "Liste adımdan ÜRETİLİR, ama alanın TUTTUĞU saat adıma düşmese bile listede kalır (2026-09-11): minutesStep=15 iken 09:07 kendi yerine eklenir ve kutuda görünür. Öncesinde eşleşen seçenek olmadığı için alan BOŞ görünüyordu — veritabanından gelen saatlerin olağan hâli. Şart, değerin KATI 'HH:mm' olmasıdır: '9:07' ya da '09:07:00' hiçbir seçenekle eşleşmez ve kutu yine boş kalır.",
2252
- "change yükü { value, selectedLabel } taşır ve ikisi de düğümün prop'una yazılır: akışta self.value ve self.selectedLabel ile okunur. selectedLabel 2026-09-11'de eklendi — 12h kipinde etiket '01:00 PM' iken value '13:00' kalır, gösterilen metnin tek kaynağı budur. Temizleme (X) de change yayar, ikisi de boş metin olur.",
2253
- "isLoading KİLİT DEĞİLDİR (2026-09-11): alan odaklanabilir kalır, kök aria-busy taşır ve açık liste yükleniyor satırını gösterir. Öncesinde isLoading alanı disabled yapıyordu; ortak Select'i kullanan üç bileşenden en son bu düzeltildi. Tek şart: liste KAPALIYKEN isLoading açıksa chevron'a tıklamak listeyi açmaz (metin alanına tıklamak ve klavye açar) — ortak Select'in kuralı.",
2343
+ "change yükü { value, selectedLabel } taşır ve ikisi de düğümün prop'una yazılır: akışta self.value ve self.selectedLabel ile okunur. selectedLabel 2026-09-11'de eklendi — 12h kipinde etiket '01:00 PM' iken value '13:00' kalır, gösterilen metnin tek kaynağı budur. Temizleme (panelin 'Seçimi temizle' düğmesi) de change yayar, ikisi de boş metin olur.",
2344
+ "isLoading KİLİT DEĞİLDİR (2026-09-11): alan odaklanabilir kalır, kök aria-busy taşır ve açık liste yükleniyor satırını gösterir. Öncesinde isLoading alanı disabled yapıyordu; ortak Select'i kullanan üç bileşenden en son bu düzeltildi. 2026-10-05'ten beri liste kapalıyken de tıklama ya da tuş paneli açar ve yükleniyor satırı görünür.",
2254
2345
  "focus/blur GRUP düzeyindedir: paylaşılan Select kendi focus'unu yayar ama blur'ü yok, o yüzden ikisi de kapsayıcı üstünden köklendi — checkboxgroup/otpinput/slider ile aynı desen. Alanın kendi kromuna (chevron, X) basmak artık SAHTE blur yaymaz: sarmalayıcı mousedown'ı iptal edip odağı alanda tutuyor, yani blur yalnız alan gerçekten terk edilince gelir. (Odaksız alanda chevron'a basmak listeyi açar ve normal focus'unu yayar.)",
2255
2346
  'Doğrulama kuralları: required · min · max (2026-09-11; pattern bildirimi kaldırıldı — panel saat alanına regex kuralı hiç çizmiyor, yazılan satırı düğüm seçilince siliyordu). min/max değerleri de HH:mm metnidir ve saniye taşıyan bir değer karşılaştırmadan sessizce düşer (CQ-095).',
2256
2347
  'format YALNIZ GÖSTERİMDİR: 12h etiketleri 01:00 PM biçiminde çizer, saklanan value her iki kipte de HH:mm kalır. Liste içi arama DEĞERİ değil ETİKETİ arar, yani 12h kipinde "13" yazmak saat 13:00\'ü BULMAZ (etiketi "01:00 PM"), "01" bulur.'
@@ -2261,7 +2352,7 @@ export const componentKnowledge = {
2261
2352
  minTime: "Bu saatten öncesi listede KALIR ama seçilemez. Serbest metin alanı, bağışlayıcı okunur: '9', '9:00', '9.00', '0900' hepsi 09:00'dır; okunamayan metin sınır KOYMAZ (sessizce sınırsız).",
2262
2353
  maxTime: 'Bu saatten sonrası listede kalır ama seçilemez; minTime ile aynı bağışlayıcı okuma.',
2263
2354
  disabledTimes: "[{ time: 'HH:mm' }] — aralığın içinde olsalar bile seçilemeyen saatler. Okunamayan satır hiçbir saati engellemez. Zaten seçili olan bir saati engellemek onu TEMİZLEMEZ: alan değeri pasif hâlde tutmayı sürdürür, gerekiyorsa akıştan boşalt.",
2264
- clearable: 'Seçili saatin yanındaki X (varsayılan açık). Temizleme change yayar, ayrı bir olay yoktur.',
2355
+ clearable: "Panelin altındaki 'Seçimi temizle' düğmesi (varsayılan açık, yalnız değer varken; 2026-10-05'e kadar alandaki X idi). Temizleme change yayar, ayrı bir olay yoktur.",
2265
2356
  emptyText: 'Liste içinde arama hiçbir saati bulamayınca yazılacak metin; boş bırakılırsa arayüz dilinden gelen "sonuç yok" metni kullanılır.',
2266
2357
  format: "'24h' (varsayılan) | '12h'. Yalnız etiketleri değiştirir; tarih/saat bileşenleri 24 saatlik gösterime sabit olduğu için aynı sayfada ikisi ayrışır (CQ-098).",
2267
2358
  selectedLabel: "Gizli durum prop'u: `change` seçilen saatin GÖSTERİLEN metnini buraya yazar (temizlemede boş metin). Yalnız kullanıcı seçimiyle dolar — value'yu akıştan yazmak burayı GÜNCELLEMEZ.",
@@ -2326,10 +2417,12 @@ export const componentKnowledge = {
2326
2417
  "columns bir ÜST SINIRDIR: kap her kolona en az 8rem (labelPosition left iken 14rem) bırakamıyorsa kolon sayısı kendiliğinden düşer — 375px'te columns 4 iki kolon (left etiketle tek kolon) çizer, 628px ve üstünde aynen kalır. Dar ekran için ayrıca @media yazmana gerek yok.",
2327
2418
  "badge rengi değere göre verilir: fields[].colorMap = [{ value: 'active', color: 'success' }, { value: 'pending', color: 'warning' }, { value: 'failed', color: 'error' }]. Tonlu rozet tonun tintli zemininde ve tonla kökten devralınan rengin karışımı yazıyla çizilir (iki temada da ≥ 5.7 kontrast ölçüldü). Sınır: info tonu açık temada neredeyse beyazdır, hap görünmez — durum ayrımı için success/warning/error tercih et.",
2328
2419
  "tarih ve saat tr/en dışı dilde (ar, de…) o dilin Intl biçimiyle yazılır (ar: 14 مارس 2022); tr ve en date-fns desenleriyle aynen (14 Mar 2022 / Mar 14, 2022). Eskiden bu diller Türkçe ay adına düşüyordu.",
2329
- "mount ilk görünür olduğunda BİR kez yayılır: isHidden açık açılan sayfada çıkmaz, gösterilince çıkar; sonradan gizleyip göstermek yeniden yaymaz."
2420
+ "mount ilk görünür olduğunda BİR kez yayılır: isHidden açık açılan sayfada çıkmaz, gösterilince çıkar; sonradan gizleyip göstermek yeniden yaymaz.",
2421
+ PROTECTED_VALUE_NOTE + " Künyede: kaydın __protected metası bir alanı maskeli işaretlerse o alanın format'ı UYGULANMAZ, kilitli maske çizilir; nokta ayraçlı iç içe yollar metaya bakılmadan normal çizilir (meta kök alan slug'ı taşır)."
2330
2422
  ],
2331
2423
  propNotes: {
2332
2424
  record: 'Gösterilecek TEK kayıt (nesne); akıştan beslenecekse setter hedefi budur. Boş nesne = boş durum.',
2425
+ revealEntity: REVEAL_ENTITY_NOTE,
2333
2426
  fields: "[{ label, field, format, currency, colorMap, icon, isHidden }] — field boş satırlar elenir, isHidden satır çizilmez (table kolonlarındaki isHidden ile aynı iş), label boşsa field kullanılır, icon ETİKETİN yanına çizilir. colorMap: [{ value, color }] YALNIZ badge biçiminde okunur — value alanın değeriyle (metin olarak, kırpılmış, büyük/küçük harfe DUYARLI) eşleşir, color primary | info | success | warning | error tonlarından biridir (ham renk kabul edilmez, tema jetonuna çözülür); eşleşmeyen değer eski vurgu renginde kalır; tanınan ton taşımayan (color boş ya da geçersiz) satır atlanır, aynı değerli sonraki geçerli satır kazanır; tag biçimi tonlanmaz.",
2334
2427
  labelPosition: "top (varsayılan) | left — left'te etiket sütunu minmax(96px, %38) ile ayrılır.",
2335
2428
  columns: "Izgara kolon sayısı ÜST SINIRI, 1-4. Kanvas toolbar'ı sınıra çeker; sağ panel büyük değeri uyarı ikonuyla kabul eder, runtime yine 1-4'e kırpar. Dar kapta kolon sayısı kendiliğinden düşer (her kolona en az 8rem, left etiketle 14rem).",
@@ -2345,6 +2438,7 @@ export const componentKnowledge = {
2345
2438
  "startField'ı geçersiz/boş satır SESSİZCE atılır; end geçersizse start'a eşitlenir, ters aralık start'a kırpılır; id yoksa event-<index> üretilir.",
2346
2439
  "Taşıma ve boyutlandırma iyimserdir: eventMove sonrası komponent rows'u DEĞİŞTİRMEZ; akış yeni tarihi uca yazıp rows'u tazeleyince (id:start:end imzası değişince) iyimser katman sıfırlanır — kalıcılaştırılmayan değişiklik, veri değiştiği anda geri döner (kanban ile aynı sözleşme).",
2347
2440
  "Veri tazeleme kancası monthChange (oklar/Bugün, HER görünümde) ve viewChange'dir; ikisi de görünen aralığı start/end ('yyyy-MM-dd', iki uç dahil) olarak taşır — sorguyu month/year'a değil start/end'e bağla: ajanda ve hafta ay sınırını aşar, ay ızgarası da komşu ayların günlerini gösterir. end TARİH-YALNIZ ve DAHİLDİR: filtreyi KESİŞİM olarak yaz — etkinlikBaşlangıç < (end + 1 gün) VE etkinlikBitiş >= start; `başlangıç <= end` saatli kolonda son günün saatli kayıtlarını, `başlangıç >= start VE bitiş <= end` kenardan taşan kayıtları düşürür. İlk mount'ta yayılmazlar; açılış aralığını defaultDate/defaultView belirler. month 1-TABANLIDIR.",
2441
+ "BAĞLI VERİ (2026-09-17, f-31): rows bağlıysa (roller title, start, end, color, id; start/end tarih rolü) runtime listeyi görünen ayın çevresiyle okur — yalnız start alanı behavior.filterable'daysa (değilse süzmeden ilk sayfa): start gte ayın 1'i − 7 gün, lt sonraki ayın 1'i + max(7, agendaDays) gün; sayfalanmaz, en çok 1000 olay. İlk okuma defaultDate'in ayıyla (boşsa bugün), monthChange aralık değişince yeniden okur. Aralıktan önce başlayan olay gelmez. Akış yazmak gerekmez.",
2348
2442
  "isCreatable:true iken tıklama dateClick YERİNE eventCreate yayar: ay hücresi tek günlük allDay:true, hafta/gün boş slotu 60 dakikalık saatli taslak. Basılı tutup sürüklemek aralık seçer: ayda birden çok gün (allDay:true, end son gün dahil), hafta/gün kolonunda aynı günün birden çok saat slotu, etkinlik bloklarının üstünden de (end son slotun sonu) — bırakınca TEK eventCreate. Sürükleyerek seçim fare/kalemle çalışır; dokunmatikte yalnız tek hücre tıklaması oluşturur. Basış sürerken isLoading açılır ya da isCreatable kapanırsa bırakış olay yaymaz. isCreatable kapalıyken slot tıklaması hiçbir şey yapmaz.",
2349
2443
  "isEditable ile sürükleyerek taşıma: ay görünümünde ve tüm-gün şeridinde gün kayar (saat korunur), hafta/gün kolonunda saat 30 dakikaya yuvarlanır; tüm-gün etkinlik saat KAZANMAZ. Hafta/gün görünümünde saatli bloğun üst/alt kenarından boyutlandırma da vardır (30 dk adım, en az 30 dk) ve AYNI eventMove olayını yayar. Ajanda listesinde sürükleme yoktur.",
2350
2444
  "Tüm-gün kararı: satırın allDayField (varsayılan 'allDay') bayrağı true ise her zaman tüm gün; false ise yalnız aralıkta saat bilgisi varsa saatli sayılır (tarih-yalnız / 00:00→00:00 satır false'la da şeritte kalır, görünmez olmaz); değer true/false, 'true'/'false', 1/0; bayrak yoksa süresi >=24 saat ya da 00:00→00:00 olan etkinlik tüm gün sayılır. Tüm gün etkinlik saat ızgarası yerine üst şeride çizilir; çok günlü etkinlik ay görünümünde kapladığı HER güne ayrı çip düşer (sürekli bant yok).",
@@ -2357,11 +2451,13 @@ export const componentKnowledge = {
2357
2451
  "Dil: Bugün, görünüm adları, 'Etkinlik yok', 'Tüm gün' ve ok adları tr/en/ar sözlüğünden gelir; ay/gün adları da aynı üç dilde (başka dil İngilizceye düşer, Türkçeye değil). RTL'de çip şeridi ve ok yönü mantıksaldır (şerit sağda, önceki oku sağa bakar), çakışan bloklar sağdan dizilir.",
2358
2452
  "Etkinlik rengi her zeminde okunur: yazı rengi etkinlik renginin ~%35'i + tema yazı renginin karışımıdır (açık sarı, beyaz, 'info' dahil kontrast ≥ 4.5, açık ve koyu tema); kenar şeridi ve zemin tonu ham renktir. Yani ham rengi yazıda aynen bekleme — renk kimliğini şerit ve zemin taşır.",
2359
2453
  "Aynı kimlikli iki satır ÇÖKERTMEZ: ikisi de çizilir, yükte id aynen gider; iyimser taşıma kopyaları ayrı tutar (sürüklenen kopya kendi anahtarıyla kayar), ama data-element-id'leri aynıdır ve page_screenshot eylemi ilk eşleşmeye gider — id'leri benzersiz tut. Takvimde olmayan tarih ('2026-02-30', saatli '2026-02-30T10:00' dahil) satırı düşürür, defaultDate'te bugüne düşer (sessizce ertesi aya kaymaz); sayıya çevrilemeyen, boş ya da null startHour/endHour 8–18'e, maxVisibleEvents 3'e döner.",
2360
- "Dar ekranda başlık ve düğme grubu iki satıra bölünür (başlık kırpılmaz); tüm-gün şeridi ~8em'de kayar, çok sayıda tüm-gün etkinlik saat ızgarasını ezmez; 8+ çakışan blok dar sütunda yalnız renkli şerit gösterir — gün görünümüne geç."
2454
+ "Dar ekranda başlık ve düğme grubu iki satıra bölünür (başlık kırpılmaz); tüm-gün şeridi ~8em'de kayar, çok sayıda tüm-gün etkinlik saat ızgarasını ezmez; 8+ çakışan blok dar sütunda yalnız renkli şerit gösterir — gün görünümüne geç.",
2455
+ "source 'bpm-tasks' iken rows süreç görevleridir (Page.bpm.tasks.calendar(from, to).data): alan eşlemesi okunmaz; state planned görev plannedStartAt'tan dueAt'e uzanır (bilgi rengi), açık görev termin gününde gün boyu kayıt olur — saat penceresi dışındaki termin de hafta/gün görünümünde gün boyu şeridinde görünür (termini geçmişse hata, değilse uyarı rengi; renk dakikada bir tazelenir). Başlık name'in uygulama dilidir. Süreç görevleri sürüklenmez/boyutlanmaz (isEditable yok sayılır). eventClick satırı taskId ile taşır; akış Page.bpm.task(taskId) açar. Aralık en çok 92 gün."
2361
2456
  ],
2362
2457
  propNotes: {
2363
2458
  rows: 'Etkinlik satırları; monthChange/viewChange akışlarının setter hedefi. Alan adları titleField/startField/endField/colorField/idField/allDayField ile çözülür (nokta ayraçlı iç içe yol çalışır; boşsa title/start/end/color/id/allDay).',
2364
2459
  allDayField: "Tüm-gün bayrağının kolonu (boşsa 'allDay'). Tanınan değer true/false, 'true'/'false', 1/0; başka değer ya da kolon yoksa aralıktan çıkarılır. true saatli kaydı şeride alır; false 24 saati aşan saatli kaydı ızgarada tutar ama saatsiz (gece yarısı → gece yarısı) kaydı ızgaraya ALMAZ — şeritte kalır.",
2460
+ source: "rows (varsayılan, alan eşlemesi) | bpm-tasks (süreç görevleri: { id, name, dueAt, plannedStartAt, state }).",
2365
2461
  colorField: "Geçerli CSS rengi olduğu gibi kullanılır, semantik durum adı tema değişkenine çözülür, tanınmayan değer accent'e düşer. 'info' beyaz temada görünmezdir — ham renk ver.",
2366
2462
  maxVisibleEvents: 'Ay hücresinde görünen çip sayısı (varsayılan 3); fazlası +n olur (+n ayrı tıklanmaz, hücre tıklaması sayılır).',
2367
2463
  defaultDate: "Açılış tarihi (yyyy-MM-dd; katalog varsayılanı örnek veriyle aynı ay olan '2026-08-01'). Gün korunur: hafta/gün/ajanda o günden açılır. Değiştikçe takvim oraya gider; boşsa bugün. 'bugün' için sabit tarih YAZMAYIN, boş bırakın; ifadeyle bağlanacaksa code prop'u '{{ }}' içinde yazılır: { type: 'code', ref: \"{{ new Date().toISOString().slice(0, 10) }}\" } — parantezsiz ifade metin olarak gelir (PAGE-032 reddeder).",
@@ -2415,6 +2511,7 @@ export const componentKnowledge = {
2415
2511
  behavior: [
2416
2512
  "cardMove/cardClick/cardAdd/cardRemove yükü BİLİNÇLİ olarak yalnız params ile gider (self'e yazılsa id/from/to çöp prop olur ve tetiklenen render iyimser katmanı aynı karede silerdi): akışta event.data.id / .row / .from / .to / .column ile okunur.",
2417
2513
  "Taşıma iyimserdir: komponent rows'u DEĞİŞTİRMEZ; cardMove akışı yeni kolonu uca yazıp rows'u tazeler — (id:kolon) imzası değişince iyimser katman sıfırlanır. Kalıcılaştırılmayan taşıma, veri değiştiği anda ya da isLoading kapandığı anda eski kolonuna döner.",
2514
+ "BAĞLI VERİ (2026-09-17, f-31): rows bağlıysa (roller title, subtitle, column, color, id) cardMove'da runtime kolon alanını kendisi yazar: tek update { <column rolü alanı>: to, <birincil anahtar> } — tanımda edit.update açık, kolon alanı editable'da ve describe write.update true ise; akış yazılmaz. Yazılamayan ya da reddedilen taşımada liste yeniden okunur ve kart kayıtlı kolonuna döner. id rolü başka alana eşlense de satırın birincil anahtarı ezilmez. columns ikinci yuva (value, label): aynı ya da başka tabloya ayrı bağlanır; ikincil okuma kanbanın isLoading durumuna dokunmaz.",
2418
2515
  "Ekleme ve silme İYİMSER DEĞİLDİR: isAddable kolon altına '+ addText' düğmesi koyar ve yalnız cardAdd { column } yayar; isRemovable karta × düğmesi koyar ve yalnız cardRemove { id, row, column } yayar (cardClick yaymaz). Kart ancak akış satırı yazıp/silip rows'u tazeleyince eklenir/kaybolur — silmeden önce onay sormak akışın elindedir.",
2419
2516
  "Kolon eşleşmesi columns[].value ile TAM string eşitliğidir; sayı value metne çevrilir (2 ile '2' eşleşir). Eşleşmeyen satır ilk kolona değil 'atanmamış' kuyruğuna düşer (kesikli kenarlık; yalnız doluyken çizilir, başlığı unassignedText, boşsa uygulama diline göre 'Atanmamış' / 'Unassigned' / 'غير مُسنَد', ekleme düğmesi yok). Aynı value'lu ikinci kolon ve value'su boş kolon çizilmez.",
2420
2517
  "emptyText iki yerde çizilir: kartı olmayan her kolonun içinde (yalnız doluysa) ve hiç kolon yokken panonun yerinde (boşsa '—').",
@@ -2491,6 +2588,225 @@ export const componentKnowledge = {
2491
2588
  canProceed: "Aktif adımın kapısı; ifadeye bağlanır. Yalnız false/'false' engeller.",
2492
2589
  currentStep: "0 tabanlı aktif adım; setter hedefi, aralık dışı değer kırpılır. Studio'dan yeni bırakılan düğümde 0 yerine null KAYDEDİLİR (frontend CQ-091, ortak mapper falsy varsayılanı düşürüyor): bileşen null'ı ilk adım sayar ama {{ <stepper>.currentStep }} / self.currentStep kullanıcı ilk kez adım değiştirene kadar null okur — ifadede {{ <stepper>.currentStep || 0 }} yaz. Şemayı kendin yazıyorsan currentStep: 0'ı açıkça ver."
2493
2590
  }
2591
+ },
2592
+ 'task-inbox': {
2593
+ summary: 'Süreç görev kutusu: sekmeler (bana atanan · grubumun · vekâleten · başlattıklarım · tamamladıklarım · planlı), SLA renk çipi, satır/toplu üstlenme; veriyi KENDİSİ çekmez, rows akıştan (process.task.list sistem ucu, microservice adımı) gelir.',
2594
+ guide: 'bpm',
2595
+ behavior: [
2596
+ "Veri yolu: mount/tabChange akışı `process.task.list` sistem ucunu ({ tab, applicationSlug }) microservice adımıyla çağırır ve Steps.<adım>.data'yı rows'a yazar; sekme sayacı dizinin uzunluğudur (sistem ucu totalData döndürmez). Komponent uç çağırmaz.",
2597
+ "tabChange setter'dır: activeTab self'e yazılır; akış event.data.tab ile yeni sekmeyi okur ve rows'u tazeler. Seçim sekme değişince sıfırlanır.",
2598
+ "SLA çipi dueAt varsa çizilir: createdAt→dueAt penceresinin %50'sine kadar yeşil, %90'a kadar sarı, sonrası kırmızı; süre geçince metin 'Süresi geçti' olur. createdAt yoksa yalnız geçti/geçmedi ayrımı yapılır.",
2599
+ "Üstlen düğmesi ve toplu seçim YALNIZ group sekmesinde, isClaimable !== false ve state open olan satırlarda görünür; claim yükünde version gider — akış process.task.claim { id, version } çağırır, 409'da (TaskAlreadyClaimed) rows'u tazeler.",
2600
+ "claim/bulkClaim/taskClick yükü BİLİNÇLİ olarak yalnız params ile gider (self'e yazılmaz): akışta event.data.taskId / .row / .taskIds ile okunur.",
2601
+ "Satırlarda sekme (tab) alanı varsa yalnız aktif sekmenin satırları gösterilir; yoksa bütün rows aktif sekmeye ait sayılır. pageSize ilk N satırı keser (sayfalama yok).",
2602
+ "Sekme başlıkları tabs boşsa uygulama dilinden gelir; tabs doluysa id/label/count aynen kullanılır (sayaçlar akışın işidir, canlı soket sayacı b-24 ile gelir).",
2603
+ "planned sekmesi plannedStart'ı gelmemiş görevleri listeler; satır state planned iken 'Başlangıç: 3 gün sonra' yazar (açılmış görevde plannedStartAt kalsa da yazı çıkmaz). Planlı görev üstlenilemez/tamamlanamaz, eylem listesi boştur; tarihi gelince platform açar.",
2604
+ "scope realm iken satırda applicationName rozeti çizilir (üç uygulamanın görevleri tek listede); akış process.task.list { tab, scope: 'realm' } okur. 'app' kapsamı platformda 'application'dır: applicationId verilmezse akış sayfanın uygulama slug'ını applicationSlug olarak gönderir (machine.context.state.appName) ve kutu o uygulamanın görevleriyle uygulamasız (proje düzeyi) süreçlerin görevlerini gösterir. Realm kutusu yalnız okumadır; eylemler aynı process.task.* uçlarından.",
2605
+ "Sekmeler rol tablist'tir: sağ/sol ok bir sonraki/önceki sekmeyi ister (tabChange) ve odağı o sekmeye taşır; yalnız etkin sekme Tab sırasındadır.",
2606
+ "Doğal dil araması (showSearch:true): kutu 'bu ay geciken satınalmalar' gibi metni search { q } olayıyla yayar; akış process.task.list { tab, q } sonucunu rows'a yazar; sistem ucu appliedFilter DÖNDÜRMEZ — rozetler gerekiyorsa appliedFilter Page.bpm.tasks(tab, { q }) yanıtından okunur. Rozetler platformun anladığı süzgeçtir: süreç (processNames ile adı), termini geçmiş, açılış aralığı (bitiş günü dahil gösterilir), öncelik ≥ N. 'Süzgeci kaldır' clearFilter yayar ve kutuyu boşaltır; tek rozet kaldırılamaz (sunucu yalnız q kabul eder)."
2607
+ ],
2608
+ propNotes: {
2609
+ rows: "[{ id, title, processName, subjectLabel, subjectHref, from, createdAt, dueAt, state, nextStep, isClaimable, version, applicationName?, plannedStartAt?, tab? }] — bpm/tasks satırının düzleştirilmiş hâli (applicationName ← applicationName, plannedStartAt ← plannedStartAt); version claim için gerekir.",
2610
+ activeTab: "mine | group | delegated | started | done | planned; tabChange'in setter hedefi.",
2611
+ tabs: '[{ id, label, count }] — boşsa altı varsayılan sekme uygulama dilinde çizilir.',
2612
+ scope: "app | realm — tabChange yüküyle akışa geçer; realm'de satırda uygulama rozeti çizilir.",
2613
+ timeZone: "IANA saat dilimi (ör. 'Europe/Istanbul') — süzgeç rozetlerindeki açılış aralığı bu dilimde yazılır; boşken tarayıcının dilimi kullanılır. Platform appliedFilter'ın from/to alanlarını UTC gönderir."
2614
+ }
2615
+ },
2616
+ 'task-actions': {
2617
+ summary: "İş nesnesinin açık süreç görevi için karar çubuğu: approval'da Onayla/Reddet, user-task'ta düğümün özel eylemleri ya da Tamamla, izin varsa Bilgi iste ve Yeniden ata. Görev yoksa ya da kapalıysa hiç çizilmez.",
2618
+ guide: 'bpm',
2619
+ behavior: [
2620
+ "task akıştan gelir (process.task.get { id } sonucu); state open/claimed/unassigned dışındaysa (waiting-info dahil) çubuk görünmez. kind 'provide-info' görevde yalnız Bilgi gönder çıkar.",
2621
+ "Eylem düğmesi yorum penceresini açar (showComment:true ya da eylem yorum isterse). reject, request-info, provide-info, reassign ve isCommentRequired:true eylemlerde yorum boşken Gönder kilitlidir; reassign yeni atanan kimliğini de ister.",
2622
+ "action yükü YALNIZ params ile gider: event.data = { action, taskId, version, comment?, payload?, targetUserId? }. Akış eylemi sistem ucuna yönlendirir: claim → process.task.claim, unclaim → process.task.unclaim, request-info → process.task.request-info { question: comment }, provide-info → process.task.provide-info { answer: comment }, reassign → process.task.reassign { targetUserId, reason: comment }, start-assessment → process.task.assessment.start, sign → process.task.sign, diğerleri → process.task.complete { action, payload, version, comment }.",
2623
+ "Hata gösterimi error prop'udur: akış 409/422 sonrası error'a { status, code, message } yazar; 409 ya da TaskAlreadyClaimed her zaman 'başkası üstlendi — görev yenilendi' cümlesiyle çizilir, TaskCommentRequired ve UndoWindowClosed kendi cümleleriyle.",
2624
+ "Özel eylemler actions[] ile verilir ({ id, label, completes, isCommentRequired, tone }); approval görevinde Onayla/Reddet'in ardına eklenir. actions boşken task'a bağlı get() yanıtının customActions'ı ({ id, label: { tr, en }, completes }) etiketiyle kullanılır — genel sayfada akış eşleme yazmaz.",
2625
+ "Görev formu: fields ([{ key, label, type, isRequired }]) ya da boşken get() yanıtının formFields'i (düğüm form.dtoId DTO'sunun alanları) çubuğun üstünde çizilir; tip string/textarea → metin, number/float → sayı, bool → onay kutusu, date/datetime/time → tarih. Zorunlu alan boşken karar veren düğmeler (reject, request-info, reassign, provide-info dışındakiler) kilitlidir; değerler action yükünün payload'una key adıyla (sayılar sayı olarak) girer. Görev kapalıyken form çizilmez.",
2626
+ "İmzalı adım (task.signature ya da get() yanıtındaki signature): tamamlayan eylem 'İmzala' (approval'da 'İmzala ve onayla') olur, Reddet ve completes:false özel eylemler kalır. Pencere anlamı salt okunur gösterir, parola zorunlu, e-posta oturumdaki ilk imza için; yük payload.signature = { meaning, email?, password }. Akış process.task.sign { id, meaning, password, email, fileId, comment, payload (signature dışındaki form), version } çağırır — parola parametre ifadesinde event.data.payload.signature'dan okunur, state'e yazılmaz; imzasız tamamlama 422 SignatureRequired, yanlış parola 401 ReauthenticationRequired.",
2627
+ "Çevrimdışı: bağlantı yokken offline 'disabled' adımda ve imzalı adımda düğmeler kilitlenir ve nedeni yazılır; diğer eylemler Page.bpm.task(id).complete ile kuyruğa alınır ({ queued: true }) ve Page.bpm.offline.sync() ile POST bpm/tasks/sync'e gider. pendingCount (Page.bpm.offline.count()) 'Gönderilecek: N' satırını çizer; çakışma satırları Page.bpm.offline.list() ve resolve(clientActionId, 'retry' | 'discard') ile çözülür.",
2628
+ "Yardımcı (showAssistant:true): 'Özetle' assistantSummary { taskId }, 'Sor' kutusu assistantAsk { taskId, question } yayar; akış Page.bpm.task(taskId).assistant(question?) sonucunu assistant'a yazar (istek sürerken { isLoading: true }, hata { error } — ikisi de panelde görünür). Panel 'AI önerisi' rozeti, özet/yanıt, yalnız çubuğun sunduğu önerilen eylem (düğme adıyla), gerekçe ve adımdaki önceki sonuç sayılarını çizer; KARAR DÜĞMESİ YOKTUR (K-33). 'Gerekçeyi yorum taslağına al' yalnız yorum penceresinin başlangıç metnini doldurur; kararı kullanıcı çubuktan verir.",
2629
+ "Okuma sınavı (assessment prop'u doluyken ya da get() yanıtı assessment kuralı taşırken): yalnız Bilgi iste / Yeniden ata düğmeleri kalır, okuma kanıtı eylemi geçen denemeyi bekler. Sınav YALNIZ görev eyleme açıkken çizilir (state open/claimed/unassigned); kapalı ya da bilgi bekleyen görevde sınav bölümü hiç görünmez. questions boşken 'Sınava başla' action { action: 'start-assessment', taskId } yayar — akış process.task.assessment.start { id } sonucunu assessment'e OLDUĞU GİBİ yazar: cevapsız sorular, passScore (soru sayısına kırpılmış), attempts (adımın izin verdiği hak) ve bu kullanıcının son denemesinin lastScore/isPassed'i sunucudan gelir. Sorular kart olarak çizilir (options doluysa seçenek, boşsa metin), 'Deneme N / M · geçme notu P / T' ve cevap sayacı görünür; tüm sorular cevaplanınca 'Cevapları gönder' action { action: 'submit-assessment', taskId, payload: { answers } } yayar — akış process.task.complete { action, payload } çağırır. YÜKTE version YOKTUR: sınavı açmak görevi üstlenir ve sürümü ilerletir, panelin çizildiği sürüm bayattır. Geçerse görev kapanır; kalırsa hak varsa görev açık kalır ve sonraki başlatma yeni denemeyi verir. Denemeler kullanıcı başına sayılır; sınavı yalnız görevin atandığı kişi açıp gönderebilir (başkası 403)."
2630
+ ],
2631
+ propNotes: {
2632
+ task: "process.task.get sonucu olduğu gibi ({ task, actions, signature, offline }: düğmeler sunucunun actions listesini izler) ya da görev satırı { id, kind: user-task | approval | provide-info, state, version, requestInfo, allowReassign, signature: { meaning, level, reauth }, offline: allowed | disabled }. signature.meaning yoksa diyalog anlam seçtirir; reauth:false ise parola sorulmaz.",
2633
+ pendingCount: "Çevrimdışı kuyrukta bekleyen eylem sayısı (Page.bpm.offline.count()); 0 iken satır çizilmez.",
2634
+ actions: '[{ id, label, completes, isCommentRequired, tone }] — tanımdaki actions[] ile aynı id. Boş bırakılırsa get() yanıtının customActions\'ı kullanılır.',
2635
+ fields: "[{ key, label, type: string | textarea | number | date | datetime | time | bool, isRequired }] — boşsa get() yanıtının formFields'i (DTO alanları: key = slug, label = ad).",
2636
+ error: "{ status, code, message } — akışın son eylem hatası; boşken mesaj çizilmez.",
2637
+ showAssistant: 'Yardımcı paneli; varsayılan false.',
2638
+ assistant: "{ text, suggestedAction, rationale, similarOutcomes: { sonuç: sayı }, isLoading, error } — Page.bpm.task(id).assistant(question?) yanıtı (sunucu isAiSuggestion taşır) ve akışın yükleniyor/hata bayrakları.",
2639
+ assessment: "Okuma sınavı denemesi: null ise sınav yok; {} ise 'Sınava başla'; process.task.assessment.start sonucu { id, number, passScore, questions: [{ id, text, options }], attempts, lastScore, isPassed } olduğu gibi — attempts/lastScore/isPassed SUNUCUDAN gelir, akış kendi sayacını tutmaz. Adımın sınav isteyip istemediği ayrıca get() yanıtının assessment alanıdır ({ count, passScore, attempts }); deneme açılmadan önce paneli o kural açar. Cevaplar yeni deneme id'sinde sıfırlanır."
2640
+ }
2641
+ },
2642
+ 'read-proof-matrix': {
2643
+ summary: 'Kontrollü dokümanın okuma kanıtı matrisi: okuyucu × revizyon; okudu · bekliyor · sınavı geçemedi · atlandı · geçersiz (eskiyen revizyonun okuması) · ayrıldı rozetleri süreç defterinden hesaplanır; revizyon başına sayılar ve bekleyenlere hatırlatma. Veriyi KENDİSİ çekmez.',
2644
+ guide: 'bpm',
2645
+ behavior: [
2646
+ "Veri yolu: her revizyonun dağıtım süreç örneği için akış process.instance.timeline { id: instanceId } çağırır ve revisions'a [{ label, number, state: effective | superseded | draft, instanceId, events }] setter yazar; readers'a kullanıcı listesinden [{ userId, name, isActive }].",
2647
+ "Hücre durumu defterden: task-created payload.assignee dağıtımı verir; havuz görevinde assignee boştur (yalnız candidates yazılır) ve kopyayı task-claimed olayının aktörü (actorUserId) sahiplenir; task-reassigned kopyayı payload.from'dan payload.to'ya taşır — devreden kişi o kopyadan düşer, devralan bekleyen olur. read-proof payload.userId (ya da aktör, yoksa kopyanın o anki sahibi) okumayı ve payload.at tarihini verir; outcome assessment-failed ile kapanan görev 'sınavı geçemedi', task-cancelled/task-superseded 'atlandı'; state superseded revizyondaki okuma 'geçersiz'; dağıtımda olup okumayan isActive:false kişi 'ayrıldı', diğerleri 'bekliyor'; dağıtımda olmayan 'dağıtımda değil'.",
2648
+ "Satır sırası readers listesidir; defterde görünüp listede olmayanlar kimlikleriyle sona (alfabetik) eklenir. Sütun başlığı revizyon etiketi, durum rozeti ve 'X okudu · Y bekliyor · Z geçersiz' özetidir.",
2649
+ "showRemind:true ve bekleyen okuyucu varken sütunda 'Okumayanlara hatırlat (N)' düğmesi remind yayar: event.data = { revision, instanceId, userIds }; akış bildirim gönderir. Ayrılanlar userIds'e girmez.",
2650
+ "revisions ya da okuyucu yoksa emptyText (varsayılan 'Okuma kaydı yok'); isLoading iken 'Yükleniyor…' role=status."
2651
+ ],
2652
+ propNotes: {
2653
+ revisions: "[{ label, number, state, instanceId, events: [{ kind, taskId, actorUserId, payload, occurredAt }] }] — events process.instance.timeline yanıtının events'i olduğu gibi.",
2654
+ readers: '[{ userId, name, isActive }] — isActive:false okumayanı ayrıldı sayar.',
2655
+ showRemind: 'Hatırlat düğmesi; varsayılan true.'
2656
+ }
2657
+ },
2658
+ 'process-timeline': {
2659
+ summary: 'Süreç örneğinin defteri (kim, ne, hangi karar, yorum) ardından sıradaki ve gelecek adımlar; bölge yeniden başlatma turları ve geçersizleşen görevler işaretli.',
2660
+ guide: 'bpm',
2661
+ behavior: [
2662
+ "Veri process.instance.timeline { id } yanıtından bağlanır: rows ← events, currentNodes ← currentNodes, nextNodes ← nextNodes. Defter satırı adımı sunucunun eklediği nodeName ile (düz metin) gösterir, adı olmayan adımda nodeId kalır. actorName akışta kullanıcı adıyla (process.user.list) doldurulmazsa actorUserId gösterilir.",
2663
+ 'Olaylar sequence sırasıyla çizilir; region-restarted her görüldüğünde yeni tur başlar ve "N. tur" ayırıcısı basılır.',
2664
+ 'task-superseded olan görevin bütün satırları üstü çizili "Geçersizleşti" etiketiyle çizilir; showSuperseded:false iken listeden çıkar.',
2665
+ 'currentNodes "Sırada", nextNodes "Gelecek adım" rozetiyle çizilir; sıradaki bir adım gelecekler arasında tekrar edilmez. showFuture:false gelecek adımları gizler.',
2666
+ 'clickItem yükü yalnız params ile gider: event.data = { currentItem, index }.',
2667
+ "showVerify:true 'Hash doğrula' düğmesini çizer ve verifyLedger olayını yayar; akış process.instance.ledger.verify { id } sonucunun isValid'ini ledgerStatus ('valid' | 'broken'), brokenAtSequence'ini brokenAtSequence'e yazar, rozet 'Defter geçerli' ya da 'Defter N. satırda bozuk' olur. showExport:true 'Defteri indir (CSV)' düğmesiyle exportLedger yayar; akış Page.bpm.instance(id).exportLedger() sonucunu ({ fileName, contentType, text (BOM'lu), dataUrl }) dataUrl ile dosyaya kaydeder. Komponent uç çağırmaz."
2668
+ ],
2669
+ propNotes: {
2670
+ ledgerStatus: "'' (denetlenmedi, rozet yok) | 'valid' | 'broken' — verifyLedger akışının yazdığı sonuç.",
2671
+ brokenAtSequence: "number | null — ledgerStatus 'broken' iken ilk bozuk satırın sequence'i.",
2672
+ rows: '[{ sequence, kind, nodeId, nodeName, taskId, actorName, occurredAt, payload: { outcome, comment, body } }] — bpm/instances/{id}/timeline events dizisi; nodeName düz metin (eski kayıtlardan çok dilli sözlük de gelebilir; komponent ikisini de okur). comment-added satırının metni yanıtın comments dizisindedir: akış payload.commentId ile eşleyip payload.body olarak ekler (okunamayan iç yorum comments içinde gelmez).',
2673
+ users: '[{ id, name }] — yorum metnindeki @<kullanıcı id> bahsetmelerini adla gösterir; boşsa id kalır.',
2674
+ currentNodes: "[{ id, name }] — name çok dilli sözlük ({ tr, en }) ya da düz metin olabilir.",
2675
+ nextNodes: "[{ id, name, adaptationLabel }] — adaptationLabel uyarlamanın eklediği/değiştirdiği adımı işaretler."
2676
+ }
2677
+ },
2678
+ 'process-monitor': {
2679
+ summary: 'Süreç izleme panosu: açık · SLA geçen · hatalı · sahipsiz · askıda · son 30 günde kapanan sayaçları, örnek tablosu, hatalı satırda Yeniden dene/Adımı atla, sahipsiz satırda Ata, seçili örneklerde toplu yeniden ata · termin uzat · askıya al · adıma atla · iptal ve son toplu işlem için Geri al. Veriyi KENDİSİ çekmez.',
2680
+ guide: 'bpm',
2681
+ behavior: [
2682
+ "Veri yolu: mount/filter akışı process.instance.list (query alanları) ile örnekleri okuyup rows'a setter yazar. bpm/instances özet satırı id, definitionId, definitionSlug, state, subjectRowId, initiatorUserId, priority, startedAt, completedAt, outcome, slaDueAt yanında definitionName (düz metin) ve currentNodes ([{ id, name }] — bekleyen adımlar, düz metin adıyla çizilir) taşır. tokens, lastError, versionNumber/overrideId akışta process.instance.get { id } ile, assigneeName/unitId kendi okumalarıyla, openTaskIds/unassignedTaskIds process.task.list { tab: 'all' } ile eklenir. tokens eklenmezse atla/adıma atla yükünde nodeId/fromNodeIds olmaz. Komponent uç çağırmaz.",
2683
+ "Sayaç kutuları tıklanınca filter'a yazar ve filter olayını yayar; tablo kutunun saydığı satırları gösterir (Açık: yalnız açıklar, Kapanan 30g: son 30 günde kapananlar — scope). Kutuların altındaki süzgeç çubuğu durum, süreç, birim (satırlarda varsa), öncelik ve yalnız gecikenleri yazar. Yükteki query yalnız sunucu alanlarını (definitionId, applicationId, state, subjectRowId, initiatorUserId) taşır; unitId, priority, slaBreached, unassigned ve scope sayfada süzülür.",
2684
+ "SLA durumu slaDueAt'ten hesaplanır: açık örnekte termin geçtiyse 'SLA geçti', değilse 'Süresinde'; kapalı örnekte ve terminsiz örnekte gösterilmez.",
2685
+ "Satır eylemleri: state faulted → Yeniden dene + Adımı atla; açık ve unassignedTaskIds dolu → Ata. Adımı atla, askıya al, adıma atla ve iptal gerekçesiz gönderilemez; yeniden ata ve ata hedef kullanıcı, termin uzat yeni tarih, adıma atla hedef adım ister.",
2686
+ "Toplu eylem yalnız uygun durumdaki seçili örneklere gider: yeniden ata/termin uzat açık görevi olan açık örnekler (taskIds dolar), askıya al yalnız running (sunucu başkasını askıya almaz), adıma atla running/faulted, iptal bütün açık örnekler. Uygun örnek yoksa düğme kilitlidir.",
2687
+ "Geri al bandı lastBatchOperation kind reassign ya da extend-due, state completed ve undoneAt boşken çizilir; undo olayı batchOperationId taşır, akış process.batch.undo { id } çağırır.",
2688
+ "instanceAction/bulkAction/undo/clickItem/filter yükleri YALNIZ params ile gider (self'e yazılmaz; filter prop'u komponent içinde de güncellenir)."
2689
+ ],
2690
+ propNotes: {
2691
+ rows: "[{ id, definitionSlug, definitionName, currentNodes, state, priority, startedAt, completedAt, slaDueAt } (bpm/instances özet satırı) + akışın eklediği { definitionName, versionNumber, overrideId, lastError, tokens:[{ nodeId, state }] (instance(id).get()), unitId, assigneeName, openTaskIds, unassignedTaskIds }].",
2692
+ filter: "{ definitionId, applicationId, state (all | running | suspended | faulted | completed), subjectRowId, initiatorUserId, unitId, priority, slaBreached, unassigned }. Sayaç kutusu durumu ve slaBreached/unassigned anahtarlarını birlikte yazar; süreç, birim ve öncelik korunur.",
2693
+ lastBatchOperation: "{ id, kind, state, undoneAt } — akışın son toplu işlem yanıtı (process.batch.execute ya da process.batch.undo sonucu).",
2694
+ allowBulk: "false iken seçim kutuları ve toplu çubuk çizilmez; satır eylemleri kalır.",
2695
+ holds: "[{ scope: process | instance | user, scopeKey, isActive }] — Page.bpm.legalHolds() sonucu; etkin örnek (kimlik) ya da süreç (definitionSlug) bekletmesi satıra 'Yasal bekletmede' rozeti koyar. Kişi bekletmesi satırda işaretlenmez (katılımcılar satırda yok).",
2696
+ predictedRemaining: "[{ instanceId, remainingHours, sampleSize }] — Page.bpm.analytics(slug, 'prediction', { from, to }).prediction; açık örnekte sampleSize > 0 ve remainingHours doluysa satıra '~N sa kaldı' rozeti (tam saate yuvarlanır; 0 — süre aşılmış tahmin — '1 saatten az kaldı'). Kapanmış örnekte ve örneksiz tahminde rozet yok. Tahmin süreç başınadır: akış panodaki her süreç için ayrı çağırır; tahmin görünümü pencereden önce başlayıp hâlâ açık olan örnekleri de kapsar."
2697
+ }
2698
+ },
2699
+ 'process-variants': {
2700
+ summary: 'Süreç madenciliği varyant listesi: yol (adım zinciri), örnek sayısı ve payı (en sık varyanta göre çubuk), ortalama çevrim saati; seçili varyant vurgulu; tanım dışı geçişler (adıma atlama, adım atlama, sürüme taşıma) listesi ve XES / OCEL indir düğmeleri. Veriyi KENDİSİ çekmez.',
2701
+ guide: 'bpm',
2702
+ behavior: [
2703
+ "Veri yolu: mount akışı Page.bpm.analytics(slug, 'variants', { from, to }).variants sonucunu variants'a, Page.bpm.analytics(slug, 'conformance', …).conformance sonucunu conformance'a setter yazar. Heatmap bu komponentte değil: Page.bpm.analytics(slug, 'heatmap', …).chart.heatmapSeries / visitSeries chart rows'una bağlanır (yanıtın view alanı görünüm adıdır).",
2704
+ "Varyant satırı path dizisini (ya da tasarımcı örneğinde 'a, b, c' / 'a → b' metnini) okur; boş yol çizilmez. Çubuk genişliği payın en sık varyanta oranıdır (en sık 100%).",
2705
+ "Satıra tıklamak value'yu yolun '>' ile birleşmiş anahtarına yazar (setter) ve select olayını yayar; aynı anahtar kayıtlı sayfada vurguyu geri getirir.",
2706
+ "Sapma satırları zaman sırasıyla (metin değil zaman karşılaştırılır, eşitlikte sunucu sırası); instance-jumped 'kontrol → onay' biçiminde hedefi gösterir. Örnek kimliği düğmesi clickInstance yayar.",
2707
+ "download olayı yalnız { format: xes | ocel } taşır; akış Page.bpm.exportLog(slug, format, { from, to }) ile { fileName, contentType, text, dataUrl } alır ve dataUrl'den kaydeder. showDownload false iken düğmeler çizilmez."
2708
+ ],
2709
+ propNotes: {
2710
+ value: "string — seçili varyantın anahtarı: düğüm kimlikleri '>' ile birleşik (ör. 'baslangic>kontrol>bitis').",
2711
+ variants: "[{ path: string[], instanceCount, sharePercent, averageCycleHours, sampleInstanceIds }] — bpm/analytics/{slug}/variants yanıtının variants listesi olduğu gibi.",
2712
+ conformance: "[{ instanceId, kind: instance-jumped | node-skipped | instance-migrated, nodeId, targetNodeId, actorUserId, reason, occurredAt }] — bpm/analytics/{slug}/conformance yanıtının conformance listesi.",
2713
+ showDownload: "XES indir / OCEL indir düğmeleri; varsayılan true."
2714
+ }
2715
+ },
2716
+ 'case-view': {
2717
+ summary: 'Çalışan vaka (CMMN) görünümü: kök aşama şeridi (bekleyen aşama kesik çizgili, sürenin vurgulu), sunucunun şu an izin verdiği eylemler (isteğe bağlı öğe ekleme, öğe başlatma / tamamlama / devre dışı bırakma), açık plan öğeleri ve görevleri, kilometre taşları, vaka dosyası ve vaka defteri. Veriyi KENDİSİ çekmez.',
2718
+ guide: 'bpm',
2719
+ behavior: [
2720
+ "Veri yolu: mount akışı Page.bpm.cases.get(caseInstanceId) çağırır ve yanıtın view alanını (state, planItems, availableActions, caseFile, events) aynı adlı prop'lara setter yazar; view adları vaka tanımından doldurur, tanım okunamazsa öğe kimliği görünür.",
2721
+ "Aşama şeridi yalnız kök aşamaları TANIMIN plan sırasıyla ve her aşamanın son tekrarıyla çizer: sıra planItems satırlarındaki index alanıdır (Page.bpm.cases.get view'i tanımdan doldurur), motorun öğeleri açtığı sıra değil; tanımda artık olmayan aşama (index null) sona gider. available (giriş koşulu bekleyen) aşama kesik çizgili ve pasiftir, active olan aria-current=step taşır, completed üstü çizili.",
2722
+ "Eylem düğmeleri yalnız availableActions satırlarıdır (sunucu hesaplar): discretionary 'Eylem ekle' altında, start / complete / disable / enable 'Eylemler' altında. Bilinmeyen eylem ya da plan öğesi kimliği olmayan öğe eylemi çizilmez. 'Kapanış'ı enable etmek sentry sağlanmadan 422 CaseSentryNotSatisfied döner; sunucu enable'ı zaten listelemez.",
2723
+ "action olayı { action, itemId, planItemId } taşır; akış Page.bpm.cases.act(caseInstanceId, event.data) ile güncel örneği alır ve view'i yeniden setter yazar. Açık öğenin görevi varsa 'Görevi aç' clickTask { taskId, planItemId, itemId } yayar; görev task-inbox / task-actions ile aynı görevdir (kind case-task).",
2724
+ "caseFile nesne ({ alan: değer }) ya da [{ id, value }] satırları olabilir; metin olmayan değer JSON olarak yazılır. showTimeline false iken defter çizilmez."
2725
+ ],
2726
+ propNotes: {
2727
+ state: 'active | completed | terminated — vaka durumu rozeti.',
2728
+ planItems: "[{ id, itemId, name, type: stage | human-task | milestone, parentId, state: available | enabled | active | completed | terminated | disabled, taskId, occurrence, endedAt, index }] — bpm/case-instances/{id} planItems'ı; name metin ya da { tr, en } olabilir. index tanımın plan sırasıdır ve view ile gelir (tanımda olmayan öğede null); şerit onu izler.",
2729
+ availableActions: "[{ action: discretionary | start | complete | disable | enable, itemId, planItemId, name }] — sunucunun availableActions listesi; discretionary satırında planItemId yok.",
2730
+ caseFile: "{ alan: değer } ya da [{ id, value }] — vaka dosyası.",
2731
+ events: "[{ sequence, kind, itemId, actorUserId, occurredAt }] — case_instance_events defteri; kind case-started | plan-item-* | milestone-reached | discretionary-added | case-file-updated | case-completed.",
2732
+ showTimeline: 'Defter bölümü; varsayılan true.'
2733
+ }
2734
+ },
2735
+ 'delegation-editor': {
2736
+ summary: 'Vekalet editörü: kendim ya da astım adına vekil, tarih aralığı ve isteğe bağlı süreç filtresiyle vekalet verir; etkin · başlayacak · biten vekaletleri kaynak rozetiyle (manuel · izin süreci · yönetici) listeler ve sonlandırır. Veriyi KENDİSİ çekmez.',
2737
+ guide: 'bpm',
2738
+ behavior: [
2739
+ "Veri yolu: mount akışı process.delegation.list { userId? } ile delegations'a, kullanıcı listesiyle users'a, süreç listesiyle processes'e setter yazar. subordinateUserIds doluysa 'Kimin adına' seçicisi çıkar (akış closure alt ağacından doldurur).",
2740
+ "save yükü: { fromUserId? (yalnız başkası adına), toUserId, startsAt (ISO), endsAt? (ISO), processSlugs (boş = tüm süreçler), reason? }; akış process.delegation.create (event.data alanları; boş processSlugs gönderilmez) çağırır, 409 DelegationOverlap / 422 DelegationChainNotAllowed mesajını error prop'una yazar.",
2741
+ "İstemci doğrulaması sunucu kuralını izler: vekil zorunlu, kişi kendine vekalet veremez, başlangıç zorunlu, bitiş başlangıçtan sonra; bunlar geçerliyse aynı kişi için kesişen aralık ve kesişen süreç (boş liste = hepsi) çakışma sayılır. Hatalar ilk Kaydet denemesinden sonra görünür.",
2742
+ "Satır sırası: etkin, başlayacak (başlangıca göre), biten (en yeni önce). Biten satırda Sonlandır yoktur; end yükü { delegationId } → process.delegation.end { id }.",
2743
+ "'Vekil yönetim yetkilerini devralmaz; başlatanın vekili o talebi onaylayamaz' notu her zaman görünür."
2744
+ ],
2745
+ propNotes: {
2746
+ delegations: "[{ id, fromUserId, toUserId, startsAt, endsAt, processSlugs, source (manual | leave-process | manager), reason, endedAt }] — bpm/delegations yanıtı olduğu gibi.",
2747
+ users: "[{ id, name }] — vekil seçici ve satır adları; bulunmayan kimlik olduğu gibi yazılır.",
2748
+ subordinateUserIds: "string[] — yöneticinin adına vekalet verebileceği astlar; boşsa yalnız 'kendim'.",
2749
+ processes: "[{ slug, name }] — süreç filtresi onay kutuları; boşsa filtre çizilmez (vekalet tüm süreçleri kapsar).",
2750
+ error: "{ status, code, message } — akışın son kayıt hatası."
2751
+ }
2752
+ },
2753
+ 'handover-wizard': {
2754
+ summary: 'Devir sihirbazı (3 adım): açık görev grupları ve grup başına hedef (üst yönetici · kişi · gruba geri bırak · yönetici kuyruğu) → başlattığı süreçler, yönettiği birimler, tuttuğu pozisyonlar, vekaletler → onay (zorla devret, devret ve pasifleştir). Veriyi KENDİSİ çekmez.',
2755
+ guide: 'bpm',
2756
+ behavior: [
2757
+ "Veri yolu: mount akışı process.handover.preview { userId } yanıtını preview'a yazar. preview değişince kararlar önerilen hedeften yeniden kurulur ve sihirbaz ilk adıma döner.",
2758
+ "Varsayılan hedef: suggestedTarget seçeneklerde varsa o; yoksa aday görevde group, atanmış görevde managerUserId varsa manager, yoksa admin-queue. Atanmış görevde manager seçeneği yalnız managerUserId doluyken çıkar; group yalnız aday görevlerde.",
2759
+ "Hedef 'user' seçilen grupta kişi seçilmeden İleri/Devret kilitlidir (zorla modda da). Zorla devret işaretliyken karar verilmeyen atanmış görev grupları sunucuda üst yöneticiye (yoksa yönetici kuyruğuna), aday görev grupları gruba gider (kişi adaylıktan çıkar; aday kalmazsa yönetici kuyruğu).",
2760
+ "apply yükü: { userId, decisions: [{ kind, key, target, targetUserId? (yalnız user) }], force, deactivate }; akış process.handover.apply { userId, decisions, force } çağırır. deactivate:true 'Devret ve pasifleştir' düğmesidir — platformda uygulama kullanıcısı pasifleştirme ucu henüz yok, akış bu bayrağı kendi adımına bağlar.",
2761
+ "stepChange yükü { step: tasks | ownership | confirm, index }. Adım başlıkları aria-current='step' taşır. İkinci adım bilgi amaçlıdır: başlattığı süreçler açık kalır, birim/pozisyon organizasyon ekranından atanır, vekaletler devirle sonlanır."
2762
+ ],
2763
+ propNotes: {
2764
+ preview: "{ userId, managerUserId, items: [{ kind (assigned-tasks | candidate-tasks | started-instances | managed-units | held-positions | delegations), key (süreç slug'ı, birim/pozisyon kodu ya da *), count, suggestedTarget }] } — bpm/handovers/preview/{userId} yanıtı.",
2765
+ users: "[{ id, name }] — 'kişi' hedefi seçicisi; devredilen kullanıcı listeden çıkarılır.",
2766
+ lastHandover: "{ id, completedAt } — dolu olduğunda 'Devir tamamlandı' bandı çizilir.",
2767
+ allowDeactivate: "true iken son adımda 'Devret ve pasifleştir' düğmesi çıkar."
2768
+ }
2769
+ },
2770
+ 'notification-center': {
2771
+ summary: 'Süreç bildirim merkezi: bildirim listesi (okunmamış kalın, okundu onayı gerekenler rozetli), okundu say · okudum · tümünü okundu say, bağlantıya git ve gönderim tercihleri (anında · günlük özet · yalnız SLA, sessiz saatler, saat dilimi). Veriyi KENDİSİ çekmez.',
2772
+ guide: 'bpm',
2773
+ behavior: [
2774
+ "Veri yolu: mount akışı process.notification.list sonucunu notifications'a, process.notification-preference.get sonucunu preference'a yazar. Liste en yeni önce sıralanır.",
2775
+ "Sayaç: okunmamışlar + okunmuş ama onay (ack) bekleyenler. Okundu onayı gereken satırda yalnız 'Okudum' (ack) düğmesi, okunmamış sıradan satırda 'Okundu say' (read) düğmesi çıkar.",
2776
+ "open yükü { notificationId, link?, taskId?, instanceId?, markRead }: markRead okunmamış satırda true'dur; akış gerekirse process.notification.read { id } çağırıp bağlantıya gider. read/ack yükü { notificationId }, markAllRead yükü { notificationIds } (yalnız okunmamışlar).",
2777
+ "Tercih formu preference'tan kurulur (HH:mm:ss → HH:mm); savePreference yükü sunucu biçimindedir: { mode, digestAt 'HH:mm:00', quietFrom/quietTo 'HH:mm:00' ya da sessiz saat kapalıyken null, timeZone }. Saat dilimi boşken, sessiz saatin bir ucu eksikken ya da saat SS:DD değilken Kaydet kilitlidir.",
2778
+ "Kanal seçimi ve üst çubuk soket rozeti bu bileşende yok: backend tercihinde kanal alanı yok; canlı sayaç için akış process-notifications hub'ına abone olmalı (runtime aboneliği henüz yok)."
2779
+ ],
2780
+ propNotes: {
2781
+ notifications: "[{ id, title, body, link, category (task | sla | watch | mention …), taskId, instanceId, ackRequired, readAt, acknowledgedAt, createdAt }] — bpm/notifications data dizisi.",
2782
+ preference: "{ mode (immediate | digest | sla-only), digestAt, quietFrom, quietTo, timeZone } — bpm/notification-preferences yanıtı.",
2783
+ defaultTimeZone: "preference.timeZone boşken forma yazılan saat dilimi (IANA ya da sunucunun tanıdığı kimlik).",
2784
+ showPreferences: "false iken Tercihler düğmesi ve formu çizilmez."
2785
+ }
2786
+ },
2787
+ 'approval-chain-editor': {
2788
+ summary: "Onay zinciri editörü (uygulama yöneticisi uyarlaması): Üstte sürüm · uyarlama (rev) · açık örnek çipleri; 'Onay zinciri' sekmesinde zaman çizelgesi: başlangıç olayı, bölgeden önceki tekil yol, 'Uyarlamaya açık bölge' kutusu (sayaç, adım kartları), bölgeden sonra ilk dallanmaya kadar kilitli adımlar (gri, kilit ikonlu) ve bitiş. Kartta ad + 'Kısmen açık'/'Eklendi' rozeti, kişi · politika · süre özeti, ↑ ↓ sıralama ve eklenen adımda × kaldır; adıma basınca host drawer'ın üstünde overlay'li ikinci drawer (medium) açılır: kim onaylar · referans kişi · politika · SLA · hatırlatma · aşılınca · kendi talebini onaylama (butonsuz, × ya da overlay ile kapanır). Tür başına '<tür> adımı ekle'; uyarlama varken açık örnek bandı; 'Simülasyon' sekmesinde kuralları simüle et ve sonuç kartı; alt çubukta varsayılana dön (yalnız kayıtlı uyarlama varken) · kaydedilmemiş değişiklik göstergesi · kaydet. Veriyi KENDİSİ çekmez.",
2789
+ guide: 'bpm',
2790
+ behavior: [
2791
+ "Veri yolu: mount akışı process.override.get { id: definitionId } yanıtını view'e yazar (baseModel = aktif sürüm, effectiveModel = uyarlama uygulanmış, editableScopes, override.patch/conflictState). Rol/pozisyon/birim/kullanıcı listeleri roles · positions · units · users prop'larına; açık örnek sayısı openInstanceCount'a.",
2792
+ "Zincir yalnız editable: open bölgeden kurulur (regionId boşsa ilk açık bölge). Kenarları sıralı zincir olmayan bölgede ekleme ve sıralama kapanır. Kural seçicisi bölgenin limits.assigneeRules kümesinden, adım türü limits.nodeTypes kümesinden gelir; limits.maxSteps dolunca ekleme kilitlenir.",
2793
+ "save yükü { definitionId, baseVersion, overrideRevision, patch }: patch aktif sürüme karşı TAM uyarlamadır — bu bölgenin işlemleri yeniden kurulur (değişen alanlar add/replace/remove, eklenen adım 'nodes/-', sıra değişince bölgenin edges'i replace); kayıtlı uyarlamanın bölge dışındaki ve editörün düzenlemediği alanlara ait işlemleri korunur (uyarlama çatışmalıysa ya da başka sürüme yazılmışsa korunmaz). Akış process.override.save { id: definitionId, baseVersion, overrideRevision, patch } çağırır, ardından process.override.get ile view'i tazeler. İstemci doğrulaması (ad, kim onaylar, izinli kural, ISO SLA, adım sınırı) geçmeden yayılmaz.",
2794
+ "simulate yükü { definitionId, subjectRowId?, overridePatch } — kaydedilmemiş uyarlamayla kuru koşu: process.override.simulate { id, subjectRowId, overridePatch } sonucunu simulation'a yazın; satırlar 'adım · kişiler · vekil' olarak çizilir.",
2795
+ "reset ve migrateOpen yükü { definitionId } → process.override.reset / process.override.migrate-open { id }. Kayıtlı uyarlama varken ve openInstanceCount > 0 iken zincir sekmesinde 'N açık örnek hâlâ eski zincirle ilerliyor' bandı çıkar; 'Yeni zincire taşı' düğmesi (migrateOpen) yalnız showFooter iken bandın içindedir; view.isReadOnly (Studio görünümü) iken alt düğmeler ve düzenleme kapalıdır.",
2796
+ "422 satırları insan diline çevrilir: error prop'una sistem ucunun hata kaydından kurulan nesne ({ status, code, message, data, errors } — Steps.<adım>.error doluyken gövde .data'dadır) ya da mapBpmError sonucu yazılır ({ errors: [{ code, path, message }] } ya da { data: { errors } }); RuleNotAllowed 'Sabit kişi kuralı bu süreçte izinli değil. İzinli kurallar: …', RegionLocked, ParamNotEditable, MaxStepsExceeded, NodeTypeNotAllowed. Diğer hatalarda error.message, yoksa ham reddin reason'ı ya da data.message'ı yazılır (409 bayat sürüm/revizyon, 403); akış get() ile yeniden okumalı. conflictState conflicted iken çatışma bandı ve conflictDetail çizilir."
2797
+ ],
2798
+ propNotes: {
2799
+ view: "bpm/definitions/{id}/override yanıtı: { definitionId, slug, activeVersionNumber, overrideRevision, isReadOnly, override { revision, patch, conflictState, conflictDetail }, baseModel, effectiveModel, editableScopes [{ nodeId, parentRegionId, degree, editableParams, limits }] }.",
2800
+ regionId: 'Düzenlenecek açık bölgenin id\'si; boşsa ilk açık bölge (birden çok bölgede seçici çıkar).',
2801
+ roles: "[{ slug, name }] — role:<slug> kuralının değer seçicisi.",
2802
+ positions: "[{ code, name }] — position:<kod> kuralının değer seçicisi.",
2803
+ units: "[{ code, name }] — unit-members:<kod> ve ancestor-manager:<tip> değer seçicisi.",
2804
+ users: "[{ id, name }] — user:<id> değer seçicisi.",
2805
+ simulation: "{ steps: [{ nodeId, name, assignees [{ userId, name }], candidates, source (delegation → 'vekil'), note }] } — simulate sonucu.",
2806
+ openInstanceCount: "Uyarlamaya taşınabilecek açık örnek sayısı; üstteki çipte ve taşı bandında görünür, 0 iken ikisi de yok.",
2807
+ showFooter: "false iken alt çubuk (varsayılana dön · kaydedilmemiş göstergesi · kaydet) ve bandın taşı düğmesi çizilmez, kaydedilmemiş göstergesi üst çip satırına geçer; düğmeleri çevreleyen drawer/modal'ın actions'ı verir. Kaydet = drawer aksiyonu { type: 'submit', formId: <bu bileşenin elementId'si> } — editör gizli bir <form id=elementId> taşır, submit kendi doğrulamasıyla save olayını yayar. Varsayılana dön / taşı aksiyonları reset / migrate-open akışını definitionId'yi sayfa durumundan alarak doğrudan çağırır.",
2808
+ error: "Akışın son kayıt/simülasyon hatası: mapBpmError sonucu { status, code, message, errors? } ya da sistem ucunun hata kaydından kurulan { status, code, message, reason, data, errors } (eski Page.bpm reddi { code, reason, data } de okunur)."
2809
+ }
2494
2810
  }
2495
2811
  };
2496
2812
  /**
@@ -2509,6 +2825,24 @@ export const componentKnowledge = {
2509
2825
  * `ComponentHeightType` · `ComponentAlignType`) — platformun kabul ettiği kümenin tek tanımı
2510
2826
  * orasıdır ve backend artık tanımadığı jetonu 400 ile reddeder.
2511
2827
  */
2828
+ /**
2829
+ * SATIR İÇİ stil alanları — `style` prop'unun KEBAB-CASE isteyen dalları (TB-129 · S2-39).
2830
+ *
2831
+ * Kural tek komponente özgü değil bir YAZIM SÖZLEŞMESİDİR: `style.root` emotion `css()` bloğudur ve
2832
+ * camelCase okur, `style.thead|th|tr|td` ise satır içi `style` attribute'una basılır
2833
+ * (`column-view.ts` `toStyleString` anahtarı OLDUĞU GİBİ yazar) — orada `fontSize` sessizce düşer,
2834
+ * `font-size` çalışır. Gateway'in F-06 çevirisi bu dalları da camelCase yapıp stili öldürüyordu
2835
+ * (ölçüm: otomotiv liste tablosu, 2026-09-20); artık bu sözlükteki alanların ALTINA hiç dokunulmaz.
2836
+ *
2837
+ * Sözlüğe yeni satır eklerken ölçüt: alanın değeri DOM'un `style` attribute'una string olarak mı
2838
+ * yazılıyor? Öyleyse buraya girer; emotion bloğuysa girmez.
2839
+ */
2840
+ export const INLINE_STYLE_FIELDS_BY_TYPE = {
2841
+ table: ['thead', 'th', 'tr', 'td']
2842
+ };
2843
+ export function inlineStyleFields(componentType) {
2844
+ return componentType === undefined ? undefined : INLINE_STYLE_FIELDS_BY_TYPE[componentType];
2845
+ }
2512
2846
  export const APPEARANCE_TOKEN_SETS = {
2513
2847
  paddingType: {
2514
2848
  values: ['none', 'normal', 'custom'],
@@ -2608,3 +2942,140 @@ export const knowledgeNote = 'knowledge alanı elle doğrulanmış davranış bi
2608
2942
  export function knowledgeFor(slug) {
2609
2943
  return slug ? componentKnowledge[slug] : undefined;
2610
2944
  }
2945
+ /* ─────────────────────────── TB-123 · katalog doğrulaması ─────────────────────────── */
2946
+ /**
2947
+ * ENUM TİPLERİ — seçenek listesi gerçekten bir DEĞER KÜMESİ olan prop tipleri.
2948
+ *
2949
+ * Ölçüm (2026-09-20, 101 komponentlik uygulama sözlüğü): `dropdown` (180/180), `radio` (85/85) ve
2950
+ * `switcher` (78/78) prop'larının HEPSİ seçenek taşır ve seçeneklerin hepsi string'dir. `number`
2951
+ * tipinde ise `options` bir ENUM DEĞİL sınır çiftidir (`opacity` → [0, 100], `transitionMs` →
2952
+ * [0, 1000]) ve `component` tipinde izinli komponent tipi filtresidir — ikisi de denetlenmez.
2953
+ * `multiselect` kapalı bir küme taşır ama değeri dizidir; bilerek dışarıda bırakıldı (gateway'in
2954
+ * eksik denetimi platformun kendi duvarına düşer, fazla denetimi geçerli yazmayı bloklardı).
2955
+ */
2956
+ const ENUM_PROP_TYPES = new Set(['dropdown', 'radio', 'switcher']);
2957
+ /**
2958
+ * Platformun komponent sözlüğünü (`GET /components/{app}`) doğrulama kurallarına indirger:
2959
+ * tip → (prop adı → enum değerleri | undefined). YALNIZ ÜST DÜZEY prop'lar girer; platformun
2960
+ * duvarı da yalnız onları denetliyor (ölçüm: `surfaceStyle.contentOverflow: 'clip'` geçti).
2961
+ */
2962
+ export function catalogTypeRules(components) {
2963
+ const rules = new Map();
2964
+ for (const component of components) {
2965
+ const slug = typeof component.slug === 'string' ? component.slug : undefined;
2966
+ const declared = component.definition?.props;
2967
+ if (slug === undefined || !Array.isArray(declared))
2968
+ continue;
2969
+ const props = new Map();
2970
+ for (const entry of declared) {
2971
+ const name = typeof entry?.name === 'string' ? entry.name : undefined;
2972
+ if (name === undefined || name === '')
2973
+ continue;
2974
+ const options = ENUM_PROP_TYPES.has(String(entry.type ?? '')) && Array.isArray(entry.options)
2975
+ ? entry.options.map(option => option?.value).filter((value) => typeof value === 'string')
2976
+ : undefined;
2977
+ props.set(name, options !== undefined && options.length > 0 ? options : undefined);
2978
+ }
2979
+ if (props.size > 0)
2980
+ rules.set(slug, { props });
2981
+ }
2982
+ return rules;
2983
+ }
2984
+ /**
2985
+ * Prop değerinin DENETLENEBİLİR hâli. Şemada prop'lar `{ type, ref, data }` sarmalında yaşar;
2986
+ * `static` sarmalın taşıdığı değer denetlenir, `code`/`translation`/`flow`/`property` sarmalları
2987
+ * çalışma zamanında çözülür ve sabit bir değerleri yoktur — onlara dokunulmaz.
2988
+ */
2989
+ function staticPropValue(value) {
2990
+ if (value === null || typeof value !== 'object' || Array.isArray(value))
2991
+ return value;
2992
+ const record = value;
2993
+ if (typeof record.type !== 'string')
2994
+ return value;
2995
+ if (record.type !== 'static')
2996
+ return undefined;
2997
+ return record.data ?? record.ref;
2998
+ }
2999
+ /**
3000
+ * TB-123 / S2-33 — tam şema yazan yolların (page_update · layout_update) katalog denetimi.
3001
+ *
3002
+ * Platformun doğrulama duvarı yalnız micro-op ucunda koşuyor: aynı geçersiz değer
3003
+ * `page_schema_patch`'te `invalid-enum-value` ile reddedilirken `page_update`'te 200 dönüyor ve
3004
+ * kusur ancak EKRANDA görülüyordu. Burası aynı kararı aynı kural kimlikleriyle, istek gitmeden
3005
+ * verir. Kural kimlikleri platformun kendi yanıtından alındı (ölçüm 2026-09-20).
3006
+ *
3007
+ * Katalog okunamazsa (`rules` boş) doğrulama SUSAR: bilinmeyen sözlük yüzünden geçerli bir yazmayı
3008
+ * bloklamak, denetimi atlamaktan kötüdür.
3009
+ */
3010
+ export function schemaCatalogErrors(nodes, rules) {
3011
+ const errors = [];
3012
+ if (rules.size === 0)
3013
+ return errors;
3014
+ const visit = (node) => {
3015
+ if (!node || typeof node !== 'object')
3016
+ return;
3017
+ const record = node;
3018
+ const componentId = String(record.elementId ?? record.name ?? record.id ?? '?');
3019
+ const type = typeof record.type === 'string' ? record.type : undefined;
3020
+ const typeRules = type === undefined ? undefined : rules.get(type);
3021
+ if (typeRules !== undefined && record.props && typeof record.props === 'object' && !Array.isArray(record.props)) {
3022
+ for (const [name, raw] of Object.entries(record.props)) {
3023
+ if (!typeRules.props.has(name)) {
3024
+ errors.push({
3025
+ componentId,
3026
+ path: `props.${name}`,
3027
+ rule: 'unknown-prop',
3028
+ message: `'${type}' komponentinin '${name}' diye bir prop'u yok.`,
3029
+ suggestions: [...typeRules.props.keys()].sort()
3030
+ });
3031
+ continue;
3032
+ }
3033
+ const options = typeRules.props.get(name);
3034
+ const value = staticPropValue(raw);
3035
+ if (options === undefined || value === undefined || value === null || value === '')
3036
+ continue;
3037
+ if (options.includes(String(value)))
3038
+ continue;
3039
+ errors.push({
3040
+ componentId,
3041
+ path: `props.${name}`,
3042
+ rule: 'invalid-enum-value',
3043
+ message: `'${String(value)}' '${name}' için geçerli bir değer değil.`,
3044
+ suggestions: [...options]
3045
+ });
3046
+ }
3047
+ }
3048
+ if (record.appearance && typeof record.appearance === 'object' && !Array.isArray(record.appearance)) {
3049
+ for (const [name, value] of Object.entries(record.appearance)) {
3050
+ const tokens = APPEARANCE_TOKEN_SETS[name];
3051
+ if (tokens === undefined || value === undefined || value === null || value === '')
3052
+ continue;
3053
+ if (tokens.values.includes(String(value)))
3054
+ continue;
3055
+ errors.push({
3056
+ componentId,
3057
+ path: `appearance.${name}`,
3058
+ rule: 'invalid-appearance',
3059
+ message: `'${name}' için geçerli bir değer kullanın: ${tokens.values.join(', ')}. Gelen: '${String(value)}'.`,
3060
+ suggestions: [...tokens.values]
3061
+ });
3062
+ }
3063
+ }
3064
+ for (const child of Array.isArray(record.children) ? record.children : [])
3065
+ visit(child);
3066
+ };
3067
+ for (const node of Array.isArray(nodes) ? nodes : [])
3068
+ visit(node);
3069
+ return errors;
3070
+ }
3071
+ export function schemaCatalogMessage(errors, tool) {
3072
+ const lines = errors.map(error => {
3073
+ const accepted = error.suggestions === undefined || error.suggestions.length === 0
3074
+ ? ''
3075
+ : ` → kabul edilenler: ${error.suggestions.join(' · ')}`;
3076
+ return `${error.componentId} ${error.path} [${error.rule}] ${error.message}${accepted}`;
3077
+ });
3078
+ return `${tool}: şema katalog doğrulamasından geçmedi (istek gönderilmedi) — ${lines.join(' | ')}. `
3079
+ + 'Bu denetim page_schema_patch yolundaki platform duvarının aynısıdır (TB-123): geçersiz değer sessizce kaydedilip ekranda kaybolmasın diye tam şema yolunda da koşar. '
3080
+ + "Değer kümelerini component_get('<tip>') ile doğrulayın.";
3081
+ }