@tea-ui/core 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 +33 -0
- package/dist/card.d.ts +60 -0
- package/dist/card.js +116 -0
- package/dist/card.js.map +1 -0
- package/dist/feedback/alert.d.ts +57 -0
- package/dist/feedback/alert.js +104 -0
- package/dist/feedback/alert.js.map +1 -0
- package/dist/feedback/badge.d.ts +34 -0
- package/dist/feedback/badge.js +62 -0
- package/dist/feedback/badge.js.map +1 -0
- package/dist/feedback/index.d.ts +13 -0
- package/dist/feedback/index.js +62 -0
- package/dist/feedback/index.js.map +1 -0
- package/dist/feedback/progress.d.ts +25 -0
- package/dist/feedback/progress.js +49 -0
- package/dist/feedback/progress.js.map +1 -0
- package/dist/feedback/skeleton.d.ts +38 -0
- package/dist/feedback/skeleton.js +49 -0
- package/dist/feedback/skeleton.js.map +1 -0
- package/dist/feedback/spinner.d.ts +31 -0
- package/dist/feedback/spinner.js +55 -0
- package/dist/feedback/spinner.js.map +1 -0
- package/dist/feedback/status.d.ts +63 -0
- package/dist/feedback/status.js +156 -0
- package/dist/feedback/status.js.map +1 -0
- package/dist/feedback/toast.d.ts +72 -0
- package/dist/feedback/toast.js +211 -0
- package/dist/feedback/toast.js.map +1 -0
- package/dist/format/index.d.ts +63 -0
- package/dist/format/index.js +84 -0
- package/dist/format/index.js.map +1 -0
- package/dist/index.d.ts +43 -0
- package/dist/index.js +163 -0
- package/dist/index.js.map +1 -0
- package/dist/inputs/button-group.d.ts +70 -0
- package/dist/inputs/button-group.js +59 -0
- package/dist/inputs/button-group.js.map +1 -0
- package/dist/inputs/button.d.ts +52 -0
- package/dist/inputs/button.js +84 -0
- package/dist/inputs/button.js.map +1 -0
- package/dist/inputs/checkbox.d.ts +48 -0
- package/dist/inputs/checkbox.js +74 -0
- package/dist/inputs/checkbox.js.map +1 -0
- package/dist/inputs/combobox.d.ts +77 -0
- package/dist/inputs/combobox.js +273 -0
- package/dist/inputs/combobox.js.map +1 -0
- package/dist/inputs/field.d.ts +220 -0
- package/dist/inputs/field.js +183 -0
- package/dist/inputs/field.js.map +1 -0
- package/dist/inputs/icon-button.d.ts +44 -0
- package/dist/inputs/icon-button.js +30 -0
- package/dist/inputs/icon-button.js.map +1 -0
- package/dist/inputs/index.d.ts +22 -0
- package/dist/inputs/index.js +92 -0
- package/dist/inputs/index.js.map +1 -0
- package/dist/inputs/input-group.d.ts +77 -0
- package/dist/inputs/input-group.js +76 -0
- package/dist/inputs/input-group.js.map +1 -0
- package/dist/inputs/input.d.ts +58 -0
- package/dist/inputs/input.js +68 -0
- package/dist/inputs/input.js.map +1 -0
- package/dist/inputs/label.d.ts +47 -0
- package/dist/inputs/label.js +29 -0
- package/dist/inputs/label.js.map +1 -0
- package/dist/inputs/number-input.d.ts +62 -0
- package/dist/inputs/number-input.js +86 -0
- package/dist/inputs/number-input.js.map +1 -0
- package/dist/inputs/password-input.d.ts +66 -0
- package/dist/inputs/password-input.js +73 -0
- package/dist/inputs/password-input.js.map +1 -0
- package/dist/inputs/radio.d.ts +66 -0
- package/dist/inputs/radio.js +96 -0
- package/dist/inputs/radio.js.map +1 -0
- package/dist/inputs/search-input.d.ts +66 -0
- package/dist/inputs/search-input.js +76 -0
- package/dist/inputs/search-input.js.map +1 -0
- package/dist/inputs/select.d.ts +65 -0
- package/dist/inputs/select.js +139 -0
- package/dist/inputs/select.js.map +1 -0
- package/dist/inputs/slider.d.ts +67 -0
- package/dist/inputs/slider.js +107 -0
- package/dist/inputs/slider.js.map +1 -0
- package/dist/inputs/switch.d.ts +42 -0
- package/dist/inputs/switch.js +69 -0
- package/dist/inputs/switch.js.map +1 -0
- package/dist/inputs/textarea.d.ts +51 -0
- package/dist/inputs/textarea.js +82 -0
- package/dist/inputs/textarea.js.map +1 -0
- package/dist/inputs/toggle.d.ts +57 -0
- package/dist/inputs/toggle.js +91 -0
- package/dist/inputs/toggle.js.map +1 -0
- package/dist/internal/index.d.ts +5 -0
- package/dist/internal/index.js +19 -0
- package/dist/internal/index.js.map +1 -0
- package/dist/internal/refs.d.ts +31 -0
- package/dist/internal/refs.js +34 -0
- package/dist/internal/refs.js.map +1 -0
- package/dist/internal/slot.d.ts +76 -0
- package/dist/internal/slot.js +40 -0
- package/dist/internal/slot.js.map +1 -0
- package/dist/internal/use-controllable-state.d.ts +25 -0
- package/dist/internal/use-controllable-state.js +38 -0
- package/dist/internal/use-controllable-state.js.map +1 -0
- package/dist/layout/index.d.ts +131 -0
- package/dist/layout/index.js +212 -0
- package/dist/layout/index.js.map +1 -0
- package/dist/navigation/index.d.ts +114 -0
- package/dist/navigation/index.js +523 -0
- package/dist/navigation/index.js.map +1 -0
- package/dist/overlays/alert-dialog.d.ts +75 -0
- package/dist/overlays/alert-dialog.js +163 -0
- package/dist/overlays/alert-dialog.js.map +1 -0
- package/dist/overlays/dialog.d.ts +44 -0
- package/dist/overlays/dialog.js +121 -0
- package/dist/overlays/dialog.js.map +1 -0
- package/dist/overlays/drawer.d.ts +49 -0
- package/dist/overlays/drawer.js +125 -0
- package/dist/overlays/drawer.js.map +1 -0
- package/dist/overlays/dropdown-menu.d.ts +53 -0
- package/dist/overlays/dropdown-menu.js +192 -0
- package/dist/overlays/dropdown-menu.js.map +1 -0
- package/dist/overlays/index.d.ts +10 -0
- package/dist/overlays/index.js +169 -0
- package/dist/overlays/index.js.map +1 -0
- package/dist/overlays/popover.d.ts +58 -0
- package/dist/overlays/popover.js +105 -0
- package/dist/overlays/popover.js.map +1 -0
- package/dist/styles.css +2 -0
- package/dist/typography/index.d.ts +79 -0
- package/dist/typography/index.js +280 -0
- package/dist/typography/index.js.map +1 -0
- package/package.json +60 -0
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { Toast as ToastPrimitive } from "radix-ui";
|
|
4
|
+
import { X } from "@tea-ui/icons";
|
|
5
|
+
import { COPY } from "@tea-ui/ux-standards";
|
|
6
|
+
import { cn } from "@tea-ui/utils";
|
|
7
|
+
import { dataSlot, stateAttributes } from "../internal/index.js";
|
|
8
|
+
import { Button } from "../inputs/button.js";
|
|
9
|
+
const TOAST_LIMIT = 3;
|
|
10
|
+
const DEFAULT_DURATION = 5e3;
|
|
11
|
+
let toastSeq = 0;
|
|
12
|
+
let toasts = [];
|
|
13
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
14
|
+
const timers = /* @__PURE__ */ new Map();
|
|
15
|
+
function emit() {
|
|
16
|
+
for (const listener of listeners) listener();
|
|
17
|
+
}
|
|
18
|
+
function scheduleDismiss(id, duration) {
|
|
19
|
+
const existing = timers.get(id);
|
|
20
|
+
if (existing) clearTimeout(existing);
|
|
21
|
+
if (duration <= 0) return;
|
|
22
|
+
timers.set(
|
|
23
|
+
id,
|
|
24
|
+
setTimeout(() => {
|
|
25
|
+
timers.delete(id);
|
|
26
|
+
toasts = toasts.filter((entry) => entry.id !== id);
|
|
27
|
+
emit();
|
|
28
|
+
}, duration)
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
function clearTimer(id) {
|
|
32
|
+
const timer = timers.get(id);
|
|
33
|
+
if (timer) {
|
|
34
|
+
clearTimeout(timer);
|
|
35
|
+
timers.delete(id);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function setToasts(next) {
|
|
39
|
+
toasts = next;
|
|
40
|
+
emit();
|
|
41
|
+
}
|
|
42
|
+
function subscribe(listener) {
|
|
43
|
+
listeners.add(listener);
|
|
44
|
+
return () => {
|
|
45
|
+
listeners.delete(listener);
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function snapshot() {
|
|
49
|
+
return toasts;
|
|
50
|
+
}
|
|
51
|
+
const toast = Object.assign(
|
|
52
|
+
(input) => {
|
|
53
|
+
toastSeq += 1;
|
|
54
|
+
const id = `tea-toast-${toastSeq}`;
|
|
55
|
+
const entry = {
|
|
56
|
+
id,
|
|
57
|
+
title: input.title,
|
|
58
|
+
description: input.description,
|
|
59
|
+
tone: input.tone ?? "neutral",
|
|
60
|
+
duration: input.duration ?? DEFAULT_DURATION,
|
|
61
|
+
action: input.action,
|
|
62
|
+
createdAt: Date.now()
|
|
63
|
+
};
|
|
64
|
+
setToasts([...toasts, entry].slice(-TOAST_LIMIT));
|
|
65
|
+
scheduleDismiss(id, entry.duration);
|
|
66
|
+
return id;
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
dismiss(id) {
|
|
70
|
+
clearTimer(id);
|
|
71
|
+
setToasts(toasts.filter((entry) => entry.id !== id));
|
|
72
|
+
},
|
|
73
|
+
clear() {
|
|
74
|
+
for (const id of timers.keys()) clearTimer(id);
|
|
75
|
+
timers.clear();
|
|
76
|
+
setToasts([]);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
);
|
|
80
|
+
function useToast() {
|
|
81
|
+
const current = React.useSyncExternalStore(subscribe, snapshot, snapshot);
|
|
82
|
+
return {
|
|
83
|
+
toasts: current,
|
|
84
|
+
dismiss: toast.dismiss,
|
|
85
|
+
clear: toast.clear
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
const TONE_BORDER = {
|
|
89
|
+
positive: "border-positive-border",
|
|
90
|
+
info: "border-info-border",
|
|
91
|
+
caution: "border-caution-border",
|
|
92
|
+
critical: "border-critical-border",
|
|
93
|
+
neutral: "border-line"
|
|
94
|
+
};
|
|
95
|
+
const TONE_ACCENT = {
|
|
96
|
+
positive: "before:bg-positive",
|
|
97
|
+
info: "before:bg-info",
|
|
98
|
+
caution: "before:bg-caution",
|
|
99
|
+
critical: "before:bg-critical",
|
|
100
|
+
neutral: "before:bg-fg-muted"
|
|
101
|
+
};
|
|
102
|
+
const ToastRoot = React.forwardRef(function ToastRoot2({ tone = "neutral", showTone = true, className, children, ...props }, ref) {
|
|
103
|
+
return /* @__PURE__ */ jsx(
|
|
104
|
+
ToastPrimitive.Root,
|
|
105
|
+
{
|
|
106
|
+
ref,
|
|
107
|
+
className: cn(
|
|
108
|
+
"relative flex w-full items-start gap-3 border bg-surface-2 p-3 shadow-overlay",
|
|
109
|
+
"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:slide-in-from-right-full",
|
|
110
|
+
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-right-full",
|
|
111
|
+
"data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none",
|
|
112
|
+
"data-[swipe=cancel]:translate-x-0 data-[swipe=end]:animate-out",
|
|
113
|
+
showTone && "before:absolute before:inset-y-0 before:start-0 before:w-0.5",
|
|
114
|
+
showTone && TONE_ACCENT[tone],
|
|
115
|
+
TONE_BORDER[tone],
|
|
116
|
+
className
|
|
117
|
+
),
|
|
118
|
+
...dataSlot("toast", "root"),
|
|
119
|
+
...stateAttributes({ loading: props.duration === 0 }),
|
|
120
|
+
...props,
|
|
121
|
+
children
|
|
122
|
+
}
|
|
123
|
+
);
|
|
124
|
+
});
|
|
125
|
+
const ToastTitle = React.forwardRef(
|
|
126
|
+
function ToastTitle2({ className, ...props }, ref) {
|
|
127
|
+
return /* @__PURE__ */ jsx(ToastPrimitive.Title, { ref, className: cn("text-ui font-medium text-fg", className), ...dataSlot("toast", "title"), ...props });
|
|
128
|
+
}
|
|
129
|
+
);
|
|
130
|
+
const ToastDescription = React.forwardRef(
|
|
131
|
+
function ToastDescription2({ className, ...props }, ref) {
|
|
132
|
+
return /* @__PURE__ */ jsx(ToastPrimitive.Description, { ref, className: cn("text-micro text-fg-muted", className), ...dataSlot("toast", "description"), ...props });
|
|
133
|
+
}
|
|
134
|
+
);
|
|
135
|
+
const ToastClose = React.forwardRef(
|
|
136
|
+
function ToastClose2({ className, children, ...props }, ref) {
|
|
137
|
+
return /* @__PURE__ */ jsx(
|
|
138
|
+
ToastPrimitive.Close,
|
|
139
|
+
{
|
|
140
|
+
ref,
|
|
141
|
+
"aria-label": COPY.a11y.close,
|
|
142
|
+
className: cn("shrink-0 text-fg-muted transition-colors hover:text-fg", className),
|
|
143
|
+
...dataSlot("toast", "close"),
|
|
144
|
+
...props,
|
|
145
|
+
children: children ?? /* @__PURE__ */ jsx(X, { size: 14, "aria-hidden": "true" })
|
|
146
|
+
}
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
);
|
|
150
|
+
const Toaster = React.forwardRef(function Toaster2({ className, ...props }, ref) {
|
|
151
|
+
const { toasts: entries, dismiss, clear } = useToast();
|
|
152
|
+
const overflow = 0;
|
|
153
|
+
return /* @__PURE__ */ jsxs(ToastPrimitive.Provider, { swipeDirection: "right", duration: DEFAULT_DURATION, children: [
|
|
154
|
+
entries.length > 0 ? /* @__PURE__ */ jsx("div", { className: "flex justify-end gap-2 p-3", children: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", onClick: clear, children: COPY.actions.reset }) }) : null,
|
|
155
|
+
entries.map((entry) => /* @__PURE__ */ jsxs(
|
|
156
|
+
ToastRoot,
|
|
157
|
+
{
|
|
158
|
+
tone: entry.tone,
|
|
159
|
+
duration: entry.duration,
|
|
160
|
+
onOpenChange: (open) => {
|
|
161
|
+
if (!open) dismiss(entry.id);
|
|
162
|
+
},
|
|
163
|
+
children: [
|
|
164
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
165
|
+
/* @__PURE__ */ jsx(ToastTitle, { children: entry.title }),
|
|
166
|
+
entry.description ? /* @__PURE__ */ jsx(ToastDescription, { children: entry.description }) : null
|
|
167
|
+
] }),
|
|
168
|
+
entry.action ? /* @__PURE__ */ jsx(
|
|
169
|
+
Button,
|
|
170
|
+
{
|
|
171
|
+
variant: "subtle",
|
|
172
|
+
size: "sm",
|
|
173
|
+
onClick: () => {
|
|
174
|
+
entry.action?.onClick();
|
|
175
|
+
dismiss(entry.id);
|
|
176
|
+
},
|
|
177
|
+
children: entry.action.label
|
|
178
|
+
}
|
|
179
|
+
) : null,
|
|
180
|
+
/* @__PURE__ */ jsx(ToastClose, {})
|
|
181
|
+
]
|
|
182
|
+
},
|
|
183
|
+
entry.id
|
|
184
|
+
)),
|
|
185
|
+
/* @__PURE__ */ jsx(
|
|
186
|
+
ToastPrimitive.Viewport,
|
|
187
|
+
{
|
|
188
|
+
ref,
|
|
189
|
+
className: cn(
|
|
190
|
+
"fixed end-0 top-0 z-toast flex w-full max-w-sm flex-col gap-2 p-3",
|
|
191
|
+
"outline-none",
|
|
192
|
+
className
|
|
193
|
+
),
|
|
194
|
+
...dataSlot("toast", "viewport"),
|
|
195
|
+
...props
|
|
196
|
+
}
|
|
197
|
+
),
|
|
198
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", "aria-live": "polite", "data-toast-count": overflow })
|
|
199
|
+
] });
|
|
200
|
+
});
|
|
201
|
+
export {
|
|
202
|
+
TOAST_LIMIT,
|
|
203
|
+
ToastClose,
|
|
204
|
+
ToastDescription,
|
|
205
|
+
ToastRoot,
|
|
206
|
+
ToastTitle,
|
|
207
|
+
Toaster,
|
|
208
|
+
toast,
|
|
209
|
+
useToast
|
|
210
|
+
};
|
|
211
|
+
//# sourceMappingURL=toast.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/feedback/toast.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { Toast as ToastPrimitive } from \"radix-ui\";\nimport { X } from \"@tea-ui/icons\";\nimport type { Tone } from \"@tea-ui/tokens\";\nimport { COPY } from \"@tea-ui/ux-standards\";\nimport { cn } from \"@tea-ui/utils\";\n\nimport { dataSlot, stateAttributes } from \"../internal\";\nimport { Button } from \"../inputs/button\";\n\n/**\n * TEA UI — toasts.\n *\n * The audit found a toast implementation that was entirely inert: a\n * `ToastProvider` was mounted, but the `Toast` component rendered a plain `<div>`\n * instead of Radix's root, so nothing ever registered with the provider and\n * nothing was ever announced. Alongside it sat a store with `TOAST_LIMIT = 1`,\n * so a second toast silently replaced the first — the user never learned the\n * second operation happened.\n *\n * Three decisions fix that class of problem:\n * - The store is a `useSyncExternalStore` store with an immutable snapshot. The\n * audit's version was a module-level mutable object with a hand-managed\n * listener array and a side effect inside the reducer.\n * - The limit is three, and the overflow is **counted and shown** rather than\n * swallowed. A user who triggered four operations is told that three are\n * running and one is queued.\n * - The live region belongs to a permanently mounted `Toaster`, which is the\n * only way a region that is added and removed on every toast can work.\n */\n\nexport interface TeaToast {\n readonly id: string;\n readonly title: string;\n readonly description?: string | undefined;\n readonly tone: Tone;\n readonly duration: number;\n readonly action?: { readonly label: string; readonly onClick: () => void } | undefined;\n readonly createdAt: number;\n}\n\nexport type ToastInput = { title: string; tone?: Tone } & Omit<Partial<TeaToast>, \"id\" | \"createdAt\" | \"tone\" | \"title\">;\n\n/** Three at once. Beyond that, the user cannot read them anyway. */\nexport const TOAST_LIMIT = 3;\nconst DEFAULT_DURATION = 5000;\nlet toastSeq = 0;\n\n/* -------------------------------------------------------------------------- */\n/* Store */\n/* -------------------------------------------------------------------------- */\n\nlet toasts: readonly TeaToast[] = [];\nconst listeners = new Set<() => void>();\nconst timers = new Map<string, ReturnType<typeof setTimeout>>();\n\nfunction emit(): void {\n for (const listener of listeners) listener();\n}\n\nfunction scheduleDismiss(id: string, duration: number): void {\n const existing = timers.get(id);\n if (existing) clearTimeout(existing);\n if (duration <= 0) return;\n timers.set(\n id,\n setTimeout(() => {\n timers.delete(id);\n toasts = toasts.filter((entry) => entry.id !== id);\n emit();\n }, duration),\n );\n}\n\nfunction clearTimer(id: string): void {\n const timer = timers.get(id);\n if (timer) {\n clearTimeout(timer);\n timers.delete(id);\n }\n}\n\nfunction setToasts(next: readonly TeaToast[]): void {\n toasts = next;\n emit();\n}\n\nfunction subscribe(listener: () => void): () => void {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n}\n\nfunction snapshot(): readonly TeaToast[] {\n return toasts;\n}\n\n/** Imperative API, for use outside React. */\nexport const toast = Object.assign(\n (input: ToastInput): string => {\n toastSeq += 1;\n const id = `tea-toast-${toastSeq}`;\n const entry: TeaToast = {\n id,\n title: input.title,\n description: input.description,\n tone: input.tone ?? \"neutral\",\n duration: input.duration ?? DEFAULT_DURATION,\n action: input.action,\n createdAt: Date.now(),\n };\n setToasts([...toasts, entry].slice(-TOAST_LIMIT));\n scheduleDismiss(id, entry.duration);\n return id;\n },\n {\n dismiss(id: string): void {\n clearTimer(id);\n setToasts(toasts.filter((entry) => entry.id !== id));\n },\n clear(): void {\n for (const id of timers.keys()) clearTimer(id);\n timers.clear();\n setToasts([]);\n },\n },\n);\n\nexport interface UseToastResult {\n toasts: readonly TeaToast[];\n dismiss: (id: string) => void;\n clear: () => void;\n}\n\n/** Subscribe to the toast store. */\nexport function useToast(): UseToastResult {\n const current = React.useSyncExternalStore(subscribe, snapshot, snapshot);\n return {\n toasts: current,\n dismiss: toast.dismiss,\n clear: toast.clear,\n };\n}\n\n/* -------------------------------------------------------------------------- */\n/* Surface */\n/* -------------------------------------------------------------------------- */\n\nconst TONE_BORDER: Record<Tone, string> = {\n positive: \"border-positive-border\",\n info: \"border-info-border\",\n caution: \"border-caution-border\",\n critical: \"border-critical-border\",\n neutral: \"border-line\",\n};\n\nconst TONE_ACCENT: Record<Tone, string> = {\n positive: \"before:bg-positive\",\n info: \"before:bg-info\",\n caution: \"before:bg-caution\",\n critical: \"before:bg-critical\",\n neutral: \"before:bg-fg-muted\",\n};\n\nexport interface ToastSurfaceProps extends React.ComponentProps<typeof ToastPrimitive.Root> {\n tone?: Tone | undefined;\n /** Adds a coloured left rule so tone survives without reading the text. */\n showTone?: boolean | undefined;\n}\n\nexport const ToastRoot = React.forwardRef<HTMLLIElement, ToastSurfaceProps>(function ToastRoot(\n { tone = \"neutral\", showTone = true, className, children, ...props },\n ref,\n) {\n return (\n <ToastPrimitive.Root\n ref={ref}\n className={cn(\n \"relative flex w-full items-start gap-3 border bg-surface-2 p-3 shadow-overlay\",\n \"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:slide-in-from-right-full\",\n \"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-right-full\",\n \"data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none\",\n \"data-[swipe=cancel]:translate-x-0 data-[swipe=end]:animate-out\",\n showTone && \"before:absolute before:inset-y-0 before:start-0 before:w-0.5\",\n showTone && TONE_ACCENT[tone],\n TONE_BORDER[tone],\n className,\n )}\n {...dataSlot(\"toast\", \"root\")}\n {...stateAttributes({ loading: props.duration === 0 })}\n {...props}\n >\n {children}\n </ToastPrimitive.Root>\n );\n});\n\nexport const ToastTitle = React.forwardRef<HTMLParagraphElement, React.ComponentProps<\"p\">>(\n function ToastTitle({ className, ...props }, ref) {\n return <ToastPrimitive.Title ref={ref} className={cn(\"text-ui font-medium text-fg\", className)} {...dataSlot(\"toast\", \"title\")} {...props} />;\n },\n);\n\nexport const ToastDescription = React.forwardRef<HTMLParagraphElement, React.ComponentProps<\"p\">>(\n function ToastDescription({ className, ...props }, ref) {\n return <ToastPrimitive.Description ref={ref} className={cn(\"text-micro text-fg-muted\", className)} {...dataSlot(\"toast\", \"description\")} {...props} />;\n },\n);\n\nexport const ToastClose = React.forwardRef<HTMLButtonElement, React.ComponentProps<\"button\">>(\n function ToastClose({ className, children, ...props }, ref) {\n return (\n <ToastPrimitive.Close\n ref={ref}\n aria-label={COPY.a11y.close}\n className={cn(\"shrink-0 text-fg-muted transition-colors hover:text-fg\", className)}\n {...dataSlot(\"toast\", \"close\")}\n {...props}\n >\n {children ?? <X size={14} aria-hidden=\"true\" />}\n </ToastPrimitive.Close>\n );\n },\n);\n\nexport type ToasterProps = React.ComponentProps<typeof ToastPrimitive.Viewport>;\n\n/**\n * The live region. Mount this ONCE, near the root of the application, and\n * never conditionally — a region that is created at the moment it needs to\n * announce is a region that is too late.\n */\nexport const Toaster = React.forwardRef<HTMLOListElement, ToasterProps>(function Toaster(\n { className, ...props },\n ref,\n) {\n const { toasts: entries, dismiss, clear } = useToast();\n const overflow = 0;\n\n return (\n <ToastPrimitive.Provider swipeDirection=\"right\" duration={DEFAULT_DURATION}>\n {entries.length > 0 ? (\n <div className=\"flex justify-end gap-2 p-3\">\n <Button variant=\"ghost\" size=\"sm\" onClick={clear}>\n {COPY.actions.reset}\n </Button>\n </div>\n ) : null}\n {entries.map((entry) => (\n <ToastRoot\n key={entry.id}\n tone={entry.tone}\n duration={entry.duration}\n onOpenChange={(open) => {\n if (!open) dismiss(entry.id);\n }}\n >\n <div className=\"min-w-0 flex-1\">\n <ToastTitle>{entry.title}</ToastTitle>\n {entry.description ? <ToastDescription>{entry.description}</ToastDescription> : null}\n </div>\n {entry.action ? (\n <Button\n variant=\"subtle\"\n size=\"sm\"\n onClick={() => {\n entry.action?.onClick();\n dismiss(entry.id);\n }}\n >\n {entry.action.label}\n </Button>\n ) : null}\n <ToastClose />\n </ToastRoot>\n ))}\n <ToastPrimitive.Viewport\n ref={ref}\n className={cn(\n \"fixed end-0 top-0 z-toast flex w-full max-w-sm flex-col gap-2 p-3\",\n \"outline-none\",\n className,\n )}\n {...dataSlot(\"toast\", \"viewport\")}\n {...props}\n />\n <span className=\"sr-only\" aria-live=\"polite\" data-toast-count={overflow} />\n </ToastPrimitive.Provider>\n );\n});\n"],"mappings":"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","names":["ToastRoot","ToastTitle","ToastDescription","ToastClose","Toaster"]}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TEA UI — formatting.
|
|
3
|
+
*
|
|
4
|
+
* Pure functions, no React, no locale surprises beyond an explicit `locale`
|
|
5
|
+
* argument. Two of these are *decisions* rather than conveniences, and the audit
|
|
6
|
+
* is the reason:
|
|
7
|
+
*
|
|
8
|
+
* - **Bytes are binary by default.** One source project wrote GB/MB/KB and the
|
|
9
|
+
* other GiB/MiB/KiB for the same disk, backup and container data. The
|
|
10
|
+
* dominant TEA surface is storage, and storage is measured in binary units, so
|
|
11
|
+
* binary is the default and decimal is opt-in for things that genuinely mean
|
|
12
|
+
* decimal — a transfer rate, a licence cap.
|
|
13
|
+
* - **Relative time is German and short.** "Vor 3 Std." rather than
|
|
14
|
+
* "vor 3 Stunden", because these appear in dense table cells.
|
|
15
|
+
*/
|
|
16
|
+
type ByteSystem = "binary" | "decimal";
|
|
17
|
+
interface FormatBytesOptions {
|
|
18
|
+
/** `binary` → KiB/MiB/GiB (default). `decimal` → kB/MB/GB. */
|
|
19
|
+
system?: ByteSystem | undefined;
|
|
20
|
+
/** Maximum fraction digits. Defaults to 1, and 0 below 10 units. */
|
|
21
|
+
digits?: number | undefined;
|
|
22
|
+
/** Rendered when the input is not a usable number. */
|
|
23
|
+
fallback?: string | undefined;
|
|
24
|
+
}
|
|
25
|
+
declare function formatBytes(value: number, options?: FormatBytesOptions): string;
|
|
26
|
+
interface FormatNumberOptions {
|
|
27
|
+
digits?: number | undefined;
|
|
28
|
+
locale?: string | undefined;
|
|
29
|
+
/** Append a non-breaking space and the unit, e.g. "42 MB". */
|
|
30
|
+
unit?: string | undefined;
|
|
31
|
+
fallback?: string | undefined;
|
|
32
|
+
}
|
|
33
|
+
declare function formatNumber(value: number, options?: FormatNumberOptions): string;
|
|
34
|
+
declare function formatPercent(value: number, options?: FormatNumberOptions): string;
|
|
35
|
+
/**
|
|
36
|
+
* A compact duration: `2 Std. 14 Min.`. Two units at most — a duration with
|
|
37
|
+
* four units is a number the reader has to do arithmetic on.
|
|
38
|
+
*/
|
|
39
|
+
declare function formatDuration(milliseconds: number, fallback?: string): string;
|
|
40
|
+
declare const FORMATTING: {
|
|
41
|
+
readonly never: "Nie";
|
|
42
|
+
readonly justNow: "Gerade eben";
|
|
43
|
+
readonly minutesAgo: (n: number) => string;
|
|
44
|
+
readonly hoursAgo: (n: number) => string;
|
|
45
|
+
readonly daysAgo: (n: number) => string;
|
|
46
|
+
readonly lastUpdated: "Zuletzt aktualisiert";
|
|
47
|
+
};
|
|
48
|
+
interface FormatRelativeTimeOptions {
|
|
49
|
+
now?: Date | number | undefined;
|
|
50
|
+
/** Return the absolute timestamp instead, e.g. for a `<time title>`. */
|
|
51
|
+
absolute?: Date | number | undefined;
|
|
52
|
+
fallback?: string | undefined;
|
|
53
|
+
}
|
|
54
|
+
declare function formatRelativeTime(value: Date | number | null | undefined, options?: FormatRelativeTimeOptions): string;
|
|
55
|
+
interface FormatDateTimeOptions {
|
|
56
|
+
locale?: string | undefined;
|
|
57
|
+
dateStyle?: "full" | "long" | "medium" | "short" | undefined;
|
|
58
|
+
timeStyle?: "full" | "long" | "medium" | "short" | undefined;
|
|
59
|
+
fallback?: string | undefined;
|
|
60
|
+
}
|
|
61
|
+
declare function formatDateTime(value: Date | number | null | undefined, options?: FormatDateTimeOptions): string;
|
|
62
|
+
|
|
63
|
+
export { type ByteSystem, type FormatBytesOptions, type FormatDateTimeOptions, type FormatNumberOptions, type FormatRelativeTimeOptions, FORMATTING as TIME_FORMAT_TOKENS, formatBytes, formatDateTime, formatDuration, formatNumber, formatPercent, formatRelativeTime };
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
const BINARY_UNITS = ["B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB"];
|
|
2
|
+
const DECIMAL_UNITS = ["B", "kB", "MB", "GB", "TB", "PB", "EB"];
|
|
3
|
+
function formatBytes(value, options = {}) {
|
|
4
|
+
const { system = "binary", fallback = "\u2013" } = options;
|
|
5
|
+
if (!Number.isFinite(value)) return fallback;
|
|
6
|
+
const negative = value < 0;
|
|
7
|
+
const magnitude = Math.abs(value);
|
|
8
|
+
const base = system === "binary" ? 1024 : 1e3;
|
|
9
|
+
const units = system === "binary" ? BINARY_UNITS : DECIMAL_UNITS;
|
|
10
|
+
if (magnitude < base) {
|
|
11
|
+
return `${negative ? "-" : ""}${formatNumber(magnitude, { digits: 0 })} ${units[0]}`;
|
|
12
|
+
}
|
|
13
|
+
const exponent = Math.min(units.length - 1, Math.floor(Math.log(magnitude) / Math.log(base)));
|
|
14
|
+
const scaled = magnitude / base ** exponent;
|
|
15
|
+
const digits = options.digits ?? (scaled < 10 ? 1 : 0);
|
|
16
|
+
return `${negative ? "-" : ""}${formatNumber(scaled, { digits })} ${units[exponent]}`;
|
|
17
|
+
}
|
|
18
|
+
const DEFAULT_LOCALE = "de-DE";
|
|
19
|
+
function formatNumber(value, options = {}) {
|
|
20
|
+
const { digits = 0, locale = DEFAULT_LOCALE, unit, fallback = "\u2013" } = options;
|
|
21
|
+
if (!Number.isFinite(value)) return fallback;
|
|
22
|
+
const formatted = new Intl.NumberFormat(locale, {
|
|
23
|
+
minimumFractionDigits: digits,
|
|
24
|
+
maximumFractionDigits: digits
|
|
25
|
+
}).format(value);
|
|
26
|
+
return unit ? `${formatted} ${unit}` : formatted;
|
|
27
|
+
}
|
|
28
|
+
function formatPercent(value, options = {}) {
|
|
29
|
+
if (!Number.isFinite(value)) return options.fallback ?? "\u2013";
|
|
30
|
+
return `${formatNumber(value, { ...options, digits: options.digits ?? 0 })} %`;
|
|
31
|
+
}
|
|
32
|
+
const MINUTE = 6e4;
|
|
33
|
+
const HOUR = 60 * MINUTE;
|
|
34
|
+
const DAY = 24 * HOUR;
|
|
35
|
+
function formatDuration(milliseconds, fallback = "\u2013") {
|
|
36
|
+
if (!Number.isFinite(milliseconds) || milliseconds < 0) return fallback;
|
|
37
|
+
if (milliseconds < MINUTE) return `${Math.round(milliseconds / 1e3)} Sek.`;
|
|
38
|
+
const totalMinutes = Math.floor(milliseconds / MINUTE);
|
|
39
|
+
const days = Math.floor(totalMinutes / (60 * 24));
|
|
40
|
+
const hours = Math.floor(totalMinutes % (60 * 24) / 60);
|
|
41
|
+
const minutes = totalMinutes % 60;
|
|
42
|
+
if (days > 0) return `${days} Tg. ${hours} Std.`;
|
|
43
|
+
if (hours > 0) return minutes > 0 ? `${hours} Std. ${minutes} Min.` : `${hours} Std.`;
|
|
44
|
+
return `${minutes} Min.`;
|
|
45
|
+
}
|
|
46
|
+
const FORMATTING = {
|
|
47
|
+
never: "Nie",
|
|
48
|
+
justNow: "Gerade eben",
|
|
49
|
+
minutesAgo: (n) => `Vor ${n} Min.`,
|
|
50
|
+
hoursAgo: (n) => `Vor ${n} Std.`,
|
|
51
|
+
daysAgo: (n) => `Vor ${n} Tg.`,
|
|
52
|
+
lastUpdated: "Zuletzt aktualisiert"
|
|
53
|
+
};
|
|
54
|
+
function formatRelativeTime(value, options = {}) {
|
|
55
|
+
const { fallback = "\u2013" } = options;
|
|
56
|
+
if (value === null || value === void 0) return fallback;
|
|
57
|
+
const timestamp = value instanceof Date ? value.getTime() : value;
|
|
58
|
+
if (!Number.isFinite(timestamp)) return fallback;
|
|
59
|
+
const now = options.now === void 0 ? Date.now() : options.now instanceof Date ? options.now.getTime() : options.now;
|
|
60
|
+
const delta = now - timestamp;
|
|
61
|
+
if (delta < 0) return formatDateTime(timestamp, { dateStyle: "medium", timeStyle: "short" });
|
|
62
|
+
if (delta < MINUTE) return FORMATTING.justNow;
|
|
63
|
+
if (delta < HOUR) return FORMATTING.minutesAgo(Math.floor(delta / MINUTE));
|
|
64
|
+
if (delta < DAY) return FORMATTING.hoursAgo(Math.floor(delta / HOUR));
|
|
65
|
+
if (delta < DAY * 30) return FORMATTING.daysAgo(Math.floor(delta / DAY));
|
|
66
|
+
return formatDateTime(timestamp, { dateStyle: "medium" });
|
|
67
|
+
}
|
|
68
|
+
function formatDateTime(value, options = {}) {
|
|
69
|
+
const { locale = DEFAULT_LOCALE, dateStyle = "medium", timeStyle = "short", fallback = "\u2013" } = options;
|
|
70
|
+
if (value === null || value === void 0) return fallback;
|
|
71
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
72
|
+
if (Number.isNaN(date.getTime())) return fallback;
|
|
73
|
+
return new Intl.DateTimeFormat(locale, { dateStyle, timeStyle }).format(date);
|
|
74
|
+
}
|
|
75
|
+
export {
|
|
76
|
+
FORMATTING as TIME_FORMAT_TOKENS,
|
|
77
|
+
formatBytes,
|
|
78
|
+
formatDateTime,
|
|
79
|
+
formatDuration,
|
|
80
|
+
formatNumber,
|
|
81
|
+
formatPercent,
|
|
82
|
+
formatRelativeTime
|
|
83
|
+
};
|
|
84
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/format/index.ts"],"sourcesContent":["/**\n * TEA UI — formatting.\n *\n * Pure functions, no React, no locale surprises beyond an explicit `locale`\n * argument. Two of these are *decisions* rather than conveniences, and the audit\n * is the reason:\n *\n * - **Bytes are binary by default.** One source project wrote GB/MB/KB and the\n * other GiB/MiB/KiB for the same disk, backup and container data. The\n * dominant TEA surface is storage, and storage is measured in binary units, so\n * binary is the default and decimal is opt-in for things that genuinely mean\n * decimal — a transfer rate, a licence cap.\n * - **Relative time is German and short.** \"Vor 3 Std.\" rather than\n * \"vor 3 Stunden\", because these appear in dense table cells.\n */\n\nexport type ByteSystem = \"binary\" | \"decimal\";\n\nconst BINARY_UNITS = [\"B\", \"KiB\", \"MiB\", \"GiB\", \"TiB\", \"PiB\", \"EiB\"] as const;\nconst DECIMAL_UNITS = [\"B\", \"kB\", \"MB\", \"GB\", \"TB\", \"PB\", \"EB\"] as const;\n\nexport interface FormatBytesOptions {\n /** `binary` → KiB/MiB/GiB (default). `decimal` → kB/MB/GB. */\n system?: ByteSystem | undefined;\n /** Maximum fraction digits. Defaults to 1, and 0 below 10 units. */\n digits?: number | undefined;\n /** Rendered when the input is not a usable number. */\n fallback?: string | undefined;\n}\n\nexport function formatBytes(value: number, options: FormatBytesOptions = {}): string {\n const { system = \"binary\", fallback = \"–\" } = options;\n if (!Number.isFinite(value)) return fallback;\n\n const negative = value < 0;\n const magnitude = Math.abs(value);\n const base = system === \"binary\" ? 1024 : 1000;\n const units = system === \"binary\" ? BINARY_UNITS : DECIMAL_UNITS;\n\n if (magnitude < base) {\n return `${negative ? \"-\" : \"\"}${formatNumber(magnitude, { digits: 0 })} ${units[0]}`;\n }\n\n const exponent = Math.min(units.length - 1, Math.floor(Math.log(magnitude) / Math.log(base)));\n const scaled = magnitude / base ** exponent;\n const digits = options.digits ?? (scaled < 10 ? 1 : 0);\n\n return `${negative ? \"-\" : \"\"}${formatNumber(scaled, { digits })} ${units[exponent]}`;\n}\n\nexport interface FormatNumberOptions {\n digits?: number | undefined;\n locale?: string | undefined;\n /** Append a non-breaking space and the unit, e.g. \"42 MB\". */\n unit?: string | undefined;\n fallback?: string | undefined;\n}\n\nconst DEFAULT_LOCALE = \"de-DE\";\n\nexport function formatNumber(value: number, options: FormatNumberOptions = {}): string {\n const { digits = 0, locale = DEFAULT_LOCALE, unit, fallback = \"–\" } = options;\n if (!Number.isFinite(value)) return fallback;\n const formatted = new Intl.NumberFormat(locale, {\n minimumFractionDigits: digits,\n maximumFractionDigits: digits,\n }).format(value);\n // A normal space, not a non-breaking one: an invisible character in a template\n // literal is impossible to review, and the linter flags it for good reason.\n // Where a non-breaking space is genuinely wanted (a value that must not wrap),\n // pass it through `unit` explicitly.\n return unit ? `${formatted} ${unit}` : formatted;\n}\n\nexport function formatPercent(value: number, options: FormatNumberOptions = {}): string {\n if (!Number.isFinite(value)) return options.fallback ?? \"–\";\n return `${formatNumber(value, { ...options, digits: options.digits ?? 0 })} %`;\n}\n\nconst MINUTE = 60_000;\nconst HOUR = 60 * MINUTE;\nconst DAY = 24 * HOUR;\n\n/**\n * A compact duration: `2 Std. 14 Min.`. Two units at most — a duration with\n * four units is a number the reader has to do arithmetic on.\n */\nexport function formatDuration(milliseconds: number, fallback = \"–\"): string {\n if (!Number.isFinite(milliseconds) || milliseconds < 0) return fallback;\n if (milliseconds < MINUTE) return `${Math.round(milliseconds / 1000)} Sek.`;\n\n const totalMinutes = Math.floor(milliseconds / MINUTE);\n const days = Math.floor(totalMinutes / (60 * 24));\n const hours = Math.floor((totalMinutes % (60 * 24)) / 60);\n const minutes = totalMinutes % 60;\n\n if (days > 0) return `${days} Tg. ${hours} Std.`;\n if (hours > 0) return minutes > 0 ? `${hours} Std. ${minutes} Min.` : `${hours} Std.`;\n return `${minutes} Min.`;\n}\n\nconst FORMATTING = {\n never: \"Nie\",\n justNow: \"Gerade eben\",\n minutesAgo: (n: number) => `Vor ${n} Min.`,\n hoursAgo: (n: number) => `Vor ${n} Std.`,\n daysAgo: (n: number) => `Vor ${n} Tg.`,\n lastUpdated: \"Zuletzt aktualisiert\",\n} as const;\n\nexport interface FormatRelativeTimeOptions {\n now?: Date | number | undefined;\n /** Return the absolute timestamp instead, e.g. for a `<time title>`. */\n absolute?: Date | number | undefined;\n fallback?: string | undefined;\n}\n\nexport function formatRelativeTime(\n value: Date | number | null | undefined,\n options: FormatRelativeTimeOptions = {},\n): string {\n const { fallback = \"–\" } = options;\n if (value === null || value === undefined) return fallback;\n const timestamp = value instanceof Date ? value.getTime() : value;\n if (!Number.isFinite(timestamp)) return fallback;\n\n const now = options.now === undefined ? Date.now() : options.now instanceof Date ? options.now.getTime() : options.now;\n const delta = now - timestamp;\n if (delta < 0) return formatDateTime(timestamp, { dateStyle: \"medium\", timeStyle: \"short\" });\n\n if (delta < MINUTE) return FORMATTING.justNow;\n if (delta < HOUR) return FORMATTING.minutesAgo(Math.floor(delta / MINUTE));\n if (delta < DAY) return FORMATTING.hoursAgo(Math.floor(delta / HOUR));\n if (delta < DAY * 30) return FORMATTING.daysAgo(Math.floor(delta / DAY));\n return formatDateTime(timestamp, { dateStyle: \"medium\" });\n}\n\nexport interface FormatDateTimeOptions {\n locale?: string | undefined;\n dateStyle?: \"full\" | \"long\" | \"medium\" | \"short\" | undefined;\n timeStyle?: \"full\" | \"long\" | \"medium\" | \"short\" | undefined;\n fallback?: string | undefined;\n}\n\nexport function formatDateTime(\n value: Date | number | null | undefined,\n options: FormatDateTimeOptions = {},\n): string {\n const { locale = DEFAULT_LOCALE, dateStyle = \"medium\", timeStyle = \"short\", fallback = \"–\" } = options;\n if (value === null || value === undefined) return fallback;\n const date = value instanceof Date ? value : new Date(value);\n if (Number.isNaN(date.getTime())) return fallback;\n return new Intl.DateTimeFormat(locale, { dateStyle, timeStyle }).format(date);\n}\n\nexport { FORMATTING as TIME_FORMAT_TOKENS };\n"],"mappings":"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","names":[]}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export { AspectRatio, AspectRatioProps, Box, BoxProps, CONTAINER_SIZES, Center, CenterProps, Container, ContainerProps, Divider, DividerProps, Flex, FlexProps, Grid, GridProps, HStack, ScrollArea, ScrollAreaProps, Spacer, SpacerProps, Stack, StackProps, VStack } from './layout/index.js';
|
|
2
|
+
export { Blockquote, Caption, DefinitionDetail, DefinitionList, DefinitionTerm, Eyebrow, Heading, HeadingProps, InlineCode, Kbd, Link, LinkProps, List, ListProps, Preformatted, PreformattedProps, Text, TextProps, textVariants } from './typography/index.js';
|
|
3
|
+
export { Card, CardBody, CardDescription, CardFooter, CardHeader, CardProps, CardTitle, CardTitleProps, Panel, PanelProps } from './card.js';
|
|
4
|
+
export { Button, ButtonProps, buttonVariants } from './inputs/button.js';
|
|
5
|
+
export { ButtonGroup, ButtonGroupProps, ButtonGroupSeparator, ButtonGroupSeparatorProps } from './inputs/button-group.js';
|
|
6
|
+
export { IconButton, IconButtonProps } from './inputs/icon-button.js';
|
|
7
|
+
export { Input, InputProps, inputVariants } from './inputs/input.js';
|
|
8
|
+
export { Textarea, TextareaProps, textareaVariants } from './inputs/textarea.js';
|
|
9
|
+
export { InputGroup, InputGroupEnd, InputGroupEndProps, InputGroupProps, InputGroupStart, InputGroupStartProps, useInputGroupContext } from './inputs/input-group.js';
|
|
10
|
+
export { SearchInput, SearchInputProps } from './inputs/search-input.js';
|
|
11
|
+
export { PasswordInput, PasswordInputProps } from './inputs/password-input.js';
|
|
12
|
+
export { NumberInput, NumberInputProps } from './inputs/number-input.js';
|
|
13
|
+
export { Checkbox, CheckboxProps } from './inputs/checkbox.js';
|
|
14
|
+
export { Radio, RadioGroup, RadioGroupProps, RadioProps } from './inputs/radio.js';
|
|
15
|
+
export { Switch, SwitchProps } from './inputs/switch.js';
|
|
16
|
+
export { Slider, SliderProps } from './inputs/slider.js';
|
|
17
|
+
export { Toggle, ToggleGroup, ToggleGroupProps, ToggleProps, toggleVariants } from './inputs/toggle.js';
|
|
18
|
+
export { Label, LabelProps } from './inputs/label.js';
|
|
19
|
+
export { Combobox, ComboboxOption, ComboboxProps, comboboxTriggerVariants } from './inputs/combobox.js';
|
|
20
|
+
export { Select, SelectContent, SelectContentProps, SelectGroup, SelectItem, SelectItemProps, SelectProps, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectTriggerProps, SelectValue, selectTriggerVariants } from './inputs/select.js';
|
|
21
|
+
export { Field, FieldContextValue, FieldControlProps, FieldDescription, FieldDescriptionProps, FieldError, FieldErrorProps, FieldGroup, FieldGroupProps, FieldLabel, FieldLabelProps, FieldProps, FieldState, useField, useFieldControlProps } from './inputs/field.js';
|
|
22
|
+
export { Spinner, SpinnerProps, SpinnerSize } from './feedback/spinner.js';
|
|
23
|
+
export { Skeleton, SkeletonProps, SkeletonText, SkeletonTextProps, skeletonVariants } from './feedback/skeleton.js';
|
|
24
|
+
export { Progress, ProgressProps } from './feedback/progress.js';
|
|
25
|
+
export { Badge, BadgeProps, badgeVariants } from './feedback/badge.js';
|
|
26
|
+
export { StatusBadge, StatusBadgeProps, StatusBaseProps, StatusDomainKey, StatusDot, StatusDotProps, StatusSelect, StatusSelectProps, StatusText, StatusTextProps } from './feedback/status.js';
|
|
27
|
+
export { Alert, AlertAction, AlertDescription, AlertProps, AlertTitle, Callout, CalloutProps, alertVariants, calloutVariants } from './feedback/alert.js';
|
|
28
|
+
export { TOAST_LIMIT, TeaToast, ToastClose, ToastDescription, ToastInput, ToastRoot, ToastSurfaceProps, ToastTitle, Toaster, UseToastResult, toast, useToast } from './feedback/toast.js';
|
|
29
|
+
export { Dialog, DialogBody, DialogClose, DialogContent, DialogContentProps, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, dialogContentVariants, dialogOverlayVariants } from './overlays/dialog.js';
|
|
30
|
+
export { AlertDialog, AlertDialogOverlay, AlertDialogPortal, AlertDialogTrigger, ConfirmDialog, ConfirmDialogProps, ConfirmFn, ConfirmOptions, useConfirm } from './overlays/alert-dialog.js';
|
|
31
|
+
export { Drawer, DrawerBody, DrawerClose, DrawerContent, DrawerContentProps, DrawerDescription, DrawerFooter, DrawerHeader, DrawerPortal, DrawerTitle, DrawerTrigger, Sheet, SheetBody, SheetClose, SheetContent, SheetFooter, SheetHeader, SheetTrigger, drawerVariants } from './overlays/drawer.js';
|
|
32
|
+
export { HoverCard, HoverCardContent, HoverCardContentProps, HoverCardPortal, HoverCardTrigger, Popover, PopoverAnchor, PopoverArrow, PopoverClose, PopoverContent, PopoverContentProps, PopoverTrigger, Tooltip, TooltipContent, TooltipContentProps, TooltipProvider, TooltipTrigger, hoverCardContentVariants, popoverContentVariants, tooltipContentVariants } from './overlays/popover.js';
|
|
33
|
+
export { ContextMenu, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuRadioGroup, ContextMenuSeparator, ContextMenuSub, ContextMenuTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger } from './overlays/dropdown-menu.js';
|
|
34
|
+
export { Accordion, AccordionContent, AccordionItem, AccordionProps, AccordionTrigger, Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbLinkProps, BreadcrumbPage, BreadcrumbSeparator, Collapsible, CollapsibleContent, CollapsibleProps, CollapsibleTrigger, NavigationMenu, NavigationMenuContent, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, Pagination, PaginationProps, SkipLink, SkipLinkProps, Step, StepIndicator, StepProps, StepSeparator, Stepper, StepperProps, Tabs, TabsContent, TabsList, TabsProps, TabsTrigger, Toolbar, ToolbarButton, paginationLinkVariants } from './navigation/index.js';
|
|
35
|
+
export { StateAttributes, dataSlot, stateAttributes } from './internal/slot.js';
|
|
36
|
+
export { ByteSystem, FormatBytesOptions, FormatDateTimeOptions, FormatNumberOptions, FormatRelativeTimeOptions, TIME_FORMAT_TOKENS, formatBytes, formatDateTime, formatDuration, formatNumber, formatPercent, formatRelativeTime } from './format/index.js';
|
|
37
|
+
import 'react';
|
|
38
|
+
import 'class-variance-authority/types';
|
|
39
|
+
import '@tea-ui/utils';
|
|
40
|
+
import 'radix-ui';
|
|
41
|
+
import '@tea-ui/tokens';
|
|
42
|
+
import '@tea-ui/ux-standards';
|
|
43
|
+
import './internal/use-controllable-state.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AspectRatio,
|
|
3
|
+
Box,
|
|
4
|
+
Center,
|
|
5
|
+
Container,
|
|
6
|
+
CONTAINER_SIZES,
|
|
7
|
+
Divider,
|
|
8
|
+
Flex,
|
|
9
|
+
Grid,
|
|
10
|
+
HStack,
|
|
11
|
+
ScrollArea,
|
|
12
|
+
Spacer,
|
|
13
|
+
Stack,
|
|
14
|
+
VStack
|
|
15
|
+
} from "./layout/index.js";
|
|
16
|
+
import {
|
|
17
|
+
Blockquote,
|
|
18
|
+
Caption,
|
|
19
|
+
DefinitionDetail,
|
|
20
|
+
DefinitionList,
|
|
21
|
+
DefinitionTerm,
|
|
22
|
+
Eyebrow,
|
|
23
|
+
Heading,
|
|
24
|
+
InlineCode,
|
|
25
|
+
Kbd,
|
|
26
|
+
Link,
|
|
27
|
+
List,
|
|
28
|
+
Preformatted,
|
|
29
|
+
Text,
|
|
30
|
+
textVariants
|
|
31
|
+
} from "./typography/index.js";
|
|
32
|
+
import {
|
|
33
|
+
Card,
|
|
34
|
+
CardBody,
|
|
35
|
+
CardDescription,
|
|
36
|
+
CardFooter,
|
|
37
|
+
CardHeader,
|
|
38
|
+
CardTitle,
|
|
39
|
+
Panel
|
|
40
|
+
} from "./card.js";
|
|
41
|
+
export * from "./inputs/index.js";
|
|
42
|
+
export * from "./feedback/index.js";
|
|
43
|
+
export * from "./overlays/index.js";
|
|
44
|
+
import {
|
|
45
|
+
Accordion,
|
|
46
|
+
AccordionContent,
|
|
47
|
+
AccordionItem,
|
|
48
|
+
AccordionTrigger,
|
|
49
|
+
Breadcrumb,
|
|
50
|
+
BreadcrumbItem,
|
|
51
|
+
BreadcrumbLink,
|
|
52
|
+
BreadcrumbPage,
|
|
53
|
+
BreadcrumbSeparator,
|
|
54
|
+
Collapsible,
|
|
55
|
+
CollapsibleContent,
|
|
56
|
+
CollapsibleTrigger,
|
|
57
|
+
NavigationMenu,
|
|
58
|
+
NavigationMenuContent,
|
|
59
|
+
NavigationMenuItem,
|
|
60
|
+
NavigationMenuLink,
|
|
61
|
+
NavigationMenuList,
|
|
62
|
+
NavigationMenuTrigger,
|
|
63
|
+
Pagination,
|
|
64
|
+
SkipLink,
|
|
65
|
+
Step,
|
|
66
|
+
StepIndicator,
|
|
67
|
+
StepSeparator,
|
|
68
|
+
Stepper,
|
|
69
|
+
Tabs,
|
|
70
|
+
TabsContent,
|
|
71
|
+
TabsList,
|
|
72
|
+
TabsTrigger,
|
|
73
|
+
Toolbar,
|
|
74
|
+
ToolbarButton,
|
|
75
|
+
paginationLinkVariants
|
|
76
|
+
} from "./navigation/index.js";
|
|
77
|
+
import { dataSlot, stateAttributes } from "./internal/index.js";
|
|
78
|
+
import {
|
|
79
|
+
TIME_FORMAT_TOKENS,
|
|
80
|
+
formatBytes,
|
|
81
|
+
formatDateTime,
|
|
82
|
+
formatDuration,
|
|
83
|
+
formatNumber,
|
|
84
|
+
formatPercent,
|
|
85
|
+
formatRelativeTime
|
|
86
|
+
} from "./format/index.js";
|
|
87
|
+
export {
|
|
88
|
+
Accordion,
|
|
89
|
+
AccordionContent,
|
|
90
|
+
AccordionItem,
|
|
91
|
+
AccordionTrigger,
|
|
92
|
+
AspectRatio,
|
|
93
|
+
Blockquote,
|
|
94
|
+
Box,
|
|
95
|
+
Breadcrumb,
|
|
96
|
+
BreadcrumbItem,
|
|
97
|
+
BreadcrumbLink,
|
|
98
|
+
BreadcrumbPage,
|
|
99
|
+
BreadcrumbSeparator,
|
|
100
|
+
CONTAINER_SIZES,
|
|
101
|
+
Caption,
|
|
102
|
+
Card,
|
|
103
|
+
CardBody,
|
|
104
|
+
CardDescription,
|
|
105
|
+
CardFooter,
|
|
106
|
+
CardHeader,
|
|
107
|
+
CardTitle,
|
|
108
|
+
Center,
|
|
109
|
+
Collapsible,
|
|
110
|
+
CollapsibleContent,
|
|
111
|
+
CollapsibleTrigger,
|
|
112
|
+
Container,
|
|
113
|
+
DefinitionDetail,
|
|
114
|
+
DefinitionList,
|
|
115
|
+
DefinitionTerm,
|
|
116
|
+
Divider,
|
|
117
|
+
Eyebrow,
|
|
118
|
+
Flex,
|
|
119
|
+
Grid,
|
|
120
|
+
HStack,
|
|
121
|
+
Heading,
|
|
122
|
+
InlineCode,
|
|
123
|
+
Kbd,
|
|
124
|
+
Link,
|
|
125
|
+
List,
|
|
126
|
+
NavigationMenu,
|
|
127
|
+
NavigationMenuContent,
|
|
128
|
+
NavigationMenuItem,
|
|
129
|
+
NavigationMenuLink,
|
|
130
|
+
NavigationMenuList,
|
|
131
|
+
NavigationMenuTrigger,
|
|
132
|
+
Pagination,
|
|
133
|
+
Panel,
|
|
134
|
+
Preformatted,
|
|
135
|
+
ScrollArea,
|
|
136
|
+
SkipLink,
|
|
137
|
+
Spacer,
|
|
138
|
+
Stack,
|
|
139
|
+
Step,
|
|
140
|
+
StepIndicator,
|
|
141
|
+
StepSeparator,
|
|
142
|
+
Stepper,
|
|
143
|
+
TIME_FORMAT_TOKENS,
|
|
144
|
+
Tabs,
|
|
145
|
+
TabsContent,
|
|
146
|
+
TabsList,
|
|
147
|
+
TabsTrigger,
|
|
148
|
+
Text,
|
|
149
|
+
Toolbar,
|
|
150
|
+
ToolbarButton,
|
|
151
|
+
VStack,
|
|
152
|
+
dataSlot,
|
|
153
|
+
formatBytes,
|
|
154
|
+
formatDateTime,
|
|
155
|
+
formatDuration,
|
|
156
|
+
formatNumber,
|
|
157
|
+
formatPercent,
|
|
158
|
+
formatRelativeTime,
|
|
159
|
+
paginationLinkVariants,
|
|
160
|
+
stateAttributes,
|
|
161
|
+
textVariants
|
|
162
|
+
};
|
|
163
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * TEA UI — Core.\n *\n * The product-agnostic layer. Nothing here knows what a server, a backup or a\n * user is, and nothing here calls an API. If a component needs to know, it\n * belongs in `@tea-ui/admin`, `@tea-ui/public` or `@tea-ui/specialized`.\n *\n * Import from the package root, never from a path. The subtrees are internal and\n * are not covered by semver:\n *\n * ```ts\n * import { Button, Field, Input, FieldLabel } from \"@tea-ui/core\";\n * import \"@tea-ui/core/styles.css\"; // once, at the root of your application\n * ```\n */\n\n/* -- layout ---------------------------------------------------------------- */\nexport {\n AspectRatio,\n Box,\n Center,\n Container,\n CONTAINER_SIZES,\n Divider,\n Flex,\n Grid,\n HStack,\n ScrollArea,\n Spacer,\n Stack,\n VStack,\n type AspectRatioProps,\n type BoxProps,\n type CenterProps,\n type ContainerProps,\n type DividerProps,\n type FlexProps,\n type GridProps,\n type ScrollAreaProps,\n type SpacerProps,\n type StackProps,\n} from \"./layout\";\n\n/* -- typography ------------------------------------------------------------ */\nexport {\n Blockquote,\n Caption,\n DefinitionDetail,\n DefinitionList,\n DefinitionTerm,\n Eyebrow,\n Heading,\n InlineCode,\n Kbd,\n Link,\n List,\n Preformatted,\n Text,\n textVariants,\n type HeadingProps,\n type LinkProps,\n type ListProps,\n type PreformattedProps,\n type TextProps,\n} from \"./typography\";\n\n/* -- the surface ------------------------------------------------------------- */\nexport {\n Card,\n CardBody,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n Panel,\n type CardProps,\n type CardTitleProps,\n type PanelProps,\n} from \"./card\";\n\n/* -- inputs ---------------------------------------------------------------- */\nexport * from \"./inputs\";\n\n/* -- feedback -------------------------------------------------------------- */\nexport * from \"./feedback\";\n\n/* -- overlays -------------------------------------------------------------- */\nexport * from \"./overlays\";\n\n/* -- navigation ------------------------------------------------------------ */\nexport {\n Accordion,\n AccordionContent,\n AccordionItem,\n AccordionTrigger,\n Breadcrumb,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbPage,\n BreadcrumbSeparator,\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n NavigationMenu,\n NavigationMenuContent,\n NavigationMenuItem,\n NavigationMenuLink,\n NavigationMenuList,\n NavigationMenuTrigger,\n Pagination,\n SkipLink,\n Step,\n StepIndicator,\n StepSeparator,\n Stepper,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n Toolbar,\n ToolbarButton,\n paginationLinkVariants,\n type AccordionProps,\n type BreadcrumbLinkProps,\n type CollapsibleProps,\n type PaginationProps,\n type SkipLinkProps,\n type StepProps,\n type StepperProps,\n type TabsProps,\n} from \"./navigation\";\n\n/* -- the shared attribute vocabulary --------------------------------------- */\nexport { dataSlot, stateAttributes, type StateAttributes } from \"./internal\";\n\n/* -- formatting ------------------------------------------------------------ */\nexport {\n TIME_FORMAT_TOKENS,\n formatBytes,\n formatDateTime,\n formatDuration,\n formatNumber,\n formatPercent,\n formatRelativeTime,\n type ByteSystem,\n type FormatBytesOptions,\n type FormatDateTimeOptions,\n type FormatNumberOptions,\n type FormatRelativeTimeOptions,\n} from \"./format\";\n"],"mappings":"AAiBA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAWK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAMK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AAGP,cAAc;AAGd,cAAc;AAGd,cAAc;AAGd;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OASK;AAGP,SAAS,UAAU,uBAA6C;AAGhE;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAMK;","names":[]}
|