tamga-ui 0.4.3 → 0.5.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 (204) hide show
  1. package/CHANGELOG.md +908 -0
  2. package/README.md +3 -1
  3. package/dist/blocks/count-row.d.ts +3 -8
  4. package/dist/blocks/count-row.d.ts.map +1 -1
  5. package/dist/blocks/count-row.js +3 -8
  6. package/dist/blocks/filter-bar.d.ts +42 -28
  7. package/dist/blocks/filter-bar.d.ts.map +1 -1
  8. package/dist/blocks/filter-bar.js +13 -5
  9. package/dist/blocks/index.d.ts +4 -17
  10. package/dist/blocks/index.d.ts.map +1 -1
  11. package/dist/blocks/index.js +4 -17
  12. package/dist/blocks/save-bar.d.ts +4 -12
  13. package/dist/blocks/save-bar.d.ts.map +1 -1
  14. package/dist/blocks/save-bar.js +4 -12
  15. package/dist/components/a11y.d.ts.map +1 -1
  16. package/dist/components/a11y.js +4 -15
  17. package/dist/components/advanced-input.d.ts +54 -48
  18. package/dist/components/advanced-input.d.ts.map +1 -1
  19. package/dist/components/advanced-input.js +64 -59
  20. package/dist/components/announcement.d.ts +34 -0
  21. package/dist/components/announcement.d.ts.map +1 -0
  22. package/dist/components/announcement.js +12 -0
  23. package/dist/components/appearance.d.ts +33 -1
  24. package/dist/components/appearance.d.ts.map +1 -1
  25. package/dist/components/appearance.js +78 -7
  26. package/dist/components/avatar.d.ts +28 -21
  27. package/dist/components/avatar.d.ts.map +1 -1
  28. package/dist/components/avatar.js +46 -22
  29. package/dist/components/badge.d.ts +54 -4
  30. package/dist/components/badge.d.ts.map +1 -1
  31. package/dist/components/badge.js +42 -9
  32. package/dist/components/bar.d.ts.map +1 -1
  33. package/dist/components/bar.js +4 -20
  34. package/dist/components/button.d.ts +15 -7
  35. package/dist/components/button.d.ts.map +1 -1
  36. package/dist/components/button.js +54 -8
  37. package/dist/components/chart.d.ts +5 -0
  38. package/dist/components/chart.d.ts.map +1 -1
  39. package/dist/components/chart.js +18 -11
  40. package/dist/components/checkbox.d.ts +23 -1
  41. package/dist/components/checkbox.d.ts.map +1 -1
  42. package/dist/components/checkbox.js +3 -4
  43. package/dist/components/chrome.d.ts +38 -54
  44. package/dist/components/chrome.d.ts.map +1 -1
  45. package/dist/components/chrome.js +55 -63
  46. package/dist/components/combobox.d.ts.map +1 -1
  47. package/dist/components/combobox.js +19 -3
  48. package/dist/components/data-table.d.ts +4 -4
  49. package/dist/components/data-table.d.ts.map +1 -1
  50. package/dist/components/data-table.js +15 -16
  51. package/dist/components/date-picker.d.ts.map +1 -1
  52. package/dist/components/date-picker.js +11 -4
  53. package/dist/components/disclosure.d.ts +17 -2
  54. package/dist/components/disclosure.d.ts.map +1 -1
  55. package/dist/components/disclosure.js +4 -8
  56. package/dist/components/display.d.ts +119 -94
  57. package/dist/components/display.d.ts.map +1 -1
  58. package/dist/components/display.js +103 -106
  59. package/dist/components/empty-state.d.ts +70 -52
  60. package/dist/components/empty-state.d.ts.map +1 -1
  61. package/dist/components/empty-state.js +40 -52
  62. package/dist/components/error-state.d.ts +21 -4
  63. package/dist/components/error-state.d.ts.map +1 -1
  64. package/dist/components/error-state.js +16 -6
  65. package/dist/components/file-upload.d.ts +45 -2
  66. package/dist/components/file-upload.d.ts.map +1 -1
  67. package/dist/components/file-upload.js +32 -7
  68. package/dist/components/gauge.d.ts +72 -9
  69. package/dist/components/gauge.d.ts.map +1 -1
  70. package/dist/components/gauge.js +52 -49
  71. package/dist/components/icons.d.ts +1 -1
  72. package/dist/components/icons.d.ts.map +1 -1
  73. package/dist/components/icons.js +4 -0
  74. package/dist/components/input.d.ts +21 -0
  75. package/dist/components/input.d.ts.map +1 -1
  76. package/dist/components/input.js +15 -1
  77. package/dist/components/layout.d.ts +47 -70
  78. package/dist/components/layout.d.ts.map +1 -1
  79. package/dist/components/layout.js +31 -73
  80. package/dist/components/link.d.ts +5 -10
  81. package/dist/components/link.d.ts.map +1 -1
  82. package/dist/components/live-scope.d.ts.map +1 -1
  83. package/dist/components/live-scope.js +5 -8
  84. package/dist/components/log-view.d.ts +32 -1
  85. package/dist/components/log-view.d.ts.map +1 -1
  86. package/dist/components/log-view.js +42 -15
  87. package/dist/components/number-input.d.ts +20 -2
  88. package/dist/components/number-input.d.ts.map +1 -1
  89. package/dist/components/number-input.js +32 -9
  90. package/dist/components/overlay.d.ts +69 -61
  91. package/dist/components/overlay.d.ts.map +1 -1
  92. package/dist/components/overlay.js +134 -77
  93. package/dist/components/pagination.d.ts.map +1 -1
  94. package/dist/components/pagination.js +12 -7
  95. package/dist/components/pie.d.ts.map +1 -1
  96. package/dist/components/pie.js +8 -7
  97. package/dist/components/primitives.d.ts +136 -6
  98. package/dist/components/primitives.d.ts.map +1 -1
  99. package/dist/components/primitives.js +73 -20
  100. package/dist/components/progress.d.ts +44 -9
  101. package/dist/components/progress.d.ts.map +1 -1
  102. package/dist/components/progress.js +21 -9
  103. package/dist/components/radio-group.d.ts.map +1 -1
  104. package/dist/components/radio-group.js +11 -12
  105. package/dist/components/rail-link.d.ts +17 -1
  106. package/dist/components/rail-link.d.ts.map +1 -1
  107. package/dist/components/rail-link.js +3 -3
  108. package/dist/components/rich-text.d.ts +8 -1
  109. package/dist/components/rich-text.d.ts.map +1 -1
  110. package/dist/components/rich-text.js +13 -19
  111. package/dist/components/says-bubble.d.ts +38 -0
  112. package/dist/components/says-bubble.d.ts.map +1 -0
  113. package/dist/components/says-bubble.js +6 -0
  114. package/dist/components/scroll-x.d.ts +23 -0
  115. package/dist/components/scroll-x.d.ts.map +1 -0
  116. package/dist/components/scroll-x.js +27 -0
  117. package/dist/components/section.d.ts +18 -1
  118. package/dist/components/section.d.ts.map +1 -1
  119. package/dist/components/section.js +12 -1
  120. package/dist/components/segmented.d.ts +17 -1
  121. package/dist/components/segmented.d.ts.map +1 -1
  122. package/dist/components/segmented.js +26 -6
  123. package/dist/components/skeleton.d.ts.map +1 -1
  124. package/dist/components/skeleton.js +1 -1
  125. package/dist/components/slider.d.ts +16 -2
  126. package/dist/components/slider.d.ts.map +1 -1
  127. package/dist/components/slider.js +12 -5
  128. package/dist/components/sparkline.d.ts +9 -2
  129. package/dist/components/sparkline.d.ts.map +1 -1
  130. package/dist/components/sparkline.js +9 -5
  131. package/dist/components/spinner.d.ts +16 -1
  132. package/dist/components/spinner.d.ts.map +1 -1
  133. package/dist/components/spinner.js +24 -1
  134. package/dist/components/square-picker.d.ts +4 -20
  135. package/dist/components/square-picker.d.ts.map +1 -1
  136. package/dist/components/square-picker.js +4 -20
  137. package/dist/components/stacked-bar.d.ts.map +1 -1
  138. package/dist/components/stacked-bar.js +5 -4
  139. package/dist/components/surface.d.ts +32 -3
  140. package/dist/components/surface.d.ts.map +1 -1
  141. package/dist/components/surface.js +11 -4
  142. package/dist/components/switch.d.ts +14 -1
  143. package/dist/components/switch.d.ts.map +1 -1
  144. package/dist/components/switch.js +2 -3
  145. package/dist/components/tabs.d.ts +35 -11
  146. package/dist/components/tabs.d.ts.map +1 -1
  147. package/dist/components/tabs.js +48 -5
  148. package/dist/components/timeline-strip.d.ts +28 -3
  149. package/dist/components/timeline-strip.d.ts.map +1 -1
  150. package/dist/components/timeline-strip.js +19 -8
  151. package/dist/components/tone.d.ts +51 -14
  152. package/dist/components/tone.d.ts.map +1 -1
  153. package/dist/components/tone.js +76 -14
  154. package/dist/components/tree-select.d.ts.map +1 -1
  155. package/dist/components/tree-select.js +10 -3
  156. package/dist/fonts/LICENSE-jetbrains-mono.txt +93 -0
  157. package/dist/fonts/LICENSE-onest.txt +93 -0
  158. package/dist/fonts/LICENSE-red-hat-display.txt +93 -0
  159. package/dist/fonts/jetbrains-mono-latin-ext-wght-normal.woff2 +0 -0
  160. package/dist/fonts/jetbrains-mono-latin-wght-normal.woff2 +0 -0
  161. package/dist/fonts/onest-latin-ext-wght-normal.woff2 +0 -0
  162. package/dist/fonts/onest-latin-wght-normal.woff2 +0 -0
  163. package/dist/fonts/red-hat-display-latin-ext-wght-normal.woff2 +0 -0
  164. package/dist/fonts/red-hat-display-latin-wght-normal.woff2 +0 -0
  165. package/dist/fonts.css +54 -0
  166. package/dist/index.d.ts +10 -7
  167. package/dist/index.d.ts.map +1 -1
  168. package/dist/index.js +9 -6
  169. package/dist/kit.css +3175 -645
  170. package/dist/lib/color.d.ts +8 -19
  171. package/dist/lib/color.d.ts.map +1 -1
  172. package/dist/lib/color.js +8 -19
  173. package/dist/lib/data-props.d.ts +4 -15
  174. package/dist/lib/data-props.d.ts.map +1 -1
  175. package/dist/lib/data-props.js +4 -15
  176. package/dist/lib/image.d.ts +4 -20
  177. package/dist/lib/image.d.ts.map +1 -1
  178. package/dist/lib/image.js +4 -20
  179. package/dist/lib/palette.d.ts +16 -20
  180. package/dist/lib/palette.d.ts.map +1 -1
  181. package/dist/lib/palette.js +136 -71
  182. package/dist/lib/scroll-lock.d.ts +4 -14
  183. package/dist/lib/scroll-lock.d.ts.map +1 -1
  184. package/dist/lib/scroll-lock.js +4 -14
  185. package/dist/patterns/app-shell.d.ts.map +1 -1
  186. package/dist/patterns/app-shell.js +4 -13
  187. package/dist/patterns/appearance-template.d.ts +20 -15
  188. package/dist/patterns/appearance-template.d.ts.map +1 -1
  189. package/dist/patterns/appearance-template.js +29 -8
  190. package/dist/patterns/list-template.d.ts.map +1 -1
  191. package/dist/patterns/list-template.js +1 -1
  192. package/dist/patterns/overview-template.d.ts.map +1 -1
  193. package/dist/patterns/overview-template.js +1 -1
  194. package/dist/patterns/settings-template.d.ts +1 -12
  195. package/dist/patterns/settings-template.d.ts.map +1 -1
  196. package/dist/patterns/settings-template.js +2 -2
  197. package/dist/patterns/shared.d.ts.map +1 -1
  198. package/dist/patterns/shared.js +8 -1
  199. package/dist/styles.css +2 -1
  200. package/dist/theme.css +96 -259
  201. package/package.json +4 -2
  202. package/dist/components/control-base.d.ts +0 -7
  203. package/dist/components/control-base.d.ts.map +0 -1
  204. package/dist/components/control-base.js +0 -6
@@ -5,7 +5,7 @@ import { cn } from "../lib/cn.js";
5
5
  import { inputVariants } from "./input.js";
6
6
  import { dataProps } from "../lib/data-props.js";
7
7
  import { Icon } from "./icon.js";
8
- import { Check, Close, Customize, Eye, EyeSlash, Search } from "./icons.js";
8
+ import { Check, Clock, Close, Copy, Customize, Eye, EyeSlash, Key, Search } from "./icons.js";
9
9
  /* ------------------------------------------------------------------ *
10
10
  * Gelişmiş girdiler.
11
11
  *
@@ -17,20 +17,21 @@ import { Check, Close, Customize, Eye, EyeSlash, Search } from "./icons.js";
17
17
  *
18
18
  * Gerekçe: docs/gerekce/01-form-ve-girdi.md
19
19
  */
20
- export function PasswordInput({ labels, invalid = false, className, ...props }) {
20
+ export function PasswordInput({ labels, strength, invalid = false, className, ...props }) {
21
21
  const [shown, setShown] = useState(false);
22
- return (_jsxs("span", { className: "relative flex items-center", children: [_jsx("input", { type: shown ? "text" : "password", "aria-invalid": invalid || undefined, className: cn(inputVariants({ invalid }), "w-full pr-11", className), ...props }), _jsx("button", { type: "button", className: "tamga-field-btn", "aria-label": shown ? labels.hide : labels.show, "aria-pressed": shown, onClick: () => setShown((v) => !v), children: _jsx(Icon, { icon: shown ? EyeSlash : Eye, size: "xs" }) })] }));
22
+ const alan = (_jsxs("span", { className: "relative flex items-center", children: [_jsx("input", { type: shown ? "text" : "password", "aria-invalid": invalid || undefined, className: cn(inputVariants({ invalid }), "w-full pr-11", className), ...props }), _jsx("button", { type: "button", className: "tamga-field-btn", "aria-label": shown ? labels.hide : labels.show, "aria-pressed": shown, onClick: () => setShown((v) => !v), children: _jsx(Icon, { icon: shown ? EyeSlash : Eye, size: "xs" }) })] }));
23
+ if (!strength)
24
+ return alan;
25
+ const toplam = strength.of ?? 4;
26
+ const yanan = Math.max(0, Math.min(toplam, strength.value));
27
+ return (_jsxs("span", { className: "flex flex-col gap-2.5", children: [alan, _jsx("span", { className: "tamga-guc", style: { gridTemplateColumns: `repeat(${toplam}, 1fr)` }, children: Array.from({ length: toplam }, (_, i) => (_jsx("span", { "data-dolu": i < yanan || undefined }, i))) }), strength.note ? _jsx("span", { className: "text-small text-ink-faint", children: strength.note }) : null] }));
23
28
  }
24
29
  /**
25
- * Maskeli sır — API anahtarı, webhook secret.
30
+ * Maskeli sır · API anahtarı, webhook secret. `PasswordInput`un kardeşi ama işi
31
+ * TERS: buraya yazılmıyor, okunup kopyalanıyor, o yüzden salt-okunur. Maske ilk
32
+ * ve son birkaç karakteri bırakıyor.
26
33
  *
27
- * `PasswordInput`'un kardeşi ama İŞİ TERS: parola alanına bir şey YAZILIR,
28
- * buraya yazılmaz — okunur ve kopyalanır. O yüzden salt-okunur, ve asıl
29
- * düğmesi kopyalama.
30
- *
31
- * Maske ilk ve son birkaç karakteri bırakıyor. Tamamen gizlemek, kullanıcının
32
- * "hangi anahtar bu" sorusunu cevapsız bırakır; üç anahtarı olan biri
33
- * hangisine baktığını bilemez.
34
+ * Gerekçe: docs/gerekce/01-form-ve-girdi.md
34
35
  */
35
36
  export function SecretField({ value, labels, visibleChars = 4, className, ...rest }) {
36
37
  const [shown, setShown] = useState(false);
@@ -57,24 +58,17 @@ export function SecretField({ value, labels, visibleChars = 4, className, ...res
57
58
  window.clearTimeout(timer.current);
58
59
  timer.current = window.setTimeout(() => setCopied("idle"), 1600);
59
60
  }
60
- return (_jsxs("span", { ...dataProps(rest), className: cn("relative flex items-center", className), children: [_jsx("input", { readOnly: true, value: shown ? value : masked, className: "tamga-input w-full pr-18 font-mono",
61
- /* Salt-okunur bir alan yine de odaklanabilir olmalı: kullanıcı onu
62
- seçip elle kopyalayabilsin. `disabled` bunu imkânsız kılardı. */
63
- onFocus: (e) => e.currentTarget.select() }), _jsxs("span", { className: "absolute right-1.5 flex gap-0.5", children: [_jsx("button", { type: "button", className: "tamga-mini-btn", "aria-label": shown ? labels.hide : labels.reveal, "aria-pressed": shown, onClick: () => setShown((v) => !v), children: _jsx(Icon, { icon: shown ? EyeSlash : Eye, size: "xs" }) }), _jsx("button", { type: "button", className: "tamga-mini-btn", "aria-label": copied === "done" ? labels.copied : copied === "failed" ? labels.failed : labels.copy, onClick: copy, children: _jsx(Icon, { icon: copied === "done" ? Check : Customize, size: "xs" }) })] })] }));
61
+ return (_jsxs("span", { ...dataProps(rest), className: cn("flex flex-wrap items-center gap-2.5", className), children: [_jsxs("span", { className: "tamga-secret", children: [_jsx(Icon, { icon: Key, size: "xs", className: "shrink-0 text-ink-faint" }), _jsx("input", { readOnly: true, value: shown ? value : masked, onFocus: (e) => e.currentTarget.select() })] }), _jsx("button", { type: "button", className: "tamga-icon-btn", "aria-label": shown ? labels.hide : labels.reveal, "aria-pressed": shown, onClick: () => setShown((v) => !v), children: _jsx(Icon, { icon: shown ? EyeSlash : Eye, size: "sm" }) }), _jsxs("button", { type: "button", className: "tamga-btn", onClick: copy, children: [_jsx(Icon, { icon: copied === "done" ? Check : Copy, size: "xs" }), copied === "done" ? labels.copied : copied === "failed" ? labels.failed : labels.copy] })] }));
64
62
  }
65
63
  /**
66
- * Etiket girdisi.
67
- *
68
- * Enter ya da virgül bir etiketi kapatıyor; boşken Backspace sonuncuyu siliyor.
69
- * İkincisi küçük görünür ama en çok kullanılan yoldur — yanlış yazılan bir
70
- * etiketi silmek için fareye uzanmak, akışı kesen tek şeydir.
64
+ * Etiket girdisi · Enter ya da virgül bir etiketi kapatıyor, boşken Backspace
65
+ * sonuncuyu siliyor. Yinelenen etiket SESSİZCE yutuluyor, hata verilmiyor.
71
66
  *
72
- * Yinelenen ETİKET SESSİZCE YUTULUYOR, hata verilmiyor: aynı etiketi iki kez
73
- * yazmak bir hata değil, bir tekrardır, ve kullanıcı zaten istediğini almış
74
- * olur.
67
+ * Gerekçe: docs/gerekce/01-form-ve-girdi.md
75
68
  */
76
69
  export function TagsInput({ value, onChange, placeholder, labels, max, className, ...rest }) {
77
70
  const [draft, setDraft] = useState("");
71
+ const [silinecek, setSilinecek] = useState(null);
78
72
  const full = max !== undefined && value.length >= max;
79
73
  function commit() {
80
74
  const tag = draft.trim();
@@ -83,27 +77,42 @@ export function TagsInput({ value, onChange, placeholder, labels, max, className
83
77
  return;
84
78
  onChange([...value, tag]);
85
79
  }
86
- return (_jsxs("span", { ...dataProps(rest), className: cn("tamga-input h-auto min-h-10 w-full flex-wrap items-center gap-1.5 py-1.5", className), style: { display: "flex" }, children: [value.map((tag) => (_jsxs("span", { className: "tamga-chip gap-1", children: [tag, _jsx("button", { type: "button", "aria-label": labels.remove(tag), onClick: () => onChange(value.filter((x) => x !== tag)), className: "-mr-1 inline-flex items-center", children: _jsx(Icon, { icon: Close, size: "xs" }) })] }, tag))), !full ? (_jsx("input", { value: draft, placeholder: value.length === 0 ? placeholder : undefined, onChange: (e) => setDraft(e.target.value), onBlur: commit, onKeyDown: (e) => {
80
+ return (_jsxs("span", { ...dataProps(rest), className: cn("tamga-input h-auto min-h-10 w-full flex-wrap items-center gap-1.5 py-1.5", className), style: { display: "flex" }, children: [value.map((tag, i) => (_jsxs("span", { className: "tamga-token", "data-silinecek": i === silinecek || undefined, children: [tag, _jsx("button", { type: "button", "aria-label": labels.remove(tag), onClick: () => onChange(value.filter((x) => x !== tag)), className: "tamga-token-x", children: _jsx(Icon, { icon: Close, size: "xs" }) })] }, tag))), !full ? (_jsx("input", { value: draft, placeholder: value.length === 0 ? placeholder : undefined, onChange: (e) => {
81
+ setDraft(e.target.value);
82
+ setSilinecek(null);
83
+ }, onBlur: commit, onKeyDown: (e) => {
87
84
  if (e.key === "Enter" || e.key === ",") {
88
85
  e.preventDefault();
89
86
  commit();
90
87
  }
91
88
  else if (e.key === "Backspace" && draft === "" && value.length > 0) {
92
- onChange(value.slice(0, -1));
89
+ /* İKİ ADIM: ilk Backspace son etiketi İŞARETLİYOR, ikincisi
90
+ siliyor. Tek adımlı hâlinde bir tuş fazla basan kişi
91
+ yazdığı etiketi silip fark etmiyordu; işaretli hâl o bir
92
+ karelik duraklamayı veriyor. Başka bir tuş işareti kaldırıyor. */
93
+ if (silinecek === value.length - 1) {
94
+ onChange(value.slice(0, -1));
95
+ setSilinecek(null);
96
+ }
97
+ else {
98
+ setSilinecek(value.length - 1);
99
+ }
100
+ }
101
+ else {
102
+ setSilinecek(null);
93
103
  }
94
104
  }, className: "min-w-24 flex-1 bg-transparent text-body text-ink outline-none" })) : null] }));
95
105
  }
96
106
  /**
97
- * Çoklu seçim — aranabilir.
107
+ * Çoklu seçim · aranabilir. `Combobox`tan ayrı olmasının sebebi görünüm değil
108
+ * DAVRANIŞ: çoklu seçimde liste seçince KAPANMIYOR. Seçilenler girdinin içinde
109
+ * çip olarak duruyor.
98
110
  *
99
- * `Combobox` tek seçim yapar; bu birden çok. Ayrı bileşen olmasının sebebi
100
- * görünüm değil DAVRANIŞ: tek seçimde liste seçince kapanır, çoklu seçimde
101
- * KAPANMAZ — üç şey seçecek biri listeyi üç kez açmak zorunda kalmamalı.
102
- *
103
- * Seçilenler girdinin İÇİNDE çip olarak duruyor, altında ayrı bir listede
104
- * değil: seçim ile seçilenler arasındaki mesafe arttıkça, kullanıcı neyi
105
- * seçtiğini görmek için gözünü iki yere birden koymak zorunda kalır.
111
+ * Gerekçe: docs/gerekce/01-form-ve-girdi.md
106
112
  */
113
+ /* Kutuda yazıyla duran çip sayısı. Dördüncüden sonrası "+N": bir filtre
114
+ kutusunun iki satırı geçmemesi gerekiyor. */
115
+ const GORUNEN_CIP = 4;
107
116
  export function MultiSelect({ options, value, onChange, placeholder, labels, className, ...rest }) {
108
117
  const id = useId();
109
118
  const [open, setOpen] = useState(false);
@@ -115,19 +124,11 @@ export function MultiSelect({ options, value, onChange, placeholder, labels, cla
115
124
  function toggle(v) {
116
125
  onChange(value.includes(v) ? value.filter((x) => x !== v) : [...value, v]);
117
126
  }
118
- /**
119
- * KLAVYE, ve onsuz bu kontrol yarım.
120
- *
121
- * Etiket eklemenin doğal yolu YAZIP ENTER'A BASMAK: kullanıcı "adidas" yazıp
122
- * Enter, "nike" yazıp Enter diyor ve iki çip ekliyor. Önce yalnız fareyle
123
- * çalışıyordu; yazdıktan sonra listeye uzanıp tıklamak gerekiyordu, ve
124
- * klavyeyle gezen biri seçim yapamıyordu.
125
- *
126
- * Enter vurgulanan seçeneği ekler/çıkarır, ve kutuyu boşaltır
127
- * Ok tuşları vurguyu gezdirir
128
- * Backspace kutu BOŞKEN son çipi kaldırır (yazarken silmeye karışmaz)
129
- * Escape listeyi kapatır
130
- */
127
+ /* KLAVYE, ve onsuz bu kontrol yarım:
128
+ Enter vurgulanan seçeneği ekler/çıkarır, ve kutuyu boşaltır
129
+ Ok tuşları vurguyu gezdirir
130
+ Backspace kutu BOŞKEN son çipi kaldırır (yazarken silmeye karışmaz)
131
+ Escape listeyi kapatır */
131
132
  function tus(e) {
132
133
  if (e.key === "ArrowDown") {
133
134
  e.preventDefault();
@@ -165,27 +166,31 @@ export function MultiSelect({ options, value, onChange, placeholder, labels, cla
165
166
  onBlur: (e) => {
166
167
  if (!box.current?.contains(e.relatedTarget))
167
168
  setOpen(false);
168
- }, children: [_jsxs("span", { className: "tamga-input relative h-auto min-h-10 w-full flex-wrap items-center gap-1.5 py-1.5", "data-leading": "true", style: { display: "flex" }, children: [_jsx(Icon, { icon: Search, size: "xs", "aria-hidden": true, className: "pointer-events-none absolute left-3 top-3 text-ink-faint" }), chosen.map((o) => (_jsxs("span", { className: "tamga-chip gap-1", children: [o.label, _jsx("button", { type: "button", "aria-label": labels.remove(o.label), onClick: () => toggle(o.value), className: "-mr-1 inline-flex items-center", children: _jsx(Icon, { icon: Close, size: "xs" }) })] }, o.value))), _jsx("input", { value: query, placeholder: chosen.length === 0 ? placeholder : undefined, onChange: (e) => {
169
+ }, children: [_jsxs("span", { className: "tamga-input relative h-auto min-h-10 w-full flex-wrap items-center gap-1.5 py-1.5", "data-leading": "true", style: { display: "flex" }, children: [_jsx(Icon, { icon: Search, size: "xs", "aria-hidden": true, className: "pointer-events-none absolute left-3 top-3 text-ink-faint" }), chosen.slice(0, GORUNEN_CIP).map((o) => (_jsxs("span", { className: "tamga-token", children: [o.label, _jsx("button", { type: "button", "aria-label": labels.remove(o.label), onClick: () => toggle(o.value), className: "tamga-token-x", children: _jsx(Icon, { icon: Close, size: "xs" }) })] }, o.value))), chosen.length > GORUNEN_CIP ? (_jsxs("span", { className: "tamga-token", "aria-hidden": true, children: ["+", chosen.length - GORUNEN_CIP] })) : null, _jsx("input", { value: query, placeholder: chosen.length === 0 ? placeholder : undefined, onChange: (e) => {
169
170
  setQuery(e.target.value);
170
171
  setActive(0);
171
172
  setOpen(true);
172
- }, onKeyDown: tus, onFocus: () => setOpen(true), role: "combobox", "aria-expanded": open, "aria-controls": id, "aria-label": labels.open, className: "min-w-24 flex-1 bg-transparent text-body text-ink outline-none" })] }), open ? (_jsx("div", { id: id, role: "listbox", "aria-multiselectable": true, className: "tamga-overlay absolute z-30 mt-2 max-h-64 w-full overflow-y-auto py-1", children: shown.length === 0 ? (_jsx("p", { className: "px-4 py-3 text-small text-ink-faint", children: labels.empty })) : (shown.map(({ value: v, label: etiket, hint, ...rest }, i) => {
173
+ }, onKeyDown: tus, onFocus: () => setOpen(true), role: "combobox", "aria-expanded": open, "aria-controls": id, "aria-label": labels.open, className: "min-w-24 flex-1 bg-transparent text-body text-ink outline-none" })] }), open ? (_jsx("div", { id: id, role: "listbox", "aria-multiselectable": true, className: "tamga-overlay tamga-menu absolute z-30 mt-2 max-h-64 w-full overflow-y-auto", children: shown.length === 0 ? (_jsx("p", { className: "px-4 py-3 text-small text-ink-faint", children: labels.empty })) : (shown.map(({ value: v, label: etiket, hint, ...rest }, i) => {
173
174
  const on = value.includes(v);
174
175
  return (_jsxs("button", { ...rest, type: "button", role: "option", "aria-selected": on, "data-selected": on, "data-active": i === active || undefined, className: "tamga-option w-full", onMouseEnter: () => setActive(i), onClick: () => toggle(v), children: [_jsx("span", { className: "flex-1 text-left", children: etiket }), hint ? _jsx("span", { className: "font-mono text-caption text-ink-faint", children: hint }) : null, on ? _jsx(Icon, { icon: Check, size: "xs" }) : null] }, v));
175
176
  })) })) : null] }));
176
177
  }
177
178
  /**
178
- * Zamanlama girdisi — "her N dakikada bir".
179
+ * Zamanlama girdisi · "her N dakikada bir". NEDEN CRON DEĞİL: kürasyonlu
180
+ * seçenek, serbestlik değil. Aralıklar dakika olarak veriliyor, çevirisi
181
+ * çağıranın.
179
182
  *
180
- * NEDEN CRON DEĞİL. Bir cron ifadesi (yıldız-eğik-beş biçimi) bir geliştirici
181
- * için okunur, bir panel
182
- * kullanıcısı için değildir — ve yanlış yazılan bir cron ifadesi hata
183
- * vermez, sadece yanlış zamanda çalışır. Bu bileşen kürasyonlu bir liste
184
- * sunuyor: kürasyonlu seçenek, serbestlik değil.
185
- *
186
- * Aralıklar dakika olarak veriliyor, çevirisi çağıranın: "5 dakika" ile
187
- * "5 minutes" arasındaki farkı kit bilemez.
183
+ * Gerekçe: docs/gerekce/01-form-ve-girdi.md
188
184
  */
189
- export function ScheduleInput({ value, onChange, options, label, className, }) {
190
- return (_jsx("select", { className: cn("tamga-input w-full", className), "aria-label": label, value: value, onChange: (e) => onChange(Number(e.target.value)), children: options.map(({ minutes, label: etiket, ...rest }) => (_jsx("option", { ...rest, value: minutes, children: etiket }, minutes))) }));
185
+ export function ScheduleInput({ days, onDaysChange, from, to, onFromChange, onToChange, labels, summary, className, ...rest }) {
186
+ const secili = new Set(days);
187
+ const cevir = (g) => {
188
+ const next = new Set(secili);
189
+ if (next.has(g))
190
+ next.delete(g);
191
+ else
192
+ next.add(g);
193
+ onDaysChange([...next].sort((a, b) => a - b));
194
+ };
195
+ return (_jsxs("div", { ...dataProps(rest), className: cn("flex flex-col gap-4", className), children: [_jsx("div", { role: "group", "aria-label": labels.days, className: "flex flex-wrap gap-2", children: labels.dayNames.map((ad, g) => (_jsx("button", { type: "button", "aria-pressed": secili.has(g), onClick: () => cevir(g), className: "tamga-gun-btn", "data-on": secili.has(g) || undefined, children: ad }, ad))) }), _jsxs("div", { className: "flex flex-wrap items-center gap-2.5 text-body", children: [_jsx("span", { className: "font-semibold text-ink", children: labels.hours }), _jsx("input", { type: "time", value: from, onChange: (e) => onFromChange(e.target.value), "aria-label": labels.hours, className: "tamga-input tamga-sayi w-auto" }), _jsx("span", { className: "text-ink-faint", children: labels.between }), _jsx("input", { type: "time", value: to, onChange: (e) => onToChange(e.target.value), "aria-label": labels.between, className: "tamga-input tamga-sayi w-auto" }), labels.zone ? _jsx("span", { className: "text-ink-faint", children: labels.zone }) : null] }), _jsxs("p", { className: "tamga-ozet", children: [_jsx(Icon, { icon: Clock, size: "xs", weight: "bold", className: "text-accent" }), summary] })] }));
191
196
  }
@@ -0,0 +1,34 @@
1
+ import type { ReactNode } from "react";
2
+ import type { IconGlyph } from "./icons.js";
3
+ /**
4
+ * Duyuru şeridi · sayfanın en üstünde, tüm genişlikte.
5
+ *
6
+ * Gerekçe: docs/gerekce/05-yuzey-ve-kabuk.md
7
+ */
8
+ export declare function Announcement({ look, icon, tag, title, children, action, className, ...rest }: {
9
+ /**
10
+ * `loud` the filled accent strip, for something the reader should ACT on (a campaign, a
11
+ * deadline). `quiet` the washed strip, for a standing condition that only needs to be READ
12
+ * ("you are in test mode"). TR: `loud` dolu vurgu şeridi · okuyanın bir şey YAPMASI gereken
13
+ * durum için (kampanya, son tarih). `quiet` yıkanmış şerit · yalnız OKUNMASI yeten, duran bir
14
+ * koşul için ("test modundasın").
15
+ */
16
+ look?: "loud" | "quiet";
17
+ /** The glyph at the head of the strip. TR: Şeridin başındaki glif. */
18
+ icon?: IconGlyph;
19
+ /**
20
+ * A short word in a dark plate before the text, for the quiet strip: "TEST MODE", "BETA".
21
+ * It is the one place a mode names itself. TR: Sessiz şeritte metinden önce, koyu bir plaka
22
+ * içinde kısa bir sözcük: "TEST MODU", "BETA". Bir kipin kendi adını söylediği tek yer.
23
+ */
24
+ tag?: string;
25
+ /** TR: Kalın ilk satır. Sessiz şeritte yok: orada tek bir cümle var. */
26
+ title?: string;
27
+ children: ReactNode;
28
+ /** The button or link at the end. TR: Sondaki düğme ya da bağlantı. */
29
+ action?: ReactNode;
30
+ className?: string;
31
+ /** `data-*` hooks pass through. TR: `data-*` kancaları geçiyor. */
32
+ [k: `data-${string}`]: unknown;
33
+ }): import("react").JSX.Element;
34
+ //# sourceMappingURL=announcement.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"announcement.d.ts","sourceRoot":"","sources":["../../src/components/announcement.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIvC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,EAC3B,IAAa,EACb,IAAI,EACJ,GAAG,EACH,KAAK,EACL,QAAQ,EACR,MAAM,EACN,SAAS,EACT,GAAG,IAAI,EACR,EAAE;IACD;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACxB,sEAAsE;IACtE,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB;;;;OAIG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,wEAAwE;IACxE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,SAAS,CAAC;IACpB,uEAAuE;IACvE,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mEAAmE;IACnE,CAAC,CAAC,EAAE,QAAQ,MAAM,EAAE,GAAG,OAAO,CAAC;CAChC,+BAoBA"}
@@ -0,0 +1,12 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { cn } from "../lib/cn.js";
3
+ import { dataProps } from "../lib/data-props.js";
4
+ import { Icon } from "./icon.js";
5
+ /**
6
+ * Duyuru şeridi · sayfanın en üstünde, tüm genişlikte.
7
+ *
8
+ * Gerekçe: docs/gerekce/05-yuzey-ve-kabuk.md
9
+ */
10
+ export function Announcement({ look = "loud", icon, tag, title, children, action, className, ...rest }) {
11
+ return (_jsxs("div", { ...dataProps(rest), className: cn("tamga-announce", look === "loud" && "tamga-announce-loud", look === "quiet" && "tamga-announce-quiet", className), children: [icon ? _jsx(Icon, { icon: icon, size: "md", weight: "fill" }) : null, tag ? _jsx("span", { className: "tamga-announce-tag", children: tag }) : null, _jsxs("div", { className: "flex min-w-0 flex-1 basis-55 flex-col gap-0.5", children: [title ? _jsx("strong", { className: "font-display text-subhead", children: title }) : null, _jsx("span", { className: "text-small", children: children })] }), action] }));
12
+ }
@@ -36,12 +36,44 @@ export type ThemeChoice = "light" | "dark" | "system";
36
36
  export declare function ThemeCards({ value, onChange, labels, className, ...rest }: {
37
37
  value: ThemeChoice;
38
38
  onChange: (next: ThemeChoice) => void;
39
- /** The three names and the group's accessible name. TR: Üç ad ve kümenin erişilebilir adı. */
39
+ /** The three names, a one-line note under each, and the group's accessible name. TR: Üç ad, her birinin altındaki tek satır, ve kümenin erişilebilir adı. */
40
40
  labels: {
41
41
  light: string;
42
42
  dark: string;
43
43
  system: string;
44
44
  group: string;
45
+ lightNote?: string;
46
+ darkNote?: string;
47
+ systemNote?: string;
48
+ };
49
+ className?: string;
50
+ /** `data-*` hooks pass through. TR: `data-*` kancaları geçiyor. */
51
+ [k: `data-${string}`]: unknown;
52
+ }): import("react").JSX.Element;
53
+ export type RailChoice = "narrow" | "wide" | "free";
54
+ /**
55
+ * Sidebar width picked from three little pictures of the panel.
56
+ * TR: Panelin üç küçük resminden seçilen kenar çubuğu genişliği.
57
+ *
58
+ * This was a `Segmented` of three words. On the same screen the theme was
59
+ * asked with pictures and this with words, and how much room a menu takes is
60
+ * the kind of thing you see rather than read.
61
+ * TR: Bu üç kelimelik bir `Segmented` idi. Aynı ekranda tema resimle, bu
62
+ * kelimeyle soruluyordu; oysa bir menünün ne kadar yer kapladığı okunacak
63
+ * değil görülecek bir şey.
64
+ */
65
+ export declare function RailCards({ value, onChange, labels, className, ...rest }: {
66
+ value: RailChoice;
67
+ onChange: (next: RailChoice) => void;
68
+ /** The three names, a one-line note under each, and the group's accessible name. TR: Üç ad, her birinin altındaki tek satır, ve kümenin erişilebilir adı. */
69
+ labels: {
70
+ narrow: string;
71
+ wide: string;
72
+ free: string;
73
+ group: string;
74
+ narrowNote?: string;
75
+ wideNote?: string;
76
+ freeNote?: string;
45
77
  };
46
78
  className?: string;
47
79
  /** `data-*` hooks pass through. TR: `data-*` kancaları geçiyor. */
@@ -1 +1 @@
1
- {"version":3,"file":"appearance.d.ts","sourceRoot":"","sources":["../../src/components/appearance.tsx"],"names":[],"mappings":"AAEA,OAAO,EAA2B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAehE,MAAM,MAAM,YAAY,GAAG;IACzB,8DAA8D;IAC9D,GAAG,EAAE,MAAM,CAAC;IACZ,kHAAkH;IAClH,KAAK,EAAE,MAAM,CAAC;CACf,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE5B;;;GAGG;AACH,wBAAgB,aAAa,CAAC,EAC5B,OAAO,EACP,KAAK,EACL,QAAQ,EACR,WAAW,EACX,MAAa,EACb,SAAS,EACT,GAAG,IAAI,EACR,EAAE;IACD,OAAO,EAAE,SAAS,YAAY,EAAE,CAAC;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,uGAAuG;IACvG,WAAW,EAAE,MAAM,CAAC;IACpB,2FAA2F;IAC3F,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mEAAmE;IACnE,CAAC,CAAC,EAAE,QAAQ,MAAM,EAAE,GAAG,OAAO,CAAC;CAChC,+BAsCA;AAED,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;AAoBtD;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,QAAQ,EACR,MAAM,EACN,SAAS,EACT,GAAG,IAAI,EACR,EAAE;IACD,KAAK,EAAE,WAAW,CAAC;IACnB,QAAQ,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC;IACtC,8FAA8F;IAC9F,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACvE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mEAAmE;IACnE,CAAC,CAAC,EAAE,QAAQ,MAAM,EAAE,GAAG,OAAO,CAAC;CAChC,+BA6BA;AAED;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,QAAQ,EACR,OAAO,EACP,MAAM,EACN,OAAO,EACP,KAAK,EACL,SAAS,EACT,GAAG,IAAI,EACR,EAAE;IACD,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IACxC,iGAAiG;IACjG,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE;QACN,gGAAgG;QAChG,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,eAAe,EAAE,MAAM,CAAC;KACzB,CAAC;IACF,+HAA+H;IAC/H,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,SAAS,CAAC;IACpC,mFAAmF;IACnF,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mEAAmE;IACnE,CAAC,CAAC,EAAE,QAAQ,MAAM,EAAE,GAAG,OAAO,CAAC;CAChC,+BAoDA"}
1
+ {"version":3,"file":"appearance.d.ts","sourceRoot":"","sources":["../../src/components/appearance.tsx"],"names":[],"mappings":"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"}
@@ -2,10 +2,13 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useId, useRef, useState } from "react";
4
4
  import { cn } from "../lib/cn.js";
5
+ import { makePalette } from "../lib/palette.js";
5
6
  import { dataProps } from "../lib/data-props.js";
6
7
  import { IMAGE_ACCEPT, prepareImage } from "../lib/image.js";
7
8
  import { Alert } from "./primitives.js";
8
9
  import { Button } from "./button.js";
10
+ import { Icon } from "./icon.js";
11
+ import { Check, Eyedropper } from "./icons.js";
9
12
  /**
10
13
  * Brand colour chosen from a few squares, or written by hand.
11
14
  * TR: Birkaç kareden seçilen ya da elle yazılan marka rengi.
@@ -13,10 +16,59 @@ import { Button } from "./button.js";
13
16
  export function ColorSwatches({ options, value, onChange, customLabel, custom = true, className, ...rest }) {
14
17
  const secili = (hex) => hex.toLowerCase() === value.toLowerCase();
15
18
  const hazirMi = options.some((o) => secili(o.hex));
16
- return (_jsxs("span", { ...dataProps(rest), className: cn("flex flex-wrap items-center gap-3", className), children: [options.map(({ hex, label: etiket, ...rest }) => (_jsx("button", { ...rest, type: "button", className: "tamga-swatch", "data-selected": secili(hex), "aria-label": etiket, title: etiket, onClick: () => onChange(hex), children: _jsx("span", { "aria-hidden": true, style: { background: hex } }) }, hex))), custom ? (_jsxs("label", { className: "tamga-swatch", "data-selected": !hazirMi, title: customLabel, children: [_jsx("span", { className: "sr-only", children: customLabel }), _jsx("input", { type: "color", value: hazirMi ? options[0].hex : value, onChange: (e) => onChange(e.target.value), className: "tamga-color-input", "aria-label": customLabel })] })) : null] }));
19
+ return (_jsxs("span", { ...dataProps(rest), className: cn("flex flex-wrap items-center gap-3", className), children: [options.map(({ hex, label: etiket, ...rest }) => (_jsx("button", { ...rest, type: "button", className: "tamga-swatch", style: { background: hex, color: mürekkep(hex) }, "data-selected": secili(hex), "aria-pressed": secili(hex), "aria-label": etiket, title: etiket, onClick: () => onChange(hex), children: secili(hex) ? _jsx(Icon, { icon: Check, size: "base", weight: "bold" }) : null }, hex))), custom ? (_jsxs("label", { className: "tamga-swatch tamga-swatch-custom", "data-selected": !hazirMi, title: customLabel, style: hazirMi
20
+ ? /* Hiçbir hazır renk seçili değilken kutu o rengi giyiyor;
21
+ seçiliyken damalı zemin "burada henüz bir renk yok" diyor. */
22
+ { background: DAMA }
23
+ : { background: value, color: mürekkep(value) }, children: [_jsx("span", { className: "sr-only", children: customLabel }), _jsx(Icon, { icon: hazirMi ? Eyedropper : Check, size: "base", weight: "bold", style: hazirMi ? { color: "var(--color-ink)" } : undefined }), _jsx("input", { type: "color", value: hazirMi ? options[0].hex : value, onChange: (e) => onChange(e.target.value), className: "tamga-color-input", "aria-label": customLabel })] })) : null] }));
17
24
  }
18
- function Yarim({ theme }) {
19
- return (_jsxs("span", { className: "tamga-theme-half", "data-theme": theme, "aria-hidden": true, children: [_jsxs("span", { className: "tamga-theme-rail", children: [_jsx("span", { className: "tamga-theme-dot", "data-accent": "true" }), _jsx("span", { className: "tamga-theme-dot" }), _jsx("span", { className: "tamga-theme-dot" })] }), _jsxs("span", { className: "tamga-theme-body", children: [_jsx("span", { className: "tamga-theme-line", style: { width: "70%" } }), _jsx("span", { className: "tamga-theme-line", style: { width: "45%" } }), _jsx("span", { className: "tamga-theme-line", "data-accent": "true", style: { width: "30%" } }), _jsx("span", { className: "tamga-theme-line", style: { width: "60%" } })] })] }));
25
+ /* Damalı zemin: "burada renk yok". Kutunun kendisi bir renk olduğu için boş
26
+ hâlin de bir zemini olmak zorunda, ve düz bir gri yedinci bir renk gibi
27
+ okunuyordu. */
28
+ const DAMA = "repeating-linear-gradient(135deg, var(--color-hover) 0 6px, var(--color-sunk) 6px 12px)";
29
+ /**
30
+ * Ink that stays readable on a given fill.
31
+ * TR: Verilen dolgunun üstünde okunur kalan mürekkep.
32
+ *
33
+ * TOKEN DEĞİL, HESAP · ve önce token'dı: `--color-accent-ink`. Kusuru
34
+ * tarayıcıda göründü. Kutular SEÇİLEN ham rengi gösteriyor, token ise o an
35
+ * YÜRÜRLÜKTEKİ paletin mürekkebi; koyu temada antrasit marka seçilince palet
36
+ * vurguyu açıyor (#838c9d) ve mürekkebini koyulaştırıyor (#222326), oysa
37
+ * kutunun zemini hâlâ ham #3f4756. Sonuç koyunun üstünde koyu çentik: 1.4
38
+ * kontrast, yani görünmez.
39
+ *
40
+ * Cevap paletin kendisinde: o rengin PALETİ hangi mürekkebi seçiyorsa kutu da
41
+ * onu giyiyor. Eşik uydurmuyoruz, üreteci ikinci kez yazmıyoruz.
42
+ */
43
+ const MUREKKEP = new Map();
44
+ function mürekkep(hex) {
45
+ const anahtar = hex.toLowerCase();
46
+ let m = MUREKKEP.get(anahtar);
47
+ if (m === undefined) {
48
+ m = makePalette(anahtar).light.accentInk;
49
+ MUREKKEP.set(anahtar, m);
50
+ }
51
+ return m;
52
+ }
53
+ /* Panelin yarısı: ray ve gövde. Bir tema kartı bunu bir kez çiziyor,
54
+ "Sistem" kartı iki kez · ikincisi çapraz kesilerek üstüne biniyor.
55
+
56
+ MİNYATÜR SABİT RENKLERLE, ve kitin tek istisnası bu. Seçenekler o an
57
+ yürürlükteki temayı değil SEÇİLİRSE ne olacağını gösteriyor; token
58
+ kullanılsaydı üçü de aynı görünürdü. Tek token: marka vurgusu, çünkü
59
+ önizlemenin yarısı o. */
60
+ function Yarim({ theme, clip = false }) {
61
+ return (_jsxs("span", { className: "tamga-theme-half", "data-theme": theme, "data-clip": clip || undefined, "aria-hidden": true, children: [_jsxs("span", { className: "tamga-theme-rail", children: [_jsx("span", { className: "tamga-theme-dot", "data-accent": "true", style: { width: "80%" } }), _jsx("span", { className: "tamga-theme-dot", style: { width: "100%" } }), _jsx("span", { className: "tamga-theme-dot", style: { width: "70%" } }), _jsx("span", { className: "tamga-theme-dot", style: { width: "60%" } })] }), _jsxs("span", { className: "tamga-theme-body", children: [_jsx("span", { className: "tamga-theme-line", "data-accent": "true", style: { width: "50%" } }), _jsx("span", { className: "tamga-theme-line", style: { width: "100%" } }), _jsx("span", { className: "tamga-theme-line", style: { width: "70%" } })] })] }));
62
+ }
63
+ /**
64
+ * A miniature of the panel with a radio and a name under it.
65
+ * TR: Altında bir radyo ve bir ad duran panel minyatürü.
66
+ *
67
+ * Tema ve kenar çubuğu aynı soruyu soruyor ("hangisi olsun") ve ayrı
68
+ * çizilmişlerdi; ortak olan kap, farklı olan yalnız minyatürün içi.
69
+ */
70
+ function OnizlemeKarti({ selected, onSelect, label, sub, children, }) {
71
+ return (_jsxs("button", { type: "button", role: "radio", "aria-checked": selected, tabIndex: selected ? 0 : -1, "data-selected": selected, className: "tamga-preview-card", onClick: onSelect, children: [_jsx("span", { className: "tamga-preview-box", children: children }), _jsxs("span", { className: "tamga-preview-foot", children: [_jsx("span", { className: "tamga-radio", "data-checked": selected, "aria-hidden": true }), _jsxs("span", { className: "tamga-preview-text", children: [_jsx("strong", { children: label }), sub ? _jsx("span", { children: sub }) : null] })] })] }));
20
72
  }
21
73
  /**
22
74
  * Theme picked from three little pictures of the panel.
@@ -31,11 +83,30 @@ function Yarim({ theme }) {
31
83
  */
32
84
  export function ThemeCards({ value, onChange, labels, className, ...rest }) {
33
85
  const secenekler = [
34
- { deger: "light", ad: labels.light },
35
- { deger: "dark", ad: labels.dark },
36
- { deger: "system", ad: labels.system },
86
+ { deger: "light", ad: labels.light, alt: labels.lightNote },
87
+ { deger: "dark", ad: labels.dark, alt: labels.darkNote },
88
+ { deger: "system", ad: labels.system, alt: labels.systemNote },
89
+ ];
90
+ return (_jsx("div", { ...dataProps(rest), role: "radiogroup", "aria-label": labels.group, className: cn("tamga-preview-grid", className), children: secenekler.map((s) => (_jsx(OnizlemeKarti, { selected: value === s.deger, onSelect: () => onChange(s.deger), label: s.ad, sub: s.alt, children: _jsxs("span", { className: "tamga-theme-box", children: [_jsx(Yarim, { theme: s.deger === "dark" ? "dark" : "light" }), s.deger === "system" ? _jsx(Yarim, { theme: "dark", clip: true }) : null] }) }, s.deger))) }));
91
+ }
92
+ /**
93
+ * Sidebar width picked from three little pictures of the panel.
94
+ * TR: Panelin üç küçük resminden seçilen kenar çubuğu genişliği.
95
+ *
96
+ * This was a `Segmented` of three words. On the same screen the theme was
97
+ * asked with pictures and this with words, and how much room a menu takes is
98
+ * the kind of thing you see rather than read.
99
+ * TR: Bu üç kelimelik bir `Segmented` idi. Aynı ekranda tema resimle, bu
100
+ * kelimeyle soruluyordu; oysa bir menünün ne kadar yer kapladığı okunacak
101
+ * değil görülecek bir şey.
102
+ */
103
+ export function RailCards({ value, onChange, labels, className, ...rest }) {
104
+ const secenekler = [
105
+ { deger: "wide", ad: labels.wide, alt: labels.wideNote },
106
+ { deger: "narrow", ad: labels.narrow, alt: labels.narrowNote },
107
+ { deger: "free", ad: labels.free, alt: labels.freeNote },
37
108
  ];
38
- return (_jsx("div", { ...dataProps(rest), role: "radiogroup", "aria-label": labels.group, className: cn("flex flex-wrap gap-3", className), children: secenekler.map((s) => (_jsxs("button", { type: "button", role: "radio", "aria-checked": value === s.deger, tabIndex: value === s.deger ? 0 : -1, "data-selected": value === s.deger, className: "tamga-theme-card", onClick: () => onChange(s.deger), children: [_jsxs("span", { className: "tamga-theme-box", children: [s.deger === "dark" ? _jsx(Yarim, { theme: "dark" }) : _jsx(Yarim, { theme: "light" }), s.deger === "system" ? _jsx(Yarim, { theme: "dark" }) : null] }), _jsx("span", { className: "tamga-theme-name", children: s.ad })] }, s.deger))) }));
109
+ return (_jsx("div", { ...dataProps(rest), role: "radiogroup", "aria-label": labels.group, className: cn("tamga-preview-grid", className), children: secenekler.map((s) => (_jsx(OnizlemeKarti, { selected: value === s.deger, onSelect: () => onChange(s.deger), label: s.ad, sub: s.alt, children: _jsxs("span", { className: "tamga-rail-mini", "data-mode": s.deger, "aria-hidden": true, children: [_jsxs("span", { className: "tamga-rail-mini-rail", children: [_jsx("span", { "data-accent": "true" }), _jsx("span", {}), _jsx("span", {}), _jsx("span", {}), s.deger === "free" ? _jsx("span", { className: "tamga-rail-mini-toggle" }) : null] }), _jsxs("span", { className: "tamga-rail-mini-body", children: [_jsx("span", {}), _jsx("span", {})] })] }) }, s.deger))) }));
39
110
  }
40
111
  /**
41
112
  * One image with a preview, a replace and a remove.
@@ -1,10 +1,13 @@
1
+ import type { Tone } from "./tone.js";
1
2
  /** Square, monochrome. Identity is text — color is reserved for health. */
2
- export declare function Avatar({ name, size, src, bare, letters, ...rest }: {
3
+ export declare function Avatar({ name, size, src, bare, look, letters, status, ...rest }: {
3
4
  name: string;
4
5
  size?: number;
5
6
  /**
6
- * falls back to initials when absent or broken TR: yoksa ya da yüklenemezse baş harflere
7
- * düşer
7
+ * The photo. Without it the tile carries initials; a photo that FAILS to load is the
8
+ * browser's broken-image mark, not the initials. TR: Fotoğraf. Yoksa karo baş harfleri
9
+ * taşıyor; yüklenEMEyen bir fotoğrafta baş harfler değil tarayıcının kırık görsel işareti
10
+ * kalıyor.
8
11
  */
9
12
  src?: string;
10
13
  /**
@@ -16,6 +19,14 @@ export declare function Avatar({ name, size, src, bare, letters, ...rest }: {
16
19
  * düğmesi çıplak bir simge taşıyan bir araç çubuğunda tek başına farklı gösteriyordu.
17
20
  */
18
21
  bare?: boolean;
22
+ /**
23
+ * `solid` the accent tile with light initials, `soft` the light tile with dark ones. Two, not
24
+ * a palette: an avatar is not a status, and a wall of differently coloured tiles reads as a
25
+ * legend nobody wrote. TR: `solid` vurgu karosu ve açık baş harfler, `soft` açık karo ve koyu
26
+ * harfler. İki tane, bir palet değil: avatar bir durum değil, ve farklı renkli karolardan
27
+ * oluşan bir duvar, kimsenin yazmadığı bir lejant gibi okunuyor.
28
+ */
29
+ look?: "solid" | "soft";
19
30
  /**
20
31
  * How many initials to show. An avatar standing alone carries two, the least it takes to
21
32
  * point at a person. But two do not fit in an OVERLAPPING stack: the tile above clips the
@@ -28,29 +39,25 @@ export declare function Avatar({ name, size, src, bare, letters, ...rest }: {
28
39
  * harf ise yarım okunamaz. `AvatarStack` bu yüzden 1 geçiyor.
29
40
  */
30
41
  letters?: 1 | 2;
42
+ /**
43
+ * A presence mark on the tile's bottom-right corner, in the tone's own colour. It is the ONE
44
+ * place colour is allowed on an avatar: the tile stays monochrome because identity is text,
45
+ * and this square is not identity but health. Absent by default · a mark on every avatar is
46
+ * a legend nobody wrote. TR: Karonun sağ alt köşesinde, tonun kendi rengiyle bir varlık
47
+ * işareti. Avatarda rengin izinli olduğu TEK yer: kimlik metin olduğu için karo tek renkli
48
+ * kalıyor, ve bu kare kimlik değil sağlık. Varsayılanı yok · her avatarda duran bir işaret,
49
+ * kimsenin yazmadığı bir lejant olurdu.
50
+ */
51
+ status?: Tone;
31
52
  /** `data-*` hooks pass through. TR: `data-*` kancaları geçiyor. */
32
53
  [k: `data-${string}`]: unknown;
33
54
  }): import("react").JSX.Element;
34
55
  /**
35
- * Üst üste binen ekip.
36
- *
37
- * İKİ ŞEY AYRI AYRI YANLIŞTI ve ikisi de aynı sonucu veriyordu: karolar
38
- * birbirine yapışıp tek bir karışık blok olarak okunuyordu.
39
- *
40
- * Birincisi ÖRTÜŞME SABİTTİ — her boyutta 8px. Bir 24px karoda bu üçte bir
41
- * demek, ve iki baş harften biri kapanıyor. Şimdi boyuna oranlı: dörtte bir,
42
- * yani karo büyüdükçe örtüşme de büyüyor ama oran sabit kalıyor.
43
- *
44
- * İkincisi AYIRICI HALKA YOKTU. Avatarın kendi 1px kenarı yeterli sanılmıştı
45
- * ve değildi: iki karo bitişince o kenarlar tek bir çizgi oluyor, ve
46
- * hangisinin önde olduğu okunmuyor. Üstteki karonun etrafına ARKA PLAN
47
- * RENGİNDE bir halka koyunca, üstteki alttakini gerçekten kesiyor.
56
+ * Üst üste binen ekip · örtüşme boyuna ORANLI (dörtte bir), ve üstteki karonun
57
+ * etrafında arka plan renginde bir AYIRICI HALKA var: onsuz bitişen 1px kenarlar
58
+ * tek çizgi oluyor. `surface` bu yüzden prop, halka zeminin rengi olmalı.
48
59
  *
49
- * `surface` bu yüzden bir prop: halka, yığının ÜSTÜNDE DURDUĞU zeminin rengi
50
- * olmalı. Varsayılan kart zemini (`--color-shell`), çünkü bir ekip listesi
51
- * neredeyse her zaman bir kartın içindedir — ama sayfa zemininde duracaksa
52
- * çağıran onu söyler. Bulanıklık yok: `0 0 0` yayılımsız bir halka, gölge
53
- * değil.
60
+ * Gerekçe: docs/gerekce/05-yuzey-ve-kabuk.md
54
61
  */
55
62
  export declare function AvatarStack({ names, extra, size, surface, ...rest }: {
56
63
  names: string[];
@@ -1 +1 @@
1
- {"version":3,"file":"avatar.d.ts","sourceRoot":"","sources":["../../src/components/avatar.tsx"],"names":[],"mappings":"AAWA,2EAA2E;AAC3E,wBAAgB,MAAM,CAAC,EACrB,IAAI,EACJ,IAAS,EACT,GAAG,EACH,IAAY,EACZ,OAAW,EACX,GAAG,IAAI,EACR,EAAE;IACD,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;;;;OAOG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;;;;;;;;;OAUG;IACH,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;IAChB,mEAAmE;IACnE,CAAC,CAAC,EAAE,QAAQ,MAAM,EAAE,GAAG,OAAO,CAAC;CAChC,+BAkCA;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,KAAK,EACL,IAAS,EACT,OAA8B,EAC9B,GAAG,IAAI,EACR,EAAE;IACD,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mEAAmE;IACnE,CAAC,CAAC,EAAE,QAAQ,MAAM,EAAE,GAAG,OAAO,CAAC;CAChC,+BA4BA"}
1
+ {"version":3,"file":"avatar.d.ts","sourceRoot":"","sources":["../../src/components/avatar.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAWtC,2EAA2E;AAC3E,wBAAgB,MAAM,CAAC,EACrB,IAAI,EACJ,IAAS,EACT,GAAG,EACH,IAAY,EACZ,IAAc,EACd,OAAW,EACX,MAAM,EACN,GAAG,IAAI,EACR,EAAE;IACD,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;;;;OAOG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IACxB;;;;;;;;;;OAUG;IACH,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;IAChB;;;;;;;;OAQG;IACH,MAAM,CAAC,EAAE,IAAI,CAAC;IACd,mEAAmE;IACnE,CAAC,CAAC,EAAE,QAAQ,MAAM,EAAE,GAAG,OAAO,CAAC;CAChC,+BA0EA;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,KAAK,EACL,IAAS,EACT,OAA8B,EAC9B,GAAG,IAAI,EACR,EAAE;IACD,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mEAAmE;IACnE,CAAC,CAAC,EAAE,QAAQ,MAAM,EAAE,GAAG,OAAO,CAAC;CAChC,+BAuCA"}