@devoplus/one-sdk 0.0.0-stage → 0.2.0-next.117

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 (139) hide show
  1. package/CHANGELOG.md +268 -0
  2. package/README.md +893 -2
  3. package/bin/accessRequest.d.mts +96 -0
  4. package/bin/accessRequest.mjs +340 -0
  5. package/bin/appOps.d.mts +97 -0
  6. package/bin/appOps.mjs +336 -0
  7. package/bin/dataCommand.mjs +131 -0
  8. package/bin/devConfig.mjs +132 -0
  9. package/bin/one.mjs +341 -0
  10. package/bin/session.mjs +239 -0
  11. package/dist/agentInput.d.ts +9 -0
  12. package/dist/agentInput.d.ts.map +1 -0
  13. package/dist/agentInput.js +102 -0
  14. package/dist/agentInput.js.map +1 -0
  15. package/dist/agentTools.d.ts +83 -0
  16. package/dist/agentTools.d.ts.map +1 -0
  17. package/dist/agentTools.js +164 -0
  18. package/dist/agentTools.js.map +1 -0
  19. package/dist/ai.d.ts +67 -0
  20. package/dist/ai.d.ts.map +1 -0
  21. package/dist/ai.js +129 -0
  22. package/dist/ai.js.map +1 -0
  23. package/dist/audit.d.ts +21 -0
  24. package/dist/audit.d.ts.map +1 -0
  25. package/dist/audit.js +58 -0
  26. package/dist/audit.js.map +1 -0
  27. package/dist/backend.d.ts +27 -0
  28. package/dist/backend.d.ts.map +1 -0
  29. package/dist/backend.js +63 -0
  30. package/dist/backend.js.map +1 -0
  31. package/dist/cache.d.ts +20 -0
  32. package/dist/cache.d.ts.map +1 -0
  33. package/dist/cache.js +84 -0
  34. package/dist/cache.js.map +1 -0
  35. package/dist/client.d.ts +147 -0
  36. package/dist/client.d.ts.map +1 -0
  37. package/dist/client.js +469 -0
  38. package/dist/client.js.map +1 -0
  39. package/dist/components.d.ts +235 -0
  40. package/dist/components.d.ts.map +1 -0
  41. package/dist/components.js +1491 -0
  42. package/dist/components.js.map +1 -0
  43. package/dist/context.d.ts +110 -0
  44. package/dist/context.d.ts.map +1 -0
  45. package/dist/context.js +126 -0
  46. package/dist/context.js.map +1 -0
  47. package/dist/data/crud.d.ts +74 -0
  48. package/dist/data/crud.d.ts.map +1 -0
  49. package/dist/data/crud.js +614 -0
  50. package/dist/data/crud.js.map +1 -0
  51. package/dist/data/ddl.d.ts +76 -0
  52. package/dist/data/ddl.d.ts.map +1 -0
  53. package/dist/data/ddl.js +362 -0
  54. package/dist/data/ddl.js.map +1 -0
  55. package/dist/data/fold.d.ts +14 -0
  56. package/dist/data/fold.d.ts.map +1 -0
  57. package/dist/data/fold.js +76 -0
  58. package/dist/data/fold.js.map +1 -0
  59. package/dist/data/model.d.ts +113 -0
  60. package/dist/data/model.d.ts.map +1 -0
  61. package/dist/data/model.js +408 -0
  62. package/dist/data/model.js.map +1 -0
  63. package/dist/data/values.d.ts +29 -0
  64. package/dist/data/values.d.ts.map +1 -0
  65. package/dist/data/values.js +152 -0
  66. package/dist/data/values.js.map +1 -0
  67. package/dist/dexa.d.ts +44 -0
  68. package/dist/dexa.d.ts.map +1 -0
  69. package/dist/dexa.js +74 -0
  70. package/dist/dexa.js.map +1 -0
  71. package/dist/dexaCommand.d.ts +116 -0
  72. package/dist/dexaCommand.d.ts.map +1 -0
  73. package/dist/dexaCommand.js +226 -0
  74. package/dist/dexaCommand.js.map +1 -0
  75. package/dist/export/columns.d.ts +62 -0
  76. package/dist/export/columns.d.ts.map +1 -0
  77. package/dist/export/columns.js +127 -0
  78. package/dist/export/columns.js.map +1 -0
  79. package/dist/export/csv.d.ts +10 -0
  80. package/dist/export/csv.d.ts.map +1 -0
  81. package/dist/export/csv.js +30 -0
  82. package/dist/export/csv.js.map +1 -0
  83. package/dist/export/report.d.ts +19 -0
  84. package/dist/export/report.d.ts.map +1 -0
  85. package/dist/export/report.js +91 -0
  86. package/dist/export/report.js.map +1 -0
  87. package/dist/export/response.d.ts +14 -0
  88. package/dist/export/response.d.ts.map +1 -0
  89. package/dist/export/response.js +70 -0
  90. package/dist/export/response.js.map +1 -0
  91. package/dist/export/xlsx.d.ts +15 -0
  92. package/dist/export/xlsx.d.ts.map +1 -0
  93. package/dist/export/xlsx.js +167 -0
  94. package/dist/export/xlsx.js.map +1 -0
  95. package/dist/export/zip.d.ts +7 -0
  96. package/dist/export/zip.d.ts.map +1 -0
  97. package/dist/export/zip.js +83 -0
  98. package/dist/export/zip.js.map +1 -0
  99. package/dist/files.d.ts +52 -0
  100. package/dist/files.d.ts.map +1 -0
  101. package/dist/files.js +137 -0
  102. package/dist/files.js.map +1 -0
  103. package/dist/index.d.ts +31 -0
  104. package/dist/index.d.ts.map +1 -0
  105. package/dist/index.js +35 -0
  106. package/dist/index.js.map +1 -0
  107. package/dist/jobs.d.ts +57 -0
  108. package/dist/jobs.d.ts.map +1 -0
  109. package/dist/jobs.js +157 -0
  110. package/dist/jobs.js.map +1 -0
  111. package/dist/log.d.ts +22 -0
  112. package/dist/log.d.ts.map +1 -0
  113. package/dist/log.js +107 -0
  114. package/dist/log.js.map +1 -0
  115. package/dist/notify.d.ts +41 -0
  116. package/dist/notify.d.ts.map +1 -0
  117. package/dist/notify.js +11 -0
  118. package/dist/notify.js.map +1 -0
  119. package/dist/org.d.ts +184 -0
  120. package/dist/org.d.ts.map +1 -0
  121. package/dist/org.js +114 -0
  122. package/dist/org.js.map +1 -0
  123. package/dist/people.d.ts +39 -0
  124. package/dist/people.d.ts.map +1 -0
  125. package/dist/people.js +88 -0
  126. package/dist/people.js.map +1 -0
  127. package/dist/problem.d.ts +12 -0
  128. package/dist/problem.d.ts.map +1 -0
  129. package/dist/problem.js +33 -0
  130. package/dist/problem.js.map +1 -0
  131. package/dist/runtime.d.ts +92 -0
  132. package/dist/runtime.d.ts.map +1 -0
  133. package/dist/runtime.js +8 -0
  134. package/dist/runtime.js.map +1 -0
  135. package/dist/scenarios.d.ts +125 -0
  136. package/dist/scenarios.d.ts.map +1 -0
  137. package/dist/scenarios.js +251 -0
  138. package/dist/scenarios.js.map +1 -0
  139. package/package.json +55 -3
@@ -0,0 +1,1491 @@
1
+ // Hazır arayüz bileşenleri (karar defteri D-83). Uygulama sayfası bileşenleri KENDİ adresinden yükler:
2
+ // <link rel="stylesheet" href="/one-ui.css"> görsel dil + bileşen stilleri
3
+ // <script src="/one-bridge.js"></script> `window.one` (önce yüklenir: belirteç, dil, indirme, bildirim)
4
+ // <script src="/one-components.js"></script> <one-table> <one-form> <one-filter> <one-person-picker>
5
+ // <one-file-upload> <one-chart>
6
+ // Sunucu tarafı üçünü de `clientAssetResponse(pathname)` ile döndürür (client.ts).
7
+ //
8
+ // Tasarım kararları (ÖNERİ — D-83 uygulama biçimi):
9
+ // - Bağımlılıksız Custom Elements, ışık DOM'u (Shadow DOM DEĞİL). Gerekçe: (1) `/one-ui.css` sınıfları ve değişkenleri
10
+ // bileşenin içine de uygulanır — tema geçişi (`one:context` → köprü `<html data-theme>` yazar) ve Portal tasarım değerleri
11
+ // ek bir kod olmadan bileşene de geçer, stil iki yerde tutulmaz; (2) `<label for>`, form ve klavye davranışı tarayıcının
12
+ // kendi öğeleriyle çalışır; (3) yazdırma (D-85: PDF = tarayıcının yazdırması) gölge ağaca takılmaz. Bedeli: uygulamanın
13
+ // kendi CSS'i bileşene sızabilir — sınıflar `one-` önekiyle ayrılır.
14
+ // - Platform CSP'si (D-76 U12: `script-src 'self'`, Trusted Types önce yalnız rapor kipinde) altında çalışır: satır içi
15
+ // betik, `eval`, `new Function`, `innerHTML`, `on…=` öznitelik/özellik ataması YOK. Her öğe DOM API'siyle kurulur,
16
+ // kullanıcı verisi yalnız `textContent` ile yazılır (statik denetim: components.test.ts).
17
+ // - Ağ isteği yalnız uygulamanın KENDİ origin'ine gider (`connect-src 'self'`); köprünün belirteci başka bir adrese asla
18
+ // eklenmez (adres origin denetiminden geçmezse istek gönderilmez).
19
+ // - Bileşen metinleri TR + EN; dil öğenin `lang` özniteliği → Portal bağlamı (`one.context.lang`) → sayfa adresindeki
20
+ // `?lang=` → `<html lang>` sırasıyla seçilir ve `one:context` gelince yeniden çizilir.
21
+ // - Tarih `gg.aa.yyyy`, sayı ve para `tr-TR` biçimindedir (D-76 U8).
22
+ /** Bileşen betiğinin uygulama içindeki yolu. */
23
+ export const COMPONENTS_SCRIPT_PATH = '/one-components.js';
24
+ /** Bileşenlerin etiket adları. */
25
+ export const ONE_COMPONENT_TAGS = ['one-table', 'one-form', 'one-filter', 'one-person-picker', 'one-file-upload', 'one-chart'];
26
+ /** Kişi aramanın varsayılan adresi (`peopleSearchHandler` bu yolda sunulur). */
27
+ export const PEOPLE_SEARCH_PATH = '/api/one/people';
28
+ /** `<one-file-upload>`'ın varsayılan yükleme adresi (create-one-app iskeletinin dosya ucu). */
29
+ export const FILE_UPLOAD_DEFAULT_ACTION = '/api/files';
30
+ /** `<one-file-upload>`'ın varsayılan boyut sınırı (iskeletin `UPLOAD_MAX_BYTES` değeriyle aynı). */
31
+ export const FILE_UPLOAD_DEFAULT_MAX_BYTES = 5 * 1024 * 1024;
32
+ /** `<one-table>` sayfa boyutu: varsayılan ve tavan. */
33
+ export const TABLE_DEFAULT_PAGE_SIZE = 20;
34
+ export const TABLE_MAX_PAGE_SIZE = 100;
35
+ /**
36
+ * `/one-components.js` — tarayıcıda çalışır (derleme yok). `String.raw` ters bölüleri olduğu gibi korur; betikte ters
37
+ * tırnak KULLANILMAZ ve tek şablon yer tutucusu bu dosyadaki sabitlerdir (yol ve sınır değerleri tek kaynaktan gelsin). Davranış components.test.ts'te gerçek bir DOM uygulamasında (jsdom) denenir.
38
+ */
39
+ export const ONE_COMPONENTS_SCRIPT = String.raw `(function (w) {
40
+ 'use strict';
41
+ var doc = w.document;
42
+ if (!doc || !w.customElements || typeof w.HTMLElement !== 'function') return;
43
+ if (w.customElements.get('one-table')) return;
44
+
45
+ var STRINGS = {
46
+ tr: {
47
+ loading: 'Yükleniyor…', empty: 'Kayıt yok.', noMatch: 'Aramanızla eşleşen kayıt yok.', loadError: 'Liste getirilemedi.',
48
+ retry: 'Yeniden dene', search: 'Listede ara', prev: 'Önceki sayfa', next: 'Sonraki sayfa',
49
+ pageOf: 'Sayfa {page} / {pages}', page: 'Sayfa {page}', rows: '{count} kayıt',
50
+ selectAll: 'Bu sayfadaki bütün satırları seç', selectRow: 'Satırı seç: {name}', selectedCount: '{count} satır seçili.',
51
+ exportXlsx: "Excel'e aktar", exportCsv: 'CSV olarak indir', exporting: 'Dosya hazırlanıyor…', exportError: 'Dosya hazırlanamadı.',
52
+ noBridge: 'Portal bağlantısı yüklenmedi; dosya indirilemiyor.',
53
+ sortBy: '{label}: sırala', ascending: 'artan', descending: 'azalan',
54
+ yes: 'Evet', no: 'Hayır',
55
+ badResponse: 'Sunucu yanıtı beklenen biçimde değil.', badSrc: 'Adres uygulamanın kendi adresi olmalı.',
56
+ networkError: 'Sunucuya ulaşılamadı. Bağlantınızı denetleyip yeniden deneyin.',
57
+ sessionError: 'Oturumunuz doğrulanamadı. Sayfayı yenileyip yeniden deneyin.', forbidden: 'Bu işlem için yetkiniz yok.',
58
+ required: 'Bu alan zorunludur.', minLength: 'En az {n} karakter girin.', maxLength: 'En çok {n} karakter girebilirsiniz.',
59
+ min: 'Değer en az {n} olmalı.', max: 'Değer en çok {n} olabilir.', pattern: 'Biçim geçersiz.',
60
+ notNumber: 'Geçerli bir sayı girin.', notDate: 'Geçerli bir tarih girin.', notChoice: 'Listeden bir seçenek seçin.',
61
+ save: 'Kaydet', cancel: 'Vazgeç', saving: 'Kaydediliyor…', saved: 'Kaydedildi.', saveError: 'Kaydedilemedi.',
62
+ fixErrors: 'Kaydetmeden önce işaretli alanları düzeltin.', choose: 'Seçin', all: 'Tümü',
63
+ discardTitle: 'Kaydedilmemiş değişiklikler', discard: 'Kaydedilmemiş değişiklikleriniz kaybolacak. Devam edilsin mi?',
64
+ discardAccept: 'Değişiklikleri at', keepEditing: 'Düzenlemeye devam et',
65
+ actingReadOnly: 'Bu oturum başkası adına açıldığı için (Vekalet / Yerine Görüntüle) değişiklik kaydedilemez.',
66
+ requiredMark: '(zorunlu)',
67
+ from: 'başlangıç', to: 'bitiş', clear: 'Süzgeci temizle', rangeError: 'Başlangıç tarihi bitiş tarihinden sonra olamaz.',
68
+ personPlaceholder: 'Ad yazarak arayın', personMin: 'Aramak için en az 2 karakter yazın.', personNone: 'Eşleşen kişi yok.',
69
+ personError: 'Kişiler getirilemedi.', personSearching: 'Aranıyor…', personResults: '{count} kişi bulundu.',
70
+ personLabel: 'Kişi', remove: '{name}: kaldır', selected: 'Seçili: {name}',
71
+ fileLabel: 'Dosya', tooLarge: '{name}: dosya çok büyük (en çok {max}).', badType: '{name}: bu dosya türü kabul edilmiyor.',
72
+ uploading: '{name} yükleniyor…', uploaded: '{name} yüklendi.', uploadError: '{name} yüklenemedi.',
73
+ allowed: 'Kabul edilen türler: {types}. En çok {max}.', maxOnly: 'En çok {max}.',
74
+ chart: 'Grafik', chartEmpty: 'Gösterilecek veri yok.', chartData: 'Grafik verisi', category: 'Kategori', total: 'Toplam'
75
+ },
76
+ en: {
77
+ loading: 'Loading…', empty: 'No records.', noMatch: 'No records match your search.', loadError: 'The list could not be loaded.',
78
+ retry: 'Try again', search: 'Search the list', prev: 'Previous page', next: 'Next page',
79
+ pageOf: 'Page {page} of {pages}', page: 'Page {page}', rows: '{count} records',
80
+ selectAll: 'Select all rows on this page', selectRow: 'Select row: {name}', selectedCount: '{count} rows selected.',
81
+ exportXlsx: 'Export to Excel', exportCsv: 'Download as CSV', exporting: 'Preparing the file…', exportError: 'The file could not be prepared.',
82
+ noBridge: 'The portal connection is not loaded; the file cannot be downloaded.',
83
+ sortBy: '{label}: sort', ascending: 'ascending', descending: 'descending',
84
+ yes: 'Yes', no: 'No',
85
+ badResponse: 'The server response is not in the expected format.', badSrc: "The address must be the application's own address.",
86
+ networkError: 'The server could not be reached. Check your connection and try again.',
87
+ sessionError: 'Your session could not be verified. Reload the page and try again.', forbidden: 'You are not authorized for this action.',
88
+ required: 'This field is required.', minLength: 'Enter at least {n} characters.', maxLength: 'You can enter at most {n} characters.',
89
+ min: 'The value must be at least {n}.', max: 'The value can be at most {n}.', pattern: 'The format is not valid.',
90
+ notNumber: 'Enter a valid number.', notDate: 'Enter a valid date.', notChoice: 'Choose an option from the list.',
91
+ save: 'Save', cancel: 'Cancel', saving: 'Saving…', saved: 'Saved.', saveError: 'Could not be saved.',
92
+ fixErrors: 'Correct the marked fields before saving.', choose: 'Choose', all: 'All',
93
+ discardTitle: 'Unsaved changes', discard: 'Your unsaved changes will be lost. Do you want to continue?',
94
+ discardAccept: 'Discard changes', keepEditing: 'Keep editing',
95
+ actingReadOnly: 'Changes cannot be saved because this session was opened on behalf of someone else (delegation or view as user).',
96
+ requiredMark: '(required)',
97
+ from: 'from', to: 'to', clear: 'Clear filters', rangeError: 'The start date cannot be after the end date.',
98
+ personPlaceholder: 'Search by name', personMin: 'Type at least 2 characters to search.', personNone: 'No matching people.',
99
+ personError: 'People could not be loaded.', personSearching: 'Searching…', personResults: '{count} people found.',
100
+ personLabel: 'Person', remove: '{name}: remove', selected: 'Selected: {name}',
101
+ fileLabel: 'File', tooLarge: '{name}: the file is too large (at most {max}).', badType: '{name}: this file type is not accepted.',
102
+ uploading: 'Uploading {name}…', uploaded: '{name} uploaded.', uploadError: '{name} could not be uploaded.',
103
+ allowed: 'Accepted types: {types}. At most {max}.', maxOnly: 'At most {max}.',
104
+ chart: 'Chart', chartEmpty: 'There is no data to show.', chartData: 'Chart data', category: 'Category', total: 'Total'
105
+ }
106
+ };
107
+ var XLSX_MIME = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
108
+ var SVG_NS = 'http://www.w3.org/2000/svg';
109
+ var FOLD = { 'ç': 'c', 'ğ': 'g', 'ı': 'i', 'ö': 'o', 'ş': 's', 'ü': 'u', 'â': 'a', 'î': 'i', 'û': 'u' };
110
+ var ASCII = { 'ç': 'c', 'Ç': 'C', 'ğ': 'g', 'Ğ': 'G', 'ı': 'i', 'İ': 'I', 'ö': 'o', 'Ö': 'O', 'ş': 's', 'Ş': 'S', 'ü': 'u', 'Ü': 'U' };
111
+ var TYPES = {
112
+ text: 'text', string: 'text', longtext: 'longText', 'long-text': 'longText', textarea: 'longText',
113
+ number: 'number', integer: 'number', decimal: 'number', money: 'money', currency: 'money',
114
+ date: 'date', datetime: 'datetime', 'date-time': 'datetime', timestamp: 'datetime',
115
+ boolean: 'boolean', bool: 'boolean', choice: 'choice', select: 'choice', 'enum': 'choice',
116
+ person: 'person', user: 'person', file: 'file'
117
+ };
118
+ var KEY_RE = /^[A-Za-z_][A-Za-z0-9_.-]{0,99}$/;
119
+
120
+ // ── Ortak yardımcılar ──────────────────────────────────────────────────────────────────────────────────────
121
+ function own(o, k) { return o != null && Object.prototype.hasOwnProperty.call(o, k); }
122
+ function report(e) { if (w.console && w.console.error) w.console.error(e); }
123
+ var uidSeq = 0;
124
+ function uid(prefix) { uidSeq += 1; return 'one-' + prefix + '-' + uidSeq; }
125
+
126
+ function langOf(el) {
127
+ var v = el.getAttribute('lang');
128
+ if (!v && w.one && w.one.context && w.one.context.lang) v = w.one.context.lang;
129
+ if (!v) { try { v = new URLSearchParams(w.location.search).get('lang'); } catch (e) { v = null; } }
130
+ if (!v) v = doc.documentElement.getAttribute('lang');
131
+ return /^en(?:$|[-_])/i.test(String(v || '')) ? 'en' : 'tr';
132
+ }
133
+ function t(lang, key, vars) {
134
+ var s = (STRINGS[lang] && STRINGS[lang][key]) || STRINGS.tr[key] || key;
135
+ if (vars) s = s.replace(/\{(\w+)\}/g, function (m, k) { return own(vars, k) ? String(vars[k]) : m; });
136
+ return s;
137
+ }
138
+ function textOf(v, lang) {
139
+ if (v == null) return '';
140
+ if (typeof v === 'string' || typeof v === 'number') return String(v);
141
+ if (typeof v === 'object') {
142
+ var s = v[lang];
143
+ if (typeof s !== 'string' || s.trim() === '') s = typeof v.tr === 'string' && v.tr ? v.tr : (typeof v.en === 'string' ? v.en : '');
144
+ return String(s);
145
+ }
146
+ return '';
147
+ }
148
+ function fold(v) {
149
+ return String(v == null ? '' : v).toLocaleLowerCase('tr-TR').replace(/[çğıöşüâîû]/g, function (c) { return FOLD[c]; });
150
+ }
151
+ function typeOf(v) { var k = String(v || 'text').toLowerCase(); return own(TYPES, k) ? TYPES[k] : 'text'; }
152
+
153
+ // Öğe kurucusu: metin yalnız textContent ile yazılır; 'on…' adlı öznitelik REDDEDİLİR (satır içi işleyici yok).
154
+ function setAttrs(e, attrs) {
155
+ if (!attrs) return;
156
+ for (var k in attrs) {
157
+ if (!own(attrs, k)) continue;
158
+ var v = attrs[k];
159
+ if (v === null || v === undefined || v === false) continue;
160
+ if (k === 'text') { e.textContent = String(v); continue; }
161
+ if (/^on/i.test(k)) throw new TypeError('one: olay işleyicisi öznitelik olarak yazılmaz (' + k + ')');
162
+ e.setAttribute(k, v === true ? '' : String(v));
163
+ }
164
+ }
165
+ function add(e, kids) {
166
+ if (kids == null) return e;
167
+ if (!Array.isArray(kids)) kids = [kids];
168
+ for (var i = 0; i < kids.length; i++) {
169
+ var c = kids[i];
170
+ if (c == null || c === false) continue;
171
+ e.appendChild(typeof c === 'string' ? doc.createTextNode(c) : c);
172
+ }
173
+ return e;
174
+ }
175
+ function h(tag, attrs, kids) { var e = doc.createElement(tag); setAttrs(e, attrs); return add(e, kids); }
176
+ function svg(tag, attrs, kids) { var e = doc.createElementNS(SVG_NS, tag); setAttrs(e, attrs); return add(e, kids); }
177
+ function clear(e) { while (e.firstChild) e.removeChild(e.firstChild); }
178
+ function listen(e, type, fn) { e.addEventListener(type, fn); return e; }
179
+ // İç denetimlerin 'change' olayı bileşenin dışına taşmaz: bileşen kendi 'change' olayını (ayrıntılı) yayar.
180
+ function quiet(e) { e.addEventListener('change', function (ev) { ev.stopPropagation(); }); return e; }
181
+ function emit(el, type, detail, cancelable) {
182
+ return el.dispatchEvent(new w.CustomEvent(type, { detail: detail, bubbles: true, cancelable: !!cancelable }));
183
+ }
184
+ function getPath(row, key) {
185
+ if (row == null) return undefined;
186
+ if (own(row, key)) return row[key];
187
+ var parts = String(key).split('.'), cur = row;
188
+ for (var i = 0; i < parts.length; i++) { if (cur == null || typeof cur !== 'object') return undefined; cur = cur[parts[i]]; }
189
+ return cur;
190
+ }
191
+ function clone(v) { return v == null ? v : JSON.parse(JSON.stringify(v)); }
192
+
193
+ // ── Biçim (U8: tarih gg.aa.yyyy, sayı tr-TR) ─────────────────────────────────────────────────────────────
194
+ function pad2(n) { return (n < 10 ? '0' : '') + n; }
195
+ var DATE_ONLY = /^(\d{4})-(\d{2})-(\d{2})$/;
196
+ function asDate(v) { var d = new Date(v); return isNaN(d.getTime()) ? null : d; }
197
+ function fmtDate(v) {
198
+ if (v == null || v === '') return '';
199
+ var m = DATE_ONLY.exec(String(v));
200
+ if (m) return m[3] + '.' + m[2] + '.' + m[1];
201
+ var d = asDate(v);
202
+ return d ? pad2(d.getDate()) + '.' + pad2(d.getMonth() + 1) + '.' + d.getFullYear() : String(v);
203
+ }
204
+ function fmtDateTime(v) {
205
+ if (v == null || v === '') return '';
206
+ if (DATE_ONLY.test(String(v))) return fmtDate(v);
207
+ var d = asDate(v);
208
+ return d ? fmtDate(d) + ' ' + pad2(d.getHours()) + ':' + pad2(d.getMinutes()) : String(v);
209
+ }
210
+ function fmtNumber(v, digits) {
211
+ if (v == null || v === '') return '';
212
+ var n = Number(v);
213
+ if (!isFinite(n)) return String(v);
214
+ return new Intl.NumberFormat('tr-TR', { maximumFractionDigits: digits == null ? 6 : digits }).format(n);
215
+ }
216
+ function fmtMoney(v, currency) {
217
+ if (v == null || v === '') return '';
218
+ var n = Number(v);
219
+ if (!isFinite(n)) return String(v);
220
+ var cur = /^[A-Z]{3}$/.test(String(currency || '')) ? currency : 'TRY';
221
+ return new Intl.NumberFormat('tr-TR', { style: 'currency', currency: cur }).format(n);
222
+ }
223
+ function fmtSize(bytes) {
224
+ var n = Number(bytes) || 0;
225
+ if (n >= 1048576) return fmtNumber(n / 1048576, 1) + ' MB';
226
+ if (n >= 1024) return fmtNumber(n / 1024, 1) + ' KB';
227
+ return fmtNumber(n, 0) + ' B';
228
+ }
229
+ function personName(v) { return v == null ? '' : typeof v === 'object' ? String(v.name || v.fullName || v.id || '') : String(v); }
230
+ function fileName(v) { return v == null ? '' : typeof v === 'object' ? String(v.name || v.key || '') : String(v); }
231
+ function choiceLabel(options, v, lang) {
232
+ var list = Array.isArray(options) ? options : [];
233
+ for (var i = 0; i < list.length; i++) if (list[i] && String(list[i].value) === String(v)) return textOf(list[i].label, lang) || String(v);
234
+ return v == null ? '' : String(v);
235
+ }
236
+ function display(col, v, row, lang) {
237
+ if (typeof col.format === 'function') {
238
+ try { var r = col.format(v, row, lang); return r == null ? '' : String(r); } catch (e) { report(e); return ''; }
239
+ }
240
+ if (Array.isArray(v)) return v.map(function (x) { return display({ type: col.type, options: col.options, currency: col.currency }, x, row, lang); }).join(', ');
241
+ switch (col.type) {
242
+ case 'number': return fmtNumber(v);
243
+ case 'money': return fmtMoney(v, col.currency);
244
+ case 'date': return fmtDate(v);
245
+ case 'datetime': return fmtDateTime(v);
246
+ case 'boolean': return v == null || v === '' ? '' : t(lang, v === true || v === 1 || v === 'true' ? 'yes' : 'no');
247
+ case 'choice': return choiceLabel(col.options, v, lang);
248
+ case 'person': return personName(v);
249
+ case 'file': return fileName(v);
250
+ default: return v == null ? '' : typeof v === 'object' ? '' : String(v);
251
+ }
252
+ }
253
+ function compare(a, b, type) {
254
+ var an = a == null || a === '', bn = b == null || b === '';
255
+ if (an || bn) return an === bn ? 0 : an ? 1 : -1;
256
+ if (type === 'number' || type === 'money') return Number(a) - Number(b);
257
+ if (type === 'boolean') return (a === true || a === 'true' || a === 1 ? 1 : 0) - (b === true || b === 'true' || b === 1 ? 1 : 0);
258
+ if (type === 'date' || type === 'datetime') {
259
+ var ta = Date.parse(a), tb = Date.parse(b);
260
+ if (!isNaN(ta) && !isNaN(tb)) return ta - tb;
261
+ }
262
+ return String(a).localeCompare(String(b), 'tr', { sensitivity: 'base', numeric: true });
263
+ }
264
+
265
+ // ── Ağ: yalnız kendi origin'i; belirteç köprüden (one.fetch) ──────────────────────────────────────────────
266
+ function sameOrigin(src) {
267
+ if (typeof src !== 'string' || src.trim() === '') return null;
268
+ var u;
269
+ try { u = new URL(src, w.location.href); } catch (e) { return null; }
270
+ if (u.origin !== w.location.origin || (u.protocol !== 'https:' && u.protocol !== 'http:')) return null;
271
+ return u;
272
+ }
273
+ function relative(u) { return u.pathname + u.search; }
274
+ // Portal içinde belirteç gelmeden istek atılmaz (aksi hâlde ilk istek oturumsuz gider ve 401 döner).
275
+ function whenToken() {
276
+ var one = w.one;
277
+ if (!one || !one.framed || one.token || typeof one.onToken !== 'function' || !one.parents || one.parents.length === 0) return Promise.resolve();
278
+ return new Promise(function (resolve) { var off = one.onToken(function () { off(); resolve(); }); });
279
+ }
280
+ function send(url, init) {
281
+ return whenToken().then(function () {
282
+ var opts = init || {};
283
+ if (!opts.credentials) opts.credentials = 'same-origin';
284
+ var one = w.one;
285
+ return one && typeof one.fetch === 'function' ? one.fetch(url, opts) : w.fetch(url, opts);
286
+ });
287
+ }
288
+ function readJson(res) {
289
+ return res.text().then(function (txt) {
290
+ if (!txt) return null;
291
+ try { return JSON.parse(txt); } catch (e) { return undefined; }
292
+ }, function () { return undefined; });
293
+ }
294
+ function failure(status, body, fallbackKey) {
295
+ if (body && typeof body === 'object' && typeof body.detail === 'string' && body.detail.trim()) return { text: body.detail.trim() };
296
+ if (status === 401) return { key: 'sessionError' };
297
+ if (status === 403) return { key: 'forbidden' };
298
+ return { key: fallbackKey };
299
+ }
300
+ function messageOf(m, lang) { return m ? (m.text || t(lang, m.key, m.vars)) : ''; }
301
+ function toast(severity, summary, detail) {
302
+ var one = w.one;
303
+ if (!one || typeof one.toast !== 'function' || !summary) return;
304
+ try { one.toast(detail ? { severity: severity, summary: summary, detail: detail } : { severity: severity, summary: summary }); } catch (e) { report(e); }
305
+ }
306
+ function setDirty(dirty) {
307
+ var one = w.one;
308
+ if (one && typeof one.setDirty === 'function') { try { one.setDirty(dirty); } catch (e) { report(e); } }
309
+ }
310
+ function actingReadOnly(el) { return !!(w.one && w.one.actor) && !el.hasAttribute('acting-write'); }
311
+
312
+ // ── Dil değişimi: bağlı bileşenler 'one:context' gelince yeniden çizilir ─────────────────────────────────
313
+ var live = [];
314
+ var hooked = false;
315
+ function hookContext() {
316
+ if (hooked || !w.one || typeof w.one.onContext !== 'function') return;
317
+ hooked = true;
318
+ w.one.onContext(function () {
319
+ var list = live.slice();
320
+ for (var i = 0; i < list.length; i++) { try { list[i].render(); } catch (e) { report(e); } }
321
+ });
322
+ }
323
+
324
+ class Base extends w.HTMLElement {
325
+ connectedCallback() {
326
+ // Betik yüklenmeden önce atanmış özellikler (öğe henüz yükseltilmemişken) sınıf erişicisine aktarılır.
327
+ var props = this.constructor.props || [];
328
+ for (var i = 0; i < props.length; i++) {
329
+ var p = props[i];
330
+ if (own(this, p)) { var v = this[p]; delete this[p]; this[p] = v; }
331
+ }
332
+ if (live.indexOf(this) < 0) live.push(this);
333
+ hookContext();
334
+ this.render();
335
+ if (!this._started) { this._started = true; this.start(); }
336
+ }
337
+ disconnectedCallback() { var i = live.indexOf(this); if (i >= 0) live.splice(i, 1); }
338
+ start() {}
339
+ // Yükseltme sırasında ilk öznitelikler connectedCallback'ten ÖNCE bildirilir; o anda iş yapılmaz (çift istek olmasın).
340
+ attributeChangedCallback(name, oldValue, newValue) { if (oldValue !== newValue && this._started && this.isConnected) this.attributeChanged(name); }
341
+ attributeChanged() { this.render(); }
342
+ lang_() { return langOf(this); }
343
+ // Yeniden çizimde odak aynı denetimde kalır (dil değişimi, sıralama, sayfa).
344
+ render() {
345
+ if (!this.isConnected) return;
346
+ var active = doc.activeElement, fid = null, sel = null;
347
+ if (active && active !== this && this.contains(active)) {
348
+ fid = active.getAttribute('data-one-focus');
349
+ try { if (typeof active.selectionStart === 'number') sel = [active.selectionStart, active.selectionEnd]; } catch (e) { sel = null; }
350
+ }
351
+ this.draw();
352
+ if (fid) {
353
+ var list = this.querySelectorAll('[data-one-focus]');
354
+ for (var i = 0; i < list.length; i++) {
355
+ if (list[i].getAttribute('data-one-focus') !== fid) continue;
356
+ list[i].focus();
357
+ if (sel) { try { list[i].setSelectionRange(sel[0], sel[1]); } catch (e) { /* seçim desteklenmiyor */ } }
358
+ break;
359
+ }
360
+ }
361
+ }
362
+ draw() {}
363
+ }
364
+
365
+ // ══ <one-table> ═════════════════════════════════════════════════════════════════════════════════════════
366
+ function normalizeColumns(cols) {
367
+ if (!Array.isArray(cols)) throw new TypeError('one-table: columns bir dizi olmalı');
368
+ return cols.map(function (c) {
369
+ if (!c || typeof c.key !== 'string' || !KEY_RE.test(c.key)) throw new TypeError('one-table: kolonun key alanı geçersiz');
370
+ var type = typeOf(c.type);
371
+ return {
372
+ key: c.key, label: c.label == null ? c.key : c.label, type: type, sortable: c.sortable !== false,
373
+ align: c.align === 'end' || c.align === 'start' ? c.align : (type === 'number' || type === 'money' ? 'end' : 'start'),
374
+ options: Array.isArray(c.options) ? c.options : [], currency: c.currency, format: typeof c.format === 'function' ? c.format : null
375
+ };
376
+ });
377
+ }
378
+ function filenameFrom(header, fallback) {
379
+ var v = String(header || ''), name = null, m = /filename\*\s*=\s*(?:UTF-8|utf-8)''([^;]+)/.exec(v);
380
+ if (m) { try { name = decodeURIComponent(m[1].trim()); } catch (e) { name = null; } }
381
+ if (!name) { m = /filename\s*=\s*"([^"]*)"/.exec(v) || /filename\s*=\s*([^;]+)/.exec(v); if (m) name = m[1].trim(); }
382
+ name = name ? name.split(/[\\/]/).pop().replace(/[\u0000-\u001f\u007f]/g, '').slice(0, 150) : '';
383
+ return name || fallback;
384
+ }
385
+
386
+ class OneTable extends Base {
387
+ static get observedAttributes() { return ['src', 'page-size', 'selectable', 'export', 'caption', 'lang', 'paging', 'clickable', 'no-search', 'row-key']; }
388
+ static get props() { return ['columns', 'rows', 'filters', 'emptyText']; }
389
+ constructor() {
390
+ super();
391
+ this._columns = []; this._rows = null; this._filters = {}; this._values = {}; this._emptyText = null;
392
+ this._sort = null; this._order = 'asc'; this._q = ''; this._qRaw = ''; this._page = 0; this._cursors = [null];
393
+ this._items = []; this._next = null; this._total = null;
394
+ this._state = 'idle'; this._error = null; this._selected = {}; this._seq = 0; this._timer = 0; this._busyExport = '';
395
+ }
396
+ get columns() { return this._columns.slice(); }
397
+ set columns(v) { this._columns = normalizeColumns(v); this.render(); }
398
+ get rows() { return this._rows; }
399
+ set rows(v) {
400
+ if (v != null && !Array.isArray(v)) throw new TypeError('one-table: rows bir dizi olmalı');
401
+ this._rows = v == null ? null : v.slice(); this._page = 0;
402
+ if (this._rows) { this._state = 'ready'; this._error = null; }
403
+ this.render();
404
+ }
405
+ get filters() { return clone(this._filters); }
406
+ set filters(v) { this._filters = v && typeof v === 'object' ? clone(v) : {}; this._values = {}; this._restart(); }
407
+ get emptyText() { return this._emptyText; }
408
+ set emptyText(v) { this._emptyText = v == null ? null : v; this.render(); }
409
+ get selection() { var out = [], s = this._selected; for (var k in s) if (own(s, k)) out.push(s[k]); return out; }
410
+ clearSelection() { this._selected = {}; this.render(); this._selectionChanged(); }
411
+ applyFilter(detail) {
412
+ this._filters = detail && detail.params && typeof detail.params === 'object' ? clone(detail.params) : {};
413
+ this._values = detail && detail.values && typeof detail.values === 'object' ? clone(detail.values) : {};
414
+ this._restart();
415
+ }
416
+ reload() { return this._rows ? (this.render(), Promise.resolve()) : this._load(); }
417
+ start() { if (!this._rows && this.getAttribute('src')) this._load(); }
418
+ attributeChanged(name) {
419
+ if (name === 'src' || name === 'paging' || name === 'page-size') { this._page = 0; this._cursors = [null]; if (!this._rows) { this._load(); return; } }
420
+ this.render();
421
+ }
422
+ _remote() { return !this._rows && !!this.getAttribute('src'); }
423
+ _pageSize() { var n = parseInt(this.getAttribute('page-size') || '', 10); return n > 0 ? Math.min(n, ${TABLE_MAX_PAGE_SIZE}) : ${TABLE_DEFAULT_PAGE_SIZE}; }
424
+ _pageMode() { return this.getAttribute('paging') === 'page'; }
425
+ _key(row, index) { var k = getPath(row, this.getAttribute('row-key') || 'id'); return k == null || k === '' ? 'i' + index : String(k); }
426
+ _restart() { this._page = 0; this._cursors = [null]; if (!this.isConnected) return; if (this._remote()) this._load(); else this.render(); }
427
+ // Uzak sorgu: sayfalama (cursor/page + limit) yalnız liste isteğinde; dışa aktarma aynı süzgeç ve sırayla tamamını ister.
428
+ _params(paged) {
429
+ var p = [], f = this._filters;
430
+ if (paged) {
431
+ p.push(['limit', String(this._pageSize())]);
432
+ if (this._pageMode()) p.push(['page', String(this._page + 1)]);
433
+ else if (this._cursors[this._page]) p.push(['cursor', this._cursors[this._page]]);
434
+ }
435
+ if (this._sort) { p.push(['sort', this._sort]); p.push(['order', this._order]); }
436
+ if (this._q) p.push(['q', this._q]);
437
+ for (var k in f) {
438
+ if (!own(f, k) || f[k] == null || f[k] === '') continue;
439
+ var list = Array.isArray(f[k]) ? f[k] : [f[k]];
440
+ for (var i = 0; i < list.length; i++) p.push([k, String(list[i])]);
441
+ }
442
+ return p;
443
+ }
444
+ _url(paged, extra) {
445
+ var u = sameOrigin(this.getAttribute('src'));
446
+ if (!u) return null;
447
+ var p = this._params(paged).concat(extra || []);
448
+ for (var j = 0; j < p.length; j++) u.searchParams.delete(p[j][0]); // aynı adlı eski değerler silinir
449
+ for (var k = 0; k < p.length; k++) u.searchParams.append(p[k][0], p[k][1]);
450
+ return u;
451
+ }
452
+ _load() {
453
+ var self = this, u = this._url(true);
454
+ var my = ++this._seq;
455
+ if (!u) { this._state = 'error'; this._error = { key: 'badSrc' }; this.render(); report(new Error('one-table: src uygulamanın kendi adresi olmalı')); return Promise.resolve(); }
456
+ this._state = 'loading'; this._error = null; this.render();
457
+ return send(relative(u), { headers: { accept: 'application/json' } }).then(function (res) {
458
+ if (my !== self._seq) return;
459
+ return readJson(res).then(function (body) {
460
+ if (my !== self._seq) return;
461
+ if (!res.ok) { self._state = 'error'; self._error = failure(res.status, body, 'loadError'); self.render(); return; }
462
+ if (!body || !Array.isArray(body.items)) { self._state = 'error'; self._error = { key: 'badResponse' }; self.render(); return; }
463
+ self._items = body.items;
464
+ self._next = typeof body.nextCursor === 'string' && body.nextCursor ? body.nextCursor : null;
465
+ self._total = typeof body.total === 'number' && body.total >= 0 ? body.total : null;
466
+ self._state = 'ready';
467
+ self.render();
468
+ emit(self, 'load', { items: body.items, nextCursor: self._next });
469
+ });
470
+ }, function (e) {
471
+ if (my !== self._seq) return;
472
+ report(e); self._state = 'error'; self._error = { key: 'networkError' }; self.render();
473
+ });
474
+ }
475
+ // Yerel veri: arama + süzgeç + sıralama tarayıcıda.
476
+ _localRows(lang) {
477
+ var cols = this._columns, q = fold(this._q).split(/\s+/).filter(Boolean), vals = this._values, self = this;
478
+ var rows = this._rows.map(function (row, i) { return { row: row, index: i }; }).filter(function (x) {
479
+ for (var k in vals) {
480
+ if (!own(vals, k)) continue;
481
+ var want = vals[k], have = getPath(x.row, k);
482
+ if (want == null || want === '') continue;
483
+ if (typeof want === 'object') {
484
+ var hv = have == null ? '' : String(have).slice(0, 10);
485
+ if (want.from && (!hv || hv < want.from)) return false;
486
+ if (want.to && (!hv || hv > want.to)) return false;
487
+ continue;
488
+ }
489
+ var col = null;
490
+ for (var c = 0; c < cols.length; c++) if (cols[c].key === k) col = cols[c];
491
+ if (col && (col.type === 'text' || col.type === 'longText')) { if (fold(have).indexOf(fold(want)) < 0) return false; }
492
+ else if (fold(have) !== fold(want)) return false;
493
+ }
494
+ if (q.length === 0) return true;
495
+ var hay = cols.map(function (col) { return fold(display(col, getPath(x.row, col.key), x.row, lang)); }).join(' ');
496
+ return q.every(function (part) { return hay.indexOf(part) >= 0; });
497
+ });
498
+ if (this._sort) {
499
+ var col = null;
500
+ for (var i = 0; i < cols.length; i++) if (cols[i].key === this._sort) col = cols[i];
501
+ var dir = this._order === 'desc' ? -1 : 1, type = col ? col.type : 'text';
502
+ rows.sort(function (a, b) {
503
+ var av = getPath(a.row, self._sort), bv = getPath(b.row, self._sort);
504
+ if (col && (type === 'choice' || type === 'person' || type === 'file')) { av = display(col, av, a.row, lang); bv = display(col, bv, b.row, lang); }
505
+ // Boş değer yönden bağımsız olarak sonda kalır.
506
+ var ae = av == null || av === '', be = bv == null || bv === '';
507
+ if (ae || be) return ae === be ? a.index - b.index : ae ? 1 : -1;
508
+ var r = compare(av, bv, type);
509
+ return r === 0 ? a.index - b.index : r * dir;
510
+ });
511
+ }
512
+ return rows;
513
+ }
514
+ _toggleSort(key) {
515
+ if (this._sort === key) this._order = this._order === 'asc' ? 'desc' : 'asc';
516
+ else { this._sort = key; this._order = 'asc'; }
517
+ this._restart();
518
+ }
519
+ _selectionChanged() {
520
+ var rows = this.selection, keys = [];
521
+ for (var k in this._selected) if (own(this._selected, k)) keys.push(k);
522
+ emit(this, 'selectionchange', { rows: rows, keys: keys });
523
+ }
524
+ _select(row, key, on, single) {
525
+ if (single) this._selected = {};
526
+ if (on) this._selected[key] = row; else delete this._selected[key];
527
+ }
528
+ _export(format) {
529
+ var self = this, lang = this.lang_(), u = this._url(false, [['format', format]]);
530
+ var one = w.one;
531
+ if (!u) { toast('error', t(lang, 'exportError'), t(lang, 'badSrc')); return Promise.resolve(); }
532
+ if (!one || typeof one.download !== 'function') { toast('error', t(lang, 'exportError'), t(lang, 'noBridge')); report(new Error('one-table: /one-bridge.js yüklenmemiş')); return Promise.resolve(); }
533
+ this._busyExport = format; this.render();
534
+ var done = function () { self._busyExport = ''; self.render(); };
535
+ return send(relative(u), { headers: { accept: format === 'csv' ? 'text/csv' : XLSX_MIME } }).then(function (res) {
536
+ if (!res.ok) return readJson(res).then(function (body) { toast('error', t(lang, 'exportError'), messageOf(failure(res.status, body, 'exportError'), lang)); });
537
+ return res.arrayBuffer().then(function (data) {
538
+ var base = (self.getAttribute('export-name') || 'liste').replace(/[^A-Za-z0-9._-]+/g, '-');
539
+ var name = filenameFrom(res.headers.get('content-disposition'), base + '.' + format);
540
+ var mime = (res.headers.get('content-type') || (format === 'csv' ? 'text/csv' : XLSX_MIME)).split(';')[0].trim();
541
+ return one.download({ name: name, mime: mime, data: data });
542
+ });
543
+ }).then(done, function (e) { report(e); toast('error', t(lang, 'exportError'), t(lang, 'networkError')); done(); });
544
+ }
545
+ draw() {
546
+ var self = this, lang = this.lang_(), cols = this._columns;
547
+ clear(this);
548
+ this.classList.add('one-table-host');
549
+ // Araç çubuğu: arama + dışa aktarma.
550
+ var bar = h('div', { 'class': 'one-table-toolbar one-row' });
551
+ if (!this.hasAttribute('no-search')) {
552
+ var sid = uid('search');
553
+ var input = h('input', { id: sid, type: 'search', 'class': 'one-input', placeholder: t(lang, 'search'), autocomplete: 'off', 'data-one-focus': 'search' });
554
+ input.value = this._qRaw;
555
+ listen(quiet(input), 'input', function () {
556
+ self._qRaw = input.value;
557
+ var value = input.value.trim();
558
+ w.clearTimeout(self._timer);
559
+ self._timer = w.setTimeout(function () { if (value === self._q) return; self._q = value; self._restart(); }, 300);
560
+ });
561
+ add(bar, h('div', { 'class': 'one-field one-table-search' }, [h('label', { 'for': sid, 'class': 'one-sr-only', text: t(lang, 'search') }), input]));
562
+ }
563
+ var formats = String(this.getAttribute('export') || '').split(/[\s,]+/).filter(function (f) { return f === 'xlsx' || f === 'csv'; });
564
+ if (formats.length > 0 && this._remote()) {
565
+ formats.forEach(function (f) {
566
+ var btn = h('button', { type: 'button', 'class': 'one-btn', 'data-one-focus': 'export:' + f, disabled: !!self._busyExport, 'aria-busy': self._busyExport === f ? 'true' : null,
567
+ text: self._busyExport === f ? t(lang, 'exporting') : t(lang, f === 'xlsx' ? 'exportXlsx' : 'exportCsv') });
568
+ listen(btn, 'click', function () { self._export(f); });
569
+ add(bar, btn);
570
+ });
571
+ }
572
+ if (bar.firstChild) add(this, bar);
573
+
574
+ var region = h('div', { 'class': 'one-table-region', 'aria-busy': this._state === 'loading' ? 'true' : 'false' });
575
+ add(this, region);
576
+ var status = h('p', { 'class': 'one-sr-only', role: 'status', 'aria-live': 'polite' });
577
+ if (this._state === 'loading' || (this._state === 'idle' && this._remote())) {
578
+ add(region, h('div', { 'class': 'one-loading', text: t(lang, 'loading') }));
579
+ add(this, status);
580
+ return;
581
+ }
582
+ if (this._state === 'error') {
583
+ var retry = h('button', { type: 'button', 'class': 'one-btn', 'data-one-focus': 'retry', text: t(lang, 'retry') });
584
+ listen(retry, 'click', function () { self.reload(); });
585
+ add(region, h('div', { 'class': 'one-message one-message-error', role: 'alert' }, [h('p', { text: messageOf(this._error, lang) }), retry]));
586
+ return;
587
+ }
588
+ var size = this._pageSize(), remote = this._remote(), list, pages = 1, totalCount = null;
589
+ if (remote) {
590
+ list = this._items.map(function (row, i) { return { row: row, index: i }; });
591
+ if (this._pageMode() && this._total != null) { pages = Math.max(1, Math.ceil(this._total / size)); totalCount = this._total; }
592
+ } else {
593
+ var all = this._rows ? this._localRows(lang) : [];
594
+ totalCount = all.length;
595
+ pages = Math.max(1, Math.ceil(all.length / size));
596
+ if (this._page >= pages) this._page = pages - 1;
597
+ list = all.slice(this._page * size, this._page * size + size);
598
+ }
599
+ if (list.length === 0) {
600
+ var filtered = !!this._q || Object.keys(this._filters).length > 0 || Object.keys(this._values).length > 0;
601
+ add(region, h('div', { 'class': 'one-empty', text: filtered ? t(lang, 'noMatch') : (this._emptyText != null ? textOf(this._emptyText, lang) : t(lang, 'empty')) }));
602
+ } else {
603
+ add(region, this._table(list, lang, cols));
604
+ }
605
+ // Sayfalayıcı
606
+ var hasPrev = this._page > 0;
607
+ var hasNext = remote ? (this._pageMode() ? this._page + 1 < pages : !!this._next) : this._page + 1 < pages;
608
+ if (hasPrev || hasNext) {
609
+ var prev = h('button', { type: 'button', 'class': 'one-btn', 'data-one-focus': 'prev', disabled: !hasPrev, text: t(lang, 'prev') });
610
+ var next = h('button', { type: 'button', 'class': 'one-btn', 'data-one-focus': 'next', disabled: !hasNext, text: t(lang, 'next') });
611
+ listen(prev, 'click', function () { if (self._page > 0) { self._page -= 1; if (self._remote()) self._load(); else self.render(); } });
612
+ listen(next, 'click', function () {
613
+ if (self._remote() && !self._pageMode()) { self._cursors[self._page + 1] = self._next; self._cursors.length = self._page + 2; }
614
+ self._page += 1;
615
+ if (self._remote()) self._load(); else self.render();
616
+ });
617
+ var info = remote && !this._pageMode() ? t(lang, 'page', { page: this._page + 1 }) : t(lang, 'pageOf', { page: this._page + 1, pages: pages });
618
+ add(this, h('nav', { 'class': 'one-pager one-row', 'aria-label': info }, [prev, h('span', { 'class': 'one-muted', text: info }), next]));
619
+ }
620
+ var selectedCount = this.selection.length;
621
+ status.textContent = (totalCount != null ? t(lang, 'rows', { count: fmtNumber(totalCount, 0) }) : '') + (selectedCount ? ' ' + t(lang, 'selectedCount', { count: selectedCount }) : '');
622
+ add(this, status);
623
+ }
624
+ _table(list, lang, cols) {
625
+ var self = this, mode = this.getAttribute('selectable'), selectable = mode !== null, single = mode === 'single';
626
+ var clickable = this.hasAttribute('clickable');
627
+ var table = h('table', { 'class': 'one-table' });
628
+ var caption = this.getAttribute('caption');
629
+ if (caption) add(table, h('caption', { 'class': 'one-sr-only', text: caption }));
630
+ var head = h('tr');
631
+ if (selectable) {
632
+ var th0 = h('th', { scope: 'col', 'class': 'one-select-cell' });
633
+ if (!single) {
634
+ var keys = list.map(function (x) { return self._key(x.row, x.index); });
635
+ var count = keys.filter(function (k) { return own(self._selected, k); }).length;
636
+ var all = h('input', { type: 'checkbox', 'aria-label': t(lang, 'selectAll'), 'data-one-focus': 'select-all' });
637
+ all.checked = count > 0 && count === keys.length;
638
+ all.indeterminate = count > 0 && count < keys.length;
639
+ listen(quiet(all), 'change', function () {
640
+ list.forEach(function (x) { self._select(x.row, self._key(x.row, x.index), all.checked, false); });
641
+ self.render(); self._selectionChanged();
642
+ });
643
+ add(th0, all);
644
+ }
645
+ add(head, th0);
646
+ }
647
+ cols.forEach(function (col) {
648
+ var label = textOf(col.label, lang);
649
+ var sorted = self._sort === col.key;
650
+ var th = h('th', { scope: 'col', 'class': col.align === 'end' ? 'one-num' : null, 'aria-sort': col.sortable ? (sorted ? (self._order === 'asc' ? 'ascending' : 'descending') : 'none') : null });
651
+ if (col.sortable) {
652
+ var btn = h('button', { type: 'button', 'class': 'one-sort', 'data-one-focus': 'sort:' + col.key }, [
653
+ h('span', { text: label }),
654
+ h('span', { 'class': 'one-sort-icon', 'aria-hidden': 'true', text: sorted ? (self._order === 'asc' ? '▲' : '▼') : '↕' })
655
+ ]);
656
+ listen(btn, 'click', function () { self._toggleSort(col.key); });
657
+ add(th, btn);
658
+ } else add(th, label);
659
+ add(head, th);
660
+ });
661
+ add(table, h('thead', null, head));
662
+ var body = h('tbody');
663
+ list.forEach(function (x) {
664
+ var key = self._key(x.row, x.index), isSel = own(self._selected, key);
665
+ var tr = h('tr', { 'data-key': key, 'aria-selected': selectable ? String(isSel) : null, tabindex: clickable ? '0' : null, 'class': clickable ? 'one-clickable' : null });
666
+ if (selectable) {
667
+ var name = cols.length ? display(cols[0], getPath(x.row, cols[0].key), x.row, lang) : key;
668
+ var box = h('input', { type: 'checkbox', 'aria-label': t(lang, 'selectRow', { name: name }), 'data-one-focus': 'row:' + key });
669
+ box.checked = isSel;
670
+ listen(quiet(box), 'change', function () { self._select(x.row, key, box.checked, single); self.render(); self._selectionChanged(); });
671
+ listen(box, 'click', function (ev) { ev.stopPropagation(); });
672
+ add(tr, h('td', { 'class': 'one-select-cell' }, box));
673
+ }
674
+ cols.forEach(function (col) {
675
+ add(tr, h('td', { 'class': col.align === 'end' ? 'one-num' : null, text: display(col, getPath(x.row, col.key), x.row, lang) }));
676
+ });
677
+ if (clickable) {
678
+ var fire = function () { emit(self, 'rowclick', { row: x.row, index: x.index }); };
679
+ listen(tr, 'click', fire);
680
+ listen(tr, 'keydown', function (ev) { if ((ev.key === 'Enter' || ev.key === ' ') && ev.target === tr) { ev.preventDefault(); fire(); } });
681
+ }
682
+ add(body, tr);
683
+ });
684
+ add(table, body);
685
+ return h('div', { 'class': 'one-table-wrap' }, table);
686
+ }
687
+ }
688
+
689
+ // ══ <one-form> ══════════════════════════════════════════════════════════════════════════════════════════
690
+ function normalizeFields(fields, who) {
691
+ if (!Array.isArray(fields)) throw new TypeError(who + ': fields bir dizi olmalı');
692
+ var seen = {};
693
+ return fields.map(function (f) {
694
+ if (!f || typeof f.key !== 'string' || !KEY_RE.test(f.key)) throw new TypeError(who + ': alanın key değeri geçersiz');
695
+ if (own(seen, f.key)) throw new TypeError(who + ': aynı key iki kez kullanılmış (' + f.key + ')');
696
+ seen[f.key] = true;
697
+ var out = {};
698
+ for (var k in f) if (own(f, k)) out[k] = f[k];
699
+ out.type = who === 'one-filter' ? f.type : typeOf(f.type);
700
+ if (out.label == null) out.label = f.key;
701
+ if (!Array.isArray(out.options)) out.options = [];
702
+ return out;
703
+ });
704
+ }
705
+ function isoToLocalInput(v) {
706
+ if (v == null || v === '') return '';
707
+ var d = asDate(v);
708
+ if (!d) return '';
709
+ return d.getFullYear() + '-' + pad2(d.getMonth() + 1) + '-' + pad2(d.getDate()) + 'T' + pad2(d.getHours()) + ':' + pad2(d.getMinutes());
710
+ }
711
+ // Ham değer (denetimin değeri) → kayıt değeri.
712
+ function toValue(f, raw) {
713
+ switch (f.type) {
714
+ case 'number': case 'money':
715
+ if (raw == null || String(raw).trim() === '') return null;
716
+ var n = Number(String(raw).trim());
717
+ return isFinite(n) ? n : String(raw);
718
+ case 'date': return raw ? String(raw) : null;
719
+ case 'datetime': if (!raw) return null; var d = asDate(raw); return d ? d.toISOString() : String(raw);
720
+ case 'boolean': return raw === true;
721
+ case 'choice':
722
+ var opts = f.options, pick = function (s) { for (var i = 0; i < opts.length; i++) if (String(opts[i].value) === s) return opts[i].value; return s; };
723
+ if (f.multiple) return (Array.isArray(raw) ? raw : []).map(pick);
724
+ return raw == null || raw === '' ? null : pick(String(raw));
725
+ case 'person': case 'file': return raw == null ? null : raw;
726
+ default: return raw == null ? '' : String(raw).trim();
727
+ }
728
+ }
729
+ function toRaw(f, v) {
730
+ switch (f.type) {
731
+ case 'number': case 'money': return v == null ? '' : String(v);
732
+ case 'date': return v ? String(v).slice(0, 10) : '';
733
+ case 'datetime': return isoToLocalInput(v);
734
+ case 'boolean': return v === true;
735
+ case 'choice': return f.multiple ? (Array.isArray(v) ? v.map(String) : []) : v == null ? '' : String(v);
736
+ case 'person': case 'file': return v == null ? null : v;
737
+ default: return v == null ? '' : String(v);
738
+ }
739
+ }
740
+ function isEmpty(f, v) {
741
+ if (v == null || v === '') return true;
742
+ if (Array.isArray(v)) return v.length === 0;
743
+ if (f.type === 'boolean') return v !== true;
744
+ return false;
745
+ }
746
+ function validateField(f, raw) {
747
+ var v = toValue(f, raw);
748
+ if (isEmpty(f, v)) return f.required ? { key: 'required' } : null;
749
+ if (f.type === 'number' || f.type === 'money') {
750
+ if (typeof v !== 'number') return { key: 'notNumber' };
751
+ if (typeof f.min === 'number' && v < f.min) return { key: 'min', vars: { n: fmtNumber(f.min) } };
752
+ if (typeof f.max === 'number' && v > f.max) return { key: 'max', vars: { n: fmtNumber(f.max) } };
753
+ }
754
+ if (f.type === 'date') {
755
+ if (!DATE_ONLY.test(v) || !asDate(v)) return { key: 'notDate' };
756
+ if (typeof f.min === 'string' && v < f.min) return { key: 'min', vars: { n: fmtDate(f.min) } };
757
+ if (typeof f.max === 'string' && v > f.max) return { key: 'max', vars: { n: fmtDate(f.max) } };
758
+ }
759
+ if (f.type === 'datetime' && !asDate(v)) return { key: 'notDate' };
760
+ if (f.type === 'choice') {
761
+ var vals = f.options.map(function (o) { return String(o.value); });
762
+ var list = Array.isArray(v) ? v : [v];
763
+ for (var i = 0; i < list.length; i++) if (vals.indexOf(String(list[i])) < 0) return { key: 'notChoice' };
764
+ }
765
+ if (f.type === 'text' || f.type === 'longText') {
766
+ if (typeof f.minLength === 'number' && v.length < f.minLength) return { key: 'minLength', vars: { n: f.minLength } };
767
+ if (typeof f.maxLength === 'number' && v.length > f.maxLength) return { key: 'maxLength', vars: { n: f.maxLength } };
768
+ if (typeof f.pattern === 'string' && f.pattern) {
769
+ var re = null;
770
+ try { re = new RegExp('^(?:' + f.pattern + ')$', 'u'); } catch (e) { report(e); }
771
+ if (re && !re.test(v)) return { key: 'pattern' };
772
+ }
773
+ }
774
+ return null;
775
+ }
776
+ // RFC 9457 'errors': { alan: ileti | ileti[] } ya da [{ field | name | pointer, detail | message }].
777
+ function errorList(errors) {
778
+ var out = [];
779
+ if (Array.isArray(errors)) {
780
+ errors.forEach(function (it) {
781
+ if (typeof it === 'string') { out.push({ field: null, message: it }); return; }
782
+ if (!it || typeof it !== 'object') return;
783
+ var field = it.field || it.name || it.key || it.property || null;
784
+ if (!field && typeof it.pointer === 'string') field = it.pointer.replace(/^#/, '').split('/').filter(Boolean).pop() || null;
785
+ var msg = it.detail || it.message || it.title;
786
+ if (typeof msg === 'string' && msg) out.push({ field: field ? String(field) : null, message: msg });
787
+ });
788
+ } else if (errors && typeof errors === 'object') {
789
+ for (var k in errors) {
790
+ if (!own(errors, k)) continue;
791
+ var v = Array.isArray(errors[k]) ? errors[k] : [errors[k]];
792
+ v.forEach(function (m) { if (typeof m === 'string' && m) out.push({ field: k, message: m }); });
793
+ }
794
+ }
795
+ return out;
796
+ }
797
+
798
+ class OneForm extends Base {
799
+ static get observedAttributes() { return ['lang', 'action', 'method', 'no-cancel', 'acting-write']; }
800
+ static get props() { return ['fields', 'value', 'submitLabel']; }
801
+ constructor() {
802
+ super();
803
+ this._fields = []; this._raw = {}; this._initial = {}; this._baseline = '{}'; this._errors = {}; this._summary = null; this._summaryList = [];
804
+ this._busy = false; this._dirty = false; this._ids = {};
805
+ }
806
+ get fields() { return this._fields.slice(); }
807
+ set fields(v) {
808
+ this._fields = normalizeFields(v, 'one-form');
809
+ var raw = {}, self = this, init = this._initial || {};
810
+ this._fields.forEach(function (f) { raw[f.key] = own(self._raw, f.key) ? self._raw[f.key] : toRaw(f, own(init, f.key) ? init[f.key] : null); });
811
+ this._raw = raw;
812
+ this._baseline = JSON.stringify(this.value);
813
+ this._errors = {};
814
+ this.render(); this._checkDirty();
815
+ }
816
+ get value() {
817
+ var out = {}, raw = this._raw;
818
+ this._fields.forEach(function (f) { out[f.key] = toValue(f, raw[f.key]); });
819
+ return out;
820
+ }
821
+ set value(v) {
822
+ var src = v && typeof v === 'object' ? v : {}, raw = {};
823
+ this._fields.forEach(function (f) { raw[f.key] = toRaw(f, own(src, f.key) ? src[f.key] : null); });
824
+ this._initial = clone(src);
825
+ this._raw = raw; this._errors = {}; this._summary = null; this._summaryList = [];
826
+ this._baseline = JSON.stringify(this.value);
827
+ this.render(); this._checkDirty();
828
+ }
829
+ get submitLabel() { return this._submitLabel || null; }
830
+ set submitLabel(v) { this._submitLabel = v == null ? null : v; this.render(); }
831
+ get dirty() { return this._dirty; }
832
+ disconnectedCallback() { super.disconnectedCallback(); if (this._dirty) setDirty(false); }
833
+ _checkDirty() {
834
+ var d = JSON.stringify(this.value) !== this._baseline;
835
+ if (d === this._dirty) return;
836
+ this._dirty = d;
837
+ setDirty(d);
838
+ emit(this, 'dirtychange', { dirty: d });
839
+ }
840
+ reset() {
841
+ var base = JSON.parse(this._baseline), raw = {};
842
+ this._fields.forEach(function (f) { raw[f.key] = toRaw(f, base[f.key]); });
843
+ this._raw = raw; this._errors = {}; this._summary = null; this._summaryList = [];
844
+ this.render(); this._checkDirty();
845
+ }
846
+ validate() {
847
+ var self = this, errors = {}, first = null;
848
+ this._fields.forEach(function (f) {
849
+ if (f.readOnly) return;
850
+ var e = validateField(f, self._raw[f.key]);
851
+ if (e) { errors[f.key] = e; if (!first) first = f.key; }
852
+ });
853
+ this._errors = errors;
854
+ this._summary = first ? { key: 'fixErrors' } : null;
855
+ this._summaryList = [];
856
+ this.render();
857
+ if (first) this._focusField(first);
858
+ return !first;
859
+ }
860
+ setErrors(errors, detail) {
861
+ var self = this, map = {}, rest = [], list = errorList(errors);
862
+ list.forEach(function (e) {
863
+ var key = null;
864
+ if (e.field) {
865
+ var want = String(e.field).replace(/^\$\./, '').toLowerCase();
866
+ self._fields.forEach(function (f) { if (f.key.toLowerCase() === want) key = f.key; });
867
+ }
868
+ if (key && !own(map, key)) map[key] = { text: e.message };
869
+ else rest.push(e.message);
870
+ });
871
+ this._errors = map;
872
+ this._summary = detail ? { text: String(detail) } : (list.length ? { key: 'fixErrors' } : null);
873
+ this._summaryList = rest;
874
+ this.render();
875
+ for (var i = 0; i < this._fields.length; i++) if (own(map, this._fields[i].key)) { this._focusField(this._fields[i].key); break; }
876
+ }
877
+ _focusField(key) {
878
+ var id = this._ids[key], el = id ? doc.getElementById(id) : null;
879
+ // Kişi ve dosya alanında odak bileşenin içindeki denetime gider.
880
+ var inner = el && el.querySelector ? el.querySelector('input, select, textarea') : null;
881
+ if (inner) el = inner;
882
+ if (el && typeof el.focus === 'function') el.focus();
883
+ }
884
+ _set(key, raw) {
885
+ this._raw[key] = raw;
886
+ if (own(this._errors, key)) {
887
+ delete this._errors[key];
888
+ var box = this.querySelector('[data-one-error="' + this._ids[key] + '"]');
889
+ var ctl = this._ids[key] ? doc.getElementById(this._ids[key]) : null;
890
+ if (box) { box.textContent = ''; box.hidden = true; }
891
+ if (ctl) ctl.removeAttribute('aria-invalid');
892
+ }
893
+ this._checkDirty();
894
+ }
895
+ _submit() {
896
+ var self = this, lang = this.lang_();
897
+ if (this._busy || actingReadOnly(this)) return Promise.resolve(false);
898
+ if (!this.validate()) return Promise.resolve(false);
899
+ var value = this.value;
900
+ if (!emit(this, 'save', { value: value }, true)) return Promise.resolve(false);
901
+ var action = this.getAttribute('action');
902
+ if (!action) return Promise.resolve(true);
903
+ var u = sameOrigin(action);
904
+ if (!u) { this._summary = { key: 'badSrc' }; this.render(); return Promise.resolve(false); }
905
+ var method = String(this.getAttribute('method') || 'POST').toUpperCase();
906
+ if (method !== 'POST' && method !== 'PUT' && method !== 'PATCH') method = 'POST';
907
+ this._busy = true; this._summary = null; this._summaryList = []; this.render();
908
+ return send(relative(u), { method: method, headers: { 'content-type': 'application/json', accept: 'application/json' }, body: JSON.stringify(value) }).then(function (res) {
909
+ return readJson(res).then(function (body) {
910
+ self._busy = false;
911
+ if (res.ok) {
912
+ self._baseline = JSON.stringify(value);
913
+ self.render(); self._checkDirty();
914
+ if (emit(self, 'saved', { value: value, response: body === undefined ? null : body }, true)) toast('success', t(self.lang_(), 'saved'));
915
+ return true;
916
+ }
917
+ var fail = failure(res.status, body, 'saveError');
918
+ if (body && body.errors) self.setErrors(body.errors, fail.text || null);
919
+ else { self._summary = fail; self.render(); }
920
+ emit(self, 'savefailed', { status: res.status, detail: messageOf(fail, self.lang_()) });
921
+ return false;
922
+ });
923
+ }, function (e) {
924
+ report(e);
925
+ self._busy = false; self._summary = { key: 'networkError' }; self.render();
926
+ emit(self, 'savefailed', { status: 0, detail: t(lang, 'networkError') });
927
+ return false;
928
+ });
929
+ }
930
+ _cancel() {
931
+ var self = this, lang = this.lang_();
932
+ var finish = function () { self.reset(); emit(self, 'cancel', { value: self.value }); };
933
+ if (!this._dirty || !w.one || typeof w.one.confirm !== 'function') { finish(); return Promise.resolve(); }
934
+ return w.one.confirm({ title: t(lang, 'discardTitle'), message: t(lang, 'discard'), severity: 'warn', acceptLabel: t(lang, 'discardAccept'), rejectLabel: t(lang, 'keepEditing') })
935
+ .then(function (ok) { if (ok) finish(); });
936
+ }
937
+ _control(f, lang, id, describedBy) {
938
+ var self = this, raw = this._raw[f.key], el;
939
+ var common = { id: id, 'data-one-focus': 'field:' + f.key, 'aria-describedby': describedBy || null, 'aria-required': f.required ? 'true' : null,
940
+ 'aria-invalid': own(this._errors, f.key) ? 'true' : null, disabled: f.readOnly ? true : null };
941
+ var ph = f.placeholder != null ? textOf(f.placeholder, lang) : null;
942
+ switch (f.type) {
943
+ case 'longText':
944
+ el = h('textarea', Object.assign({ 'class': 'one-textarea', placeholder: ph, maxlength: typeof f.maxLength === 'number' ? f.maxLength : null }, common));
945
+ el.value = raw == null ? '' : raw;
946
+ listen(quiet(el), 'input', function () { self._set(f.key, el.value); });
947
+ return el;
948
+ case 'boolean':
949
+ el = h('input', Object.assign({ type: 'checkbox' }, common));
950
+ el.checked = raw === true;
951
+ listen(quiet(el), 'change', function () { self._set(f.key, el.checked); });
952
+ return el;
953
+ case 'choice':
954
+ el = h('select', Object.assign({ 'class': 'one-select', multiple: f.multiple ? true : null }, common));
955
+ if (!f.multiple) add(el, h('option', { value: '', text: t(lang, 'choose') }));
956
+ f.options.forEach(function (o) {
957
+ var opt = h('option', { value: String(o.value), text: textOf(o.label, lang) });
958
+ opt.selected = f.multiple ? (Array.isArray(raw) && raw.indexOf(String(o.value)) >= 0) : String(raw) === String(o.value);
959
+ add(el, opt);
960
+ });
961
+ listen(quiet(el), 'change', function () {
962
+ if (f.multiple) { var out = []; for (var i = 0; i < el.options.length; i++) if (el.options[i].selected) out.push(el.options[i].value); self._set(f.key, out); }
963
+ else self._set(f.key, el.value);
964
+ });
965
+ return el;
966
+ case 'person':
967
+ el = h('one-person-picker', { id: id, 'data-one-focus': 'field:' + f.key, required: f.required ? true : null, multiple: f.multiple ? true : null,
968
+ src: f.src || null, 'aria-describedby': describedBy || null, 'aria-invalid': own(this._errors, f.key) ? 'true' : null, disabled: f.readOnly ? true : null });
969
+ el.label = f.label;
970
+ el.value = raw;
971
+ listen(el, 'change', function (ev) { ev.stopPropagation(); self._set(f.key, ev.detail ? ev.detail.value : null); });
972
+ return el;
973
+ case 'file':
974
+ el = h('one-file-upload', { id: id, 'data-one-focus': 'field:' + f.key, accept: f.accept || null, 'max-size': typeof f.maxSize === 'number' ? String(f.maxSize) : null,
975
+ action: f.action || null, multiple: f.multiple ? true : null, required: f.required ? true : null, 'aria-describedby': describedBy || null,
976
+ 'aria-invalid': own(this._errors, f.key) ? 'true' : null, disabled: f.readOnly ? true : null });
977
+ el.label = f.label;
978
+ el.value = raw;
979
+ listen(el, 'change', function (ev) { ev.stopPropagation(); self._set(f.key, ev.detail ? ev.detail.value : null); });
980
+ return el;
981
+ default:
982
+ var type = f.type === 'number' || f.type === 'money' ? 'number' : f.type === 'date' ? 'date' : f.type === 'datetime' ? 'datetime-local' : 'text';
983
+ el = h('input', Object.assign({ type: type, 'class': 'one-input', placeholder: ph,
984
+ step: f.type === 'money' ? '0.01' : f.type === 'number' ? 'any' : null,
985
+ inputmode: f.type === 'money' || f.type === 'number' ? 'decimal' : null,
986
+ min: f.min != null && (f.type === 'number' || f.type === 'money' || f.type === 'date') ? String(f.min) : null,
987
+ max: f.max != null && (f.type === 'number' || f.type === 'money' || f.type === 'date') ? String(f.max) : null,
988
+ maxlength: f.type === 'text' && typeof f.maxLength === 'number' ? f.maxLength : null }, common));
989
+ el.value = raw == null ? '' : raw;
990
+ listen(quiet(el), 'input', function () { self._set(f.key, el.value); });
991
+ if (type !== 'text') listen(el, 'change', function () { self._set(f.key, el.value); });
992
+ return el;
993
+ }
994
+ }
995
+ draw() {
996
+ var self = this, lang = this.lang_(), readOnly = actingReadOnly(this);
997
+ clear(this);
998
+ this._ids = {};
999
+ var form = h('form', { 'class': 'one-form one-stack', novalidate: true, 'aria-busy': this._busy ? 'true' : null });
1000
+ listen(form, 'submit', function (ev) { ev.preventDefault(); self._submit(); });
1001
+ if (readOnly) add(form, h('div', { 'class': 'one-message one-message-info', role: 'note', text: t(lang, 'actingReadOnly') }));
1002
+ if (this._summary) {
1003
+ var box = h('div', { 'class': 'one-message one-message-error', role: 'alert' }, h('p', { text: messageOf(this._summary, lang) }));
1004
+ if (this._summaryList.length) add(box, h('ul', null, this._summaryList.map(function (m) { return h('li', { text: m }); })));
1005
+ add(form, box);
1006
+ }
1007
+ this._fields.forEach(function (f) {
1008
+ var id = uid('field'), helpId = f.help != null ? id + '-help' : null, errId = id + '-error';
1009
+ self._ids[f.key] = id;
1010
+ var err = own(self._errors, f.key) ? messageOf(self._errors[f.key], lang) : '';
1011
+ var described = [helpId, err ? errId : null].filter(Boolean).join(' ');
1012
+ var control = self._control(f, lang, id, described);
1013
+ var label = textOf(f.label, lang);
1014
+ var wrap = h('div', { 'class': 'one-field' + (f.type === 'boolean' ? ' one-field-check' : ''), 'data-field': f.key });
1015
+ if (f.type === 'boolean') add(wrap, h('label', { 'for': id, 'class': 'one-check' }, [control, h('span', { text: label })]));
1016
+ else if (f.type === 'person' || f.type === 'file') add(wrap, control);
1017
+ else {
1018
+ add(wrap, h('label', { 'for': id, 'class': 'one-label' }, [label, f.required ? h('span', { 'class': 'one-required', 'aria-hidden': 'true', text: ' *' }) : null,
1019
+ f.required ? h('span', { 'class': 'one-sr-only', text: ' ' + t(lang, 'requiredMark') }) : null]));
1020
+ add(wrap, control);
1021
+ }
1022
+ if (helpId) add(wrap, h('p', { id: helpId, 'class': 'one-help', text: textOf(f.help, lang) }));
1023
+ add(wrap, h('p', { id: errId, 'class': 'one-field-error', 'data-one-error': id, hidden: err ? null : true, text: err }));
1024
+ add(form, wrap);
1025
+ });
1026
+ var submit = h('button', { type: 'submit', 'class': 'one-btn one-btn-primary', 'data-one-focus': 'submit', disabled: this._busy || readOnly ? true : null,
1027
+ text: this._busy ? t(lang, 'saving') : (this._submitLabel ? textOf(this._submitLabel, lang) : t(lang, 'save')) });
1028
+ var actions = h('div', { 'class': 'one-row one-form-actions' }, submit);
1029
+ if (!this.hasAttribute('no-cancel')) {
1030
+ var cancel = h('button', { type: 'button', 'class': 'one-btn', 'data-one-focus': 'cancel', disabled: this._busy ? true : null, text: t(lang, 'cancel') });
1031
+ listen(cancel, 'click', function () { self._cancel(); });
1032
+ add(actions, cancel);
1033
+ }
1034
+ add(form, actions);
1035
+ add(this, form);
1036
+ }
1037
+ }
1038
+
1039
+ // ══ <one-filter> ════════════════════════════════════════════════════════════════════════════════════════
1040
+ var FILTER_TYPES = ['text', 'choice', 'date', 'dateRange', 'boolean'];
1041
+ class OneFilter extends Base {
1042
+ static get observedAttributes() { return ['lang', 'for']; }
1043
+ static get props() { return ['fields']; }
1044
+ constructor() { super(); this._fields = []; this._values = {}; this._drafts = {}; this._error = null; this._timer = 0; }
1045
+ get fields() { return this._fields.slice(); }
1046
+ set fields(v) {
1047
+ var list = normalizeFields(v, 'one-filter');
1048
+ list.forEach(function (f) { if (FILTER_TYPES.indexOf(f.type) < 0) throw new TypeError('one-filter: tür text | choice | date | dateRange | boolean olmalı'); });
1049
+ this._fields = list; this._values = {}; this._drafts = {}; this.render();
1050
+ }
1051
+ get value() { return { values: clone(this._values), params: this._params() }; }
1052
+ clear() { this._values = {}; this._drafts = {}; this._error = null; this.render(); this._emit(); }
1053
+ _params() {
1054
+ var p = {}, v = this._values;
1055
+ this._fields.forEach(function (f) {
1056
+ var x = v[f.key];
1057
+ if (x == null || x === '') return;
1058
+ if (f.type === 'dateRange') {
1059
+ if (x.from) p[f.fromParam || f.key + 'From'] = x.from;
1060
+ if (x.to) p[f.toParam || f.key + 'To'] = x.to;
1061
+ } else p[f.param || (f.type === 'text' ? 'q' : f.key)] = String(x);
1062
+ });
1063
+ return p;
1064
+ }
1065
+ _emit() {
1066
+ var detail = this.value;
1067
+ var target = this.getAttribute('for') ? doc.getElementById(this.getAttribute('for')) : null;
1068
+ emit(this, 'change', detail);
1069
+ if (target && typeof target.applyFilter === 'function') target.applyFilter(detail);
1070
+ }
1071
+ _set(key, value, later) {
1072
+ var self = this;
1073
+ if (value == null || value === '' || (typeof value === 'object' && !value.from && !value.to)) delete this._values[key];
1074
+ else this._values[key] = value;
1075
+ w.clearTimeout(this._timer);
1076
+ if (later) this._timer = w.setTimeout(function () { self._emit(); }, 300);
1077
+ else this._emit();
1078
+ }
1079
+ draw() {
1080
+ var self = this, lang = this.lang_();
1081
+ clear(this);
1082
+ var row = h('div', { 'class': 'one-filter one-row', role: 'search' });
1083
+ this._fields.forEach(function (f) {
1084
+ var label = textOf(f.label, lang), id = uid('filter'), cur = self._values[f.key];
1085
+ if (f.type === 'dateRange') {
1086
+ // Geçersiz aralık (başlangıç > bitiş) yayılmaz ama kullanıcının yazdığı değer ekranda kalır.
1087
+ var range = self._drafts[f.key] || (cur && typeof cur === 'object' ? cur : { from: '', to: '' });
1088
+ var fromId = id + '-from', toId = id + '-to';
1089
+ var from = h('input', { id: fromId, type: 'date', 'class': 'one-input', 'data-one-focus': 'from:' + f.key, 'aria-invalid': self._error === f.key ? 'true' : null });
1090
+ var to = h('input', { id: toId, type: 'date', 'class': 'one-input', 'data-one-focus': 'to:' + f.key, 'aria-invalid': self._error === f.key ? 'true' : null });
1091
+ from.value = range.from || ''; to.value = range.to || '';
1092
+ var update = function () {
1093
+ self._drafts[f.key] = { from: from.value, to: to.value };
1094
+ if (from.value && to.value && from.value > to.value) { self._error = f.key; self.render(); return; }
1095
+ var had = self._error === f.key; self._error = null;
1096
+ self._set(f.key, { from: from.value, to: to.value }, false);
1097
+ if (had) self.render();
1098
+ };
1099
+ listen(quiet(from), 'change', update); listen(quiet(to), 'change', update);
1100
+ var group = h('fieldset', { 'class': 'one-filter-range' }, [h('legend', { 'class': 'one-label', text: label }),
1101
+ h('div', { 'class': 'one-row' }, [
1102
+ h('label', { 'for': fromId, 'class': 'one-sr-only', text: label + ' ' + t(lang, 'from') }), from,
1103
+ h('span', { 'aria-hidden': 'true', text: '-' }),
1104
+ h('label', { 'for': toId, 'class': 'one-sr-only', text: label + ' ' + t(lang, 'to') }), to])]);
1105
+ if (self._error === f.key) add(group, h('p', { 'class': 'one-field-error', role: 'alert', text: t(lang, 'rangeError') }));
1106
+ add(row, group);
1107
+ return;
1108
+ }
1109
+ var control;
1110
+ if (f.type === 'text') {
1111
+ control = h('input', { id: id, type: 'search', 'class': 'one-input', autocomplete: 'off', 'data-one-focus': 'f:' + f.key, placeholder: f.placeholder != null ? textOf(f.placeholder, lang) : null });
1112
+ control.value = cur || '';
1113
+ listen(quiet(control), 'input', function () { self._set(f.key, control.value.trim(), true); });
1114
+ } else if (f.type === 'date') {
1115
+ control = h('input', { id: id, type: 'date', 'class': 'one-input', 'data-one-focus': 'f:' + f.key });
1116
+ control.value = cur || '';
1117
+ listen(quiet(control), 'change', function () { self._set(f.key, control.value, false); });
1118
+ } else {
1119
+ var opts = f.type === 'boolean' ? [{ value: 'true', label: t(lang, 'yes') }, { value: 'false', label: t(lang, 'no') }] : f.options;
1120
+ control = h('select', { id: id, 'class': 'one-select', 'data-one-focus': 'f:' + f.key }, h('option', { value: '', text: t(lang, 'all') }));
1121
+ opts.forEach(function (o) { var opt = h('option', { value: String(o.value), text: textOf(o.label, lang) }); opt.selected = cur != null && String(cur) === String(o.value); add(control, opt); });
1122
+ listen(quiet(control), 'change', function () { self._set(f.key, control.value, false); });
1123
+ }
1124
+ add(row, h('div', { 'class': 'one-field' }, [h('label', { 'for': id, 'class': 'one-label', text: label }), control]));
1125
+ });
1126
+ var reset = h('button', { type: 'button', 'class': 'one-btn one-btn-text', 'data-one-focus': 'clear', text: t(lang, 'clear') });
1127
+ listen(reset, 'click', function () { self.clear(); });
1128
+ add(row, reset);
1129
+ add(this, row);
1130
+ }
1131
+ }
1132
+
1133
+ // ══ <one-person-picker> ═════════════════════════════════════════════════════════════════════════════════
1134
+ // Kayıtta yalnız kimlik saklanmışsa (metin) değer KAYBEDİLMEZ: ad bilinmediği için kimlik gösterilir.
1135
+ function cleanPerson(p) {
1136
+ if (typeof p === 'string' && /^[A-Za-z0-9_-]{1,64}$/.test(p)) return { id: p, name: p, title: null, department: null };
1137
+ if (!p || typeof p !== 'object' || typeof p.id !== 'string' || typeof p.name !== 'string') return null;
1138
+ return { id: p.id, name: p.name, title: typeof p.title === 'string' ? p.title : null, department: typeof p.department === 'string' ? p.department : null };
1139
+ }
1140
+ class OnePersonPicker extends Base {
1141
+ static get observedAttributes() { return ['lang', 'label', 'multiple', 'required', 'disabled']; }
1142
+ static get props() { return ['value', 'label']; }
1143
+ constructor() {
1144
+ super();
1145
+ this._value = null; this._label = null; this._q = ''; this._items = []; this._open = false; this._active = -1;
1146
+ this._status = 'idle'; this._seq = 0; this._timer = 0; this._ids = { input: uid('person'), list: uid('people') };
1147
+ var self = this;
1148
+ listen(this, 'focusout', function (ev) { if (!ev.relatedTarget || !self.contains(ev.relatedTarget)) { self._open = false; self._update(); } });
1149
+ }
1150
+ get value() { return clone(this._value); }
1151
+ set value(v) {
1152
+ if (this.hasAttribute('multiple')) this._value = (Array.isArray(v) ? v : v ? [v] : []).map(cleanPerson).filter(Boolean);
1153
+ else { var p = Array.isArray(v) ? v[0] : v; this._value = cleanPerson(p); }
1154
+ this._q = !this.hasAttribute('multiple') && this._value ? this._value.name : '';
1155
+ this.render();
1156
+ }
1157
+ get label() { return this._label; }
1158
+ set label(v) { this._label = v == null ? null : v; this.render(); }
1159
+ _multi() { return this.hasAttribute('multiple'); }
1160
+ _changed() { emit(this, 'change', { value: this.value }); }
1161
+ _search(q) {
1162
+ var self = this;
1163
+ w.clearTimeout(this._timer);
1164
+ if (q.length < 2) { this._seq += 1; this._items = []; this._open = false; this._status = q.length ? 'min' : 'idle'; this._update(); return; }
1165
+ this._status = 'loading'; this._update();
1166
+ this._timer = w.setTimeout(function () {
1167
+ var u = sameOrigin(self.getAttribute('src') || '${PEOPLE_SEARCH_PATH}');
1168
+ if (!u) { self._status = 'error'; self._update(); report(new Error('one-person-picker: src uygulamanın kendi adresi olmalı')); return; }
1169
+ u.searchParams.set('q', q); u.searchParams.set('lang', self.lang_());
1170
+ var my = ++self._seq;
1171
+ send(relative(u), { headers: { accept: 'application/json' } }).then(function (res) {
1172
+ return readJson(res).then(function (body) {
1173
+ if (my !== self._seq) return;
1174
+ if (!res.ok || !body || !Array.isArray(body.items)) { self._status = 'error'; self._open = false; self._update(); return; }
1175
+ self._items = body.items.map(cleanPerson).filter(Boolean).slice(0, 20);
1176
+ self._status = 'ready'; self._open = true; self._active = self._items.length ? 0 : -1;
1177
+ self._update();
1178
+ });
1179
+ }, function (e) { if (my !== self._seq) return; report(e); self._status = 'error'; self._open = false; self._update(); });
1180
+ }, 300);
1181
+ }
1182
+ _choose(p) {
1183
+ if (!p) return;
1184
+ if (this._multi()) {
1185
+ var list = this._value || [];
1186
+ if (!list.some(function (x) { return x.id === p.id; })) list.push(p);
1187
+ this._value = list; this._q = '';
1188
+ } else { this._value = p; this._q = p.name; }
1189
+ this._open = false; this._items = []; this._active = -1; this._status = 'idle';
1190
+ this.render();
1191
+ var input = doc.getElementById(this._ids.input);
1192
+ if (input) input.focus();
1193
+ this._changed();
1194
+ }
1195
+ // Liste ve durum satırı giriş alanına dokunmadan güncellenir (yazarken odak ve imleç kaybolmaz).
1196
+ _update() {
1197
+ var lang = this.lang_(), self = this;
1198
+ var input = doc.getElementById(this._ids.input), list = doc.getElementById(this._ids.list), status = this.querySelector('[data-one-status]');
1199
+ if (!input || !list || !status) return;
1200
+ clear(list);
1201
+ this._items.forEach(function (p, i) {
1202
+ var sub = [p.title, p.department].filter(Boolean).join(' - ');
1203
+ var opt = h('li', { id: self._ids.list + '-' + i, role: 'option', 'class': 'one-option', 'aria-selected': i === self._active ? 'true' : 'false' },
1204
+ [h('span', { 'class': 'one-option-main', text: p.name }), sub ? h('span', { 'class': 'one-option-sub one-muted', text: sub }) : null]);
1205
+ listen(opt, 'mousedown', function (ev) { ev.preventDefault(); });
1206
+ listen(opt, 'click', function () { self._choose(p); });
1207
+ add(list, opt);
1208
+ });
1209
+ var open = this._open && this._items.length > 0;
1210
+ list.hidden = !open;
1211
+ input.setAttribute('aria-expanded', open ? 'true' : 'false');
1212
+ if (open && this._active >= 0) input.setAttribute('aria-activedescendant', this._ids.list + '-' + this._active);
1213
+ else input.removeAttribute('aria-activedescendant');
1214
+ var msg = { min: 'personMin', loading: 'personSearching', error: 'personError' }[this._status];
1215
+ if (this._status === 'ready') msg = this._items.length ? null : 'personNone';
1216
+ status.textContent = this._status === 'ready' && this._items.length ? t(lang, 'personResults', { count: this._items.length }) : msg ? t(lang, msg) : '';
1217
+ status.className = 'one-help' + (this._status === 'error' ? ' one-field-error' : '');
1218
+ }
1219
+ draw() {
1220
+ var self = this, lang = this.lang_(), multi = this._multi(), disabled = this.hasAttribute('disabled');
1221
+ clear(this);
1222
+ var label = this._label != null ? textOf(this._label, lang) : (this.getAttribute('label') || t(lang, 'personLabel'));
1223
+ var wrap = h('div', { 'class': 'one-field one-combobox' });
1224
+ add(wrap, h('label', { 'for': this._ids.input, 'class': 'one-label' }, [label,
1225
+ this.hasAttribute('required') ? h('span', { 'class': 'one-required', 'aria-hidden': 'true', text: ' *' }) : null,
1226
+ this.hasAttribute('required') ? h('span', { 'class': 'one-sr-only', text: ' ' + t(lang, 'requiredMark') }) : null]));
1227
+ if (multi && this._value && this._value.length) {
1228
+ add(wrap, h('ul', { 'class': 'one-chips', 'aria-label': label }, this._value.map(function (p) {
1229
+ var rm = h('button', { type: 'button', 'class': 'one-chip-remove', 'aria-label': t(lang, 'remove', { name: p.name }), 'data-one-focus': 'rm:' + p.id, disabled: disabled ? true : null, text: '×' });
1230
+ listen(rm, 'click', function () { self._value = self._value.filter(function (x) { return x.id !== p.id; }); self.render(); self._changed(); });
1231
+ return h('li', { 'class': 'one-chip' }, [h('span', { text: p.name }), rm]);
1232
+ })));
1233
+ }
1234
+ var described = [this.getAttribute('aria-describedby'), this._ids.input + '-status'].filter(Boolean).join(' ');
1235
+ var input = h('input', { id: this._ids.input, type: 'text', 'class': 'one-input', role: 'combobox', autocomplete: 'off', 'aria-autocomplete': 'list',
1236
+ 'aria-expanded': 'false', 'aria-controls': this._ids.list, 'aria-describedby': described, placeholder: t(lang, 'personPlaceholder'),
1237
+ 'aria-required': this.hasAttribute('required') ? 'true' : null, 'aria-invalid': this.getAttribute('aria-invalid'), disabled: disabled ? true : null, 'data-one-focus': 'input' });
1238
+ input.value = this._q;
1239
+ listen(input, 'input', function () {
1240
+ self._q = input.value;
1241
+ if (!multi && self._value) { self._value = null; self._changed(); }
1242
+ self._search(input.value.trim());
1243
+ });
1244
+ listen(input, 'keydown', function (ev) {
1245
+ var n = self._items.length;
1246
+ if (ev.key === 'ArrowDown') { ev.preventDefault(); if (!self._open && n) self._open = true; else if (n) self._active = (self._active + 1) % n; self._update(); }
1247
+ else if (ev.key === 'ArrowUp') { ev.preventDefault(); if (n) { self._active = self._active <= 0 ? n - 1 : self._active - 1; self._update(); } }
1248
+ else if (ev.key === 'Enter') { if (self._open && self._active >= 0) { ev.preventDefault(); self._choose(self._items[self._active]); } }
1249
+ else if (ev.key === 'Escape') { if (self._open) { ev.preventDefault(); self._open = false; self._update(); } }
1250
+ });
1251
+ // Öneri listesi giriş alanının altında AKIŞ İÇİNDEDİR (mutlak/sabit konum YOK): Portal iframe'i içerik boyunda çizdiği
1252
+ // için akış dışındaki bir açılır liste sayfanın altında kesilirdi (D-76 U4); akış içindeki liste yüksekliği büyütür.
1253
+ add(wrap, h('div', { 'class': 'one-combobox-control' }, [input, h('ul', { id: this._ids.list, role: 'listbox', 'class': 'one-listbox', 'aria-label': label, hidden: true })]));
1254
+ add(wrap, h('p', { id: this._ids.input + '-status', 'class': 'one-help', role: 'status', 'aria-live': 'polite', 'data-one-status': '' }));
1255
+ add(this, wrap);
1256
+ this._update();
1257
+ }
1258
+ }
1259
+
1260
+ // ══ <one-file-upload> ═══════════════════════════════════════════════════════════════════════════════════
1261
+ function accepts(accept, file) {
1262
+ if (!accept) return true;
1263
+ var name = String(file.name || '').toLowerCase(), type = String(file.type || '').toLowerCase();
1264
+ return accept.split(',').some(function (a) {
1265
+ a = a.trim().toLowerCase();
1266
+ if (!a) return false;
1267
+ if (a.charAt(0) === '.') return name.length > a.length && name.slice(-a.length) === a;
1268
+ if (a.slice(-2) === '/*') return type.indexOf(a.slice(0, -1)) === 0;
1269
+ return type === a;
1270
+ });
1271
+ }
1272
+ // Başlık değeri yalnız ASCII taşıyabilir: Türkçe harfler karşılığına çevrilir, kalan her şey '_' olur.
1273
+ function asciiName(n) {
1274
+ var s = String(n || '').replace(/[çÇğĞıİöÖşŞüÜ]/g, function (c) { return ASCII[c]; }).replace(/[^\x20-\x7e]/g, '_').trim().slice(0, 200);
1275
+ return s || 'dosya';
1276
+ }
1277
+ class OneFileUpload extends Base {
1278
+ static get observedAttributes() { return ['lang', 'label', 'accept', 'max-size', 'multiple', 'required', 'disabled']; }
1279
+ static get props() { return ['value', 'label']; }
1280
+ constructor() { super(); this._value = null; this._label = null; this._jobs = []; this._id = uid('upload'); }
1281
+ get value() { return clone(this._value); }
1282
+ set value(v) {
1283
+ var clean = function (f) { return f && typeof f === 'object' && typeof f.key === 'string' ? { key: f.key, name: String(f.name || f.key), size: Number(f.size) || 0, contentType: f.contentType } : null; };
1284
+ this._value = this.hasAttribute('multiple') ? (Array.isArray(v) ? v : v ? [v] : []).map(clean).filter(Boolean) : clean(Array.isArray(v) ? v[0] : v);
1285
+ this.render();
1286
+ }
1287
+ get label() { return this._label; }
1288
+ set label(v) { this._label = v == null ? null : v; this.render(); }
1289
+ _maxSize() { var n = parseInt(this.getAttribute('max-size') || '', 10); return n > 0 ? n : ${FILE_UPLOAD_DEFAULT_MAX_BYTES}; }
1290
+ _pick(files) {
1291
+ var self = this, list = Array.prototype.slice.call(files || []);
1292
+ if (!this.hasAttribute('multiple')) list = list.slice(0, 1);
1293
+ list.forEach(function (file) {
1294
+ var job = { name: String(file.name || 'dosya'), state: 'error', progress: 0, message: null };
1295
+ if (!accepts(self.getAttribute('accept'), file)) job.message = { key: 'badType', vars: { name: job.name } };
1296
+ else if (file.size > self._maxSize()) job.message = { key: 'tooLarge', vars: { name: job.name, max: fmtSize(self._maxSize()) } };
1297
+ else { job.state = 'uploading'; job.message = { key: 'uploading', vars: { name: job.name } }; }
1298
+ self._jobs.push(job);
1299
+ if (job.state === 'uploading') self._upload(file, job);
1300
+ });
1301
+ this.render();
1302
+ }
1303
+ _upload(file, job) {
1304
+ var self = this, u = sameOrigin(this.getAttribute('action') || '${FILE_UPLOAD_DEFAULT_ACTION}');
1305
+ var finish = function (state, message, info) {
1306
+ job.state = state; job.message = message; job.progress = state === 'done' ? 100 : job.progress;
1307
+ if (info) {
1308
+ if (self.hasAttribute('multiple')) self._value = (self._value || []).concat([info]);
1309
+ else self._value = info;
1310
+ }
1311
+ self.render();
1312
+ if (info) { emit(self, 'uploaded', { file: clone(info) }); emit(self, 'change', { value: self.value }); }
1313
+ };
1314
+ if (!u) { finish('error', { key: 'badSrc' }); return; }
1315
+ whenToken().then(function () {
1316
+ var xhr = new w.XMLHttpRequest();
1317
+ xhr.open('POST', relative(u));
1318
+ var token = w.one && w.one.token;
1319
+ if (token) xhr.setRequestHeader('authorization', 'Bearer ' + token);
1320
+ xhr.setRequestHeader('content-type', file.type || 'application/octet-stream');
1321
+ xhr.setRequestHeader(self.getAttribute('name-header') || 'x-file-name', asciiName(job.name));
1322
+ xhr.setRequestHeader('accept', 'application/json');
1323
+ if (xhr.upload) xhr.upload.addEventListener('progress', function (ev) {
1324
+ if (ev.lengthComputable && ev.total > 0) { job.progress = Math.min(99, Math.round((ev.loaded / ev.total) * 100)); self._progress(job); }
1325
+ });
1326
+ xhr.addEventListener('load', function () {
1327
+ var body; try { body = xhr.responseText ? JSON.parse(xhr.responseText) : null; } catch (e) { body = undefined; }
1328
+ if (xhr.status >= 200 && xhr.status < 300 && body && typeof body.key === 'string') {
1329
+ finish('done', { key: 'uploaded', vars: { name: job.name } }, { key: body.key, name: job.name, size: Number(body.size) || file.size || 0, contentType: body.contentType || file.type || undefined });
1330
+ } else {
1331
+ var fail = failure(xhr.status, body, 'uploadError');
1332
+ finish('error', fail.key === 'uploadError' ? { key: 'uploadError', vars: { name: job.name } } : fail.text ? { text: job.name + ': ' + fail.text } : fail);
1333
+ }
1334
+ });
1335
+ var broken = function () { finish('error', { key: 'uploadError', vars: { name: job.name } }); };
1336
+ xhr.addEventListener('error', broken);
1337
+ xhr.addEventListener('abort', broken);
1338
+ xhr.send(file);
1339
+ });
1340
+ }
1341
+ _progress(job) {
1342
+ var i = this._jobs.indexOf(job), bar = this.querySelector('[data-one-job="' + i + '"]');
1343
+ if (bar) bar.value = job.progress;
1344
+ }
1345
+ draw() {
1346
+ var self = this, lang = this.lang_(), disabled = this.hasAttribute('disabled');
1347
+ clear(this);
1348
+ var label = this._label != null ? textOf(this._label, lang) : (this.getAttribute('label') || t(lang, 'fileLabel'));
1349
+ var accept = this.getAttribute('accept'), max = fmtSize(this._maxSize()), helpId = this._id + '-help';
1350
+ var described = [this.getAttribute('aria-describedby'), helpId].filter(Boolean).join(' ');
1351
+ var input = h('input', { id: this._id, type: 'file', 'class': 'one-input one-file-input', accept: accept || null, multiple: this.hasAttribute('multiple') ? true : null,
1352
+ 'aria-describedby': described, 'aria-required': this.hasAttribute('required') ? 'true' : null, 'aria-invalid': this.getAttribute('aria-invalid'), disabled: disabled ? true : null, 'data-one-focus': 'input' });
1353
+ listen(quiet(input), 'change', function () { self._pick(input.files); input.value = ''; });
1354
+ var wrap = h('div', { 'class': 'one-field one-upload' }, [
1355
+ h('label', { 'for': this._id, 'class': 'one-label' }, [label,
1356
+ this.hasAttribute('required') ? h('span', { 'class': 'one-required', 'aria-hidden': 'true', text: ' *' }) : null,
1357
+ this.hasAttribute('required') ? h('span', { 'class': 'one-sr-only', text: ' ' + t(lang, 'requiredMark') }) : null]),
1358
+ input,
1359
+ h('p', { id: helpId, 'class': 'one-help', text: accept ? t(lang, 'allowed', { types: accept.split(',').map(function (s) { return s.trim(); }).filter(Boolean).join(', '), max: max }) : t(lang, 'maxOnly', { max: max }) })
1360
+ ]);
1361
+ var items = [];
1362
+ this._jobs.forEach(function (job, i) {
1363
+ if (job.state === 'done') return;
1364
+ items.push(h('li', { 'class': 'one-upload-item' }, [
1365
+ h('span', { role: job.state === 'error' ? 'alert' : 'status', 'class': job.state === 'error' ? 'one-field-error' : 'one-muted', text: messageOf(job.message, lang) }),
1366
+ job.state === 'uploading' ? h('progress', { max: '100', value: String(job.progress), 'data-one-job': String(i), 'aria-label': messageOf(job.message, lang) }) : null
1367
+ ]));
1368
+ });
1369
+ var files = this._value == null ? [] : Array.isArray(this._value) ? this._value : [this._value];
1370
+ files.forEach(function (f) {
1371
+ var rm = h('button', { type: 'button', 'class': 'one-btn one-btn-text', 'aria-label': t(lang, 'remove', { name: f.name }), 'data-one-focus': 'rm:' + f.key, disabled: disabled ? true : null, text: '×' });
1372
+ listen(rm, 'click', function () {
1373
+ self._value = Array.isArray(self._value) ? self._value.filter(function (x) { return x.key !== f.key; }) : null;
1374
+ self.render(); emit(self, 'change', { value: self.value });
1375
+ });
1376
+ items.push(h('li', { 'class': 'one-upload-item' }, [h('span', { text: f.name }), h('span', { 'class': 'one-muted', text: fmtSize(f.size) }), rm]));
1377
+ });
1378
+ if (items.length) add(wrap, h('ul', { 'class': 'one-upload-list' }, items));
1379
+ add(this, wrap);
1380
+ }
1381
+ }
1382
+
1383
+ // ══ <one-chart> ═════════════════════════════════════════════════════════════════════════════════════════
1384
+ function chartData(d) {
1385
+ if (Array.isArray(d)) return { labels: d.map(function (x) { return x && x.label; }), series: [{ name: '', values: d.map(function (x) { return x ? x.value : 0; }) }] };
1386
+ if (d && Array.isArray(d.labels) && Array.isArray(d.series)) return { labels: d.labels, series: d.series.filter(function (s) { return s && Array.isArray(s.values); }) };
1387
+ return { labels: [], series: [] };
1388
+ }
1389
+ function num(v) { var n = Number(v); return isFinite(n) ? n : 0; }
1390
+ function niceStep(span) {
1391
+ if (span <= 0) return 1;
1392
+ var raw = span / 4, mag = Math.pow(10, Math.floor(Math.log(raw) / Math.LN10)), norm = raw / mag;
1393
+ return (norm <= 1 ? 1 : norm <= 2 ? 2 : norm <= 5 ? 5 : 10) * mag;
1394
+ }
1395
+ function shorten(s, n) { s = String(s); return s.length > n ? s.slice(0, Math.max(1, n - 1)) + '…' : s; }
1396
+ class OneChart extends Base {
1397
+ static get observedAttributes() { return ['lang', 'type', 'label', 'unit']; }
1398
+ static get props() { return ['data', 'label']; }
1399
+ constructor() { super(); this._data = null; this._label = null; }
1400
+ get data() { return this._data; }
1401
+ set data(v) { this._data = v == null ? null : clone(v); this.render(); }
1402
+ get label() { return this._label; }
1403
+ set label(v) { this._label = v == null ? null : v; this.render(); }
1404
+ _fmt(v) { var u = this.getAttribute('unit'); return fmtNumber(v, 2) + (u ? ' ' + u : ''); }
1405
+ draw() {
1406
+ var self = this, lang = this.lang_(), d = chartData(this._data), type = this.getAttribute('type');
1407
+ if (type !== 'line' && type !== 'pie') type = 'bar';
1408
+ clear(this);
1409
+ var title = this._label != null ? textOf(this._label, lang) : (this.getAttribute('label') || t(lang, 'chart'));
1410
+ var labels = d.labels.map(function (l) { return textOf(l, lang); });
1411
+ var series = d.series.map(function (s, i) { return { name: textOf(s.name, lang) || (d.series.length === 1 ? title : String(i + 1)), values: labels.map(function (_, j) { return num(s.values[j]); }) }; });
1412
+ var fig = h('figure', { 'class': 'one-chart' }, h('figcaption', { 'class': 'one-chart-title', text: title }));
1413
+ if (labels.length === 0 || series.length === 0) { add(fig, h('p', { 'class': 'one-empty', text: t(lang, 'chartEmpty') })); add(this, fig); return; }
1414
+ var W = 640, H = 320, root = svg('svg', { viewBox: '0 0 ' + W + ' ' + H, role: 'img', 'aria-label': title + ' (' + t(lang, 'chartData') + ')', preserveAspectRatio: 'xMidYMid meet', focusable: 'false' });
1415
+ if (type === 'pie') this._pie(root, labels, series[0], W, H, lang);
1416
+ else this._axes(root, labels, series, W, H, type);
1417
+ add(fig, root);
1418
+ var legendItems = type === 'pie' ? labels : series.map(function (s) { return s.name; });
1419
+ if (legendItems.length > 1 || type === 'pie') {
1420
+ var total = type === 'pie' ? series[0].values.reduce(function (a, b) { return a + Math.max(0, b); }, 0) : 0;
1421
+ add(fig, h('ul', { 'class': 'one-chart-legend', 'aria-hidden': 'true' }, legendItems.map(function (name, i) {
1422
+ var pct = type === 'pie' && total > 0 ? ' (' + fmtNumber((Math.max(0, series[0].values[i]) / total) * 100, 1) + '%)' : '';
1423
+ return h('li', null, [h('span', { 'class': 'one-chart-swatch one-chart-s' + ((i % 6) + 1) }), h('span', { text: name + pct })]);
1424
+ })));
1425
+ }
1426
+ // Ekran okuyucu için aynı veri tablo olarak (görsel kullanıcıya gizli).
1427
+ var table = h('table', { 'class': 'one-sr-only' }, h('caption', { text: t(lang, 'chartData') + ': ' + title }));
1428
+ add(table, h('thead', null, h('tr', null, [h('th', { scope: 'col', text: t(lang, 'category') })].concat(series.map(function (s) { return h('th', { scope: 'col', text: s.name }); })))));
1429
+ add(table, h('tbody', null, labels.map(function (l, i) {
1430
+ return h('tr', null, [h('th', { scope: 'row', text: l })].concat(series.map(function (s) { return h('td', { text: self._fmt(s.values[i]) }); })));
1431
+ })));
1432
+ add(fig, table);
1433
+ add(this, fig);
1434
+ }
1435
+ _axes(root, labels, series, W, H, type) {
1436
+ var self = this, L = 64, R = 16, T = 16, B = 40, pw = W - L - R, ph = H - T - B;
1437
+ var all = []; series.forEach(function (s) { all = all.concat(s.values); });
1438
+ var max = Math.max.apply(null, all.concat([0])), min = Math.min.apply(null, all.concat([0]));
1439
+ var step = niceStep(max - min), top = Math.ceil(max / step) * step, bottom = Math.floor(min / step) * step;
1440
+ if (top === bottom) top = bottom + step;
1441
+ var y = function (v) { return T + ph - ((v - bottom) / (top - bottom)) * ph; };
1442
+ for (var v = bottom; v <= top + step / 2; v += step) {
1443
+ add(root, svg('line', { x1: L, x2: W - R, y1: y(v), y2: y(v), 'class': 'one-chart-grid' }));
1444
+ add(root, svg('text', { x: L - 8, y: y(v) + 4, 'text-anchor': 'end', 'class': 'one-chart-axis', text: fmtNumber(v, 2) }));
1445
+ }
1446
+ var group = pw / labels.length;
1447
+ labels.forEach(function (l, i) {
1448
+ add(root, svg('text', { x: L + group * (i + 0.5), y: H - B + 18, 'text-anchor': 'middle', 'class': 'one-chart-axis' }, [shorten(l, Math.max(3, Math.floor(group / 7))), svg('title', { text: l })]));
1449
+ });
1450
+ if (type === 'bar') {
1451
+ var bw = (group * 0.7) / series.length;
1452
+ series.forEach(function (s, si) {
1453
+ s.values.forEach(function (v, i) {
1454
+ var x = L + group * i + group * 0.15 + bw * si, y0 = y(Math.max(0, v)), y1 = y(Math.min(0, v));
1455
+ add(root, svg('rect', { x: x, y: y0, width: Math.max(1, bw - 2), height: Math.max(0, y1 - y0), 'class': 'one-chart-s' + ((si % 6) + 1) },
1456
+ svg('title', { text: labels[i] + ' - ' + s.name + ': ' + self._fmt(v) })));
1457
+ });
1458
+ });
1459
+ } else {
1460
+ series.forEach(function (s, si) {
1461
+ var pts = s.values.map(function (v, i) { return (L + group * (i + 0.5)) + ',' + y(v); }).join(' ');
1462
+ add(root, svg('polyline', { points: pts, fill: 'none', 'stroke-width': '2', 'class': 'one-chart-line one-chart-s' + ((si % 6) + 1) }));
1463
+ s.values.forEach(function (v, i) {
1464
+ add(root, svg('circle', { cx: L + group * (i + 0.5), cy: y(v), r: '4', 'class': 'one-chart-s' + ((si % 6) + 1) }, svg('title', { text: labels[i] + ' - ' + s.name + ': ' + self._fmt(v) })));
1465
+ });
1466
+ });
1467
+ }
1468
+ }
1469
+ _pie(root, labels, s, W, H) {
1470
+ var self = this, cx = W / 2, cy = H / 2, r = Math.min(W, H) / 2 - 16;
1471
+ var vals = s.values.map(function (v) { return Math.max(0, v); }), total = vals.reduce(function (a, b) { return a + b; }, 0);
1472
+ if (total <= 0) { add(root, svg('circle', { cx: cx, cy: cy, r: r, 'class': 'one-chart-grid' })); return; }
1473
+ var angle = -Math.PI / 2;
1474
+ vals.forEach(function (v, i) {
1475
+ if (v <= 0) return;
1476
+ var tip = svg('title', { text: labels[i] + ': ' + self._fmt(v) + ' (' + fmtNumber((v / total) * 100, 1) + '%)' }), cls = 'one-chart-s' + ((i % 6) + 1);
1477
+ if (v === total) { add(root, svg('circle', { cx: cx, cy: cy, r: r, 'class': cls }, tip)); return; }
1478
+ var a2 = angle + (v / total) * Math.PI * 2;
1479
+ var x1 = cx + r * Math.cos(angle), y1 = cy + r * Math.sin(angle), x2 = cx + r * Math.cos(a2), y2 = cy + r * Math.sin(a2);
1480
+ var large = a2 - angle > Math.PI ? 1 : 0;
1481
+ add(root, svg('path', { d: 'M ' + cx + ' ' + cy + ' L ' + x1 + ' ' + y1 + ' A ' + r + ' ' + r + ' 0 ' + large + ' 1 ' + x2 + ' ' + y2 + ' Z', 'class': cls }, tip));
1482
+ angle = a2;
1483
+ });
1484
+ }
1485
+ }
1486
+
1487
+ var DEFS = [['one-table', OneTable], ['one-form', OneForm], ['one-filter', OneFilter], ['one-person-picker', OnePersonPicker], ['one-file-upload', OneFileUpload], ['one-chart', OneChart]];
1488
+ for (var i = 0; i < DEFS.length; i++) if (!w.customElements.get(DEFS[i][0])) w.customElements.define(DEFS[i][0], DEFS[i][1]);
1489
+ })(window);
1490
+ `;
1491
+ //# sourceMappingURL=components.js.map