tamga-ui 0.5.4 → 0.5.6
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/CHANGELOG.md +67 -0
- package/dist/blocks/filter-bar.d.ts +23 -1
- package/dist/blocks/filter-bar.d.ts.map +1 -1
- package/dist/blocks/filter-bar.js +11 -2
- package/dist/components/a11y.d.ts +8 -0
- package/dist/components/a11y.d.ts.map +1 -1
- package/dist/components/a11y.js +26 -0
- package/dist/components/date-picker.d.ts.map +1 -1
- package/dist/components/date-picker.js +15 -2
- package/dist/components/layout.js +1 -1
- package/dist/components/overlay.d.ts +6 -0
- package/dist/components/overlay.d.ts.map +1 -1
- package/dist/components/overlay.js +1 -26
- package/dist/fonts.css +1 -1
- package/dist/kit.css +6 -4
- package/dist/patterns/app-shell.d.ts +26 -4
- package/dist/patterns/app-shell.d.ts.map +1 -1
- package/dist/patterns/app-shell.js +6 -4
- package/dist/styles.css +1 -1
- package/dist/theme.css +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,73 @@ Versions follow [semver](https://semver.org/). Through `0.x`, breaking changes m
|
|
|
5
5
|
|
|
6
6
|
> 🇹🇷 Türkçe için [tamga.org.tr/tr](https://tamga.org.tr/tr).
|
|
7
7
|
|
|
8
|
+
## 0.5.6
|
|
9
|
+
|
|
10
|
+
> A calendar can be closed, a chosen file reaches the screen that asked for it, and the rail
|
|
11
|
+
> answers the mouse.
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- **`FilterBar.onFile`** · the file itself, and `null` when it is removed. The drawer's file
|
|
16
|
+
section let someone pick a file and then dropped it: `values` holds strings, so only the NAME
|
|
17
|
+
was ever written, and the thing the screen has to parse or upload existed nowhere. One product
|
|
18
|
+
had already moved its import button out of the drawer because of this. The name still lands in
|
|
19
|
+
`values[fileSearchKey]`, so the chip is unchanged.
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
|
|
23
|
+
- **`FilterBar` no longer names file formats; `fileAccept` does.** The picker hardcoded
|
|
24
|
+
`.xlsx,.xls,.csv`, which is one product's vocabulary living in a library: the same drawer may
|
|
25
|
+
want a photo or a PDF. Pass `fileAccept` to get the old behaviour back.
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
|
|
29
|
+
- **`DatePicker` closes on an outside click and on Escape.** The only way out of an open calendar
|
|
30
|
+
was to pick a date: someone who opened it by accident either chose a date they did not want or
|
|
31
|
+
discovered that clicking the field again closed it. The kit already had the dismissal the other
|
|
32
|
+
overlays use, and this one component never called it.
|
|
33
|
+
|
|
34
|
+
- **A click inside the calendar no longer escapes to the page.** Wrap the field in a `<label>`, the
|
|
35
|
+
way a form usually is, and every click on the calendar's own padding was forwarded by the browser
|
|
36
|
+
to the labelled input, which toggled the calendar underneath the pointer. The kit's own `Field`
|
|
37
|
+
points at its control rather than wrapping it, so this only ever bit hand written markup, and it
|
|
38
|
+
bit it silently.
|
|
39
|
+
|
|
40
|
+
- **A rail row without an address now shows a pointer.** `.tamga-rail-link` left the cursor to the
|
|
41
|
+
browser: a row carrying `href` is an `<a>` and gets the pointing hand for free, while the same row
|
|
42
|
+
in a shell whose screens are state is a `<button>` and kept the arrow. One control, two cursors,
|
|
43
|
+
and every such product patched it from the outside.
|
|
44
|
+
|
|
45
|
+
- **A narrow rail shows where one group ends and the next begins.** `NavEntry.section` drew its
|
|
46
|
+
heading only on a wide rail, which is right — a heading is unreadable in a 40px box — but nothing
|
|
47
|
+
took its place, so a rail that narrowed turned "start" and the three tools into one undivided
|
|
48
|
+
column. The group change is now a line, the same divider the brand mark already sits above.
|
|
49
|
+
|
|
50
|
+
## 0.5.5
|
|
51
|
+
|
|
52
|
+
> A page title finds its size, a shell can be driven by state instead of addresses, and the
|
|
53
|
+
> current rail row stands on the brand.
|
|
54
|
+
|
|
55
|
+
### Added
|
|
56
|
+
|
|
57
|
+
- **`AppShell` entries can carry an action instead of an address.** `NavEntry.href` was required and
|
|
58
|
+
the active row was found by comparing paths, which is right for a web panel and wrong for a
|
|
59
|
+
desktop app, where a screen is state and there is no URL. An entry may now give `onSelect`, and
|
|
60
|
+
`activePath` is then matched against its `key`. One of the two is required; nothing changes for an
|
|
61
|
+
entry that has a path.
|
|
62
|
+
|
|
63
|
+
- **`AppShell.mainClassName`** — a state class on the content surface, for something the shell
|
|
64
|
+
cannot know: a window-wide drop target marking its edge, say. Layout stays the kit's; without it
|
|
65
|
+
a product had to draw the whole shell by hand to reach that one edge.
|
|
66
|
+
|
|
67
|
+
### Changed
|
|
68
|
+
|
|
69
|
+
- **A page title is 24px, not 40px.** `PageBand` drew its heading at `--text-display-lg`, which is
|
|
70
|
+
the reference design's own size for a marketing-width page. In a dense panel — a table under the
|
|
71
|
+
title, a filter bar above it — it took the room the data needed and read as a banner rather than a
|
|
72
|
+
heading. The scale now reads 16 section · 18 dialog · 24 page · 30 KPI, and the two token comments
|
|
73
|
+
that still called 18px "page titles" and 30px "KPI numbers only" were corrected with it.
|
|
74
|
+
|
|
8
75
|
## 0.5.4
|
|
9
76
|
|
|
10
77
|
> An empty filter drawer no longer advertises itself, and a tile's icon reads as a glyph.
|
|
@@ -127,11 +127,33 @@ export type FilterBarProps = {
|
|
|
127
127
|
searchKey?: string;
|
|
128
128
|
/** The key for search-by-file if this screen has it; without it the section is not drawn. TR: Dosyayla arama bu ekranda varsa anahtarı; yoksa bölüm hiç çizilmiyor. */
|
|
129
129
|
fileSearchKey?: string;
|
|
130
|
+
/**
|
|
131
|
+
* The chosen FILE, and `null` when it is removed. TR: Seçilen DOSYANIN kendisi, kaldırılınca
|
|
132
|
+
* `null`.
|
|
133
|
+
*
|
|
134
|
+
* `values` holds strings, so the file section could only ever write the file's NAME there, and
|
|
135
|
+
* the thing the screen has to read, parse or upload existed nowhere. Given this, the name still
|
|
136
|
+
* lands in `values[fileSearchKey]` for the chip; the `File` comes here. TR: `values` dizgi
|
|
137
|
+
* tutuyor, yani dosya bölümü oraya ancak dosyanın ADINI yazabiliyordu ve ekranın okuyacağı,
|
|
138
|
+
* ayrıştıracağı ya da göndereceği şey hiçbir yerde yoktu. Verildiğinde ad yine çipe gidiyor,
|
|
139
|
+
* `File` buraya geliyor.
|
|
140
|
+
*/
|
|
141
|
+
onFile?: (file: File | null) => void;
|
|
142
|
+
/**
|
|
143
|
+
* What the picker accepts: `".xlsx,.csv"`, `"image/*"`. TR: Seçicinin kabul ettiği tür:
|
|
144
|
+
* `".xlsx,.csv"`, `"image/*"`.
|
|
145
|
+
*
|
|
146
|
+
* The kit named the formats itself for a while (`.xlsx,.xls,.csv`), which is a product's
|
|
147
|
+
* vocabulary living in a library: the same drawer may want a photo or a PDF. TR: Kit bir süre
|
|
148
|
+
* türleri kendi sayıyordu; o bir ürünün sözlüğünün kütüphanede yaşamasıdır · aynı çekmece bir
|
|
149
|
+
* fotoğraf ya da PDF de isteyebilir.
|
|
150
|
+
*/
|
|
151
|
+
fileAccept?: string;
|
|
130
152
|
/** A screen-specific button on the filter row, beside "All filters". TR: Filtre satırına, "Tüm filtreler"in yanına giren ekrana özel düğme. */
|
|
131
153
|
extra?: ReactNode;
|
|
132
154
|
/** For `DatePicker`'s calendar: "tr-TR", "en-GB". TR: `DatePicker`ın takvimi için: "tr-TR", "en-GB". */
|
|
133
155
|
locale?: string;
|
|
134
156
|
labels: FilterBarLabels;
|
|
135
157
|
};
|
|
136
|
-
export declare function FilterBar({ values, onChange, top, drawer, optionSource, searchKey, fileSearchKey, extra, locale, labels, }: FilterBarProps): import("react").JSX.Element;
|
|
158
|
+
export declare function FilterBar({ values, onChange, top, drawer, optionSource, searchKey, fileSearchKey, onFile, fileAccept, extra, locale, labels, }: FilterBarProps): import("react").JSX.Element;
|
|
137
159
|
//# sourceMappingURL=filter-bar.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filter-bar.d.ts","sourceRoot":"","sources":["../../src/blocks/filter-bar.tsx"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"filter-bar.d.ts","sourceRoot":"","sources":["../../src/blocks/filter-bar.tsx"],"names":[],"mappings":"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"}
|
|
@@ -46,7 +46,7 @@ function FieldControl({ field, values, write, optionSource, locale, labels, }) {
|
|
|
46
46
|
}
|
|
47
47
|
return (_jsx(Input, { full: true, value: values[field.key] ?? "", onChange: (e) => write(field.key, e.target.value) }));
|
|
48
48
|
}
|
|
49
|
-
export function FilterBar({ values, onChange, top, drawer, optionSource = {}, searchKey = "q", fileSearchKey, extra, locale = "en-GB", labels, }) {
|
|
49
|
+
export function FilterBar({ values, onChange, top, drawer, optionSource = {}, searchKey = "q", fileSearchKey, onFile, fileAccept, extra, locale = "en-GB", labels, }) {
|
|
50
50
|
const [drawerOpen, setDrawerOpen] = useState(false);
|
|
51
51
|
const formId = useId();
|
|
52
52
|
const active = Object.entries(values).filter(([, v]) => v);
|
|
@@ -78,5 +78,14 @@ export function FilterBar({ values, onChange, top, drawer, optionSource = {}, se
|
|
|
78
78
|
return (_jsxs("div", { className: "tamga-card tamga-card-open flex flex-col gap-3.5 p-4", children: [_jsxs("div", { className: "tamga-filter-row", children: [_jsxs("label", { className: "flex min-w-0 shrink grow-[2] basis-75 flex-col gap-1.5", children: [_jsx("span", { className: "text-small font-bold text-ink-faint", children: labels.search }), _jsxs("span", { className: "relative flex items-center", children: [_jsx(Icon, { icon: Search, size: "xs", "aria-hidden": true, className: "pointer-events-none absolute left-2.5 text-ink-faint" }), _jsx(Input, { type: "search", full: true, leading: true, placeholder: labels.search, value: values[searchKey] ?? "", onChange: (e) => write(searchKey, e.target.value) })] })] }), top.map((field) => (_jsxs(Fragment, { children: [field.break ? _jsx("span", { "aria-hidden": true, className: "h-0 basis-full" }) : null, _jsxs("div", { className: `flex min-w-0 shrink grow flex-col gap-1.5 ${field.kind === "dateRange" ? "basis-80" : "basis-40 tamga-filter-cap"}`, children: [_jsx("span", { className: "text-small font-bold text-ink-faint", children: field.label }), _jsx(FieldControl, { field: field, values: values, write: write, optionSource: optionSource, locale: locale, labels: labels })] })] }, field.key))), drawer.length > 0 && (_jsxs(Button, { className: "ml-auto", onClick: () => setDrawerOpen(true), children: [_jsx(Icon, { icon: Customize, size: "xs" }), labels.allFilters, hiddenActive > 0 && (_jsx("span", { className: "tamga-count ml-1 tabular-nums", children: hiddenActive }))] })), extra] }), active.length > 0 && (_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [active.map(([key, value]) => (_jsxs("span", { className: "tamga-token", children: [_jsxs("span", { className: "font-normal text-ink-faint", children: [labelFor(key), ":"] }), value, _jsx("button", { type: "button", className: "tamga-token-x", "aria-label": labels.remove(labelFor(key)), onClick: () => write(key, ""), children: _jsx(Icon, { icon: Close, size: "xs" }) })] }, key))), _jsx(Button, { variant: "link", size: "sm", onClick: () => onChange({}), children: labels.clearAll })] })), _jsx(Sheet, { open: drawerOpen, onClose: () => setDrawerOpen(false), title: labels.allFilters, closeLabel: labels.calendar.clear, footer: _jsxs(_Fragment, { children: [_jsx(Button, { type: "button", onClick: () => onChange({}), children: labels.clear }), _jsx(Button, { type: "submit", form: formId, variant: "primary", children: labels.apply })] }), children: _jsxs("form", { id: formId, onSubmit: (e) => {
|
|
79
79
|
e.preventDefault();
|
|
80
80
|
setDrawerOpen(false);
|
|
81
|
-
}, className: "flex flex-col", children: [drawer.map((group) => (_jsxs("div", { className: "flex flex-col gap-3.5 border-b border-dashed border-line py-4.5 last:border-b-0", children: [_jsx("p", { className: "text-caption font-extrabold uppercase tracking-label text-ink-faint", children: group.title }), _jsx("div", { className: "grid gap-3 sm:grid-cols-[repeat(2,minmax(0,1fr))]", children: group.fields.map((field) => (_jsxs("div", { className: `flex flex-col gap-1.5 ${field.kind === "dateRange" ? "sm:col-span-2" : ""}`, children: [_jsx("span", { className: "text-small text-ink-soft", children: field.label }), _jsx(FieldControl, { field: field, values: values, write: write, optionSource: optionSource, locale: locale, labels: labels })] }, field.key))) })] }, group.title))), fileSearchKey && labels.fileSearch && (_jsxs("div", { children: [_jsx("p", { className: "mb-3 text-micro font-semibold uppercase tracking-wide text-ink-faint", children: labels.fileSearch.title }), _jsx("p", { className: "mb-3 text-small leading-relaxed text-ink-soft", children: labels.fileSearch.help }), values[fileSearchKey] ? (_jsxs("span", { className: "flex items-center gap-2", children: [_jsx("span", { className: "truncate text-small text-ink", children: values[fileSearchKey] }), _jsx(Button, { type: "button", size: "sm", onClick: () =>
|
|
81
|
+
}, className: "flex flex-col", children: [drawer.map((group) => (_jsxs("div", { className: "flex flex-col gap-3.5 border-b border-dashed border-line py-4.5 last:border-b-0", children: [_jsx("p", { className: "text-caption font-extrabold uppercase tracking-label text-ink-faint", children: group.title }), _jsx("div", { className: "grid gap-3 sm:grid-cols-[repeat(2,minmax(0,1fr))]", children: group.fields.map((field) => (_jsxs("div", { className: `flex flex-col gap-1.5 ${field.kind === "dateRange" ? "sm:col-span-2" : ""}`, children: [_jsx("span", { className: "text-small text-ink-soft", children: field.label }), _jsx(FieldControl, { field: field, values: values, write: write, optionSource: optionSource, locale: locale, labels: labels })] }, field.key))) })] }, group.title))), fileSearchKey && labels.fileSearch && (_jsxs("div", { children: [_jsx("p", { className: "mb-3 text-micro font-semibold uppercase tracking-wide text-ink-faint", children: labels.fileSearch.title }), _jsx("p", { className: "mb-3 text-small leading-relaxed text-ink-soft", children: labels.fileSearch.help }), values[fileSearchKey] ? (_jsxs("span", { className: "flex items-center gap-2", children: [_jsx("span", { className: "truncate text-small text-ink", children: values[fileSearchKey] }), _jsx(Button, { type: "button", size: "sm", onClick: () => {
|
|
82
|
+
write(fileSearchKey, "");
|
|
83
|
+
onFile?.(null);
|
|
84
|
+
}, children: labels.fileSearch.remove })] })) : (_jsxs("label", { className: `${buttonVariants({})} cursor-pointer`, children: [_jsx(Icon, { icon: Upload, size: "xs" }), labels.fileSearch.choose, _jsx("input", { type: "file", accept: fileAccept, className: "sr-only", onChange: (e) => {
|
|
85
|
+
/* AD ÇİPE, DOSYA ÇAĞIRANA: ikisi ayrı şey ve blok bir
|
|
86
|
+
süre yalnız birincisini veriyordu. */
|
|
87
|
+
const dosya = e.target.files?.[0] ?? null;
|
|
88
|
+
write(fileSearchKey, dosya?.name ?? "");
|
|
89
|
+
onFile?.(dosya);
|
|
90
|
+
} })] }))] }))] }) })] }));
|
|
82
91
|
}
|
|
@@ -18,4 +18,12 @@ export declare function useListKeys({ open, containerRef, onClose, }: {
|
|
|
18
18
|
containerRef: React.RefObject<HTMLElement | null>;
|
|
19
19
|
onClose: () => void;
|
|
20
20
|
}): void;
|
|
21
|
+
/**
|
|
22
|
+
* Closes a popup when the pointer goes down outside it, or on Escape.
|
|
23
|
+
*
|
|
24
|
+
* Shared, because an overlay nobody can dismiss is a trap rather than a style:
|
|
25
|
+
* `DatePicker` kept its own open state and had none of this. The returned ref
|
|
26
|
+
* marks what counts as "inside", and that includes the trigger.
|
|
27
|
+
*/
|
|
28
|
+
export declare function useDismiss<T extends HTMLElement = HTMLDivElement>(open: boolean, close: () => void): import("react").RefObject<T | null>;
|
|
21
29
|
//# sourceMappingURL=a11y.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"a11y.d.ts","sourceRoot":"","sources":["../../src/components/a11y.ts"],"names":[],"mappings":"AAkCA;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,WAAW,EAAE,IAAI,EAAE,OAAO,uCA0DhE;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,YAAY,EACZ,OAAO,GACR,EAAE;IACD,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,KAAK,CAAC,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAClD,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,QA0DA"}
|
|
1
|
+
{"version":3,"file":"a11y.d.ts","sourceRoot":"","sources":["../../src/components/a11y.ts"],"names":[],"mappings":"AAkCA;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,WAAW,EAAE,IAAI,EAAE,OAAO,uCA0DhE;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,YAAY,EACZ,OAAO,GACR,EAAE;IACD,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,KAAK,CAAC,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAClD,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,QA0DA;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,CAAC,SAAS,WAAW,GAAG,cAAc,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,IAAI,uCAgBlG"}
|
package/dist/components/a11y.js
CHANGED
|
@@ -152,3 +152,29 @@ export function useListKeys({ open, containerRef, onClose, }) {
|
|
|
152
152
|
return () => root.removeEventListener("keydown", onKey);
|
|
153
153
|
}, [open, containerRef, onClose]);
|
|
154
154
|
}
|
|
155
|
+
/**
|
|
156
|
+
* Closes a popup when the pointer goes down outside it, or on Escape.
|
|
157
|
+
*
|
|
158
|
+
* Shared, because an overlay nobody can dismiss is a trap rather than a style:
|
|
159
|
+
* `DatePicker` kept its own open state and had none of this. The returned ref
|
|
160
|
+
* marks what counts as "inside", and that includes the trigger.
|
|
161
|
+
*/
|
|
162
|
+
export function useDismiss(open, close) {
|
|
163
|
+
const box = useRef(null);
|
|
164
|
+
useEffect(() => {
|
|
165
|
+
if (!open)
|
|
166
|
+
return;
|
|
167
|
+
const away = (e) => {
|
|
168
|
+
if (box.current && !box.current.contains(e.target))
|
|
169
|
+
close();
|
|
170
|
+
};
|
|
171
|
+
const esc = (e) => e.key === "Escape" && close();
|
|
172
|
+
document.addEventListener("mousedown", away);
|
|
173
|
+
document.addEventListener("keydown", esc);
|
|
174
|
+
return () => {
|
|
175
|
+
document.removeEventListener("mousedown", away);
|
|
176
|
+
document.removeEventListener("keydown", esc);
|
|
177
|
+
};
|
|
178
|
+
}, [open, close]);
|
|
179
|
+
return box;
|
|
180
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"date-picker.d.ts","sourceRoot":"","sources":["../../src/components/date-picker.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"date-picker.d.ts","sourceRoot":"","sources":["../../src/components/date-picker.tsx"],"names":[],"mappings":"AASA;;;;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,EACT,GAAG,IAAI,EACR,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;IACnB,mEAAmE;IACnE,CAAC,CAAC,EAAE,QAAQ,MAAM,EAAE,GAAG,OAAO,CAAC;CAChC,+BAmFA;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,EACzB,MAAM,EACN,KAAK,EACL,QAAQ,EACR,WAAW,EACX,MAAM,EACN,QAAgB,EAChB,SAAS,EACT,GAAG,IAAI,EACR,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;IACnB,mEAAmE;IACnE,CAAC,CAAC,EAAE,QAAQ,MAAM,EAAE,GAAG,OAAO,CAAC;CAChC,+BAwEA"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { useMemo, useState } from "react";
|
|
3
|
+
import { useCallback, useMemo, useState } from "react";
|
|
4
|
+
import { useDismiss } from "./a11y.js";
|
|
4
5
|
import { cn } from "../lib/cn.js";
|
|
5
6
|
import { dataProps } from "../lib/data-props.js";
|
|
6
7
|
import { Icon } from "./icon.js";
|
|
@@ -71,10 +72,22 @@ export function Calendar({ locale, value, range, onSelect, labels, className, ..
|
|
|
71
72
|
*/
|
|
72
73
|
export function DatePicker({ locale, value, onChange, placeholder, labels, disabled = false, className, ...rest }) {
|
|
73
74
|
const [open, setOpen] = useState(false);
|
|
75
|
+
/* TAKVİM DIŞARI TIKLAYINCA VE ESCAPE İLE KAPANIYOR, ve bir süre HİÇ
|
|
76
|
+
kapanmıyordu: tek çıkış yolu bir tarih seçmekti, yani yanlışlıkla açan
|
|
77
|
+
kişi ya bir tarih seçiyor ya da alanı yeniden tıklamayı buluyordu. Kutu
|
|
78
|
+
tetiği de kapsıyor: tetiğe tıklama kendi anahtarına ulaşmalı, dışarı
|
|
79
|
+
sayılmamalı. */
|
|
80
|
+
const kapat = useCallback(() => setOpen(false), []);
|
|
81
|
+
const kutu = useDismiss(open, kapat);
|
|
74
82
|
const shown = value
|
|
75
83
|
? new Intl.DateTimeFormat(locale, { dateStyle: "medium" }).format(new Date(`${value}T00:00:00Z`))
|
|
76
84
|
: "";
|
|
77
|
-
return (_jsxs("div", { ...dataProps(rest), 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", "data-inset": "true", "aria-label": labels.clear, onClick: () => onChange?.(undefined), children: _jsx(Icon, { icon: Close, size: "xs" }) })) : null, _jsx("button", { type: "button", className: "tamga-mini-btn", "data-inset": "true", "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",
|
|
85
|
+
return (_jsxs("div", { ref: kutu, ...dataProps(rest), 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", "data-inset": "true", "aria-label": labels.clear, onClick: () => onChange?.(undefined), children: _jsx(Icon, { icon: Close, size: "xs" }) })) : null, _jsx("button", { type: "button", className: "tamga-mini-btn", "data-inset": "true", "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",
|
|
86
|
+
/* TAKVİMİN TIKLAMASI SAYFAYA SIZMIYOR. Tüketen taraf alanı bir
|
|
87
|
+
`<label>` ile sarınca (kitin `Field`i sarmıyor, elle yazılan sarıyor)
|
|
88
|
+
takvimin boşluğuna her tıklama tarayıcı tarafından INPUT'A
|
|
89
|
+
yönlendiriliyor, yani takvim kendi kendine açılıp kapanıyordu. */
|
|
90
|
+
onClick: (e) => e.stopPropagation(), children: _jsx(Calendar, { locale: locale, value: value, labels: labels, onSelect: (d) => {
|
|
78
91
|
onChange?.(d);
|
|
79
92
|
setOpen(false);
|
|
80
93
|
} }) })) : null] }));
|
|
@@ -78,7 +78,7 @@ export function CellActions({ className, children, align = "end", ...props
|
|
|
78
78
|
* Doküman: /docs/page-band
|
|
79
79
|
*/
|
|
80
80
|
export function PageBand({ eyebrow, title, subtitle, actions, className, ...rest }) {
|
|
81
|
-
return (_jsxs("div", { ...dataProps(rest), className: cn("flex flex-wrap items-end gap-4", className), children: [_jsxs("div", { className: "min-w-0 flex-1 basis-65", children: [eyebrow ? (_jsx("p", { className: "mb-1.5 text-small font-semibold text-ink-faint", children: eyebrow })) : null, _jsx("h1", { className: "flex flex-wrap items-center gap-x-3 gap-y-1.5 font-display text-display-
|
|
81
|
+
return (_jsxs("div", { ...dataProps(rest), className: cn("flex flex-wrap items-end gap-4", className), children: [_jsxs("div", { className: "min-w-0 flex-1 basis-65", children: [eyebrow ? (_jsx("p", { className: "mb-1.5 text-small font-semibold text-ink-faint", children: eyebrow })) : null, _jsx("h1", { className: "flex flex-wrap items-center gap-x-3 gap-y-1.5 font-display text-display-sm leading-tight font-extrabold text-ink", children: title }), subtitle ? _jsx("p", { className: "mt-1.5 text-body text-ink-soft", children: subtitle }) : null] }), actions ? _jsx("div", { className: "ml-auto flex flex-wrap items-center gap-2", children: actions }) : null] }));
|
|
82
82
|
}
|
|
83
83
|
/**
|
|
84
84
|
* Gezinen bağlantı. `Button variant="link"` DEĞİL: o bir `<button>`, yani orta
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import type { Tone } from "./tone.js";
|
|
2
|
+
/**
|
|
3
|
+
* Katman düzlemi · 6 piksel, sayfanın ulaşabildiği 4 pikselin ötesi. Perde
|
|
4
|
+
* yalnız `Dialog` ve `Sheet`te; `Tooltip` bir etiket, hiç yükselmiyor.
|
|
5
|
+
*
|
|
6
|
+
* Gerekçe: docs/gerekce/07-katman-ve-diyalog.md
|
|
7
|
+
*/
|
|
2
8
|
export type MenuItem = {
|
|
3
9
|
kind?: "item";
|
|
4
10
|
label: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"overlay.d.ts","sourceRoot":"","sources":["../../src/components/overlay.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"overlay.d.ts","sourceRoot":"","sources":["../../src/components/overlay.tsx"],"names":[],"mappings":"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"}
|
|
@@ -9,34 +9,9 @@ import { Close } from "./icons.js";
|
|
|
9
9
|
import { SkeletonOptions, SkeletonPanel } from "./skeleton.js";
|
|
10
10
|
import { Kbd } from "./display.js";
|
|
11
11
|
import { Button } from "./button.js";
|
|
12
|
-
import { useFocusTrap, useListKeys } from "./a11y.js";
|
|
12
|
+
import { useDismiss, useFocusTrap, useListKeys } from "./a11y.js";
|
|
13
13
|
import { MiniButton } from "./button.js";
|
|
14
14
|
import { useScrollLock } from "../lib/scroll-lock.js";
|
|
15
|
-
/**
|
|
16
|
-
* Katman düzlemi · 6 piksel, sayfanın ulaşabildiği 4 pikselin ötesi. Perde
|
|
17
|
-
* yalnız `Dialog` ve `Sheet`te; `Tooltip` bir etiket, hiç yükselmiyor.
|
|
18
|
-
*
|
|
19
|
-
* Gerekçe: docs/gerekce/07-katman-ve-diyalog.md
|
|
20
|
-
*/
|
|
21
|
-
function useDismiss(open, close) {
|
|
22
|
-
const box = useRef(null);
|
|
23
|
-
useEffect(() => {
|
|
24
|
-
if (!open)
|
|
25
|
-
return;
|
|
26
|
-
const away = (e) => {
|
|
27
|
-
if (box.current && !box.current.contains(e.target))
|
|
28
|
-
close();
|
|
29
|
-
};
|
|
30
|
-
const esc = (e) => e.key === "Escape" && close();
|
|
31
|
-
document.addEventListener("mousedown", away);
|
|
32
|
-
document.addEventListener("keydown", esc);
|
|
33
|
-
return () => {
|
|
34
|
-
document.removeEventListener("mousedown", away);
|
|
35
|
-
document.removeEventListener("keydown", esc);
|
|
36
|
-
};
|
|
37
|
-
}, [open, close]);
|
|
38
|
-
return box;
|
|
39
|
-
}
|
|
40
15
|
export function DropdownMenu({ trigger, items, align = "start", width = 200, loading = false, loadingRows = 4, openOnHover = false, defaultOpen = false, ...rest }) {
|
|
41
16
|
const [open, setOpen] = useState(defaultOpen);
|
|
42
17
|
const box = useDismiss(open, () => setOpen(false));
|
package/dist/fonts.css
CHANGED
package/dist/kit.css
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! tamga-ui 0.5.
|
|
1
|
+
/*! tamga-ui 0.5.6 · MIT · https://tamga.org.tr */
|
|
2
2
|
:root {
|
|
3
3
|
|
|
4
4
|
--overlay-gap: 8px;
|
|
@@ -383,6 +383,8 @@
|
|
|
383
383
|
.tamga-rail-link {
|
|
384
384
|
position: relative;
|
|
385
385
|
display: flex;
|
|
386
|
+
|
|
387
|
+
cursor: pointer;
|
|
386
388
|
height: 40px;
|
|
387
389
|
|
|
388
390
|
width: 52px;
|
|
@@ -440,9 +442,9 @@
|
|
|
440
442
|
|
|
441
443
|
.tamga-rail-link[data-active="true"] {
|
|
442
444
|
background: var(--color-shell);
|
|
443
|
-
border-color: var(--color-
|
|
445
|
+
border-color: var(--color-accent-shadow);
|
|
444
446
|
transform: translate(-1px, -1px);
|
|
445
|
-
box-shadow: 3px 3px 0 var(--color-
|
|
447
|
+
box-shadow: 3px 3px 0 var(--color-accent-shadow);
|
|
446
448
|
}
|
|
447
449
|
|
|
448
450
|
.tamga-rail-link[data-active="true"] svg {
|
|
@@ -451,7 +453,7 @@
|
|
|
451
453
|
|
|
452
454
|
.tamga-rail-link[data-active="true"]:active {
|
|
453
455
|
transform: translate(2px, 2px);
|
|
454
|
-
box-shadow: 0 0 0 var(--color-
|
|
456
|
+
box-shadow: 0 0 0 var(--color-accent-shadow);
|
|
455
457
|
}
|
|
456
458
|
|
|
457
459
|
.tamga-btn:not(:disabled):active,
|
|
@@ -8,8 +8,23 @@ import { type LinkComponent } from "./shared.js";
|
|
|
8
8
|
* yönlendiriciyi tanımaz. Gerekçe: docs/adr/0004-sablon-katmani.md
|
|
9
9
|
*/
|
|
10
10
|
export type NavEntry = {
|
|
11
|
+
/**
|
|
12
|
+
* The entry's identity. With `onSelect` it is also what `activePath` is compared against.
|
|
13
|
+
* TR: Girişin kimliği. `onSelect` ile birlikte `activePath`in karşılaştırıldığı değer de bu.
|
|
14
|
+
*/
|
|
11
15
|
key: string;
|
|
12
|
-
|
|
16
|
+
/**
|
|
17
|
+
* Where the entry goes. A desktop app has no addresses: it gives `onSelect` instead, and one of
|
|
18
|
+
* the two is required.
|
|
19
|
+
* TR: Girişin gittiği yer. Masaüstü uygulamasının adresi yok; onun yerine `onSelect` veriyor ve
|
|
20
|
+
* ikisinden biri zorunlu.
|
|
21
|
+
*/
|
|
22
|
+
href?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Runs instead of navigating. For a shell whose screens are state, not addresses.
|
|
25
|
+
* TR: Gezinmenin yerine koşuyor · ekranları adres değil durum olan bir kabuk için.
|
|
26
|
+
*/
|
|
27
|
+
onSelect?: () => void;
|
|
13
28
|
/** The translated label. In the tooltip on a narrow rail, on the row itself on a wide one. TR: Çevrilmiş etiket. Dar rayda ipucunda, geniş rayda satırın kendisinde. */
|
|
14
29
|
label: string;
|
|
15
30
|
icon: ComponentProps<typeof Icon>["icon"];
|
|
@@ -24,8 +39,8 @@ export type NavEntry = {
|
|
|
24
39
|
* ve boş bir grup kurmak mümkün hâle gelirdi. Düz listede o iki sorun da yok: grup başlığı
|
|
25
40
|
* verinin bir alanı, ve başlık ancak bir girişi varsa görünüyor.
|
|
26
41
|
*
|
|
27
|
-
* YALNIZ GENİŞ RAYDA ÇİZİLİYOR. Dar rayda 40 piksellik bir kutuda başlık okunmuyor;
|
|
28
|
-
*
|
|
42
|
+
* BAŞLIK YALNIZ GENİŞ RAYDA ÇİZİLİYOR. Dar rayda 40 piksellik bir kutuda bir başlık okunmuyor;
|
|
43
|
+
* orada grup değişimi bir ÇİZGİYLE anlatılıyor, rayın tepesindeki marka ayracının aynısı.
|
|
29
44
|
*/
|
|
30
45
|
section?: string;
|
|
31
46
|
};
|
|
@@ -56,6 +71,13 @@ export type AppShellProps = {
|
|
|
56
71
|
topbar?: ReactNode;
|
|
57
72
|
/** A control at the foot of the rail: an expand/collapse button, say. TR: Rayın dibine giren kontrol: genişlet/daralt düğmesi gibi. */
|
|
58
73
|
railFooter?: ReactNode;
|
|
74
|
+
/**
|
|
75
|
+
* A state class on the content surface, for something the shell cannot know: a window-wide drop
|
|
76
|
+
* target marking its edge, say. Layout stays the kit's.
|
|
77
|
+
* TR: İçerik yüzeyine binen durum sınıfı · kabuğun bilemeyeceği bir şey için: pencere genelinde
|
|
78
|
+
* bir bırakma hedefinin kenarını işaretlemesi gibi. Düzen kitte kalıyor.
|
|
79
|
+
*/
|
|
80
|
+
mainClassName?: string;
|
|
59
81
|
linkComponent?: LinkComponent;
|
|
60
82
|
labels: {
|
|
61
83
|
home: string;
|
|
@@ -63,5 +85,5 @@ export type AppShellProps = {
|
|
|
63
85
|
};
|
|
64
86
|
children: ReactNode;
|
|
65
87
|
};
|
|
66
|
-
export declare function AppShell({ brand, nav, activePath, rail, topbar, railFooter, linkComponent: Link, labels, children, }: AppShellProps): import("react").JSX.Element;
|
|
88
|
+
export declare function AppShell({ brand, nav, activePath, rail, topbar, railFooter, mainClassName, linkComponent: Link, labels, children, }: AppShellProps): import("react").JSX.Element;
|
|
67
89
|
//# sourceMappingURL=app-shell.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-shell.d.ts","sourceRoot":"","sources":["../../src/patterns/app-shell.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvD,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"app-shell.d.ts","sourceRoot":"","sources":["../../src/patterns/app-shell.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvD,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAG7C,OAAO,EAAa,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5D;;;;;GAKG;AAEH,MAAM,MAAM,QAAQ,GAAG;IACrB;;;OAGG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,wKAAwK;IACxK,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,cAAc,CAAC,OAAO,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC;IAC1C;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,wJAAwJ;IACxJ,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,GAAG,EAAE,SAAS,QAAQ,EAAE,CAAC;IACzB,mGAAmG;IACnG,UAAU,EAAE,MAAM,CAAC;IACnB;;;;;;;;;;;OAWG;IACH,IAAI,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC;IACzB;;;;OAIG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,uIAAuI;IACvI,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,QAAQ,EAAE,SAAS,CAAC;CACrB,CAAC;AAEF,wBAAgB,QAAQ,CAAC,EACvB,KAAK,EACL,GAAG,EACH,UAAU,EACV,IAAe,EACf,MAAM,EACN,UAAU,EACV,aAAa,EACb,aAAa,EAAE,IAAgB,EAC/B,MAAM,EACN,QAAQ,GACT,EAAE,aAAa,+BA+Hf"}
|
|
@@ -3,16 +3,18 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
|
|
|
3
3
|
import { Fragment } from "react";
|
|
4
4
|
import { Icon } from "../components/icon.js";
|
|
5
5
|
import { RailLink } from "../components/rail-link.js";
|
|
6
|
+
import { cn } from "../lib/cn.js";
|
|
6
7
|
import { PlainLink } from "./shared.js";
|
|
7
|
-
export function AppShell({ brand, nav, activePath, rail = "narrow", topbar, railFooter, linkComponent: Link = PlainLink, labels, children, }) {
|
|
8
|
+
export function AppShell({ brand, nav, activePath, rail = "narrow", topbar, railFooter, mainClassName, linkComponent: Link = PlainLink, labels, children, }) {
|
|
8
9
|
/* Bir giriş kendi alt ağacına sahip, ve EN UZUN EŞLEŞEN KAZANIR: kökün `/`
|
|
9
10
|
olmadığı bir panelde kök giriş altındaki her rotayı yutuyordu.
|
|
10
11
|
Gerekçe: docs/gerekce/08-blok-ve-sablon.md */
|
|
11
12
|
const kapsiyor = (href) => activePath === href || activePath.startsWith(`${href}/`);
|
|
12
|
-
const enOzel = nav.reduce((kazanan, entry) => kapsiyor(entry.href) && (kazanan === null || entry.href.length > kazanan.length)
|
|
13
|
+
const enOzel = nav.reduce((kazanan, entry) => entry.href && kapsiyor(entry.href) && (kazanan === null || entry.href.length > kazanan.length)
|
|
13
14
|
? entry.href
|
|
14
15
|
: kazanan, null);
|
|
15
|
-
|
|
16
|
+
/* ADRESİ OLMAYAN GİRİŞ ANAHTARIYLA EŞLEŞİYOR: masaüstü kabuğunda ekran bir durum, yol değil. */
|
|
17
|
+
const isCurrent = (entry) => entry.href ? entry.href === enOzel : entry.key === activePath;
|
|
16
18
|
const wide = rail === "wide";
|
|
17
|
-
return (_jsxs("div", { className: "flex h-dvh w-full overflow-hidden bg-rail text-ink-soft", children: [_jsxs("aside", { className: `flex shrink-0 flex-col gap-2 bg-rail py-4 ${wide ? "w-60 px-3" : "w-20 items-center px-1"}`, "data-rail": rail, children: [brand ? (_jsxs(_Fragment, { children: [_jsx("span", { "aria-label": labels.home, className: `mb-2 flex h-10 shrink-0 items-center text-ink ${wide ? "px-2" : "w-10 justify-center"}`, children: brand }), _jsx("span", { className: `h-0 w-6 border-t border-line ${wide ? "ml-2" : ""}` })] })) : null, _jsx("nav", { "aria-label": labels.primaryNav, className: `tamga-rail-scroll flex w-full flex-1 flex-col gap-2 py-1 ${wide ? "" : "items-center"}`, children: nav.map((entry, i) => (_jsxs(Fragment, { children: [
|
|
19
|
+
return (_jsxs("div", { className: "flex h-dvh w-full overflow-hidden bg-rail text-ink-soft", children: [_jsxs("aside", { className: `flex shrink-0 flex-col gap-2 bg-rail py-4 ${wide ? "w-60 px-3" : "w-20 items-center px-1"}`, "data-rail": rail, children: [brand ? (_jsxs(_Fragment, { children: [_jsx("span", { "aria-label": labels.home, className: `mb-2 flex h-10 shrink-0 items-center text-ink ${wide ? "px-2" : "w-10 justify-center"}`, children: brand }), _jsx("span", { className: `h-0 w-6 border-t border-line ${wide ? "ml-2" : ""}` })] })) : null, _jsx("nav", { "aria-label": labels.primaryNav, className: `tamga-rail-scroll flex w-full flex-1 flex-col gap-2 py-1 ${wide ? "" : "items-center"}`, children: nav.map((entry, i) => (_jsxs(Fragment, { children: [entry.section && entry.section !== nav[i - 1]?.section ? (wide ? (_jsx("p", { className: `px-2.5 text-caption font-bold uppercase tracking-label text-ink-faint ${i > 0 ? "mt-5 pb-1.5" : "pb-1.5"}`, children: entry.section })) : i > 0 ? (_jsx("span", { className: "my-1.5 h-0 w-6 shrink-0 border-t border-line", "aria-hidden": true })) : null) : null, _jsx(RailLink, { href: entry.href, onClick: entry.onSelect, label: entry.label, active: isCurrent(entry), showLabel: wide, linkComponent: Link, "data-nav": entry.key, children: _jsx(Icon, { icon: entry.icon, size: "md", weight: isCurrent(entry) ? "fill" : "regular" }) })] }, entry.key))) }), railFooter ? _jsx("div", { className: "shrink-0", children: railFooter }) : null] }), _jsxs("div", { className: "flex min-w-0 flex-1 flex-col", children: [_jsx("header", { className: "tamga-gutter flex items-center gap-4 bg-band py-4", children: topbar }), _jsx("div", { className: "min-h-0 flex-1 overflow-hidden pr-4 pb-4", children: _jsx("main", { className: cn("tamga-surface tamga-app-main relative h-full min-h-0 overflow-y-auto", mainClassName), children: children }) })] })] }));
|
|
18
20
|
}
|
package/dist/styles.css
CHANGED
package/dist/theme.css
CHANGED