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.
- package/LICENSE +21 -0
- package/README.md +172 -0
- package/dist/blocks/count-row.d.ts +29 -0
- package/dist/blocks/count-row.d.ts.map +1 -0
- package/dist/blocks/count-row.js +19 -0
- package/dist/blocks/filter-bar.d.ts +123 -0
- package/dist/blocks/filter-bar.d.ts.map +1 -0
- package/dist/blocks/filter-bar.js +74 -0
- package/dist/blocks/index.d.ts +24 -0
- package/dist/blocks/index.d.ts.map +1 -0
- package/dist/blocks/index.js +23 -0
- package/dist/blocks/save-bar.d.ts +31 -0
- package/dist/blocks/save-bar.d.ts.map +1 -0
- package/dist/blocks/save-bar.js +21 -0
- package/dist/components/a11y.d.ts +21 -0
- package/dist/components/a11y.d.ts.map +1 -0
- package/dist/components/a11y.js +159 -0
- package/dist/components/advanced-input.d.ts +115 -0
- package/dist/components/advanced-input.d.ts.map +1 -0
- package/dist/components/advanced-input.js +189 -0
- package/dist/components/avatar.d.ts +63 -0
- package/dist/components/avatar.d.ts.map +1 -0
- package/dist/components/avatar.js +54 -0
- package/dist/components/badge.d.ts +37 -0
- package/dist/components/badge.d.ts.map +1 -0
- package/dist/components/badge.js +29 -0
- package/dist/components/bar.d.ts +32 -0
- package/dist/components/bar.d.ts.map +1 -0
- package/dist/components/bar.js +33 -0
- package/dist/components/button.d.ts +45 -0
- package/dist/components/button.d.ts.map +1 -0
- package/dist/components/button.js +56 -0
- package/dist/components/chart.d.ts +43 -0
- package/dist/components/chart.d.ts.map +1 -0
- package/dist/components/chart.js +41 -0
- package/dist/components/checkbox.d.ts +13 -0
- package/dist/components/checkbox.d.ts.map +1 -0
- package/dist/components/checkbox.js +16 -0
- package/dist/components/chrome.d.ts +87 -0
- package/dist/components/chrome.d.ts.map +1 -0
- package/dist/components/chrome.js +107 -0
- package/dist/components/combobox.d.ts +31 -0
- package/dist/components/combobox.d.ts.map +1 -0
- package/dist/components/combobox.js +62 -0
- package/dist/components/control-base.d.ts +7 -0
- package/dist/components/control-base.d.ts.map +1 -0
- package/dist/components/control-base.js +6 -0
- package/dist/components/data-table.d.ts +68 -0
- package/dist/components/data-table.d.ts.map +1 -0
- package/dist/components/data-table.js +50 -0
- package/dist/components/date-picker.d.ts +52 -0
- package/dist/components/date-picker.d.ts.map +1 -0
- package/dist/components/date-picker.js +73 -0
- package/dist/components/disclosure.d.ts +31 -0
- package/dist/components/disclosure.d.ts.map +1 -0
- package/dist/components/disclosure.js +32 -0
- package/dist/components/display.d.ts +188 -0
- package/dist/components/display.d.ts.map +1 -0
- package/dist/components/display.js +190 -0
- package/dist/components/empty-state.d.ts +150 -0
- package/dist/components/empty-state.d.ts.map +1 -0
- package/dist/components/empty-state.js +113 -0
- package/dist/components/error-state.d.ts +38 -0
- package/dist/components/error-state.d.ts.map +1 -0
- package/dist/components/error-state.js +16 -0
- package/dist/components/file-upload.d.ts +34 -0
- package/dist/components/file-upload.d.ts.map +1 -0
- package/dist/components/file-upload.js +34 -0
- package/dist/components/gauge.d.ts +47 -0
- package/dist/components/gauge.d.ts.map +1 -0
- package/dist/components/gauge.js +65 -0
- package/dist/components/icon.d.ts +32 -0
- package/dist/components/icon.d.ts.map +1 -0
- package/dist/components/icon.js +20 -0
- package/dist/components/icons.d.ts +19 -0
- package/dist/components/icons.d.ts.map +1 -0
- package/dist/components/icons.js +39 -0
- package/dist/components/input.d.ts +35 -0
- package/dist/components/input.d.ts.map +1 -0
- package/dist/components/input.js +41 -0
- package/dist/components/layout.d.ts +133 -0
- package/dist/components/layout.d.ts.map +1 -0
- package/dist/components/layout.js +132 -0
- package/dist/components/link.d.ts +22 -0
- package/dist/components/link.d.ts.map +1 -0
- package/dist/components/link.js +2 -0
- package/dist/components/live-scope.d.ts +15 -0
- package/dist/components/live-scope.d.ts.map +1 -0
- package/dist/components/live-scope.js +67 -0
- package/dist/components/log-view.d.ts +34 -0
- package/dist/components/log-view.d.ts.map +1 -0
- package/dist/components/log-view.js +30 -0
- package/dist/components/number-input.d.ts +26 -0
- package/dist/components/number-input.d.ts.map +1 -0
- package/dist/components/number-input.js +57 -0
- package/dist/components/overlay.d.ts +257 -0
- package/dist/components/overlay.d.ts.map +1 -0
- package/dist/components/overlay.js +276 -0
- package/dist/components/pagination.d.ts +38 -0
- package/dist/components/pagination.d.ts.map +1 -0
- package/dist/components/pagination.js +46 -0
- package/dist/components/pie.d.ts +40 -0
- package/dist/components/pie.d.ts.map +1 -0
- package/dist/components/pie.js +74 -0
- package/dist/components/primitives.d.ts +96 -0
- package/dist/components/primitives.d.ts.map +1 -0
- package/dist/components/primitives.js +81 -0
- package/dist/components/progress.d.ts +29 -0
- package/dist/components/progress.d.ts.map +1 -0
- package/dist/components/progress.js +16 -0
- package/dist/components/radio-group.d.ts +17 -0
- package/dist/components/radio-group.d.ts.map +1 -0
- package/dist/components/radio-group.js +23 -0
- package/dist/components/rail-link.d.ts +24 -0
- package/dist/components/rail-link.d.ts.map +1 -0
- package/dist/components/rail-link.js +24 -0
- package/dist/components/rich-text.d.ts +51 -0
- package/dist/components/rich-text.d.ts.map +1 -0
- package/dist/components/rich-text.js +147 -0
- package/dist/components/section.d.ts +15 -0
- package/dist/components/section.d.ts.map +1 -0
- package/dist/components/section.js +8 -0
- package/dist/components/segmented.d.ts +13 -0
- package/dist/components/segmented.d.ts.map +1 -0
- package/dist/components/segmented.js +12 -0
- package/dist/components/skeleton.d.ts +69 -0
- package/dist/components/skeleton.d.ts.map +1 -0
- package/dist/components/skeleton.js +67 -0
- package/dist/components/slider.d.ts +18 -0
- package/dist/components/slider.d.ts.map +1 -0
- package/dist/components/slider.js +15 -0
- package/dist/components/sparkline.d.ts +17 -0
- package/dist/components/sparkline.d.ts.map +1 -0
- package/dist/components/sparkline.js +19 -0
- package/dist/components/spinner.d.ts +15 -0
- package/dist/components/spinner.d.ts.map +1 -0
- package/dist/components/spinner.js +22 -0
- package/dist/components/stacked-bar.d.ts +21 -0
- package/dist/components/stacked-bar.d.ts.map +1 -0
- package/dist/components/stacked-bar.js +41 -0
- package/dist/components/surface.d.ts +76 -0
- package/dist/components/surface.d.ts.map +1 -0
- package/dist/components/surface.js +49 -0
- package/dist/components/switch.d.ts +12 -0
- package/dist/components/switch.d.ts.map +1 -0
- package/dist/components/switch.js +13 -0
- package/dist/components/tabs.d.ts +47 -0
- package/dist/components/tabs.d.ts.map +1 -0
- package/dist/components/tabs.js +12 -0
- package/dist/components/timeline-strip.d.ts +19 -0
- package/dist/components/timeline-strip.d.ts.map +1 -0
- package/dist/components/timeline-strip.js +14 -0
- package/dist/components/tone.d.ts +58 -0
- package/dist/components/tone.d.ts.map +1 -0
- package/dist/components/tone.js +70 -0
- package/dist/components/tree-select.d.ts +26 -0
- package/dist/components/tree-select.d.ts.map +1 -0
- package/dist/components/tree-select.js +59 -0
- package/dist/index.d.ts +54 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +70 -0
- package/dist/kit.css +2248 -0
- package/dist/lib/cn.d.ts +10 -0
- package/dist/lib/cn.d.ts.map +1 -0
- package/dist/lib/cn.js +12 -0
- package/dist/lib/color.d.ts +68 -0
- package/dist/lib/color.d.ts.map +1 -0
- package/dist/lib/color.js +134 -0
- package/dist/lib/palette.d.ts +84 -0
- package/dist/lib/palette.d.ts.map +1 -0
- package/dist/lib/palette.js +193 -0
- package/dist/lib/scroll-lock.d.ts +19 -0
- package/dist/lib/scroll-lock.d.ts.map +1 -0
- package/dist/lib/scroll-lock.js +33 -0
- package/dist/patterns/app-shell.d.ts +36 -0
- package/dist/patterns/app-shell.d.ts.map +1 -0
- package/dist/patterns/app-shell.js +14 -0
- package/dist/patterns/auth-template.d.ts +36 -0
- package/dist/patterns/auth-template.d.ts.map +1 -0
- package/dist/patterns/auth-template.js +40 -0
- package/dist/patterns/detail-template.d.ts +52 -0
- package/dist/patterns/detail-template.d.ts.map +1 -0
- package/dist/patterns/detail-template.js +11 -0
- package/dist/patterns/index.d.ts +18 -0
- package/dist/patterns/index.d.ts.map +1 -0
- package/dist/patterns/index.js +17 -0
- package/dist/patterns/list-template.d.ts +32 -0
- package/dist/patterns/list-template.d.ts.map +1 -0
- package/dist/patterns/list-template.js +8 -0
- package/dist/patterns/overview-template.d.ts +26 -0
- package/dist/patterns/overview-template.d.ts.map +1 -0
- package/dist/patterns/overview-template.js +8 -0
- package/dist/patterns/public-template.d.ts +28 -0
- package/dist/patterns/public-template.d.ts.map +1 -0
- package/dist/patterns/public-template.js +7 -0
- package/dist/patterns/settings-template.d.ts +50 -0
- package/dist/patterns/settings-template.d.ts.map +1 -0
- package/dist/patterns/settings-template.js +33 -0
- package/dist/patterns/shared.d.ts +40 -0
- package/dist/patterns/shared.d.ts.map +1 -0
- package/dist/patterns/shared.js +29 -0
- package/dist/patterns/wizard-template.d.ts +28 -0
- package/dist/patterns/wizard-template.d.ts.map +1 -0
- package/dist/patterns/wizard-template.js +15 -0
- package/dist/styles.css +5 -0
- package/dist/theme.css +812 -0
- 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"}
|