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
@@ -0,0 +1,29 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { toneOf, rankOf } from "./tone.js";
4
+ import { useLiveClaim } from "./live-scope.js";
5
+ /* `live` is a REQUEST, not a decision. The element asks the nearest LiveScope
6
+ to pulse and only the most severe asker wins — see live-scope.tsx. Call sites
7
+ keep writing `live={m.health === "down"}` exactly as before; the counting is
8
+ no longer their problem. */
9
+ export function StatusChip({ label, state, dot = true, live = false, mono = false, severity, }) {
10
+ const h = toneOf(state);
11
+ const pulses = useLiveClaim(live ? rankOf(state, severity) : null);
12
+ return (_jsxs("span", { className: `tamga-chip ${mono ? "tamga-chip-mono" : ""}`, style: { background: h.bg, color: h.fg }, children: [dot && (_jsx("span", { className: `inline-block size-[var(--mark-dot)] ${pulses ? "tamga-live" : ""}`, style: { background: h.mark } })), label] }));
13
+ }
14
+ export function Delta({ value, better, mono = true, }) {
15
+ /* good movement stays neutral — color is reserved for deviation */
16
+ const color = better ? "var(--color-ink-faint)" : "var(--color-critical)";
17
+ const rising = !value.trimStart().startsWith("-");
18
+ return (_jsxs("span", { className: `inline-flex items-center gap-1 text-small font-bold ${mono ? "font-mono" : ""}`, style: { color }, children: [_jsx("svg", { width: "9", height: "9", viewBox: "0 0 10 10", "aria-hidden": true, children: _jsx("path", { d: rising ? "M5 1L9 8H1Z" : "M5 9L1 2H9Z", style: { fill: color } }) }), value] }));
19
+ }
20
+ /**
21
+ * Solid square status mark used in dense tables. Uses `fg` rather than `mark`
22
+ * so a single 10px square still reads at rest — bars can afford to be quieter,
23
+ * a lone dot cannot.
24
+ */
25
+ export function Dot({ state, live = false, severity, }) {
26
+ const h = toneOf(state);
27
+ const pulses = useLiveClaim(live ? rankOf(state, severity) : null);
28
+ return (_jsx("span", { className: `inline-block size-2.5 shrink-0 ${pulses ? "tamga-live" : ""}`, style: { background: h.fg }, "aria-hidden": true }));
29
+ }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Yatay çubuk grafik — SIRALAMA ve KARŞILAŞTIRMA.
3
+ *
4
+ * Gerekçe: docs/gerekce/03-grafik-ve-olcum.md
5
+ */
6
+ export type Bar = {
7
+ label: string;
8
+ value: number;
9
+ /**
10
+ * The second, faint value beside the number: usually a share ("2.4%"). WHY THE COMPONENT DOES
11
+ * NOT COMPUTE IT. In a bar chart the DENOMINATOR of a share is usually NOT the sum of the
12
+ * rows drawn: in "top ten customers by orders" the meaningful denominator is every order in
13
+ * the period, not the sum of those ten. The component cannot know the denominator, and if it
14
+ * guessed it would guess wrong. TR: Sayının yanındaki ikinci, soluk değer: genelde bir pay
15
+ * ("%2.4"). NEDEN BİLEŞEN HESAPLAMIYOR. Bir çubuk grafikte payın PAYDASI çoğu zaman çizilen
16
+ * satırların toplamı DEĞİLDİR: "en çok sipariş veren on müşteri"de anlamlı payda dönemin
17
+ * bütün siparişleridir, o on kişinin toplamı değil. Paydayı bileşen bilemez; bilse de yanlış
18
+ * bilir.
19
+ */
20
+ note?: string;
21
+ };
22
+ export declare function BarChart({ bars, formatValue, labelWidth, className, }: {
23
+ bars: readonly Bar[];
24
+ formatValue?: (v: number) => string;
25
+ /**
26
+ * The width of the name column; the caller picks it from the longest name. TR: Ad sütununun
27
+ * genişliği; en uzun ada göre çağıran seçiyor.
28
+ */
29
+ labelWidth?: string;
30
+ className?: string;
31
+ }): import("react").JSX.Element;
32
+ //# sourceMappingURL=bar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bar.d.ts","sourceRoot":"","sources":["../../src/components/bar.tsx"],"names":[],"mappings":"AAKA;;;;GAIG;AAEH,MAAM,MAAM,GAAG,GAAG;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd;;;;;;;;;;OAUG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AASF,wBAAgB,QAAQ,CAAC,EACvB,IAAI,EACJ,WAAoB,EACpB,UAAoB,EACpB,SAAS,GACV,EAAE;IACD,IAAI,EAAE,SAAS,GAAG,EAAE,CAAC;IACrB,WAAW,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IACpC;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,+BA4DA"}
@@ -0,0 +1,33 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useState } from "react";
4
+ import { cn } from "../lib/cn.js";
5
+ /** Sayıyı ızgara çizgisine yuvarlar: 87 → 100, 412 → 500. */
6
+ function niceMax(v) {
7
+ if (v <= 0)
8
+ return 1;
9
+ const mag = 10 ** Math.floor(Math.log10(v));
10
+ return Math.ceil(v / mag) * mag;
11
+ }
12
+ export function BarChart({ bars, formatValue = String, labelWidth = "10rem", className, }) {
13
+ const enBuyuk = niceMax(Math.max(0, ...bars.map((b) => b.value)));
14
+ /* SATIRIN TAMAMI VURGULANIYOR, yalnız çubuk değil: uzun bir listede gözün
15
+ kaydığı şey satır. Ad solda, sayı sağda, arada bir metre uzunluğunda
16
+ çubuk var; hangi adın hangi sayıya ait olduğunu takip etmek zorlaşıyor ve
17
+ satır zemini o izi tutuyor. */
18
+ const [uzerinde, setUzerinde] = useState(null);
19
+ return (_jsxs("div", { className: cn("flex flex-col gap-0.5", className), onMouseLeave: () => setUzerinde(null), children: [bars.map((b) => {
20
+ const oran = enBuyuk > 0 ? b.value / enBuyuk : 0;
21
+ const secili = uzerinde === b.label;
22
+ return (_jsxs("div", { className: "grid cursor-default items-center gap-3 rounded-(--radius-mark) px-1.5 py-1 transition-[background] duration-(--duration-press)", style: {
23
+ gridTemplateColumns: `${labelWidth} minmax(0,1fr) auto`,
24
+ background: secili ? "var(--color-hover)" : undefined,
25
+ }, onMouseEnter: () => setUzerinde(b.label), children: [_jsx("span", { className: "truncate text-right text-small", style: { color: secili ? "var(--color-ink)" : "var(--color-ink-soft)" }, title: b.label, children: b.label }), _jsx("span", { className: "relative block h-4 rounded-(--radius-mark) bg-[var(--color-chart-fill)]", children: _jsx("span", { className: "absolute inset-y-0 left-0 rounded-(--radius-mark) transition-[background] duration-(--duration-press)", style: {
26
+ width: `${Math.max(oran * 100, b.value > 0 ? 1.5 : 0)}%`,
27
+ /* Üzerine gelinen çubuk bir kademe koyu: aynı hue, farklı
28
+ ton. Renk değiştirmek çubuğu başka bir seriye ait
29
+ gösterirdi. */
30
+ background: secili ? "var(--color-accent-line)" : "var(--color-chart-3)",
31
+ } }) }), _jsxs("span", { className: "tabular-nums text-small", style: { color: secili ? "var(--color-ink)" : "var(--color-ink-soft)" }, children: [formatValue(b.value), b.note && _jsx("span", { className: "ml-1.5 text-ink-faint", children: b.note })] })] }, b.label));
32
+ }), bars.length === 0 && _jsx("p", { className: "text-ink-faint", children: "G\u00F6sterilecek veri yok." })] }));
33
+ }
@@ -0,0 +1,45 @@
1
+ import { type VariantProps } from "class-variance-authority";
2
+ /**
3
+ * The button family, typed.
4
+ *
5
+ * Gerekçe: docs/gerekce/06-isaret-ve-ton.md
6
+ */
7
+ export declare const buttonVariants: (props?: ({
8
+ variant?: "danger" | "ghost" | "link" | "primary" | "secondary" | "success" | null | undefined;
9
+ size?: "base" | "sm" | null | undefined;
10
+ full?: boolean | null | undefined;
11
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
12
+ export type ButtonProps = React.ComponentProps<"button"> & VariantProps<typeof buttonVariants> & {
13
+ /**
14
+ * The click is still running. TR: Tıklama hâlâ sürüyor.
15
+ *
16
+ * Sürerken düğme kilitleniyor ve etiketinin yerine bir spinner geçiyor.
17
+ * Bunun düğmenin kendisinde olmasının sebebi ölçülebilir: her çağrı yeri
18
+ * kendi kilidini yazdığında biri unutuluyor, ve unutulan yer çift gönderim
19
+ * demek. Bir kez yazılan bir kural, altmış çağrı yerinde hatırlanan bir
20
+ * kuraldan güvenli.
21
+ */
22
+ busy?: boolean;
23
+ /**
24
+ * What the spinner announces while `busy`. TR: Spinner sürerken ekran
25
+ * okuyucunun söylediği şey.
26
+ *
27
+ * ZORUNLU DEĞİL AMA VARSAYILANI YOK: kit çeviri yapmıyor, ve "Loading"
28
+ * diye İngilizce bir varsayılan her Türkçe panele İngilizce bir cümle
29
+ * gönderirdi. Verilmezse düğmenin kendi metni okunuyor.
30
+ */
31
+ busyLabel?: string;
32
+ };
33
+ export declare function Button({ className, variant, size, full, busy, busyLabel, children, disabled, ...props }: ButtonProps): import("react").JSX.Element;
34
+ export declare const iconButtonVariants: (props?: ({
35
+ size?: "base" | "sm" | null | undefined;
36
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
37
+ /** 40px square. Always needs an aria-label — there is no text to read. */
38
+ export declare function IconButton({ className, size, "aria-label": label, ...props }: React.ComponentProps<"button"> & VariantProps<typeof iconButtonVariants> & {
39
+ "aria-label": string;
40
+ }): import("react").JSX.Element;
41
+ /** The densest member: 1px at rest, 2px on hover, and its edge turns accent. */
42
+ export declare function MiniButton({ className, "aria-label": label, ...props }: React.ComponentProps<"button"> & {
43
+ "aria-label": string;
44
+ }): import("react").JSX.Element;
45
+ //# sourceMappingURL=button.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../src/components/button.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAIlE;;;;GAIG;AAEH,eAAO,MAAM,cAAc;;;;8EA2BzB,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,GACtD,YAAY,CAAC,OAAO,cAAc,CAAC,GAAG;IACpC;;;;;;;;OAQG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEJ,wBAAgB,MAAM,CAAC,EACrB,SAAS,EACT,OAAO,EACP,IAAI,EACJ,IAAI,EACJ,IAAY,EACZ,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,WAAW,+BA2Bb;AAID,eAAO,MAAM,kBAAkB;;8EAG7B,CAAC;AAEH,0EAA0E;AAC1E,wBAAgB,UAAU,CAAC,EACzB,SAAS,EACT,IAAI,EACJ,YAAY,EAAE,KAAK,EACnB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,GAC/B,YAAY,CAAC,OAAO,kBAAkB,CAAC,GAAG;IAAE,YAAY,EAAE,MAAM,CAAA;CAAE,+BASnE;AAED,gFAAgF;AAChF,wBAAgB,UAAU,CAAC,EACzB,SAAS,EACT,YAAY,EAAE,KAAK,EACnB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,GAAG;IAAE,YAAY,EAAE,MAAM,CAAA;CAAE,+BAS3D"}
@@ -0,0 +1,56 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { cva } from "class-variance-authority";
3
+ import { cn } from "../lib/cn.js";
4
+ import { Spinner } from "./spinner.js";
5
+ /**
6
+ * The button family, typed.
7
+ *
8
+ * Gerekçe: docs/gerekce/06-isaret-ve-ton.md
9
+ */
10
+ export const buttonVariants = cva("tamga-btn", {
11
+ variants: {
12
+ variant: {
13
+ /* the base button — everything else is this shape plus a colour */
14
+ secondary: "",
15
+ /* the one filled thing on a page */
16
+ primary: "tamga-btn-primary",
17
+ /* confirming: status colour as an edge, never a fill */
18
+ success: "tamga-btn-success",
19
+ /* destructive: findable and deliberate, not loud */
20
+ danger: "tamga-btn-danger",
21
+ /* no edge, no offset, no lift — it is not an object on the page */
22
+ ghost: "tamga-btn-ghost",
23
+ /* reads as a link, behaves as a button. For a click that runs code but
24
+ must not compete with the buttons beside it. If it NAVIGATES, use an
25
+ anchor with .tamga-link instead — a fake link cannot be middle-clicked
26
+ and misreports itself to a screen reader. */
27
+ link: "tamga-btn-link",
28
+ },
29
+ size: {
30
+ base: "",
31
+ /* 32px, for card headers and dense toolbars */
32
+ sm: "tamga-btn-sm",
33
+ },
34
+ full: { true: "w-full", false: "" },
35
+ },
36
+ defaultVariants: { variant: "secondary", size: "base", full: false },
37
+ });
38
+ export function Button({ className, variant, size, full, busy = false, busyLabel, children, disabled, ...props }) {
39
+ return (_jsx("button", { "data-slot": "button", "data-busy": busy || undefined, "aria-busy": busy || undefined,
40
+ /* Kilit `disabled` ile: sürerken ikinci bir tıklama olayı hiç doğmuyor.
41
+ `pointer-events: none` yetmezdi — klavye Enter'ı yine gönderirdi. */
42
+ disabled: disabled || busy, className: cn(buttonVariants({ variant, size, full }), className), ...props, children: busy ? (_jsxs(_Fragment, { children: [_jsx(Spinner, { size: 16, label: busyLabel ?? "" }), _jsx("span", { className: "invisible", "aria-hidden": true, children: children })] })) : (children) }));
43
+ }
44
+ /* --------------------------- icon button -------------------------- */
45
+ export const iconButtonVariants = cva("tamga-icon-btn", {
46
+ variants: { size: { base: "", sm: "size-8" } },
47
+ defaultVariants: { size: "base" },
48
+ });
49
+ /** 40px square. Always needs an aria-label — there is no text to read. */
50
+ export function IconButton({ className, size, "aria-label": label, ...props }) {
51
+ return (_jsx("button", { "data-slot": "icon-button", "aria-label": label, className: cn(iconButtonVariants({ size }), className), ...props }));
52
+ }
53
+ /** The densest member: 1px at rest, 2px on hover, and its edge turns accent. */
54
+ export function MiniButton({ className, "aria-label": label, ...props }) {
55
+ return (_jsx("button", { "data-slot": "mini-button", "aria-label": label, className: cn("tamga-mini-btn", className), ...props }));
56
+ }
@@ -0,0 +1,43 @@
1
+ import { type Tone } from "./tone.js";
2
+ /**
3
+ * Çizgi grafik — eksenli, gerçek grafik.
4
+ *
5
+ * Gerekçe: docs/gerekce/03-grafik-ve-olcum.md
6
+ */
7
+ export type Series = {
8
+ /**
9
+ * The line's name; the legend and the screen reader use it. TR: Çizginin adı; legend ve ekran
10
+ * okuyucu bunu kullanır.
11
+ */
12
+ name: string;
13
+ values: readonly number[];
14
+ /**
15
+ * A STATUS tone: for when a line says something good or bad. LEFT OUT, THE CATEGORICAL
16
+ * PALETTE is used, and that is a correction. Every series without a tone used to fall to
17
+ * `neutral`: plotting three products' daily sales drew three lines in the SAME faint grey,
18
+ * with no way to match the legend's names to them. A series is often not a status but a
19
+ * CATEGORY (product, store, channel), and a category's colour comes from the palette. TR:
20
+ * DURUM tonu: bir çizgi iyi ya da kötü bir şeyi anlatıyorsa. VERİLMEZSE KATEGORİK PALET
21
+ * kullanılıyor, ve bu bir düzeltme. Önce ton verilmeyen her seri `neutral`a düşüyordu: üç
22
+ * ürünün günlük satışını çizdiğinde üç çizgi de AYNI soluk griydi ve legend'daki adları
23
+ * çizgilere eşleştirmenin hiçbir yolu yoktu. Bir seri çoğu zaman bir durum değil bir
24
+ * KATEGORİDİR (ürün, mağaza, kanal), ve kategorinin rengi paletten gelir.
25
+ */
26
+ tone?: Tone;
27
+ };
28
+ export declare function LineChart({ series, labels, height, formatValue, className, }: {
29
+ series: readonly Series[];
30
+ /**
31
+ * The marks under the X axis. The caller formats the numbers. TR: X ekseninin altındaki
32
+ * işaretler. Sayıları çağıran biçimlendirir.
33
+ */
34
+ labels: readonly string[];
35
+ height?: number;
36
+ /**
37
+ * "24ms", "98%"; the unit comes from the caller, the kit knows no units. TR: "24ms", "%98";
38
+ * birim çağırandan gelir, kit birim bilmez.
39
+ */
40
+ formatValue?: (v: number) => string;
41
+ className?: string;
42
+ }): import("react").JSX.Element;
43
+ //# sourceMappingURL=chart.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chart.d.ts","sourceRoot":"","sources":["../../src/components/chart.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAU,KAAK,IAAI,EAAE,MAAM,WAAW,CAAC;AAE9C;;;;GAIG;AAEH,MAAM,MAAM,MAAM,GAAG;IACnB;;;OAGG;IACH,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B;;;;;;;;;;;OAWG;IACH,IAAI,CAAC,EAAE,IAAI,CAAC;CACb,CAAC;AAcF,wBAAgB,SAAS,CAAC,EACxB,MAAM,EACN,MAAM,EACN,MAAY,EACZ,WAAoB,EACpB,SAAS,GACV,EAAE;IACD,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B;;;OAGG;IACH,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,WAAW,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,+BA+HA"}
@@ -0,0 +1,41 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useId, useState } from "react";
4
+ import { cn } from "../lib/cn.js";
5
+ import { toneOf } from "./tone.js";
6
+ /** Ton verilmemiş serinin rengi: sırayla kategorik palet. */
7
+ function seriRengi(s, i) {
8
+ return s.tone ? toneOf(s.tone).mark : `var(--color-chart-${(i % 5) + 1})`;
9
+ }
10
+ /** Sayıyı ızgara çizgisine yuvarlar: 87 → 100, 412 → 500. */
11
+ function niceMax(v) {
12
+ if (v <= 0)
13
+ return 1;
14
+ const mag = 10 ** Math.floor(Math.log10(v));
15
+ return Math.ceil(v / mag) * mag;
16
+ }
17
+ export function LineChart({ series, labels, height = 200, formatValue = String, className, }) {
18
+ const id = useId();
19
+ const [hover, setHover] = useState(null);
20
+ const all = series.flatMap((s) => [...s.values]);
21
+ const max = niceMax(Math.max(1, ...all));
22
+ const count = Math.max(...series.map((s) => s.values.length), 1);
23
+ /* viewBox birim kare: SVG ölçeklenirken çizgi kalınlığı bozulmasın diye
24
+ `vector-effect` kullanılıyor, koordinatlar yüzde üzerinden. */
25
+ const W = 100;
26
+ const H = 100;
27
+ const x = (i) => (count === 1 ? W / 2 : (i / (count - 1)) * W);
28
+ const y = (v) => H - (v / max) * H;
29
+ /* Dört ızgara çizgisi: daha azı okumayı zorlaştırır, daha çoğu grafiği
30
+ kafese çevirir. */
31
+ const ticks = [0, 0.25, 0.5, 0.75, 1].map((f) => max * f);
32
+ return (_jsxs("figure", { className: cn("tamga-surface p-4", className), children: [_jsxs("div", { className: "flex gap-3", children: [_jsx("div", { className: "flex shrink-0 flex-col justify-between text-right font-mono text-caption text-ink-faint tabular-nums", style: { height }, "aria-hidden": true, children: [...ticks].reverse().map((t) => (_jsx("span", { children: formatValue(Math.round(t)) }, t))) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("svg", { viewBox: `0 0 ${W} ${H}`, preserveAspectRatio: "none", style: { height, width: "100%" }, role: "img", "aria-labelledby": id, onMouseLeave: () => setHover(null), children: [_jsx("title", { id: id, children: series.map((s) => `${s.name}: ${formatValue(s.values[s.values.length - 1] ?? 0)}`).join(" · ") }), ticks.map((t) => (_jsx("line", { x1: 0, x2: W, y1: y(t), y2: y(t), stroke: "var(--color-line)", strokeWidth: 1, vectorEffect: "non-scaling-stroke" }, t))), series.map((s, si) => {
33
+ const renk = seriRengi(s, si);
34
+ const d = s.values.map((v, i) => `${i === 0 ? "M" : "L"}${x(i)} ${y(v)}`).join(" ");
35
+ return (_jsx("path", { d: d, fill: "none", stroke: renk, strokeWidth: 2, strokeLinejoin: "round", strokeLinecap: "round", vectorEffect: "non-scaling-stroke" }, s.name));
36
+ }), Array.from({ length: count }, (_, i) => (_jsx("rect", { x: x(i) - W / count / 2, y: 0, width: W / count, height: H, fill: "transparent", onMouseEnter: () => setHover(i) }, i))), hover !== null ? (_jsx("line", { x1: x(hover), x2: x(hover), y1: 0, y2: H, stroke: "var(--color-ink-faint)", strokeWidth: 1, vectorEffect: "non-scaling-stroke" })) : null] }), _jsx("div", { className: "mt-1 flex justify-between font-mono text-caption text-ink-faint", "aria-hidden": true, children: labels.map((l) => (_jsx("span", { children: l }, l))) })] })] }), _jsx("figcaption", { className: "mt-3 flex flex-wrap gap-x-5 gap-y-1", children: series.map((s, si) => {
37
+ const renk = seriRengi(s, si);
38
+ const v = hover !== null ? s.values[hover] : s.values[s.values.length - 1];
39
+ return (_jsxs("span", { className: "flex items-center gap-2 text-small text-ink-soft", children: [_jsx("span", { "aria-hidden": true, className: "h-0.5 w-4", style: { background: renk } }), s.name, _jsx("span", { className: "font-mono text-ink tabular-nums", children: formatValue(v ?? 0) })] }, s.name));
40
+ }) })] }));
41
+ }
@@ -0,0 +1,13 @@
1
+ import type { ReactNode } from "react";
2
+ export declare function Checkbox({ label, checked, onChange, disabled, className, }: {
3
+ /**
4
+ * The visible label. The kit does not translate; the caller passes ready text. TR: Görünen
5
+ * etiket. Kit çeviri yapmaz; hazır metni çağıran geçer.
6
+ */
7
+ label: ReactNode;
8
+ checked: boolean;
9
+ onChange?: (next: boolean) => void;
10
+ disabled?: boolean;
11
+ className?: string;
12
+ }): import("react").JSX.Element;
13
+ //# sourceMappingURL=checkbox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkbox.d.ts","sourceRoot":"","sources":["../../src/components/checkbox.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAavC,wBAAgB,QAAQ,CAAC,EACvB,KAAK,EACL,OAAO,EACP,QAAQ,EACR,QAAgB,EAChB,SAAS,GACV,EAAE;IACD;;;OAGG;IACH,KAAK,EAAE,SAAS,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,+BAkBA"}
@@ -0,0 +1,16 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { cn } from "../lib/cn.js";
4
+ import { Icon } from "./icon.js";
5
+ import { Check } from "./icons.js";
6
+ import { OFF } from "./control-base.js";
7
+ /* ---------------------------------------------------------------- *
8
+ * Checkbox — bir DEĞER, bir hedef değil.
9
+ *
10
+ * İşaretlendiğinde DOLAR. Yasa 2'nin istisnası değil, teyidi: dolgu "bu
11
+ * seçildi" demiyor, "bu değer açık" diyor. Mini butonun 1px kenarını ve 1px
12
+ * offsetini taşır, böylece kontrol ailesinin bir üyesi gibi okunur.
13
+ * ---------------------------------------------------------------- */
14
+ export function Checkbox({ label, checked, onChange, disabled = false, className, }) {
15
+ return (_jsxs("button", { type: "button", role: "checkbox", "aria-checked": checked, "aria-disabled": disabled || undefined, disabled: disabled, onClick: () => !disabled && onChange?.(!checked), className: cn("flex items-center gap-2 text-body", className), style: disabled ? OFF : undefined, children: [_jsx("span", { className: "tamga-check", "data-checked": checked, children: checked ? _jsx(Icon, { icon: Check, size: "xs", weight: "bold" }) : null }), label] }));
16
+ }
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Açık/koyu tema düğmesi.
3
+ *
4
+ * SUNUCU TEMAYI BİLMEZ. İlk boyama her zaman açık temayla çıkar ve tercih
5
+ * `useEffect` içinde uygulanır — yani koyu tema seçmiş biri bir kare boyunca
6
+ * açık ekran görür. Bunu tamamen çözmenin tek yolu `<head>`'e engelleyici bir
7
+ * script koymak, ve o script'in yeri KİT DEĞİL uygulamadır: kitin bir
8
+ * `<head>`'i yoktur.
9
+ *
10
+ * `storageKey` bu yüzden bir prop: uygulama aynı anahtarı kendi script'inde
11
+ * de okuyabilsin diye. İki taraf farklı anahtar kullanırsa tercih sessizce
12
+ * kaybolur.
13
+ *
14
+ * Metinler dışarıdan geliyor. Kit çeviri yapmaz — ve bir düğmenin adı, içinde
15
+ * metin olmadığı için erişilebilirliğin tamamıdır.
16
+ *
17
+ * İKİ BİÇİM, VE SEBEBİ ORANTI. `icon` sıkışık bir araç çubuğuna girer: 40×40,
18
+ * tek simge. Ama yanında bir dil anahtarı gibi ANAHTAR biçimli bir kontrol
19
+ * varsa, kare düğme onun iki katı yüksekliğinde durur ve şerit dengesiz
20
+ * görünür. `switch` biçimi aynı iskeleti kullanıyor — iki uçta birer simge,
21
+ * ortada kayan bir anahtar — yani ikisi yan yana aynı satırda oturuyor.
22
+ */
23
+ export declare function ThemeToggle({ labels, variant, storageKey, className, }: {
24
+ labels: {
25
+ toLight: string;
26
+ toDark: string;
27
+ };
28
+ /**
29
+ * `icon` a square button · `switch` the same shape as a language toggle. TR: `icon` kare
30
+ * düğme · `switch` bir dil anahtarıyla aynı şekil.
31
+ */
32
+ variant?: "icon" | "switch";
33
+ storageKey?: string;
34
+ className?: string;
35
+ }): import("react").JSX.Element;
36
+ /**
37
+ * Dil değiştirici.
38
+ *
39
+ * Kit YÖNLENDİRME YAPMAZ. `onChange` seçilen dili verir; nereye gidileceği —
40
+ * `router.push`, tam sayfa yenileme, bir çerez yazıp yeniden yükleme —
41
+ * uygulamanın kararı ve yönlendiricisine bağlı. Kitin `next/navigation`'a
42
+ * bağlanması, onu bir framework'e bağlamak olurdu.
43
+ *
44
+ * Etiketler ENDONİM olmalı: "English", "İngilizce" değil. Bir dili arayan
45
+ * kişi onu kendi dilinde arar. Kit bunu zorlayamaz ama doküman söyler.
46
+ *
47
+ * İki dilde SEGMENTED, üç ve fazlasında SELECT — kendiliğinden. İki seçenek
48
+ * yan yana sığar ve tek tıkla değişir; beş dil yan yana konursa üst şeridi
49
+ * doldurur ve altıncı dilde taşar.
50
+ */
51
+ export declare function LocaleSwitcher({ locales, current, onChange, label, className, }: {
52
+ /**
53
+ * `[{ value: "tr", label: "Türkçe" }, …]`: the labels are endonyms. TR: `[{ value: "tr",
54
+ * label: "Türkçe" }, …]`: etiketler endonim.
55
+ */
56
+ locales: readonly {
57
+ value: string;
58
+ label: string;
59
+ }[];
60
+ current: string;
61
+ onChange: (next: string) => void;
62
+ /** The control's name: "Dil", "Language". TR: Kontrolün adı: "Dil", "Language". */
63
+ label: string;
64
+ className?: string;
65
+ }): import("react").JSX.Element;
66
+ /**
67
+ * Kare marka karosu.
68
+ *
69
+ * Bir logonun etrafındaki kutu. Görsel yoksa baş harf — `Avatar`'la aynı
70
+ * gerekçe: gri bir yer tutucu hiçbir şeyi temsil etmez, bir harf gerçekten o
71
+ * şeyi işaret eder.
72
+ *
73
+ * `alt` boş bırakılıyor ve bu bilinçli: karo neredeyse her zaman adı YANINDA
74
+ * yazan bir şeyin yanında durur. İkisini de okutmak ekran okuyucuda adı iki
75
+ * kez tekrarlar.
76
+ */
77
+ export declare function LogoTile({ name, src, size, className, }: {
78
+ /**
79
+ * The initial is built from it, and it is what shows when the image does not load. TR: Baş
80
+ * harf buradan üretilir; görsel yüklenmezse görünen şey bu.
81
+ */
82
+ name: string;
83
+ src?: string;
84
+ size?: "base" | "sm";
85
+ className?: string;
86
+ }): import("react").JSX.Element;
87
+ //# sourceMappingURL=chrome.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chrome.d.ts","sourceRoot":"","sources":["../../src/components/chrome.tsx"],"names":[],"mappings":"AA8BA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,WAAW,CAAC,EAC1B,MAAM,EACN,OAAgB,EAChB,UAA0B,EAC1B,SAAS,GACV,EAAE;IACD,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,+BAmDA;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAAC,EAC7B,OAAO,EACP,OAAO,EACP,QAAQ,EACR,KAAK,EACL,SAAS,GACV,EAAE;IACD;;;OAGG;IACH,OAAO,EAAE,SAAS;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACrD,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,mFAAmF;IACnF,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,+BAgCA;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,QAAQ,CAAC,EACvB,IAAI,EACJ,GAAG,EACH,IAAa,EACb,SAAS,GACV,EAAE;IACD;;;OAGG;IACH,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,+BAaA"}
@@ -0,0 +1,107 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useEffect, useState } from "react";
4
+ import { cn } from "../lib/cn.js";
5
+ import { Icon } from "./icon.js";
6
+ import { Switch } from "./switch.js";
7
+ import { ThemeDark, ThemeLight } from "./icons.js";
8
+ /**
9
+ * Kabuk parçaları.
10
+ *
11
+ * Gerekçe: docs/gerekce/05-yuzey-ve-kabuk.md
12
+ */
13
+ /** Tarayıcı depolaması patlayabilir (özel pencere, kapalı site verisi). */
14
+ function read(key) {
15
+ try {
16
+ return localStorage.getItem(key);
17
+ }
18
+ catch {
19
+ return null;
20
+ }
21
+ }
22
+ function write(key, value) {
23
+ try {
24
+ localStorage.setItem(key, value);
25
+ }
26
+ catch {
27
+ /* tercih hatırlanmaz, sayfa yine çalışır */
28
+ }
29
+ }
30
+ /**
31
+ * Açık/koyu tema düğmesi.
32
+ *
33
+ * SUNUCU TEMAYI BİLMEZ. İlk boyama her zaman açık temayla çıkar ve tercih
34
+ * `useEffect` içinde uygulanır — yani koyu tema seçmiş biri bir kare boyunca
35
+ * açık ekran görür. Bunu tamamen çözmenin tek yolu `<head>`'e engelleyici bir
36
+ * script koymak, ve o script'in yeri KİT DEĞİL uygulamadır: kitin bir
37
+ * `<head>`'i yoktur.
38
+ *
39
+ * `storageKey` bu yüzden bir prop: uygulama aynı anahtarı kendi script'inde
40
+ * de okuyabilsin diye. İki taraf farklı anahtar kullanırsa tercih sessizce
41
+ * kaybolur.
42
+ *
43
+ * Metinler dışarıdan geliyor. Kit çeviri yapmaz — ve bir düğmenin adı, içinde
44
+ * metin olmadığı için erişilebilirliğin tamamıdır.
45
+ *
46
+ * İKİ BİÇİM, VE SEBEBİ ORANTI. `icon` sıkışık bir araç çubuğuna girer: 40×40,
47
+ * tek simge. Ama yanında bir dil anahtarı gibi ANAHTAR biçimli bir kontrol
48
+ * varsa, kare düğme onun iki katı yüksekliğinde durur ve şerit dengesiz
49
+ * görünür. `switch` biçimi aynı iskeleti kullanıyor — iki uçta birer simge,
50
+ * ortada kayan bir anahtar — yani ikisi yan yana aynı satırda oturuyor.
51
+ */
52
+ export function ThemeToggle({ labels, variant = "icon", storageKey = "tamga-theme", className, }) {
53
+ const [dark, setDark] = useState(false);
54
+ useEffect(() => {
55
+ const saved = read(storageKey);
56
+ const initial = saved
57
+ ? saved === "dark"
58
+ : window.matchMedia("(prefers-color-scheme: dark)").matches;
59
+ setDark(initial);
60
+ document.documentElement.classList.toggle("dark", initial);
61
+ }, [storageKey]);
62
+ function toggle() {
63
+ const next = !dark;
64
+ setDark(next);
65
+ document.documentElement.classList.toggle("dark", next);
66
+ write(storageKey, next ? "dark" : "light");
67
+ }
68
+ if (variant === "switch") {
69
+ return (_jsxs("span", { className: cn("flex items-center gap-2", className), children: [_jsx(Icon, { icon: ThemeLight, size: "xs", "aria-hidden": true, className: dark ? "text-ink-faint" : "text-ink" }), _jsx(Switch, { on: dark, onChange: toggle, label: dark ? labels.toLight : labels.toDark }), _jsx(Icon, { icon: ThemeDark, size: "xs", "aria-hidden": true, className: dark ? "text-ink" : "text-ink-faint" })] }));
70
+ }
71
+ return (_jsx("button", { type: "button", onClick: toggle, className: cn("tamga-icon-btn", className), "aria-label": dark ? labels.toLight : labels.toDark, children: _jsx(Icon, { icon: dark ? ThemeLight : ThemeDark, size: "sm" }) }));
72
+ }
73
+ /**
74
+ * Dil değiştirici.
75
+ *
76
+ * Kit YÖNLENDİRME YAPMAZ. `onChange` seçilen dili verir; nereye gidileceği —
77
+ * `router.push`, tam sayfa yenileme, bir çerez yazıp yeniden yükleme —
78
+ * uygulamanın kararı ve yönlendiricisine bağlı. Kitin `next/navigation`'a
79
+ * bağlanması, onu bir framework'e bağlamak olurdu.
80
+ *
81
+ * Etiketler ENDONİM olmalı: "English", "İngilizce" değil. Bir dili arayan
82
+ * kişi onu kendi dilinde arar. Kit bunu zorlayamaz ama doküman söyler.
83
+ *
84
+ * İki dilde SEGMENTED, üç ve fazlasında SELECT — kendiliğinden. İki seçenek
85
+ * yan yana sığar ve tek tıkla değişir; beş dil yan yana konursa üst şeridi
86
+ * doldurur ve altıncı dilde taşar.
87
+ */
88
+ export function LocaleSwitcher({ locales, current, onChange, label, className, }) {
89
+ if (locales.length <= 2) {
90
+ return (_jsx("span", { className: cn("tamga-segment", className), role: "group", "aria-label": label, children: locales.map((l) => (_jsx("button", { type: "button", "data-active": l.value === current, "aria-current": l.value === current ? "true" : undefined, onClick: () => onChange(l.value), children: l.label }, l.value))) }));
91
+ }
92
+ return (_jsx("select", { className: cn("tamga-input h-9 w-auto", className), "aria-label": label, value: current, onChange: (e) => onChange(e.target.value), children: locales.map((l) => (_jsx("option", { value: l.value, children: l.label }, l.value))) }));
93
+ }
94
+ /**
95
+ * Kare marka karosu.
96
+ *
97
+ * Bir logonun etrafındaki kutu. Görsel yoksa baş harf — `Avatar`'la aynı
98
+ * gerekçe: gri bir yer tutucu hiçbir şeyi temsil etmez, bir harf gerçekten o
99
+ * şeyi işaret eder.
100
+ *
101
+ * `alt` boş bırakılıyor ve bu bilinçli: karo neredeyse her zaman adı YANINDA
102
+ * yazan bir şeyin yanında durur. İkisini de okutmak ekran okuyucuda adı iki
103
+ * kez tekrarlar.
104
+ */
105
+ export function LogoTile({ name, src, size = "base", className, }) {
106
+ return (_jsx("span", { className: cn("tamga-logo-tile", size === "sm" && "tamga-logo-tile-sm", className), children: src ? (_jsx("img", { src: src, alt: "", className: "h-full w-full object-contain p-1.5" })) : (_jsx("span", { "aria-hidden": true, className: "font-mono text-subhead font-semibold text-ink-faint", children: name.trim().charAt(0).toLocaleUpperCase() })) }));
107
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Combobox — aranabilir seçim.
3
+ *
4
+ * Gerekçe: docs/gerekce/01-form-ve-girdi.md
5
+ */
6
+ export type ComboOption<T extends string> = {
7
+ value: T;
8
+ label: string;
9
+ /** Etiketin altındaki ikinci satır — SKU, e-posta, kategori. */
10
+ hint?: string;
11
+ };
12
+ export declare function Combobox<T extends string>({ options, value, onChange, onSearch, placeholder, labels, disabled, invalid, className, }: {
13
+ options: readonly ComboOption<T>[];
14
+ value?: T;
15
+ onChange?: (next: T | undefined) => void;
16
+ /**
17
+ * Given, filtering happens ON THE SERVER; the kit shows the list it receives as it is. TR:
18
+ * Verilirse süzme SUNUCUDA yapılır; kit gelen listeyi olduğu gibi gösterir.
19
+ */
20
+ onSearch?: (query: string) => void;
21
+ placeholder: string;
22
+ labels: {
23
+ empty: string;
24
+ clear: string;
25
+ open: string;
26
+ };
27
+ disabled?: boolean;
28
+ invalid?: boolean;
29
+ className?: string;
30
+ }): import("react").JSX.Element;
31
+ //# sourceMappingURL=combobox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"combobox.d.ts","sourceRoot":"","sources":["../../src/components/combobox.tsx"],"names":[],"mappings":"AAOA;;;;GAIG;AAEH,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,MAAM,IAAI;IAC1C,KAAK,EAAE,CAAC,CAAC;IACT,KAAK,EAAE,MAAM,CAAC;IACd,gEAAgE;IAChE,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,wBAAgB,QAAQ,CAAC,CAAC,SAAS,MAAM,EAAE,EACzC,OAAO,EACP,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,WAAW,EACX,MAAM,EACN,QAAgB,EAChB,OAAe,EACf,SAAS,GACV,EAAE;IACD,OAAO,EAAE,SAAS,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC;IACnC,KAAK,CAAC,EAAE,CAAC,CAAC;IACV,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,SAAS,KAAK,IAAI,CAAC;IACzC;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,+BAwIA"}