tamga-ui 0.1.0

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 (207) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +172 -0
  3. package/dist/blocks/count-row.d.ts +29 -0
  4. package/dist/blocks/count-row.d.ts.map +1 -0
  5. package/dist/blocks/count-row.js +19 -0
  6. package/dist/blocks/filter-bar.d.ts +123 -0
  7. package/dist/blocks/filter-bar.d.ts.map +1 -0
  8. package/dist/blocks/filter-bar.js +74 -0
  9. package/dist/blocks/index.d.ts +24 -0
  10. package/dist/blocks/index.d.ts.map +1 -0
  11. package/dist/blocks/index.js +23 -0
  12. package/dist/blocks/save-bar.d.ts +31 -0
  13. package/dist/blocks/save-bar.d.ts.map +1 -0
  14. package/dist/blocks/save-bar.js +21 -0
  15. package/dist/components/a11y.d.ts +21 -0
  16. package/dist/components/a11y.d.ts.map +1 -0
  17. package/dist/components/a11y.js +159 -0
  18. package/dist/components/advanced-input.d.ts +115 -0
  19. package/dist/components/advanced-input.d.ts.map +1 -0
  20. package/dist/components/advanced-input.js +189 -0
  21. package/dist/components/avatar.d.ts +63 -0
  22. package/dist/components/avatar.d.ts.map +1 -0
  23. package/dist/components/avatar.js +54 -0
  24. package/dist/components/badge.d.ts +37 -0
  25. package/dist/components/badge.d.ts.map +1 -0
  26. package/dist/components/badge.js +29 -0
  27. package/dist/components/bar.d.ts +32 -0
  28. package/dist/components/bar.d.ts.map +1 -0
  29. package/dist/components/bar.js +33 -0
  30. package/dist/components/button.d.ts +45 -0
  31. package/dist/components/button.d.ts.map +1 -0
  32. package/dist/components/button.js +56 -0
  33. package/dist/components/chart.d.ts +43 -0
  34. package/dist/components/chart.d.ts.map +1 -0
  35. package/dist/components/chart.js +41 -0
  36. package/dist/components/checkbox.d.ts +13 -0
  37. package/dist/components/checkbox.d.ts.map +1 -0
  38. package/dist/components/checkbox.js +16 -0
  39. package/dist/components/chrome.d.ts +87 -0
  40. package/dist/components/chrome.d.ts.map +1 -0
  41. package/dist/components/chrome.js +107 -0
  42. package/dist/components/combobox.d.ts +31 -0
  43. package/dist/components/combobox.d.ts.map +1 -0
  44. package/dist/components/combobox.js +62 -0
  45. package/dist/components/control-base.d.ts +7 -0
  46. package/dist/components/control-base.d.ts.map +1 -0
  47. package/dist/components/control-base.js +6 -0
  48. package/dist/components/data-table.d.ts +68 -0
  49. package/dist/components/data-table.d.ts.map +1 -0
  50. package/dist/components/data-table.js +50 -0
  51. package/dist/components/date-picker.d.ts +52 -0
  52. package/dist/components/date-picker.d.ts.map +1 -0
  53. package/dist/components/date-picker.js +73 -0
  54. package/dist/components/disclosure.d.ts +31 -0
  55. package/dist/components/disclosure.d.ts.map +1 -0
  56. package/dist/components/disclosure.js +32 -0
  57. package/dist/components/display.d.ts +188 -0
  58. package/dist/components/display.d.ts.map +1 -0
  59. package/dist/components/display.js +190 -0
  60. package/dist/components/empty-state.d.ts +150 -0
  61. package/dist/components/empty-state.d.ts.map +1 -0
  62. package/dist/components/empty-state.js +113 -0
  63. package/dist/components/error-state.d.ts +38 -0
  64. package/dist/components/error-state.d.ts.map +1 -0
  65. package/dist/components/error-state.js +16 -0
  66. package/dist/components/file-upload.d.ts +34 -0
  67. package/dist/components/file-upload.d.ts.map +1 -0
  68. package/dist/components/file-upload.js +34 -0
  69. package/dist/components/gauge.d.ts +47 -0
  70. package/dist/components/gauge.d.ts.map +1 -0
  71. package/dist/components/gauge.js +65 -0
  72. package/dist/components/icon.d.ts +32 -0
  73. package/dist/components/icon.d.ts.map +1 -0
  74. package/dist/components/icon.js +20 -0
  75. package/dist/components/icons.d.ts +19 -0
  76. package/dist/components/icons.d.ts.map +1 -0
  77. package/dist/components/icons.js +39 -0
  78. package/dist/components/input.d.ts +35 -0
  79. package/dist/components/input.d.ts.map +1 -0
  80. package/dist/components/input.js +41 -0
  81. package/dist/components/layout.d.ts +133 -0
  82. package/dist/components/layout.d.ts.map +1 -0
  83. package/dist/components/layout.js +132 -0
  84. package/dist/components/link.d.ts +22 -0
  85. package/dist/components/link.d.ts.map +1 -0
  86. package/dist/components/link.js +2 -0
  87. package/dist/components/live-scope.d.ts +15 -0
  88. package/dist/components/live-scope.d.ts.map +1 -0
  89. package/dist/components/live-scope.js +67 -0
  90. package/dist/components/log-view.d.ts +34 -0
  91. package/dist/components/log-view.d.ts.map +1 -0
  92. package/dist/components/log-view.js +30 -0
  93. package/dist/components/number-input.d.ts +26 -0
  94. package/dist/components/number-input.d.ts.map +1 -0
  95. package/dist/components/number-input.js +57 -0
  96. package/dist/components/overlay.d.ts +257 -0
  97. package/dist/components/overlay.d.ts.map +1 -0
  98. package/dist/components/overlay.js +276 -0
  99. package/dist/components/pagination.d.ts +38 -0
  100. package/dist/components/pagination.d.ts.map +1 -0
  101. package/dist/components/pagination.js +46 -0
  102. package/dist/components/pie.d.ts +40 -0
  103. package/dist/components/pie.d.ts.map +1 -0
  104. package/dist/components/pie.js +74 -0
  105. package/dist/components/primitives.d.ts +96 -0
  106. package/dist/components/primitives.d.ts.map +1 -0
  107. package/dist/components/primitives.js +81 -0
  108. package/dist/components/progress.d.ts +29 -0
  109. package/dist/components/progress.d.ts.map +1 -0
  110. package/dist/components/progress.js +16 -0
  111. package/dist/components/radio-group.d.ts +17 -0
  112. package/dist/components/radio-group.d.ts.map +1 -0
  113. package/dist/components/radio-group.js +23 -0
  114. package/dist/components/rail-link.d.ts +24 -0
  115. package/dist/components/rail-link.d.ts.map +1 -0
  116. package/dist/components/rail-link.js +24 -0
  117. package/dist/components/rich-text.d.ts +51 -0
  118. package/dist/components/rich-text.d.ts.map +1 -0
  119. package/dist/components/rich-text.js +147 -0
  120. package/dist/components/section.d.ts +15 -0
  121. package/dist/components/section.d.ts.map +1 -0
  122. package/dist/components/section.js +8 -0
  123. package/dist/components/segmented.d.ts +13 -0
  124. package/dist/components/segmented.d.ts.map +1 -0
  125. package/dist/components/segmented.js +12 -0
  126. package/dist/components/skeleton.d.ts +69 -0
  127. package/dist/components/skeleton.d.ts.map +1 -0
  128. package/dist/components/skeleton.js +67 -0
  129. package/dist/components/slider.d.ts +18 -0
  130. package/dist/components/slider.d.ts.map +1 -0
  131. package/dist/components/slider.js +15 -0
  132. package/dist/components/sparkline.d.ts +17 -0
  133. package/dist/components/sparkline.d.ts.map +1 -0
  134. package/dist/components/sparkline.js +19 -0
  135. package/dist/components/spinner.d.ts +15 -0
  136. package/dist/components/spinner.d.ts.map +1 -0
  137. package/dist/components/spinner.js +22 -0
  138. package/dist/components/stacked-bar.d.ts +21 -0
  139. package/dist/components/stacked-bar.d.ts.map +1 -0
  140. package/dist/components/stacked-bar.js +41 -0
  141. package/dist/components/surface.d.ts +76 -0
  142. package/dist/components/surface.d.ts.map +1 -0
  143. package/dist/components/surface.js +49 -0
  144. package/dist/components/switch.d.ts +12 -0
  145. package/dist/components/switch.d.ts.map +1 -0
  146. package/dist/components/switch.js +13 -0
  147. package/dist/components/tabs.d.ts +47 -0
  148. package/dist/components/tabs.d.ts.map +1 -0
  149. package/dist/components/tabs.js +12 -0
  150. package/dist/components/timeline-strip.d.ts +19 -0
  151. package/dist/components/timeline-strip.d.ts.map +1 -0
  152. package/dist/components/timeline-strip.js +14 -0
  153. package/dist/components/tone.d.ts +58 -0
  154. package/dist/components/tone.d.ts.map +1 -0
  155. package/dist/components/tone.js +70 -0
  156. package/dist/components/tree-select.d.ts +26 -0
  157. package/dist/components/tree-select.d.ts.map +1 -0
  158. package/dist/components/tree-select.js +59 -0
  159. package/dist/index.d.ts +54 -0
  160. package/dist/index.d.ts.map +1 -0
  161. package/dist/index.js +70 -0
  162. package/dist/kit.css +2248 -0
  163. package/dist/lib/cn.d.ts +10 -0
  164. package/dist/lib/cn.d.ts.map +1 -0
  165. package/dist/lib/cn.js +12 -0
  166. package/dist/lib/color.d.ts +68 -0
  167. package/dist/lib/color.d.ts.map +1 -0
  168. package/dist/lib/color.js +134 -0
  169. package/dist/lib/palette.d.ts +84 -0
  170. package/dist/lib/palette.d.ts.map +1 -0
  171. package/dist/lib/palette.js +193 -0
  172. package/dist/lib/scroll-lock.d.ts +19 -0
  173. package/dist/lib/scroll-lock.d.ts.map +1 -0
  174. package/dist/lib/scroll-lock.js +33 -0
  175. package/dist/patterns/app-shell.d.ts +36 -0
  176. package/dist/patterns/app-shell.d.ts.map +1 -0
  177. package/dist/patterns/app-shell.js +14 -0
  178. package/dist/patterns/auth-template.d.ts +36 -0
  179. package/dist/patterns/auth-template.d.ts.map +1 -0
  180. package/dist/patterns/auth-template.js +40 -0
  181. package/dist/patterns/detail-template.d.ts +52 -0
  182. package/dist/patterns/detail-template.d.ts.map +1 -0
  183. package/dist/patterns/detail-template.js +11 -0
  184. package/dist/patterns/index.d.ts +18 -0
  185. package/dist/patterns/index.d.ts.map +1 -0
  186. package/dist/patterns/index.js +17 -0
  187. package/dist/patterns/list-template.d.ts +32 -0
  188. package/dist/patterns/list-template.d.ts.map +1 -0
  189. package/dist/patterns/list-template.js +8 -0
  190. package/dist/patterns/overview-template.d.ts +26 -0
  191. package/dist/patterns/overview-template.d.ts.map +1 -0
  192. package/dist/patterns/overview-template.js +8 -0
  193. package/dist/patterns/public-template.d.ts +28 -0
  194. package/dist/patterns/public-template.d.ts.map +1 -0
  195. package/dist/patterns/public-template.js +7 -0
  196. package/dist/patterns/settings-template.d.ts +50 -0
  197. package/dist/patterns/settings-template.d.ts.map +1 -0
  198. package/dist/patterns/settings-template.js +33 -0
  199. package/dist/patterns/shared.d.ts +40 -0
  200. package/dist/patterns/shared.d.ts.map +1 -0
  201. package/dist/patterns/shared.js +29 -0
  202. package/dist/patterns/wizard-template.d.ts +28 -0
  203. package/dist/patterns/wizard-template.d.ts.map +1 -0
  204. package/dist/patterns/wizard-template.js +15 -0
  205. package/dist/styles.css +5 -0
  206. package/dist/theme.css +812 -0
  207. package/package.json +87 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Mantıksal
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,172 @@
1
+ # tamga-ui
2
+
3
+ Mantıksal'ın ortak arayüz kütüphanesi: token'lar, fizik ve bileşenler.
4
+
5
+ Framework değil **kütüphane** — ekranları sen kurarsın, kit parçaları verir. Kit hiçbir ürünün
6
+ adını, sözlüğünü ya da kimliğini bilmez.
7
+
8
+ - **Bileşenler** `tamga-ui`
9
+ - **İkonlar** `tamga-ui/icons`
10
+ - **Bloklar** `tamga-ui/blocks` — bir bileşenden büyük, bir ekrandan küçük
11
+ - **Şablonlar** `tamga-ui/patterns` — ekranların şekli (liste, detay, ayar, oturum, kabuk)
12
+
13
+ Doküman sitesi: depoyu klonlayıp `pnpm install && pnpm --filter tamga-docs dev` (port **6070**).
14
+
15
+ ---
16
+
17
+ ## Kurulum
18
+
19
+ ### Henüz npm'de değil
20
+
21
+ Paket yayınlanmadı. Bugün üç yol var, üçü de çalışıyor:
22
+
23
+ **1 · Tarball (en temiz).** Kit deposunda:
24
+
25
+ ```bash
26
+ pnpm install
27
+ pnpm --filter tamga-ui pack # tamga-ui-0.1.0.tgz üretir
28
+ ```
29
+
30
+ Kendi projende:
31
+
32
+ ```bash
33
+ npm install ../tamga/packages/ui/tamga-ui-0.1.0.tgz
34
+ ```
35
+
36
+ **2 · Yerel yol.** Aynı makinede duruyorsa:
37
+
38
+ ```bash
39
+ npm install file:../tamga/packages/ui
40
+ ```
41
+
42
+ > **Dikkat:** `file:` bir SEMBOLİK BAĞ kuruyor, ve Tailwind v4 `@source` taramasını sembolik
43
+ > bağın ardına götürmüyor. Sonuç sinsi: tipler çözülür, importlar çalışır, ama utility sınıfları
44
+ > üretilmediği için bileşenler yarı çıplak çıkar. Geliştirirken hızlı, teslim ederken tarball.
45
+
46
+ **3 · Git.** npm bir monorepo'nun alt klasörünü doğrudan kuramıyor, o yüzden depoyu klonlayıp
47
+ 1 ya da 2'yi kullan.
48
+
49
+ Üçünde de `prepare` betiği `dist/`i kurulum anında üretiyor; ayrıca bir build adımı gerekmiyor.
50
+
51
+ ### Gerekenler
52
+
53
+ | | |
54
+ | --- | --- |
55
+ | React | **19** (peer dependency) |
56
+ | Tailwind | **v4** |
57
+ | Node | 20+ |
58
+
59
+ Tailwind v4 bir tercih değil şart: bileşenler utility sınıfı kullanıyor ve o sınıfları **senin**
60
+ build'in üretiyor.
61
+
62
+ ### CSS
63
+
64
+ ```css
65
+ @import "tailwindcss";
66
+ @import "tamga-ui/styles.css";
67
+
68
+ @source "../../node_modules/tamga-ui/dist";
69
+ ```
70
+
71
+ **`@source` satırını atlama.** Onsuz Tailwind kitin `dist/`i içindeki sınıfları taramaz, üretmez,
72
+ ve bileşenler **stilsiz** çıkar. Yol senin CSS dosyandan `node_modules`a göre; derinliğe göre
73
+ `../` sayısı değişir.
74
+
75
+ ### Kullanım
76
+
77
+ ```tsx
78
+ import { Button, StatusChip } from "tamga-ui";
79
+ import { Plus } from "tamga-ui/icons";
80
+
81
+ <Button variant="primary">
82
+ <Icon icon={Plus} size="xs" />
83
+ Yeni kayıt
84
+ </Button>;
85
+ ```
86
+
87
+ ---
88
+
89
+ ## Kurulum anketi
90
+
91
+ **Bu bölüm kiti kuran kişi ya da ajan içindir.** Kit kurulduğunda proje çalışır ama KİMSESİZDİR:
92
+ mavi bir vurgu, baş harften bir karo, adsız bir kullanıcı. Aşağıdaki yedi sorunun cevabı
93
+ alınmadan kurulum bitmiş sayılmaz.
94
+
95
+ Her satırın son sütunu önemli: **cevap bir kere sorulup koda gömülmez, bir ayar ekranına da
96
+ konur.** Kurulumda sorulan her şey projenin üçüncü ayında da değiştirilebilir olmalı; yoksa
97
+ müşteri rengini değiştirmek istediğinde tek yol bir geliştiricinin CSS yazıp yeniden yayın
98
+ alması olur.
99
+
100
+ | # | Sorulacak | Nereye gider | Ayar ekranında |
101
+ | --- | --- | --- | --- |
102
+ | 1 | Ürünün adı | Kabuk, sekme başlığı, oturum ekranı | hayır, ürünün kimliği |
103
+ | 2 | **Marka rengi (tek hex)** | `paletUret()` → token'lar (aşağıda) | **evet** |
104
+ | 3 | Logo (geniş, yatay) | Oturum ekranı, geniş kenar çubuğu | **evet** |
105
+ | 4 | Amblem (kare) | Dar kenar çubuğu, sekme ikonu | **evet** |
106
+ | 5 | Varsayılan tema | `açık` · `koyu` · `sistem` | **evet** |
107
+ | 6 | Kenar çubuğu davranışı | `hep dar` · `hep geniş` · `kullanıcı seçsin` | **evet** |
108
+ | 7 | Arayüz dili / dilleri | Bütün `labels` prop'ları | duruma göre |
109
+
110
+ **2, 3 ve 4 birbirinden bağımsız sorulur.** Yüklenen bir logodan amblem OTOMATİK çıkarılamaz:
111
+ bir görsel dosyasında "amblem" diye işaretli bir şey yoktur, konumu sabit değildir (solda, üstte,
112
+ yazının içinde ya da hiç yok), ve yanlış kesim sessizdir. Yarım bir harf panelin her sayfasının
113
+ sol üstünde durur ve kimse bunun otomatik kesildiğini bilmez. Amblemi ya ayrı bir dosya olarak
114
+ iste, ya kullanıcıya logo üzerinde kare bir alan seçtir, ya da hiç isteme: amblem yoksa
115
+ `LogoTile` baş harften bir karo üretir ve bu çalışan bir cevaptır.
116
+
117
+ Sorulacakların ekranı `SettingsTemplate` ile kuruluyor; adım adım anlatımı doküman sitesinde
118
+ `/docs/yeni-panel` sayfasında.
119
+
120
+ ---
121
+
122
+ ## Renkleri değiştirmek
123
+
124
+ Bir bileşen hiçbir yerde sabit renk taşımıyor; hepsi token okuyor.
125
+
126
+ ### Tek hex'ten bütün palet
127
+
128
+ `tamga-ui/palette` bir marka renginden iki temanın tamamını üretiyor. Elle üç token yazmaktan
129
+ daha güvenli, çünkü üreteç kontrastı ARAYARAK buluyor: yüzün açıklığını, üstündeki mürekkebin
130
+ AA eşiğini geçene kadar adım adım kaydırıyor. Kırk ton ve iki tema, bir kapının sürekli ölçtüğü
131
+ 880 ölçüm.
132
+
133
+ ```ts
134
+ import { paletUret, paletCss } from "tamga-ui/palette";
135
+
136
+ const cift = paletUret("#e02938"); // { light, dark }
137
+ document.documentElement.setAttribute("style", paletCss(cift));
138
+ ```
139
+
140
+ Renk çalışma zamanında değişebiliyorsa (ayar ekranı) yol budur: token'lar kök elemana yazılıyor
141
+ ve kitin 87 sınıfı onları okuduğu için bütün panel tek satırda dönüyor, hiçbir CSS yeniden
142
+ derlenmeden.
143
+
144
+ ### Ya da elle
145
+
146
+ Rengin sabit olduğu ve derleme zamanında bilindiği projelerde token'ları doğrudan geçersiz
147
+ kılabilirsin:
148
+
149
+ ```css
150
+ @import "tamga-ui/styles.css";
151
+
152
+ :root {
153
+ --color-accent: #2069c9; /* birincil yüz */
154
+ --color-accent-shadow: #12245c; /* yüzün altındaki taban */
155
+ --color-accent-ink: #fdfcfa; /* yüzün üstündeki mürekkep */
156
+ }
157
+ ```
158
+
159
+ Bu yolda kontrastı kendin doğrulamak zorundasın: üreteç yok, kapı yok.
160
+
161
+ Bu yüzden **kendi bileşenlerinde de sabit renk yazma**: `text-ink`, `bg-shell`,
162
+ `var(--color-critical)` yaz. Palet değiştiğinde ekranların onunla birlikte döner; sabit yazılmış
163
+ her renk elle bulunup düzeltilir.
164
+
165
+ Token'ların tamamı doküman sitesinde (`/docs/tokens`), temayı değiştirmenin adımları
166
+ `/docs/tema` sayfasında.
167
+
168
+ ---
169
+
170
+ ## Lisans
171
+
172
+ MIT — [LICENSE](./LICENSE)
@@ -0,0 +1,29 @@
1
+ import type { ReactNode } from "react";
2
+ /**
3
+ * SAYAÇ SATIRI: tablonun tepesindeki tek satırlık okuma.
4
+ *
5
+ * KAÇ KAYIT OLDUĞU HER ZAMAN YAZIYOR. Filtre uygulandıktan sonra kaç kayda
6
+ * bakıldığını söylemeyen bir liste, kullanıcıya saydırıyor.
7
+ *
8
+ * SAĞ TARAF İKİ ŞEY TAŞIYABİLİR ve ikisi de isteğe bağlı: ekrana özel ikinci
9
+ * bir okuma (`aside` — "12 tanesi eşiği geçti" gibi) ve sayfa boyu seçimi.
10
+ * İkincisi verilmezse hiç çizilmiyor: sayfalanmayan bir listeye sayfa boyu
11
+ * sormak, olmayan bir kontrolü öğretmek.
12
+ */
13
+ export declare function CountRow({ count, unit, aside, pageSize, pageSizeOptions, onPageSize, labels, }: {
14
+ count: number;
15
+ /** "sipariş", "müşteri": sayının yanında ne yazacağı. */
16
+ unit: string;
17
+ /** Ekrana özel ikinci okuma. */
18
+ aside?: ReactNode;
19
+ pageSize?: number;
20
+ pageSizeOptions?: number[];
21
+ onPageSize?: (n: number) => void;
22
+ /** Sayının biçimi çağıranın: binlik ayıracı dile bağlı. */
23
+ labels?: {
24
+ format?: (n: number) => string;
25
+ perPage?: string;
26
+ records?: string;
27
+ };
28
+ }): import("react").JSX.Element;
29
+ //# sourceMappingURL=count-row.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"count-row.d.ts","sourceRoot":"","sources":["../../src/blocks/count-row.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIvC;;;;;;;;;;GAUG;AACH,wBAAgB,QAAQ,CAAC,EACvB,KAAK,EACL,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,eAAe,EACf,UAAU,EACV,MAAM,GACP,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAC;IACb,gCAAgC;IAChC,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,2DAA2D;IAC3D,MAAM,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACjF,+BA0BA"}
@@ -0,0 +1,19 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Label } from "../components/surface.js";
4
+ import { Select } from "../components/primitives.js";
5
+ /**
6
+ * SAYAÇ SATIRI: tablonun tepesindeki tek satırlık okuma.
7
+ *
8
+ * KAÇ KAYIT OLDUĞU HER ZAMAN YAZIYOR. Filtre uygulandıktan sonra kaç kayda
9
+ * bakıldığını söylemeyen bir liste, kullanıcıya saydırıyor.
10
+ *
11
+ * SAĞ TARAF İKİ ŞEY TAŞIYABİLİR ve ikisi de isteğe bağlı: ekrana özel ikinci
12
+ * bir okuma (`aside` — "12 tanesi eşiği geçti" gibi) ve sayfa boyu seçimi.
13
+ * İkincisi verilmezse hiç çizilmiyor: sayfalanmayan bir listeye sayfa boyu
14
+ * sormak, olmayan bir kontrolü öğretmek.
15
+ */
16
+ export function CountRow({ count, unit, aside, pageSize, pageSizeOptions, onPageSize, labels, }) {
17
+ const format = labels?.format ?? ((n) => String(n));
18
+ return (_jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3 border-b border-[var(--color-line)] px-4 py-3", children: [_jsxs(Label, { children: [_jsx("strong", { className: "tabular-nums text-ink", children: format(count) }), " ", unit] }), aside, pageSizeOptions && onPageSize && pageSize !== undefined && (_jsxs("label", { className: "flex items-center gap-2 text-small text-ink-soft", children: [labels?.perPage, _jsx(Select, { className: "w-24", options: pageSizeOptions.map(String), value: String(pageSize), onChange: (v) => onPageSize(Number(v)), placeholder: String(pageSizeOptions[0]) }), labels?.records] }))] }));
19
+ }
@@ -0,0 +1,123 @@
1
+ import { type ReactNode } from "react";
2
+ /**
3
+ * FİLTRE ÇUBUĞU.
4
+ *
5
+ * ─── NEDEN KİTTE ────────────────────────────────────────────────────────
6
+ * Bir süre üründe durdu ve orada "kite taşınmadı, bilinçli" diye bir not
7
+ * vardı: gerekçesi "Excel ile ara" ve "Tüm filtreler" gibi şeylerin bir
8
+ * e-ticaret paneli kalıbı olması. Not yanlış çıktı ve iki sebeple:
9
+ *
10
+ * ① ADR-0003'ün katman şeması `tamga-ui` kutusunun içine zaten
11
+ * "filtre paneli · toplu eylem çubuğu" yazıyor. Bir satır içi yorum,
12
+ * kilitli bir ADR'yi geçersiz kılmaz.
13
+ * ② Notun işaret ettiği sözlük SÖZCÜKLERDİ, mekanizma değil. Metinler
14
+ * `labels`a çıkınca geriye kalan şey saf mekanizma: bir arama kutusu, en
15
+ * çok dört alan, bir çekmece, ve uygulanan filtrelerin çipleri. Dosyayla
16
+ * arama da bir alan adı değil bir yöntem; her yönetim listesi yapabilir.
17
+ *
18
+ * ─── ÜÇ MADDE, VE ÜÇÜNCÜSÜ EN ÖNEMLİSİ ──────────────────────────────────
19
+ * Bir yönetim panelinin filtresi otuz alanı aynı anda açık tutmaya meyleder,
20
+ * hepsi aynı görsel ağırlıkta. Buradaki fikir tek cümle: birkaçı üstte,
21
+ * gerisi çekmecede, VE çekmecede bir şey açıksa bunu görüyorsun.
22
+ *
23
+ * Gizli bir filtre açıkken kullanıcı listeyi eksik görür ve sebebini bulamaz;
24
+ * bu, filtreyi gizlemenin tek gerçek riski. O yüzden uygulanan her filtre
25
+ * tablonun üstünde bir çip olarak duruyor, tek tıkla kalkıyor, ve çekmece
26
+ * düğmesinde aktif sayıyı gösteren bir rozet var.
27
+ *
28
+ * ─── ENTER UYGULAR ──────────────────────────────────────────────────────
29
+ * Çekmecedeki alanlar bir `<form>` içinde ve "Uygula" o formun `submit`
30
+ * düğmesi, yani Enter tarayıcının kendi davranışıyla çalışıyor: dinlenen bir
31
+ * tuş değil, formun anlamı.
32
+ */
33
+ /** Filtre durumunun tamamı: anahtar → dizgi. Boş dizgi "filtre yok" demek. */
34
+ export type FilterValues = Record<string, string>;
35
+ export type FilterFieldKind = "text" | "select"
36
+ /** Aranabilir seçim: seçenek sayısı göz gezdirmenin ötesine geçtiğinde. */
37
+ | "searchable"
38
+ /**
39
+ * ÇOKLU seçim, çip olarak. Tek seçimden farkı bir kolaylık değil bir ANLAM:
40
+ * "Nike VEYA Adidas" ile "Nike" aynı soru değil.
41
+ */
42
+ | "multi"
43
+ /** İKİ TARİH: başlangıç ve bitiş. Tek bir kutu bir aralık soramaz. */
44
+ | "dateRange";
45
+ export type FilterField = {
46
+ key: string;
47
+ label: string;
48
+ kind: FilterFieldKind;
49
+ /** Verilmezse `optionSource[key]` kullanılır; ikisi de yoksa liste boş. */
50
+ options?: string[];
51
+ };
52
+ export type FilterGroup = {
53
+ title: string;
54
+ fields: FilterField[];
55
+ };
56
+ export declare const rangeStart: (key: string) => string;
57
+ export declare const rangeEnd: (key: string) => string;
58
+ export type FilterBarLabels = {
59
+ /** Arama kutusunun yer tutucusu. */
60
+ search: string;
61
+ /**
62
+ * "Hepsi" seçeneğinin adı, ve LİSTENİN İÇİNDE bir seçenek olarak duruyor.
63
+ *
64
+ * Kullanıcı bir değer seçtikten sonra tekrar hepsini görmek istediğinde,
65
+ * geri dönüş yolunun GİDİŞ YOLUYLA AYNI YERDE olması gerekiyor. Kontrolün
66
+ * yanına bir çarpı koymak her filtreye ikinci bir düğme ekler ve ancak seçim
67
+ * varken görünür, yani kullanıcı onu aramayı öğrenemez.
68
+ */
69
+ all: string;
70
+ allFilters: string;
71
+ clearAll: string;
72
+ clear: string;
73
+ apply: string;
74
+ noMatch: string;
75
+ /** "<alan> seç" gibi; kontrolü açan düğmenin erişilebilir adı. */
76
+ open: (label: string) => string;
77
+ /** "<filtre> filtresini kaldır". */
78
+ remove: (label: string) => string;
79
+ rangeStart: string;
80
+ rangeEnd: string;
81
+ calendar: {
82
+ previousMonth: string;
83
+ nextMonth: string;
84
+ open: string;
85
+ clear: string;
86
+ };
87
+ /** Dosyayla arama bölümü; `fileSearchKey` verilmezse hiç çizilmiyor. */
88
+ fileSearch?: {
89
+ title: string;
90
+ help: ReactNode;
91
+ choose: string;
92
+ remove: string;
93
+ label: string;
94
+ };
95
+ };
96
+ export type FilterBarProps = {
97
+ values: FilterValues;
98
+ onChange: (next: FilterValues) => void;
99
+ /** Üstte duran alanlar. En çok dört tane; gerisi çekmeceye. */
100
+ top: readonly FilterField[];
101
+ /** Çekmecedeki gruplar. Düz bir yığın değil, gruplu. */
102
+ drawer: readonly FilterGroup[];
103
+ /** Seçim listelerinin kaynağı; sunucudan gelecek. */
104
+ optionSource?: Record<string, string[]>;
105
+ /**
106
+ * ARAMA KUTUSUNUN YAZDIĞI ANAHTAR.
107
+ *
108
+ * Prop, çünkü sunucunun beklediği ad ürünün kararı: kimi `q` diyor, kimi
109
+ * `ara`, kimi `search`. Blok bir süre `q`yu sabitledi ve ilk tüketicide
110
+ * sessizce kırdı: kutuya yazılan şey `q`ya gidiyor, ekran `ara`yı okuyor,
111
+ * ve arama hiçbir şey yapmıyordu. Hata vermeyen bir kırılma en pahalısı.
112
+ */
113
+ searchKey?: string;
114
+ /** Dosyayla arama bu ekranda varsa anahtarı; yoksa bölüm hiç çizilmiyor. */
115
+ fileSearchKey?: string;
116
+ /** Filtre satırına, "Tüm filtreler"in yanına giren ekrana özel düğme. */
117
+ extra?: ReactNode;
118
+ /** `DatePicker`ın takvimi için: "tr-TR", "en-GB". */
119
+ locale?: string;
120
+ labels: FilterBarLabels;
121
+ };
122
+ export declare function FilterBar({ values, onChange, top, drawer, optionSource, searchKey, fileSearchKey, extra, locale, labels, }: FilterBarProps): import("react").JSX.Element;
123
+ //# sourceMappingURL=filter-bar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filter-bar.d.ts","sourceRoot":"","sources":["../../src/blocks/filter-bar.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAWxD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,8EAA8E;AAC9E,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAElD,MAAM,MAAM,eAAe,GACvB,MAAM,GACN,QAAQ;AACV,2EAA2E;GACzE,YAAY;AACd;;;GAGG;GACD,OAAO;AACT,sEAAsE;GACpE,WAAW,CAAC;AAEhB,MAAM,MAAM,WAAW,GAAG;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,eAAe,CAAC;IACtB,2EAA2E;IAC3E,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,WAAW,EAAE,CAAA;CAAE,CAAC;AAInE,eAAO,MAAM,UAAU,QAAS,MAAM,WAAkB,CAAC;AACzD,eAAO,MAAM,QAAQ,QAAS,MAAM,WAAgB,CAAC;AAErD,MAAM,MAAM,eAAe,GAAG;IAC5B,oCAAoC;IACpC,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;;OAOG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,kEAAkE;IAClE,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAChC,oCAAoC;IACpC,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACpF,wEAAwE;IACxE,UAAU,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,SAAS,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CAChG,CAAC;AA+FF,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,YAAY,CAAC;IACrB,QAAQ,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC;IACvC,+DAA+D;IAC/D,GAAG,EAAE,SAAS,WAAW,EAAE,CAAC;IAC5B,wDAAwD;IACxD,MAAM,EAAE,SAAS,WAAW,EAAE,CAAC;IAC/B,qDAAqD;IACrD,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACxC;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4EAA4E;IAC5E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,yEAAyE;IACzE,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,qDAAqD;IACrD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,eAAe,CAAC;CACzB,CAAC;AAEF,wBAAgB,SAAS,CAAC,EACxB,MAAM,EACN,QAAQ,EACR,GAAG,EACH,MAAM,EACN,YAAiB,EACjB,SAAe,EACf,aAAa,EACb,KAAK,EACL,MAAgB,EAChB,MAAM,GACP,EAAE,cAAc,+BA8MhB"}
@@ -0,0 +1,74 @@
1
+ "use client";
2
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useId, useState } from "react";
4
+ import { Button, buttonVariants } from "../components/button.js";
5
+ import { MiniButton } from "../components/button.js";
6
+ import { Combobox } from "../components/combobox.js";
7
+ import { MultiSelect } from "../components/advanced-input.js";
8
+ import { DatePicker } from "../components/date-picker.js";
9
+ import { Icon } from "../components/icon.js";
10
+ import { Close, Customize, Search, Upload } from "../components/icons.js";
11
+ import { Input } from "../components/input.js";
12
+ import { Select, Sheet } from "../components/primitives.js";
13
+ /* Tarih aralığı İKİ ANAHTAR tutuyor. Tek bir dizgeye sıkıştırmak, sunucuya iki
14
+ ayrı parametre giderken burada tekrar ayrıştırmak demekti. */
15
+ export const rangeStart = (key) => `${key}Start`;
16
+ export const rangeEnd = (key) => `${key}End`;
17
+ function FieldControl({ field, values, write, optionSource, locale, labels, }) {
18
+ const options = field.options?.length ? field.options : (optionSource[field.key] ?? []);
19
+ if (field.kind === "dateRange") {
20
+ return (_jsxs("div", { className: "grid gap-2 sm:grid-cols-2", children: [_jsx(DatePicker, { locale: locale, value: values[rangeStart(field.key)] || undefined, onChange: (v) => write(rangeStart(field.key), v ?? ""), placeholder: labels.rangeStart, labels: labels.calendar }), _jsx(DatePicker, { locale: locale, value: values[rangeEnd(field.key)] || undefined, onChange: (v) => write(rangeEnd(field.key), v ?? ""), placeholder: labels.rangeEnd, labels: labels.calendar })] }));
21
+ }
22
+ if (field.kind === "multi") {
23
+ /* Değerler virgülle tek bir dizgede: filtre durumunun tamamı
24
+ `Record<string,string>` ve bir alanın tipi yüzünden o sözleşmeyi
25
+ değiştirmek, her ekranı ilgilendirirdi. */
26
+ const selected = (values[field.key] ?? "").split(",").filter(Boolean);
27
+ return (_jsx(MultiSelect, { className: "w-full", options: options.map((o) => ({ value: o, label: o })), value: selected, onChange: (next) => write(field.key, next.join(",")), placeholder: labels.all, labels: {
28
+ empty: labels.noMatch,
29
+ remove: labels.remove,
30
+ open: labels.open(field.label),
31
+ } }));
32
+ }
33
+ if (field.kind === "searchable") {
34
+ return (_jsx(Combobox, { className: "w-full", options: options.map((o) => ({ value: o, label: o })), value: values[field.key] || undefined, onChange: (v) => write(field.key, v ?? ""), placeholder: labels.all, labels: { empty: labels.noMatch, clear: labels.clear, open: labels.open(field.label) } }));
35
+ }
36
+ if (field.kind === "select") {
37
+ return (_jsx(Select, { className: "w-full", options: [labels.all, ...options], value: values[field.key], onChange: (v) => write(field.key, v === labels.all ? "" : v), placeholder: labels.all }));
38
+ }
39
+ return (_jsx(Input, { full: true, value: values[field.key] ?? "", onChange: (e) => write(field.key, e.target.value) }));
40
+ }
41
+ export function FilterBar({ values, onChange, top, drawer, optionSource = {}, searchKey = "q", fileSearchKey, extra, locale = "en-GB", labels, }) {
42
+ const [drawerOpen, setDrawerOpen] = useState(false);
43
+ const formId = useId();
44
+ const active = Object.entries(values).filter(([, v]) => v);
45
+ const drawerKeys = new Set(drawer.flatMap((g) => g.fields.map((f) => f.key)));
46
+ const hiddenActive = active.filter(([k]) => drawerKeys.has(k)).length;
47
+ function write(key, value) {
48
+ const next = { ...values };
49
+ if (value)
50
+ next[key] = value;
51
+ else
52
+ delete next[key];
53
+ onChange(next);
54
+ }
55
+ const allFields = [...top, ...drawer.flatMap((g) => g.fields)];
56
+ /* Aralık anahtarları (`dateStart`) alan listesinde YOK: adı, ait olduğu
57
+ alandan türetiliyor. Yoksa çipte ham anahtar görünüyordu. */
58
+ const labelFor = (key) => {
59
+ const direct = allFields.find((f) => f.key === key)?.label;
60
+ if (direct)
61
+ return direct;
62
+ const range = allFields.find((f) => f.kind === "dateRange" && (rangeStart(f.key) === key || rangeEnd(f.key) === key));
63
+ if (range) {
64
+ return `${range.label} ${rangeStart(range.key) === key ? labels.rangeStart : labels.rangeEnd}`;
65
+ }
66
+ if (key === searchKey)
67
+ return labels.search;
68
+ return key === fileSearchKey ? (labels.fileSearch?.label ?? key) : key;
69
+ };
70
+ return (_jsxs("div", { className: "flex flex-col gap-3", children: [_jsxs("div", { className: "grid items-end gap-3 grid-cols-1 md:grid-cols-2 xl:grid-cols-[minmax(10rem,1fr)_repeat(4,minmax(0,1.25fr))_auto]", children: [_jsxs("label", { className: "flex min-w-0 flex-col gap-1.5", children: [_jsx("span", { className: "text-small font-medium text-ink", children: labels.search }), _jsxs("span", { className: "relative flex items-center", children: [_jsx(Icon, { icon: Search, size: "xs", "aria-hidden": true, className: "pointer-events-none absolute left-2.5 text-ink-faint" }), _jsx(Input, { type: "search", full: true, leading: true, placeholder: labels.search, value: values[searchKey] ?? "", onChange: (e) => write(searchKey, e.target.value) })] })] }), top.map((field) => (_jsxs("div", { className: "flex min-w-0 flex-col gap-1.5", children: [_jsx("span", { className: "text-small font-medium text-ink", children: field.label }), _jsx(FieldControl, { field: field, values: values, write: write, optionSource: optionSource, locale: locale, labels: labels })] }, field.key))), _jsxs(Button, { onClick: () => setDrawerOpen(true), children: [_jsx(Icon, { icon: Customize, size: "xs" }), labels.allFilters, hiddenActive > 0 && (_jsx("span", { className: "ml-1 rounded-full bg-[var(--color-accent)] px-1.5 text-micro font-semibold text-[var(--color-accent-ink)] tabular-nums", children: hiddenActive }))] }), extra] }), active.length > 0 && (_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [active.map(([key, value]) => (_jsxs("span", { className: "inline-flex items-center gap-1.5 rounded-(--radius-ctl) border border-[var(--color-edge)] bg-shell py-1 pl-2.5 pr-1 text-small text-ink", children: [_jsxs("span", { className: "text-ink-faint", children: [labelFor(key), ":"] }), value, _jsx(MiniButton, { "aria-label": labels.remove(labelFor(key)), onClick: () => write(key, ""), children: _jsx(Icon, { icon: Close, size: "xs" }) })] }, key))), _jsx(Button, { variant: "link", size: "sm", onClick: () => onChange({}), children: labels.clearAll })] })), _jsx(Sheet, { open: drawerOpen, onClose: () => setDrawerOpen(false), title: labels.allFilters, closeLabel: labels.calendar.clear, footer: _jsxs(_Fragment, { children: [_jsx(Button, { type: "button", onClick: () => onChange({}), children: labels.clear }), _jsx(Button, { type: "submit", form: formId, variant: "primary", children: labels.apply })] }), children: _jsxs("form", { id: formId, onSubmit: (e) => {
71
+ e.preventDefault();
72
+ setDrawerOpen(false);
73
+ }, className: "flex flex-col gap-7", children: [drawer.map((group) => (_jsxs("div", { children: [_jsx("p", { className: "mb-3 text-micro font-semibold uppercase tracking-wide text-ink-faint", children: group.title }), _jsx("div", { className: "grid gap-3 sm:grid-cols-[repeat(2,minmax(0,1fr))]", children: group.fields.map((field) => (_jsxs("div", { className: `flex flex-col gap-1.5 ${field.kind === "dateRange" ? "sm:col-span-2" : ""}`, children: [_jsx("span", { className: "text-small text-ink-soft", children: field.label }), _jsx(FieldControl, { field: field, values: values, write: write, optionSource: optionSource, locale: locale, labels: labels })] }, field.key))) })] }, group.title))), fileSearchKey && labels.fileSearch && (_jsxs("div", { children: [_jsx("p", { className: "mb-3 text-micro font-semibold uppercase tracking-wide text-ink-faint", children: labels.fileSearch.title }), _jsx("p", { className: "mb-3 text-small leading-relaxed text-ink-soft", children: labels.fileSearch.help }), values[fileSearchKey] ? (_jsxs("span", { className: "flex items-center gap-2", children: [_jsx("span", { className: "truncate text-small text-ink", children: values[fileSearchKey] }), _jsx(Button, { type: "button", size: "sm", onClick: () => write(fileSearchKey, ""), children: labels.fileSearch.remove })] })) : (_jsxs("label", { className: `${buttonVariants({})} cursor-pointer`, children: [_jsx(Icon, { icon: Upload, size: "xs" }), labels.fileSearch.choose, _jsx("input", { type: "file", accept: ".xlsx,.xls,.csv", className: "sr-only", onChange: (e) => write(fileSearchKey, e.target.files?.[0]?.name ?? "") })] }))] }))] }) })] }));
74
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * BLOK KATMANI — `tamga-ui/blocks`.
3
+ *
4
+ * BİR BLOK NEDİR. Bir bileşenden büyük, bir şablondan küçük: birkaç bileşenin
5
+ * bir araya gelip TEK BİR İŞ yaptığı bölüm. Filtre çubuğu bir düğme değil ama
6
+ * bir ekran da değil; bir ekranın içindeki bir bölge.
7
+ *
8
+ * ADR-0003'ün katman şeması "filtre paneli · toplu eylem çubuğu" diye ikisini
9
+ * de `tamga-ui` kutusunun içine yazıyor. Toplu eylem çubuğu ZATEN VARDI:
10
+ * `SelectionBar`, bir bileşen olarak, kendi doküman sayfasıyla. Buraya bir
11
+ * `BulkBar` yazıldı ve aynı propları alan ikinci bir kopyaydı; silindi.
12
+ *
13
+ * DERS BU DOSYANIN BAŞINDA DURSUN: yeni bir blok yazmadan önce kitin o işi
14
+ * yapan bir bileşeni var mı diye bakılır. Bir tasarım sisteminin en sinsi
15
+ * hatası, aynı şeyin iki adla iki yerde durmasıdır.
16
+ *
17
+ * BURAYA NE GİRMEZ. Bir ürünün sözlüğünü taşıyan hiçbir şey. Bir sipariş
18
+ * kartı, bir iade satırı, bir mülk özeti: bunlar e-ticaret ya da izleme
19
+ * katmanının işi. Blok, alanı bilmeyen bölümdür.
20
+ */
21
+ export { FilterBar, rangeStart, rangeEnd, type FilterBarLabels, type FilterBarProps, type FilterField, type FilterFieldKind, type FilterGroup, type FilterValues, } from "./filter-bar.js";
22
+ export { SaveBar } from "./save-bar.js";
23
+ export { CountRow } from "./count-row.js";
24
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/blocks/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EACL,SAAS,EACT,UAAU,EACV,QAAQ,EACR,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,YAAY,GAClB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * BLOK KATMANI — `tamga-ui/blocks`.
3
+ *
4
+ * BİR BLOK NEDİR. Bir bileşenden büyük, bir şablondan küçük: birkaç bileşenin
5
+ * bir araya gelip TEK BİR İŞ yaptığı bölüm. Filtre çubuğu bir düğme değil ama
6
+ * bir ekran da değil; bir ekranın içindeki bir bölge.
7
+ *
8
+ * ADR-0003'ün katman şeması "filtre paneli · toplu eylem çubuğu" diye ikisini
9
+ * de `tamga-ui` kutusunun içine yazıyor. Toplu eylem çubuğu ZATEN VARDI:
10
+ * `SelectionBar`, bir bileşen olarak, kendi doküman sayfasıyla. Buraya bir
11
+ * `BulkBar` yazıldı ve aynı propları alan ikinci bir kopyaydı; silindi.
12
+ *
13
+ * DERS BU DOSYANIN BAŞINDA DURSUN: yeni bir blok yazmadan önce kitin o işi
14
+ * yapan bir bileşeni var mı diye bakılır. Bir tasarım sisteminin en sinsi
15
+ * hatası, aynı şeyin iki adla iki yerde durmasıdır.
16
+ *
17
+ * BURAYA NE GİRMEZ. Bir ürünün sözlüğünü taşıyan hiçbir şey. Bir sipariş
18
+ * kartı, bir iade satırı, bir mülk özeti: bunlar e-ticaret ya da izleme
19
+ * katmanının işi. Blok, alanı bilmeyen bölümdür.
20
+ */
21
+ export { FilterBar, rangeStart, rangeEnd, } from "./filter-bar.js";
22
+ export { SaveBar } from "./save-bar.js";
23
+ export { CountRow } from "./count-row.js";
@@ -0,0 +1,31 @@
1
+ import type { ReactNode } from "react";
2
+ /**
3
+ * KAYDET ŞERİDİ: kayan yüzeyin dibine yapışık.
4
+ *
5
+ * NEDEN FORMUN SONUNDA DEĞİL. Eski panellerin alışkanlığı kaydet düğmesini
6
+ * formun en altına koymak; yirmi alanlık bir formda üstteki bir alanı
7
+ * düzeltip kaydetmek için sonuna kadar kaydırmak gerekiyor. Şerit her zaman
8
+ * görünür, ve kaydedilecek bir şey olup olmadığını da söylüyor.
9
+ *
10
+ * FİZİĞİ BİR SINIFTA (`.tamga-save-bar`), ve orada ölçülmüş bir tuzak yazılı:
11
+ * `sticky bottom-0` şeridin alt kenarını yüzeyin İÇERİK kutusuna hizalıyor,
12
+ * ama yüzeyin kendi alt dolgusu var ve içerik o boşluktan akıp geçiyordu.
13
+ *
14
+ * DEĞİŞİKLİK YOKSA KAYDEDİLECEK BİR ŞEY DE YOK: düğme kapalı. Tıklanıp
15
+ * hiçbir şey olmayan bir düğme, olmayan bir düğmeden kötüdür.
16
+ */
17
+ export declare function SaveBar({ changed, busy, onCancel, extra, labels, }: {
18
+ /** Değişiklik yoksa kaydet kapalı. */
19
+ changed?: boolean;
20
+ /** Kaydetme sürüyor: iki düğme de kilitli, kaydet spinner gösteriyor. */
21
+ busy?: boolean;
22
+ onCancel?: () => void;
23
+ /** Şeridin sağında duran ekrana özel şey: bir sayaç, bir uyarı satırı. */
24
+ extra?: ReactNode;
25
+ labels: {
26
+ save: string;
27
+ cancel: string;
28
+ saving?: string;
29
+ };
30
+ }): import("react").JSX.Element;
31
+ //# sourceMappingURL=save-bar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"save-bar.d.ts","sourceRoot":"","sources":["../../src/blocks/save-bar.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,OAAO,CAAC,EACtB,OAAc,EACd,IAAY,EACZ,QAAQ,EACR,KAAK,EACL,MAAM,GACP,EAAE;IACD,sCAAsC;IACtC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,yEAAyE;IACzE,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,0EAA0E;IAC1E,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3D,+BAkBA"}
@@ -0,0 +1,21 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Button } from "../components/button.js";
4
+ /**
5
+ * KAYDET ŞERİDİ: kayan yüzeyin dibine yapışık.
6
+ *
7
+ * NEDEN FORMUN SONUNDA DEĞİL. Eski panellerin alışkanlığı kaydet düğmesini
8
+ * formun en altına koymak; yirmi alanlık bir formda üstteki bir alanı
9
+ * düzeltip kaydetmek için sonuna kadar kaydırmak gerekiyor. Şerit her zaman
10
+ * görünür, ve kaydedilecek bir şey olup olmadığını da söylüyor.
11
+ *
12
+ * FİZİĞİ BİR SINIFTA (`.tamga-save-bar`), ve orada ölçülmüş bir tuzak yazılı:
13
+ * `sticky bottom-0` şeridin alt kenarını yüzeyin İÇERİK kutusuna hizalıyor,
14
+ * ama yüzeyin kendi alt dolgusu var ve içerik o boşluktan akıp geçiyordu.
15
+ *
16
+ * DEĞİŞİKLİK YOKSA KAYDEDİLECEK BİR ŞEY DE YOK: düğme kapalı. Tıklanıp
17
+ * hiçbir şey olmayan bir düğme, olmayan bir düğmeden kötüdür.
18
+ */
19
+ export function SaveBar({ changed = true, busy = false, onCancel, extra, labels, }) {
20
+ return (_jsxs("div", { className: "tamga-save-bar", "data-changed": changed, children: [_jsx(Button, { variant: "primary", type: "submit", disabled: !changed, busy: busy, busyLabel: labels.saving, children: labels.save }), _jsx(Button, { type: "button", onClick: onCancel, disabled: busy, children: labels.cancel }), extra && _jsx("span", { className: "ml-auto", children: extra })] }));
21
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Traps Tab inside a modal surface and gives it back on close.
3
+ *
4
+ * Without this a dialog looks modal and is not: Tab walks straight out into
5
+ * the page behind the scrim, where a keyboard user is stuck operating a page
6
+ * they cannot see. The scrim only stops the mouse.
7
+ */
8
+ export declare function useFocusTrap<T extends HTMLElement>(open: boolean): import("react").RefObject<T | null>;
9
+ /**
10
+ * Roving focus for a list of options — menus and selects.
11
+ *
12
+ * Arrow keys move, Home/End jump, Enter and Space choose, Escape closes.
13
+ * `data-tamga-option` marks the items so separators and labels are skipped
14
+ * without the hook needing to know what a separator is.
15
+ */
16
+ export declare function useListKeys({ open, containerRef, onClose, }: {
17
+ open: boolean;
18
+ containerRef: React.RefObject<HTMLElement | null>;
19
+ onClose: () => void;
20
+ }): void;
21
+ //# sourceMappingURL=a11y.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"a11y.d.ts","sourceRoot":"","sources":["../../src/components/a11y.ts"],"names":[],"mappings":"AAkCA;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,WAAW,EAAE,IAAI,EAAE,OAAO,uCAqEhE;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,YAAY,EACZ,OAAO,GACR,EAAE;IACD,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,KAAK,CAAC,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAClD,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,QAmDA"}