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,62 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useId, useMemo, useRef, useState } from "react";
|
|
4
|
+
import { cn } from "../lib/cn.js";
|
|
5
|
+
import { Icon } from "./icon.js";
|
|
6
|
+
import { CaretDown, Close, Search } from "./icons.js";
|
|
7
|
+
export function Combobox({ options, value, onChange, onSearch, placeholder, labels, disabled = false, invalid = false, className, }) {
|
|
8
|
+
const id = useId();
|
|
9
|
+
const [open, setOpen] = useState(false);
|
|
10
|
+
const [query, setQuery] = useState("");
|
|
11
|
+
const [active, setActive] = useState(0);
|
|
12
|
+
const box = useRef(null);
|
|
13
|
+
const selected = options.find((o) => o.value === value);
|
|
14
|
+
const shown = useMemo(() => {
|
|
15
|
+
if (onSearch || query.trim() === "")
|
|
16
|
+
return options;
|
|
17
|
+
const q = query.trim().toLocaleLowerCase();
|
|
18
|
+
return options.filter((o) => o.label.toLocaleLowerCase().includes(q) || o.hint?.toLocaleLowerCase().includes(q));
|
|
19
|
+
}, [options, query, onSearch]);
|
|
20
|
+
/* Dışarı tıklamak kapatır — bir combobox karar istemez, bilgi verir. */
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
if (!open)
|
|
23
|
+
return;
|
|
24
|
+
const onDown = (e) => {
|
|
25
|
+
if (!box.current?.contains(e.target))
|
|
26
|
+
setOpen(false);
|
|
27
|
+
};
|
|
28
|
+
document.addEventListener("mousedown", onDown);
|
|
29
|
+
return () => document.removeEventListener("mousedown", onDown);
|
|
30
|
+
}, [open]);
|
|
31
|
+
useEffect(() => setActive(0), [query, open]);
|
|
32
|
+
function commit(o) {
|
|
33
|
+
onChange?.(o.value);
|
|
34
|
+
setQuery("");
|
|
35
|
+
setOpen(false);
|
|
36
|
+
}
|
|
37
|
+
return (_jsxs("div", { ref: box, className: cn("relative", className), children: [_jsxs("span", { className: "relative flex items-center", children: [_jsx(Icon, { icon: Search, size: "xs", className: "pointer-events-none absolute left-3 text-ink-faint" }), _jsx("input", { type: "text", role: "combobox", "aria-expanded": open, "aria-controls": `${id}-list`, "aria-autocomplete": "list", "aria-activedescendant": open && shown[active] ? `${id}-opt-${active}` : undefined, "aria-invalid": invalid || undefined, disabled: disabled, placeholder: selected ? selected.label : placeholder, value: query, onFocus: () => setOpen(true), onChange: (e) => {
|
|
38
|
+
setQuery(e.target.value);
|
|
39
|
+
setOpen(true);
|
|
40
|
+
onSearch?.(e.target.value);
|
|
41
|
+
}, onKeyDown: (e) => {
|
|
42
|
+
if (e.key === "ArrowDown") {
|
|
43
|
+
e.preventDefault();
|
|
44
|
+
setOpen(true);
|
|
45
|
+
setActive((i) => Math.min(i + 1, shown.length - 1));
|
|
46
|
+
}
|
|
47
|
+
else if (e.key === "ArrowUp") {
|
|
48
|
+
e.preventDefault();
|
|
49
|
+
setActive((i) => Math.max(i - 1, 0));
|
|
50
|
+
}
|
|
51
|
+
else if (e.key === "Enter" && open && shown[active]) {
|
|
52
|
+
e.preventDefault();
|
|
53
|
+
commit(shown[active]);
|
|
54
|
+
}
|
|
55
|
+
else if (e.key === "Escape") {
|
|
56
|
+
setOpen(false);
|
|
57
|
+
}
|
|
58
|
+
}, className: cn("tamga-input w-full pl-9", invalid && "tamga-input-invalid", selected && !query && "text-ink") }), _jsxs("span", { className: "absolute right-1.5 flex items-center gap-0.5", children: [selected ? (_jsx("button", { type: "button", className: "tamga-mini-btn", "aria-label": labels.clear, onClick: () => {
|
|
59
|
+
onChange?.(undefined);
|
|
60
|
+
setQuery("");
|
|
61
|
+
}, children: _jsx(Icon, { icon: Close, size: "xs" }) })) : null, _jsx("button", { type: "button", className: "tamga-mini-btn", "aria-label": labels.open, "aria-expanded": open, onClick: () => setOpen((v) => !v), children: _jsx(Icon, { icon: CaretDown, size: "xs" }) })] })] }), open ? (_jsx("div", { id: `${id}-list`, role: "listbox", className: "tamga-overlay absolute z-30 mt-2 max-h-72 w-full overflow-y-auto py-1", children: shown.length === 0 ? (_jsx("p", { className: "px-3 py-2.5 text-body text-ink-faint", children: labels.empty })) : (shown.map((o, i) => (_jsxs("button", { id: `${id}-opt-${i}`, type: "button", role: "option", "aria-selected": o.value === value, "data-selected": o.value === value, "data-active": i === active, className: "tamga-option w-full text-left", onMouseEnter: () => setActive(i), onClick: () => commit(o), children: [_jsx("span", { className: "block truncate", children: o.label }), o.hint ? (_jsx("span", { className: "block truncate font-mono text-caption text-ink-faint", children: o.hint })) : null] }, o.value)))) })) : null] }));
|
|
62
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"control-base.d.ts","sourceRoot":"","sources":["../../src/components/control-base.ts"],"names":[],"mappings":"AAGA,uDAAuD;AACvD,QAAA,MAAM,GAAG;aAAK,OAAO,EAAE,IAAI;aAAE,MAAM,EAAE,aAAa;CAAW,CAAC;AAE9D,OAAO,EAAE,GAAG,EAAE,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/* Seçim kontrollerinin paylaştığı tek değer. Beşi ayrı dosyada yaşıyor —
|
|
2
|
+
guard'ın modeli "bir dosya = bir primitive" ve o model doğru: bir primitive
|
|
3
|
+
kendi dosyasında olmazsa, durum story'sinin neyi kanıtladığı belirsizleşir. */
|
|
4
|
+
/** Etiketli kontrollerin ortak devre-dışı görünümü. */
|
|
5
|
+
const OFF = { opacity: 0.45, cursor: "not-allowed" };
|
|
6
|
+
export { OFF };
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* DATA TABLE — ve neden tek bir `<DataTable data={…} />` DEĞİL.
|
|
4
|
+
*
|
|
5
|
+
* Gerekçe: docs/gerekce/02-veri-ve-liste.md
|
|
6
|
+
*/
|
|
7
|
+
export type SortDirection = "asc" | "desc";
|
|
8
|
+
/**
|
|
9
|
+
* Sıralanabilir sütun başlığı.
|
|
10
|
+
*
|
|
11
|
+
* `<th>` içinde bir `<button>`: başlığın kendisini tıklanabilir yapmak,
|
|
12
|
+
* ekran okuyucuya sütunun aynı zamanda bir kontrol olduğunu söylemez.
|
|
13
|
+
* `aria-sort` da `<th>`de olmak zorunda — okuyucu sıralama durumunu oradan alır.
|
|
14
|
+
*/
|
|
15
|
+
export declare function SortHeader({ children, direction, onSort, align, className, ...rest }: {
|
|
16
|
+
children: ReactNode;
|
|
17
|
+
/** `undefined` when this column is not sorted. TR: Bu sütun sıralı değilse `undefined`. */
|
|
18
|
+
direction?: SortDirection;
|
|
19
|
+
onSort?: (next: SortDirection) => void;
|
|
20
|
+
align?: "left" | "right";
|
|
21
|
+
className?: string;
|
|
22
|
+
} & Omit<React.ComponentProps<"th">, "children" | "onClick">): import("react").JSX.Element;
|
|
23
|
+
/**
|
|
24
|
+
* Baş onay kutusu — ve `indeterminate` neden önemli.
|
|
25
|
+
*
|
|
26
|
+
* Beş satırın ikisi seçiliyse baş kutu ne işaretli ne boştur; üçüncü bir
|
|
27
|
+
* durumdadır. Boş göstermek "hiçbiri seçili değil" der ve yalandır; işaretli
|
|
28
|
+
* göstermek "hepsi seçili" der ve daha kötüdür — kullanıcı silmeye basar.
|
|
29
|
+
*/
|
|
30
|
+
export declare function SelectAll({ checked, indeterminate, onChange, label, }: {
|
|
31
|
+
checked: boolean;
|
|
32
|
+
indeterminate: boolean;
|
|
33
|
+
onChange?: (next: boolean) => void;
|
|
34
|
+
label: string;
|
|
35
|
+
}): import("react").JSX.Element;
|
|
36
|
+
/** Satır seçim kutusu — baş kutunun küçük kardeşi. */
|
|
37
|
+
export declare function SelectRow({ checked, onChange, label, }: {
|
|
38
|
+
checked: boolean;
|
|
39
|
+
onChange?: (next: boolean) => void;
|
|
40
|
+
label: string;
|
|
41
|
+
}): import("react").JSX.Element;
|
|
42
|
+
/**
|
|
43
|
+
* Seçim çubuğu — "3 kayıt seçildi" ve yanındaki toplu eylemler.
|
|
44
|
+
*
|
|
45
|
+
* Tablonun ÜSTÜNDE durur, altında değil: seçim yukarıdan yapılır ve eylem
|
|
46
|
+
* gözün gittiği yerde olmalı. Ve seçim boşken hiç render edilmez — boş bir
|
|
47
|
+
* çubuk yer kaplar, bilgi vermez.
|
|
48
|
+
*/
|
|
49
|
+
export declare function SelectionBar({ count, onClear, children, labels, className, }: {
|
|
50
|
+
count: number;
|
|
51
|
+
onClear?: () => void;
|
|
52
|
+
/**
|
|
53
|
+
* The bulk actions, usually a few `<Button size="sm">`. TR: Toplu eylemler, genelde birkaç
|
|
54
|
+
* `<Button size="sm">`.
|
|
55
|
+
*/
|
|
56
|
+
children?: ReactNode;
|
|
57
|
+
/**
|
|
58
|
+
* `selected` may return a ReactNode: in "3 records selected" the bold number is the only
|
|
59
|
+
* thing that makes the sentence scannable. TR: `selected` ReactNode döndürebiliyor: "3 kayıt
|
|
60
|
+
* seçili" cümlesinde sayının kalın olması, cümleyi taranabilir kılan tek şey.
|
|
61
|
+
*/
|
|
62
|
+
labels: {
|
|
63
|
+
selected: (n: number) => ReactNode;
|
|
64
|
+
clear: string;
|
|
65
|
+
};
|
|
66
|
+
className?: string;
|
|
67
|
+
}): import("react").JSX.Element | null;
|
|
68
|
+
//# sourceMappingURL=data-table.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-table.d.ts","sourceRoot":"","sources":["../../src/components/data-table.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAMvC;;;;GAIG;AAEH,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,MAAM,CAAC;AAE3C;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,EACzB,QAAQ,EACR,SAAS,EACT,MAAM,EACN,KAAc,EACd,SAAS,EACT,GAAG,IAAI,EACR,EAAE;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,2FAA2F;IAC3F,SAAS,CAAC,EAAE,aAAa,CAAC;IAC1B,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,IAAI,CAAC;IACvC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC,+BA+B3D;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,EACxB,OAAO,EACP,aAAa,EACb,QAAQ,EACR,KAAK,GACN,EAAE;IACD,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,KAAK,EAAE,MAAM,CAAC;CACf,+BA2BA;AAED,sDAAsD;AACtD,wBAAgB,SAAS,CAAC,EACxB,OAAO,EACP,QAAQ,EACR,KAAK,GACN,EAAE;IACD,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,KAAK,EAAE,MAAM,CAAC;CACf,+BAEA;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,EAC3B,KAAK,EACL,OAAO,EACP,QAAQ,EACR,MAAM,EACN,SAAS,GACV,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB;;;OAGG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB;;;;OAIG;IACH,MAAM,EAAE;QAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,SAAS,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,sCAuBA"}
|
|
@@ -0,0 +1,50 @@
|
|
|
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 { CaretDown, Close } from "./icons.js";
|
|
6
|
+
import { Checkbox } from "./checkbox.js";
|
|
7
|
+
/**
|
|
8
|
+
* Sıralanabilir sütun başlığı.
|
|
9
|
+
*
|
|
10
|
+
* `<th>` içinde bir `<button>`: başlığın kendisini tıklanabilir yapmak,
|
|
11
|
+
* ekran okuyucuya sütunun aynı zamanda bir kontrol olduğunu söylemez.
|
|
12
|
+
* `aria-sort` da `<th>`de olmak zorunda — okuyucu sıralama durumunu oradan alır.
|
|
13
|
+
*/
|
|
14
|
+
export function SortHeader({ children, direction, onSort, align = "left", className, ...rest }) {
|
|
15
|
+
const next = direction === "asc" ? "desc" : "asc";
|
|
16
|
+
return (_jsx("th", { scope: "col", "aria-sort": direction ? (direction === "asc" ? "ascending" : "descending") : "none", className: cn(align === "right" && "text-right", className), ...rest, children: _jsxs("button", { type: "button", onClick: () => onSort?.(next), className: cn("inline-flex items-center gap-1.5", align === "right" && "flex-row-reverse", direction ? "text-ink" : undefined), children: [children, direction ? (_jsx(Icon, { icon: CaretDown, size: "xs", className: direction === "asc" ? "rotate-180" : undefined })) : null] }) }));
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Baş onay kutusu — ve `indeterminate` neden önemli.
|
|
20
|
+
*
|
|
21
|
+
* Beş satırın ikisi seçiliyse baş kutu ne işaretli ne boştur; üçüncü bir
|
|
22
|
+
* durumdadır. Boş göstermek "hiçbiri seçili değil" der ve yalandır; işaretli
|
|
23
|
+
* göstermek "hepsi seçili" der ve daha kötüdür — kullanıcı silmeye basar.
|
|
24
|
+
*/
|
|
25
|
+
export function SelectAll({ checked, indeterminate, onChange, label, }) {
|
|
26
|
+
return (_jsx("span", {
|
|
27
|
+
/* `aria-checked="mixed"` üçüncü durumun standart karşılığı. */
|
|
28
|
+
role: "checkbox", "aria-checked": indeterminate ? "mixed" : checked, "aria-label": label, tabIndex: 0, onClick: () => onChange?.(!checked), onKeyDown: (e) => {
|
|
29
|
+
if (e.key === " " || e.key === "Enter") {
|
|
30
|
+
e.preventDefault();
|
|
31
|
+
onChange?.(!checked);
|
|
32
|
+
}
|
|
33
|
+
}, className: "inline-flex cursor-pointer", children: _jsxs("span", { className: "tamga-check", "data-checked": checked || indeterminate, children: [indeterminate ? (_jsx("span", { className: "block h-0.5 w-2 bg-current", "aria-hidden": true })) : checked ? (_jsx(Icon, { icon: CaretDown, size: "xs", className: "hidden" })) : null, checked && !indeterminate ? _jsx("span", { className: "block h-2 w-2 bg-current", "aria-hidden": true }) : null] }) }));
|
|
34
|
+
}
|
|
35
|
+
/** Satır seçim kutusu — baş kutunun küçük kardeşi. */
|
|
36
|
+
export function SelectRow({ checked, onChange, label, }) {
|
|
37
|
+
return _jsx(Checkbox, { label: _jsx("span", { className: "sr-only", children: label }), checked: checked, onChange: onChange });
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Seçim çubuğu — "3 kayıt seçildi" ve yanındaki toplu eylemler.
|
|
41
|
+
*
|
|
42
|
+
* Tablonun ÜSTÜNDE durur, altında değil: seçim yukarıdan yapılır ve eylem
|
|
43
|
+
* gözün gittiği yerde olmalı. Ve seçim boşken hiç render edilmez — boş bir
|
|
44
|
+
* çubuk yer kaplar, bilgi vermez.
|
|
45
|
+
*/
|
|
46
|
+
export function SelectionBar({ count, onClear, children, labels, className, }) {
|
|
47
|
+
if (count === 0)
|
|
48
|
+
return null;
|
|
49
|
+
return (_jsxs("div", { role: "status", className: cn("tamga-gutter flex flex-wrap items-center gap-3 border-b border-[var(--color-line)] py-3", className), style: { background: "var(--color-accent-bg)" }, children: [_jsx("span", { className: "text-body font-medium text-ink tabular-nums", children: labels.selected(count) }), children ? _jsx("span", { className: "flex flex-wrap items-center gap-2", children: children }) : null, _jsx("button", { type: "button", className: "tamga-icon-btn ml-auto", "aria-label": labels.clear, onClick: onClear, children: _jsx(Icon, { icon: Close, size: "xs" }) })] }));
|
|
50
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DatePicker — tek gün ve aralık.
|
|
3
|
+
*
|
|
4
|
+
* Gerekçe: docs/gerekce/01-form-ve-girdi.md
|
|
5
|
+
*/
|
|
6
|
+
/** `2026-04-15` — saat yok, dilim yok. */
|
|
7
|
+
export type DateISO = string;
|
|
8
|
+
export type DateRange = {
|
|
9
|
+
from?: DateISO;
|
|
10
|
+
to?: DateISO;
|
|
11
|
+
};
|
|
12
|
+
export declare function Calendar({ locale, value, range, onSelect, labels, className, }: {
|
|
13
|
+
/**
|
|
14
|
+
* `"tr-TR"`, `"en-US"`; month names and the first day of the week come from it. TR:
|
|
15
|
+
* `"tr-TR"`, `"en-US"`; ay adları ve hafta başlangıcı buradan gelir.
|
|
16
|
+
*/
|
|
17
|
+
locale: string;
|
|
18
|
+
value?: DateISO;
|
|
19
|
+
/**
|
|
20
|
+
* Given, range mode: the first click is the start, the second the end. TR: Verilirse aralık
|
|
21
|
+
* modu: ilk tıklama başlangıç, ikincisi bitiş.
|
|
22
|
+
*/
|
|
23
|
+
range?: DateRange;
|
|
24
|
+
onSelect?: (date: DateISO) => void;
|
|
25
|
+
labels: {
|
|
26
|
+
previousMonth: string;
|
|
27
|
+
nextMonth: string;
|
|
28
|
+
};
|
|
29
|
+
className?: string;
|
|
30
|
+
}): import("react").JSX.Element;
|
|
31
|
+
/**
|
|
32
|
+
* Alan + açılan takvim.
|
|
33
|
+
*
|
|
34
|
+
* Girdi salt-okunur: elle tarih yazmak, her yerelde farklı bir ayraç ve sıra
|
|
35
|
+
* demektir (`15/04/2026` · `04/15/2026` · `2026-04-15`) ve yanlış okunan bir
|
|
36
|
+
* tarih sessizce yanlış veri üretir. Takvim tek doğru giriş yolu.
|
|
37
|
+
*/
|
|
38
|
+
export declare function DatePicker({ locale, value, onChange, placeholder, labels, disabled, className, }: {
|
|
39
|
+
locale: string;
|
|
40
|
+
value?: DateISO;
|
|
41
|
+
onChange?: (next: DateISO | undefined) => void;
|
|
42
|
+
placeholder: string;
|
|
43
|
+
labels: {
|
|
44
|
+
previousMonth: string;
|
|
45
|
+
nextMonth: string;
|
|
46
|
+
open: string;
|
|
47
|
+
clear: string;
|
|
48
|
+
};
|
|
49
|
+
disabled?: boolean;
|
|
50
|
+
className?: string;
|
|
51
|
+
}): import("react").JSX.Element;
|
|
52
|
+
//# sourceMappingURL=date-picker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"date-picker.d.ts","sourceRoot":"","sources":["../../src/components/date-picker.tsx"],"names":[],"mappings":"AAOA;;;;GAIG;AAEH,0CAA0C;AAC1C,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC;AAE7B,MAAM,MAAM,SAAS,GAAG;IAAE,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,EAAE,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAgCzD,wBAAgB,QAAQ,CAAC,EACvB,MAAM,EACN,KAAK,EACL,KAAK,EACL,QAAQ,EACR,MAAM,EACN,SAAS,GACV,EAAE;IACD;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;OAGG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,MAAM,EAAE;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IACrD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,+BA0EA;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,EACzB,MAAM,EACN,KAAK,EACL,QAAQ,EACR,WAAW,EACX,MAAM,EACN,QAAgB,EAChB,SAAS,GACV,EAAE;IACD,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,GAAG,SAAS,KAAK,IAAI,CAAC;IAC/C,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAClF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,+BA0DA"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useMemo, useState } from "react";
|
|
4
|
+
import { cn } from "../lib/cn.js";
|
|
5
|
+
import { Icon } from "./icon.js";
|
|
6
|
+
import { CaretLeft, CaretRight, CalendarPlus, Close } from "./icons.js";
|
|
7
|
+
const iso = (y, m, d) => `${y}-${String(m + 1).padStart(2, "0")}-${String(d).padStart(2, "0")}`;
|
|
8
|
+
function monthMatrix(year, month, firstDay) {
|
|
9
|
+
const first = new Date(Date.UTC(year, month, 1));
|
|
10
|
+
const days = new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
|
|
11
|
+
/* Hafta başına göre kaydırma: Pazartesi başlayan bir takvimde Pazar 6'dır. */
|
|
12
|
+
const lead = (first.getUTCDay() - firstDay + 7) % 7;
|
|
13
|
+
const cells = Array.from({ length: lead }, () => null);
|
|
14
|
+
for (let d = 1; d <= days; d++)
|
|
15
|
+
cells.push(d);
|
|
16
|
+
while (cells.length % 7 !== 0)
|
|
17
|
+
cells.push(null);
|
|
18
|
+
return cells;
|
|
19
|
+
}
|
|
20
|
+
/** Yerelin hafta başlangıcı. Tarayıcı biliyorsa ondan, bilmiyorsa Pazartesi. */
|
|
21
|
+
function weekStart(locale) {
|
|
22
|
+
try {
|
|
23
|
+
const info = new Intl.Locale(locale);
|
|
24
|
+
const first = info.getWeekInfo?.().firstDay ?? info.weekInfo?.firstDay;
|
|
25
|
+
/* Intl 1=Pazartesi … 7=Pazar; Date 0=Pazar. */
|
|
26
|
+
if (first)
|
|
27
|
+
return first % 7;
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
/* eski tarayıcı: varsayılana düş */
|
|
31
|
+
}
|
|
32
|
+
return 1;
|
|
33
|
+
}
|
|
34
|
+
export function Calendar({ locale, value, range, onSelect, labels, className, }) {
|
|
35
|
+
const today = new Date();
|
|
36
|
+
const [view, setView] = useState({ y: today.getFullYear(), m: today.getMonth() });
|
|
37
|
+
const first = weekStart(locale);
|
|
38
|
+
const cells = useMemo(() => monthMatrix(view.y, view.m, first), [view, first]);
|
|
39
|
+
const monthName = new Intl.DateTimeFormat(locale, { month: "long", year: "numeric" }).format(new Date(Date.UTC(view.y, view.m, 1)));
|
|
40
|
+
const dayNames = useMemo(() => {
|
|
41
|
+
const fmt = new Intl.DateTimeFormat(locale, { weekday: "short" });
|
|
42
|
+
/* 2024-01-07 bir Pazar; oradan hafta başına kaydırıyoruz. */
|
|
43
|
+
return Array.from({ length: 7 }, (_, i) => fmt.format(new Date(Date.UTC(2024, 0, 7 + ((first + i) % 7)))));
|
|
44
|
+
}, [locale, first]);
|
|
45
|
+
const inRange = (d) => range?.from && range?.to ? d >= range.from && d <= range.to : false;
|
|
46
|
+
const isEdge = (d) => d === range?.from || d === range?.to || d === value;
|
|
47
|
+
return (_jsxs("div", { className: cn("w-70", className), children: [_jsxs("div", { className: "mb-3 flex items-center gap-2", children: [_jsx("button", { type: "button", className: "tamga-icon-btn", "aria-label": labels.previousMonth, onClick: () => setView((v) => (v.m === 0 ? { y: v.y - 1, m: 11 } : { ...v, m: v.m - 1 })), children: _jsx(Icon, { icon: CaretLeft, size: "xs" }) }), _jsx("span", { className: "flex-1 text-center text-body font-medium text-ink", children: monthName }), _jsx("button", { type: "button", className: "tamga-icon-btn", "aria-label": labels.nextMonth, onClick: () => setView((v) => (v.m === 11 ? { y: v.y + 1, m: 0 } : { ...v, m: v.m + 1 })), children: _jsx(Icon, { icon: CaretRight, size: "xs" }) })] }), _jsxs("div", { className: "grid grid-cols-7 gap-px", children: [dayNames.map((d) => (_jsx("span", { className: "pb-1 text-center text-caption text-ink-faint", children: d }, d))), cells.map((d, i) => {
|
|
48
|
+
if (d === null)
|
|
49
|
+
return _jsx("span", {}, `x${i}`);
|
|
50
|
+
const date = iso(view.y, view.m, d);
|
|
51
|
+
return (_jsx("button", { type: "button",
|
|
52
|
+
/* Seçili gün DOLGU alır — bir tarih bir değerdir, bir hedef değil;
|
|
53
|
+
checkbox ile aynı gerekçe (Yasa 2). */
|
|
54
|
+
className: "tamga-option justify-center tabular-nums", "data-selected": isEdge(date), "data-active": inRange(date) && !isEdge(date), "aria-pressed": isEdge(date), onClick: () => onSelect?.(date), children: d }, date));
|
|
55
|
+
})] })] }));
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Alan + açılan takvim.
|
|
59
|
+
*
|
|
60
|
+
* Girdi salt-okunur: elle tarih yazmak, her yerelde farklı bir ayraç ve sıra
|
|
61
|
+
* demektir (`15/04/2026` · `04/15/2026` · `2026-04-15`) ve yanlış okunan bir
|
|
62
|
+
* tarih sessizce yanlış veri üretir. Takvim tek doğru giriş yolu.
|
|
63
|
+
*/
|
|
64
|
+
export function DatePicker({ locale, value, onChange, placeholder, labels, disabled = false, className, }) {
|
|
65
|
+
const [open, setOpen] = useState(false);
|
|
66
|
+
const shown = value
|
|
67
|
+
? new Intl.DateTimeFormat(locale, { dateStyle: "medium" }).format(new Date(`${value}T00:00:00Z`))
|
|
68
|
+
: "";
|
|
69
|
+
return (_jsxs("div", { className: cn("relative", className), children: [_jsxs("span", { className: "relative flex items-center", children: [_jsx(Icon, { icon: CalendarPlus, size: "xs", className: "pointer-events-none absolute left-3 text-ink-faint" }), _jsx("input", { type: "text", readOnly: true, disabled: disabled, value: shown, placeholder: placeholder, onClick: () => !disabled && setOpen((v) => !v), className: "tamga-input w-full cursor-pointer pr-16 pl-9", "aria-haspopup": "dialog", "aria-expanded": open }), _jsxs("span", { className: "absolute right-1.5 flex gap-0.5", children: [value ? (_jsx("button", { type: "button", className: "tamga-mini-btn", "aria-label": labels.clear, onClick: () => onChange?.(undefined), children: _jsx(Icon, { icon: Close, size: "xs" }) })) : null, _jsx("button", { type: "button", className: "tamga-mini-btn", "aria-label": labels.open, onClick: () => setOpen((v) => !v), children: _jsx(Icon, { icon: CalendarPlus, size: "xs" }) })] })] }), open ? (_jsx("div", { className: "tamga-overlay absolute z-30 mt-2 p-3", children: _jsx(Calendar, { locale: locale, value: value, labels: labels, onSelect: (d) => {
|
|
70
|
+
onChange?.(d);
|
|
71
|
+
setOpen(false);
|
|
72
|
+
} }) })) : null] }));
|
|
73
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Açılıp kapanan bölümler.
|
|
4
|
+
*
|
|
5
|
+
* Gerekçe: docs/gerekce/01-form-ve-girdi.md
|
|
6
|
+
*/
|
|
7
|
+
/** Tek bir açılır bölüm. */
|
|
8
|
+
export declare function Collapsible({ title, defaultOpen, meta, className, children, }: {
|
|
9
|
+
title: string;
|
|
10
|
+
defaultOpen?: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* The secondary text to the right of the title: a count, a state. TR: Başlığın sağındaki
|
|
13
|
+
* ikincil metin: sayı, durum.
|
|
14
|
+
*/
|
|
15
|
+
meta?: ReactNode;
|
|
16
|
+
className?: string;
|
|
17
|
+
children: ReactNode;
|
|
18
|
+
}): import("react").JSX.Element;
|
|
19
|
+
/**
|
|
20
|
+
* Açılır bölümler grubu.
|
|
21
|
+
*
|
|
22
|
+
* Yalnız bir kap: her bölüm kendi durumunu tutuyor. "Aynı anda tek bölüm
|
|
23
|
+
* açık" davranışı BİLEREK yok — bir ayarlar sayfasında iki bölümü yan yana
|
|
24
|
+
* karşılaştırmak yaygın bir iş, ve otomatik kapanma onu imkânsız kılar.
|
|
25
|
+
* Gerekiyorsa çağıran kendi durumunu tutar.
|
|
26
|
+
*/
|
|
27
|
+
export declare function Accordion({ className, children }: {
|
|
28
|
+
className?: string;
|
|
29
|
+
children: ReactNode;
|
|
30
|
+
}): import("react").JSX.Element;
|
|
31
|
+
//# sourceMappingURL=disclosure.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"disclosure.d.ts","sourceRoot":"","sources":["../../src/components/disclosure.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAKxD;;;;GAIG;AAEH,4BAA4B;AAC5B,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,WAAmB,EACnB,IAAI,EACJ,SAAS,EACT,QAAQ,GACT,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;OAGG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,SAAS,CAAC;CACrB,+BAkCA;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,SAAS,CAAA;CAAE,+BAE7F"}
|
|
@@ -0,0 +1,32 @@
|
|
|
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 { Icon } from "./icon.js";
|
|
6
|
+
import { CaretRight } from "./icons.js";
|
|
7
|
+
/**
|
|
8
|
+
* Açılıp kapanan bölümler.
|
|
9
|
+
*
|
|
10
|
+
* Gerekçe: docs/gerekce/01-form-ve-girdi.md
|
|
11
|
+
*/
|
|
12
|
+
/** Tek bir açılır bölüm. */
|
|
13
|
+
export function Collapsible({ title, defaultOpen = false, meta, className, children, }) {
|
|
14
|
+
const id = useId();
|
|
15
|
+
const [open, setOpen] = useState(defaultOpen);
|
|
16
|
+
return (_jsxs("div", { className: cn("border-b border-[var(--color-line)] last:border-b-0", className), children: [_jsxs("button", { type: "button",
|
|
17
|
+
/* `tamga-gutter` şart: `.tamga-head` yalnız DİKEY boşluk taşıyor.
|
|
18
|
+
Onsuz başlık kabın kenarına yapışıyordu — ve altındaki gövde
|
|
19
|
+
gutter'lı olduğu için ikisi hizasız duruyordu. */
|
|
20
|
+
className: "tamga-head tamga-gutter w-full text-left", "aria-expanded": open, "aria-controls": id, onClick: () => setOpen((v) => !v), children: [_jsx(Icon, { icon: CaretRight, size: "xs", className: "shrink-0 transition-transform", style: { transform: open ? "rotate(90deg)" : undefined } }), _jsx("span", { className: "min-w-0 flex-1 text-body font-medium text-ink", children: title }), meta ? _jsx("span", { className: "text-small text-ink-faint", children: meta }) : null] }), _jsx("div", { id: id, hidden: !open, className: "tamga-gutter pb-4", children: children })] }));
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Açılır bölümler grubu.
|
|
24
|
+
*
|
|
25
|
+
* Yalnız bir kap: her bölüm kendi durumunu tutuyor. "Aynı anda tek bölüm
|
|
26
|
+
* açık" davranışı BİLEREK yok — bir ayarlar sayfasında iki bölümü yan yana
|
|
27
|
+
* karşılaştırmak yaygın bir iş, ve otomatik kapanma onu imkânsız kılar.
|
|
28
|
+
* Gerekiyorsa çağıran kendi durumunu tutar.
|
|
29
|
+
*/
|
|
30
|
+
export function Accordion({ className, children }) {
|
|
31
|
+
return _jsx("div", { className: cn("tamga-surface overflow-hidden", className), children: children });
|
|
32
|
+
}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import type { Icon as PhosphorIcon } from "@phosphor-icons/react";
|
|
3
|
+
import { type LinkComponent } from "./link.js";
|
|
4
|
+
import { type Tone } from "./tone.js";
|
|
5
|
+
/**
|
|
6
|
+
* Anahtar/değer listesi — detay sayfalarının omurgası.
|
|
7
|
+
*
|
|
8
|
+
* Gerekçe: docs/gerekce/05-yuzey-ve-kabuk.md
|
|
9
|
+
*/
|
|
10
|
+
export declare function Descriptions({ items, layout, className, }: {
|
|
11
|
+
items: readonly {
|
|
12
|
+
term: string;
|
|
13
|
+
value: ReactNode;
|
|
14
|
+
mono?: boolean;
|
|
15
|
+
}[];
|
|
16
|
+
/**
|
|
17
|
+
* `wide` at page width, `compact` inside a card. TR: `wide` sayfa genişliğinde, `compact` bir
|
|
18
|
+
* kartın içinde.
|
|
19
|
+
*/
|
|
20
|
+
layout?: "wide" | "compact";
|
|
21
|
+
className?: string;
|
|
22
|
+
}): import("react").JSX.Element;
|
|
23
|
+
/**
|
|
24
|
+
* Tek bir sayı, büyük. Sektörde adı "stat" ya da "KPI kartı".
|
|
25
|
+
*
|
|
26
|
+
* `SkeletonKpi` kitte YILLARCA vardı ve yerini tuttuğu bileşen yoktu — bir
|
|
27
|
+
* iskelet, var olmayan bir şeyin yerini tutuyordu. Kitin en tuhaf açığıydı.
|
|
28
|
+
*
|
|
29
|
+
* TIKLANABİLİR OLMASI SONRADAN GELDİ, ve gelmek zorundaydı. İlk hâli yalnız
|
|
30
|
+
* okunuyordu; oysa bir panodaki sayı neredeyse hiçbir zaman salt okunur
|
|
31
|
+
* değildir. Ölçüldü: bir ürün panelinde bu karo iki kez elle yeniden yazılmış,
|
|
32
|
+
* çünkü biri bir EKRAN AÇIYOR ("37 iade bekliyor" → iade listesi), öteki bir
|
|
33
|
+
* FİLTRE UYGULUYOR (aynı listeyi o adıma indiriyor). Kitin karosu ikisini de
|
|
34
|
+
* yapamadığı için iki kopya doğdu ve ikisi birbirine benzemez oldu. Yeteneği
|
|
35
|
+
* eksik bir bileşen, olmayan bir bileşenden daha çok kopya üretiyor.
|
|
36
|
+
*
|
|
37
|
+
* ÜÇ HÂL, VE SEMANTİK ELEMAN HER BİRİNDE FARKLI:
|
|
38
|
+
*
|
|
39
|
+
* okunur `<div>` — sayı bir bilgi
|
|
40
|
+
* `href` `<a>` — sayı bir yere gidiyor
|
|
41
|
+
* `onClick` `<button>` — sayı bir şeyi değiştiriyor, `pressed` ile açık/kapalı
|
|
42
|
+
*
|
|
43
|
+
* Üçünü tek elemanla yapmak (her şey `<div onClick>`) klavyeyle gezilemeyen
|
|
44
|
+
* ve ekran okuyucunun hiç duyurmadığı bir kart üretir.
|
|
45
|
+
*
|
|
46
|
+
* FİZİK YALNIZ TIKLANABİLİR HÂLDE. Kitin 1. yasası (kenar + kaymış gölge,
|
|
47
|
+
* hover'da yükselme, basınca oturma) tıklanan şeyler içindir; okunan bir
|
|
48
|
+
* karonun hover'da oynaması, tıklanabilir olduğu yalanını söyler.
|
|
49
|
+
*
|
|
50
|
+
* Sayı `tabular-nums`: değişen bir sayaç, rakam genişlikleri eşit olmadığı
|
|
51
|
+
* sürece her güncellemede yatay olarak zıplar.
|
|
52
|
+
*
|
|
53
|
+
* `delta` bir yön taşır ama İYİ/KÖTÜ taşımaz — artan bir hata oranı da
|
|
54
|
+
* artıştır. Anlamı `better` veriyor: yükselmesi mi iyi, düşmesi mi.
|
|
55
|
+
*
|
|
56
|
+
* SAYI HER ZAMAN MÜREKKEP RENGİNDE. Bir süre `attention` diye bir bayrak
|
|
57
|
+
* vardı ve sayıyı kritik renge boyuyordu; kaldırıldı. Tek tüketicisinde beş
|
|
58
|
+
* karonun üçü kırmızıydı, ve üç kırmızı hiçbir şeyi öne çıkarmıyor — yalnız
|
|
59
|
+
* paneli alarm hâlinde gösteriyor. Bir sayının kötü olduğunu söylemenin yeri
|
|
60
|
+
* `delta` (yönü ve anlamı olan bir değişim) ya da karonun açtığı ekranın
|
|
61
|
+
* kendisi; karonun rengi değil.
|
|
62
|
+
*
|
|
63
|
+
* `accent` DENENDİ VE KALDIRILDI. Karonun sol kenarında verinin kendi rengini
|
|
64
|
+
* (bir iade adımının rengi) taşıyan ince bir şerit vardı. Tek tüketicisi vardı
|
|
65
|
+
* ve o tüketici reddetti: renk zaten listedeki rozette ve çiplerde duruyordu,
|
|
66
|
+
* kartın kenarında üçüncü kez söylenince aynı bileşen iki ekranda farklı
|
|
67
|
+
* görünüyordu. Tüketicisi olmayan bir prop, `SkeletonKpi`ın yıllarca yaşadığı
|
|
68
|
+
* boşluğun aynısı: duruyor, belgeleniyor, hiçbir şeyin yerini tutmuyor.
|
|
69
|
+
*/
|
|
70
|
+
export declare function Kpi({ label, value, unit, icon, note, delta, better, chart, href, onClick, pressed, linkComponent: Link, className, }: {
|
|
71
|
+
label: string;
|
|
72
|
+
value: string | number;
|
|
73
|
+
unit?: string;
|
|
74
|
+
/** A glyph in a tile at the left, saying what is counted. TR: Solda bir karo içinde, neyin sayıldığını söyleyen simge. */
|
|
75
|
+
icon?: PhosphorIcon;
|
|
76
|
+
/** One quiet line under the number. TR: Sayının altında tek sessiz satır. */
|
|
77
|
+
note?: string;
|
|
78
|
+
/** The percentage change against the previous value. TR: Bir öncekine göre yüzde değişim. */
|
|
79
|
+
delta?: number;
|
|
80
|
+
/** Which direction is the good news. TR: Hangi yön iyi haber. */
|
|
81
|
+
better?: "up" | "down";
|
|
82
|
+
/** An inline chart, such as a `Sparkline`. TR: Satır içi grafik, `Sparkline` gibi. */
|
|
83
|
+
chart?: ReactNode;
|
|
84
|
+
/** Where the number leads. Makes the tile a link. TR: Sayının götürdüğü yer. Karoyu bağlantı yapar. */
|
|
85
|
+
href?: string;
|
|
86
|
+
/** What the number toggles. Makes the tile a button. TR: Sayının açıp kapadığı şey. Karoyu düğme yapar. */
|
|
87
|
+
onClick?: () => void;
|
|
88
|
+
/** Whether that toggle is currently on. TR: O anahtarın şu an açık olup olmadığı. */
|
|
89
|
+
pressed?: boolean;
|
|
90
|
+
/** The router's link, so the tile does not force a full page load. TR: Yönlendiricinin bağlantısı, karo tam sayfa yüklemeye zorlamasın diye. */
|
|
91
|
+
linkComponent?: LinkComponent;
|
|
92
|
+
className?: string;
|
|
93
|
+
}): import("react").JSX.Element;
|
|
94
|
+
/**
|
|
95
|
+
* KPI karolarının ızgarası.
|
|
96
|
+
*
|
|
97
|
+
* NEDEN AYRI BİR BİLEŞEN: karoların dizilişi her ekranda elle yazılıyordu
|
|
98
|
+
* (`grid gap-4 sm:grid-cols-2 xl:grid-cols-5`) ve ekrandan ekrana tutmuyordu —
|
|
99
|
+
* biri dörtlü, öteki beşli, bir üçüncüsü boşluğu 3 veriyordu. Izgara karonun
|
|
100
|
+
* kendi işi değil ama karo KÜMESİNİN işi, ve tek yerde durunca hepsi tutuyor.
|
|
101
|
+
*
|
|
102
|
+
* SÜTUN SAYISI VERİLMİYOR, SAYILIYOR: kaç karo varsa o kadar sütun (en çok
|
|
103
|
+
* altı). Elle verilen bir sütun sayısı, karo eklenince yalnız o ekranda
|
|
104
|
+
* güncelleniyor ve tek başına kalan bir karo tam satırı kaplıyor.
|
|
105
|
+
*/
|
|
106
|
+
export declare function KpiGrid({ children, className }: {
|
|
107
|
+
children: ReactNode;
|
|
108
|
+
className?: string;
|
|
109
|
+
}): import("react").JSX.Element;
|
|
110
|
+
/**
|
|
111
|
+
* Kod bloğu, kopyalanabilir.
|
|
112
|
+
*
|
|
113
|
+
* Bir panelde bu her zaman aynı üç şeydir: API anahtarı, webhook adresi,
|
|
114
|
+
* kurulum komutu. Üçünde de kullanıcının yaptığı tek şey KOPYALAMAK — o yüzden
|
|
115
|
+
* kopyalama düğmesi bir seçenek değil, bileşenin kendisi.
|
|
116
|
+
*
|
|
117
|
+
* Kopyalama panosu her yerde çalışmaz (HTTPS olmayan bir kaynakta, ya da
|
|
118
|
+
* izin verilmemişse). Başarısızlık SESSİZ olmamalı: düğme metni değişmezse
|
|
119
|
+
* kullanıcı kopyalandığını sanır ve boş yapıştırır.
|
|
120
|
+
*/
|
|
121
|
+
export declare function Code({ children, labels, className, }: {
|
|
122
|
+
/** The text to be copied itself. TR: Kopyalanacak metnin kendisi. */
|
|
123
|
+
children: string;
|
|
124
|
+
labels: {
|
|
125
|
+
copy: string;
|
|
126
|
+
copied: string;
|
|
127
|
+
failed: string;
|
|
128
|
+
};
|
|
129
|
+
className?: string;
|
|
130
|
+
}): import("react").JSX.Element;
|
|
131
|
+
/**
|
|
132
|
+
* Klavye tuşu.
|
|
133
|
+
*
|
|
134
|
+
* `<kbd>` KULLANILIYOR, `<span>` değil: bir ekran okuyucu için "Ctrl" ile
|
|
135
|
+
* "bir tuşa basılacak" arasındaki fark bu elemanda yaşıyor.
|
|
136
|
+
*/
|
|
137
|
+
export declare function Kbd({ children, className }: {
|
|
138
|
+
children: ReactNode;
|
|
139
|
+
className?: string;
|
|
140
|
+
}): import("react").JSX.Element;
|
|
141
|
+
/**
|
|
142
|
+
* Sayaç rozeti — bir ikonun köşesindeki rakam.
|
|
143
|
+
*
|
|
144
|
+
* `StatusChip` bir DURUM taşır ("Yayında"), bu bir SAYI taşır ("3"). İkisi
|
|
145
|
+
* ayrı bileşen çünkü ayrı şeyler: durum okunur, sayı sayılır.
|
|
146
|
+
*
|
|
147
|
+
* `max` üstünde "+" ile kesiliyor. Kesilmezse dört haneli bir sayı rozetin
|
|
148
|
+
* kutusunu şişirir ve altındaki ikonu ezer.
|
|
149
|
+
*
|
|
150
|
+
* Sıfır GÖSTERİLMEZ: "0 bildirim" bir bilgi değil, gürültüdür.
|
|
151
|
+
*/
|
|
152
|
+
export declare function Badge({ count, max, tone, label, className, children, }: {
|
|
153
|
+
count: number;
|
|
154
|
+
max?: number;
|
|
155
|
+
tone?: Tone;
|
|
156
|
+
/**
|
|
157
|
+
* What the number is: "unread notifications". The screen reader reads it. TR: Sayının ne
|
|
158
|
+
* olduğu: "okunmamış bildirim". Ekran okuyucu bunu okur.
|
|
159
|
+
*/
|
|
160
|
+
label: string;
|
|
161
|
+
className?: string;
|
|
162
|
+
/**
|
|
163
|
+
* What the badge sits on (an icon, an avatar). Without it the badge stands alone. TR: Rozetin
|
|
164
|
+
* üstüne oturacağı şey (ikon, avatar). Yoksa rozet tek başına durur.
|
|
165
|
+
*/
|
|
166
|
+
children?: ReactNode;
|
|
167
|
+
}): import("react").JSX.Element;
|
|
168
|
+
/**
|
|
169
|
+
* Adım göstergesi.
|
|
170
|
+
*
|
|
171
|
+
* Üründe bir sihirbaz şablonu vardı ve adım göstergesi yoktu — yani kullanıcı
|
|
172
|
+
* kaçıncı adımda olduğunu ve kaç adım kaldığını bilmiyordu. Bir sihirbazın
|
|
173
|
+
* varlık sebebi tam olarak budur.
|
|
174
|
+
*
|
|
175
|
+
* `<ol>` kullanılıyor: adımlar SIRALI ve sıra bilgi taşıyor. Ekran okuyucu
|
|
176
|
+
* "3 öğeli liste, öğe 2" der; `<div>`'lerle bu bilgi kaybolur.
|
|
177
|
+
*
|
|
178
|
+
* Tamamlanan adım bir onay işareti alıyor, aktif olan aksan kenarı, gelecek
|
|
179
|
+
* olan sönük. Üç durum üç ayrı görsel dil — çünkü "neredeyim" ve "ne kaldı"
|
|
180
|
+
* ayrı iki soru.
|
|
181
|
+
*/
|
|
182
|
+
export declare function Steps({ steps, current, className, }: {
|
|
183
|
+
steps: readonly string[];
|
|
184
|
+
/** The active step, counting from zero. TR: Sıfırdan sayan aktif adım. */
|
|
185
|
+
current: number;
|
|
186
|
+
className?: string;
|
|
187
|
+
}): import("react").JSX.Element;
|
|
188
|
+
//# sourceMappingURL=display.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"display.d.ts","sourceRoot":"","sources":["../../src/components/display.tsx"],"names":[],"mappings":"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"}
|