@elizaos/ui 2.0.0-alpha.73 → 2.0.0-alpha.76
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/components/ui/badge.d.ts +10 -0
- package/components/ui/badge.d.ts.map +1 -0
- package/components/ui/badge.js +20 -0
- package/components/ui/banner.d.ts +18 -0
- package/components/ui/banner.d.ts.map +1 -0
- package/components/ui/banner.js +27 -0
- package/components/ui/button.d.ts +12 -0
- package/components/ui/button.d.ts.map +1 -0
- package/components/ui/button.js +37 -0
- package/components/ui/card.d.ts +9 -0
- package/components/ui/card.d.ts.map +1 -0
- package/components/ui/card.js +16 -0
- package/components/ui/chat-atoms.d.ts +26 -0
- package/components/ui/chat-atoms.d.ts.map +1 -0
- package/components/ui/chat-atoms.js +17 -0
- package/components/ui/checkbox.d.ts +5 -0
- package/components/ui/checkbox.d.ts.map +1 -0
- package/components/ui/checkbox.js +8 -0
- package/components/ui/confirm-delete.d.ts +12 -0
- package/components/ui/confirm-delete.d.ts.map +1 -0
- package/components/ui/confirm-delete.js +13 -0
- package/components/ui/confirm-dialog.d.ts +24 -0
- package/components/ui/confirm-dialog.d.ts.map +1 -0
- package/components/ui/confirm-dialog.js +55 -0
- package/components/ui/connection-status.d.ts +9 -0
- package/components/ui/connection-status.d.ts.map +1 -0
- package/components/ui/connection-status.js +25 -0
- package/components/ui/copy-button.d.ts +13 -0
- package/components/ui/copy-button.d.ts.map +1 -0
- package/components/ui/copy-button.js +14 -0
- package/components/ui/dialog.d.ts +20 -0
- package/components/ui/dialog.d.ts.map +1 -0
- package/components/ui/dialog.js +22 -0
- package/components/ui/dropdown-menu.d.ts +28 -0
- package/components/ui/dropdown-menu.d.ts.map +1 -0
- package/components/ui/dropdown-menu.js +35 -0
- package/components/ui/empty-state.d.ts +13 -0
- package/components/ui/empty-state.d.ts.map +1 -0
- package/components/ui/empty-state.js +5 -0
- package/components/ui/error-boundary.d.ts +18 -0
- package/components/ui/error-boundary.d.ts.map +1 -0
- package/components/ui/error-boundary.js +27 -0
- package/components/ui/grid.d.ts +11 -0
- package/components/ui/grid.d.ts.map +1 -0
- package/components/ui/grid.js +30 -0
- package/components/ui/input.d.ts +6 -0
- package/components/ui/input.d.ts.map +1 -0
- package/components/ui/input.js +8 -0
- package/components/ui/label.d.ts +6 -0
- package/components/ui/label.d.ts.map +1 -0
- package/components/ui/label.js +9 -0
- package/components/ui/popover.d.ts +7 -0
- package/components/ui/popover.d.ts.map +1 -0
- package/components/ui/popover.js +9 -0
- package/components/ui/save-footer.d.ts +13 -0
- package/components/ui/save-footer.d.ts.map +1 -0
- package/components/ui/save-footer.js +9 -0
- package/components/ui/search-bar.d.ts +17 -0
- package/components/ui/search-bar.d.ts.map +1 -0
- package/components/ui/search-bar.js +19 -0
- package/components/ui/search-input.d.ts +11 -0
- package/components/ui/search-input.d.ts.map +1 -0
- package/components/ui/search-input.js +9 -0
- package/components/ui/section-card.d.ts +15 -0
- package/components/ui/section-card.d.ts.map +1 -0
- package/components/ui/section-card.js +9 -0
- package/components/ui/select.d.ts +14 -0
- package/components/ui/select.d.ts.map +1 -0
- package/components/ui/select.js +26 -0
- package/components/ui/separator.d.ts +5 -0
- package/components/ui/separator.d.ts.map +1 -0
- package/components/ui/separator.js +7 -0
- package/components/ui/skeleton.d.ts +17 -0
- package/components/ui/skeleton.d.ts.map +1 -0
- package/components/ui/skeleton.js +25 -0
- package/components/ui/slider.d.ts +5 -0
- package/components/ui/slider.d.ts.map +1 -0
- package/components/ui/slider.js +7 -0
- package/components/ui/sonner.d.ts +5 -0
- package/components/ui/sonner.d.ts.map +1 -0
- package/components/ui/sonner.js +15 -0
- package/components/ui/spinner.d.ts +6 -0
- package/components/ui/spinner.d.ts.map +1 -0
- package/components/ui/spinner.js +8 -0
- package/components/ui/stack.d.ts +13 -0
- package/components/ui/stack.d.ts.map +1 -0
- package/components/ui/stack.js +39 -0
- package/components/ui/status-badge.d.ts +20 -0
- package/components/ui/status-badge.d.ts.map +1 -0
- package/components/ui/status-badge.js +41 -0
- package/components/ui/switch.d.ts +5 -0
- package/components/ui/switch.d.ts.map +1 -0
- package/components/ui/switch.js +7 -0
- package/components/ui/tabs.d.ts +8 -0
- package/components/ui/tabs.d.ts.map +1 -0
- package/components/ui/tabs.js +12 -0
- package/components/ui/tag-editor.d.ts +24 -0
- package/components/ui/tag-editor.d.ts.map +1 -0
- package/components/ui/tag-editor.js +32 -0
- package/components/ui/tag-input.d.ts +19 -0
- package/components/ui/tag-input.d.ts.map +1 -0
- package/components/ui/tag-input.js +28 -0
- package/components/ui/textarea.d.ts +6 -0
- package/components/ui/textarea.d.ts.map +1 -0
- package/components/ui/textarea.js +8 -0
- package/components/ui/themed-select.d.ts +27 -0
- package/components/ui/themed-select.d.ts.map +1 -0
- package/components/ui/themed-select.js +57 -0
- package/components/ui/tooltip-extended.d.ts +76 -0
- package/components/ui/tooltip-extended.d.ts.map +1 -0
- package/components/ui/tooltip-extended.js +128 -0
- package/components/ui/tooltip.d.ts +8 -0
- package/components/ui/tooltip.d.ts.map +1 -0
- package/components/ui/tooltip.js +10 -0
- package/components/ui/typography.d.ts +17 -0
- package/components/ui/typography.d.ts.map +1 -0
- package/components/ui/typography.js +44 -0
- package/index.d.ts +42 -0
- package/index.d.ts.map +1 -0
- package/{src/index.ts → index.js} +0 -1
- package/lib/button-styles.d.ts +12 -0
- package/lib/button-styles.d.ts.map +1 -0
- package/lib/button-styles.js +11 -0
- package/lib/utils.d.ts +6 -0
- package/lib/utils.d.ts.map +1 -0
- package/{src/lib/utils.ts → lib/utils.js} +3 -4
- package/package.json +16 -18
- package/README.md +0 -6
- package/src/components/ui/badge.tsx +0 -35
- package/src/components/ui/banner.tsx +0 -81
- package/src/components/ui/button.tsx +0 -56
- package/src/components/ui/card.tsx +0 -79
- package/src/components/ui/chat-atoms.tsx +0 -129
- package/src/components/ui/checkbox.tsx +0 -28
- package/src/components/ui/confirm-delete.tsx +0 -67
- package/src/components/ui/confirm-dialog.tsx +0 -142
- package/src/components/ui/connection-status.tsx +0 -54
- package/src/components/ui/copy-button.tsx +0 -60
- package/src/components/ui/dialog.tsx +0 -120
- package/src/components/ui/dropdown-menu.tsx +0 -198
- package/src/components/ui/empty-state.tsx +0 -42
- package/src/components/ui/error-boundary.tsx +0 -63
- package/src/components/ui/grid.tsx +0 -43
- package/src/components/ui/input.tsx +0 -25
- package/src/components/ui/label.tsx +0 -24
- package/src/components/ui/popover.tsx +0 -29
- package/src/components/ui/save-footer.tsx +0 -58
- package/src/components/ui/search-bar.tsx +0 -61
- package/src/components/ui/search-input.tsx +0 -56
- package/src/components/ui/section-card.tsx +0 -85
- package/src/components/ui/select.tsx +0 -158
- package/src/components/ui/separator.tsx +0 -29
- package/src/components/ui/skeleton.tsx +0 -115
- package/src/components/ui/slider.tsx +0 -26
- package/src/components/ui/sonner.tsx +0 -28
- package/src/components/ui/spinner.tsx +0 -21
- package/src/components/ui/stack.tsx +0 -55
- package/src/components/ui/status-badge.tsx +0 -128
- package/src/components/ui/switch.tsx +0 -27
- package/src/components/ui/tabs.tsx +0 -53
- package/src/components/ui/tag-editor.tsx +0 -111
- package/src/components/ui/tag-input.tsx +0 -108
- package/src/components/ui/textarea.tsx +0 -24
- package/src/components/ui/themed-select.tsx +0 -141
- package/src/components/ui/tooltip-extended.tsx +0 -340
- package/src/components/ui/tooltip.tsx +0 -28
- package/src/components/ui/typography.tsx +0 -74
- package/src/lib/button-styles.ts +0 -19
- package/tsconfig.build.json +0 -18
- package/tsconfig.json +0 -32
- /package/{src/styles → styles}/theme.css +0 -0
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import * as SliderPrimitive from "@radix-ui/react-slider";
|
|
2
|
-
import * as React from "react";
|
|
3
|
-
|
|
4
|
-
import { cn } from "../../lib/utils";
|
|
5
|
-
|
|
6
|
-
const Slider = React.forwardRef<
|
|
7
|
-
React.ElementRef<typeof SliderPrimitive.Root>,
|
|
8
|
-
React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root>
|
|
9
|
-
>(({ className, ...props }, ref) => (
|
|
10
|
-
<SliderPrimitive.Root
|
|
11
|
-
ref={ref}
|
|
12
|
-
className={cn(
|
|
13
|
-
"relative flex w-full touch-none select-none items-center",
|
|
14
|
-
className,
|
|
15
|
-
)}
|
|
16
|
-
{...props}
|
|
17
|
-
>
|
|
18
|
-
<SliderPrimitive.Track className="relative h-2 w-full grow overflow-hidden rounded-full bg-secondary">
|
|
19
|
-
<SliderPrimitive.Range className="absolute h-full bg-primary" />
|
|
20
|
-
</SliderPrimitive.Track>
|
|
21
|
-
<SliderPrimitive.Thumb className="block h-5 w-5 rounded-full border-2 border-primary bg-bg ring-offset-bg transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50" />
|
|
22
|
-
</SliderPrimitive.Root>
|
|
23
|
-
));
|
|
24
|
-
Slider.displayName = SliderPrimitive.Root.displayName;
|
|
25
|
-
|
|
26
|
-
export { Slider };
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { useTheme } from "next-themes";
|
|
2
|
-
import { Toaster as Sonner } from "sonner";
|
|
3
|
-
|
|
4
|
-
type ToasterProps = React.ComponentProps<typeof Sonner>;
|
|
5
|
-
|
|
6
|
-
const Toaster = ({ ...props }: ToasterProps) => {
|
|
7
|
-
const { theme = "system" } = useTheme();
|
|
8
|
-
|
|
9
|
-
return (
|
|
10
|
-
<Sonner
|
|
11
|
-
theme={theme as ToasterProps["theme"]}
|
|
12
|
-
className="toaster group"
|
|
13
|
-
toastOptions={{
|
|
14
|
-
classNames: {
|
|
15
|
-
toast:
|
|
16
|
-
"group toast group-[.toaster]:bg-bg group-[.toaster]:text-txt group-[.toaster]:border-border group-[.toaster]:shadow-lg",
|
|
17
|
-
description: "group-[.toast]:text-muted",
|
|
18
|
-
actionButton:
|
|
19
|
-
"group-[.toast]:bg-primary group-[.toast]:text-primary-fg",
|
|
20
|
-
cancelButton: "group-[.toast]:bg-muted group-[.toast]:text-muted-fg",
|
|
21
|
-
},
|
|
22
|
-
}}
|
|
23
|
-
{...props}
|
|
24
|
-
/>
|
|
25
|
-
);
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
export { Toaster };
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { Loader2 } from "lucide-react";
|
|
2
|
-
import * as React from "react";
|
|
3
|
-
import { cn } from "../../lib/utils";
|
|
4
|
-
|
|
5
|
-
export interface SpinnerProps extends React.SVGAttributes<SVGSVGElement> {
|
|
6
|
-
size?: number | string;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export const Spinner = React.forwardRef<SVGSVGElement, SpinnerProps>(
|
|
10
|
-
({ className, size = 24, ...props }, ref) => {
|
|
11
|
-
return (
|
|
12
|
-
<Loader2
|
|
13
|
-
ref={ref}
|
|
14
|
-
size={size}
|
|
15
|
-
className={cn("animate-spin text-muted", className)}
|
|
16
|
-
{...props}
|
|
17
|
-
/>
|
|
18
|
-
);
|
|
19
|
-
},
|
|
20
|
-
);
|
|
21
|
-
Spinner.displayName = "Spinner";
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { cva, type VariantProps } from "class-variance-authority";
|
|
2
|
-
import * as React from "react";
|
|
3
|
-
import { cn } from "../../lib/utils";
|
|
4
|
-
|
|
5
|
-
const stackVariants = cva("flex", {
|
|
6
|
-
variants: {
|
|
7
|
-
direction: {
|
|
8
|
-
row: "flex-row",
|
|
9
|
-
col: "flex-col",
|
|
10
|
-
},
|
|
11
|
-
align: {
|
|
12
|
-
start: "items-start",
|
|
13
|
-
center: "items-center",
|
|
14
|
-
end: "items-end",
|
|
15
|
-
stretch: "items-stretch",
|
|
16
|
-
baseline: "items-baseline",
|
|
17
|
-
},
|
|
18
|
-
justify: {
|
|
19
|
-
start: "justify-start",
|
|
20
|
-
center: "justify-center",
|
|
21
|
-
end: "justify-end",
|
|
22
|
-
between: "justify-between",
|
|
23
|
-
},
|
|
24
|
-
spacing: {
|
|
25
|
-
none: "gap-0",
|
|
26
|
-
sm: "gap-2",
|
|
27
|
-
md: "gap-4",
|
|
28
|
-
lg: "gap-6",
|
|
29
|
-
},
|
|
30
|
-
},
|
|
31
|
-
defaultVariants: {
|
|
32
|
-
direction: "col",
|
|
33
|
-
spacing: "md",
|
|
34
|
-
},
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
export interface StackProps
|
|
38
|
-
extends React.HTMLAttributes<HTMLDivElement>,
|
|
39
|
-
VariantProps<typeof stackVariants> {}
|
|
40
|
-
|
|
41
|
-
export const Stack = React.forwardRef<HTMLDivElement, StackProps>(
|
|
42
|
-
({ className, direction, align, justify, spacing, ...props }, ref) => {
|
|
43
|
-
return (
|
|
44
|
-
<div
|
|
45
|
-
ref={ref}
|
|
46
|
-
className={cn(
|
|
47
|
-
stackVariants({ direction, align, justify, spacing }),
|
|
48
|
-
className,
|
|
49
|
-
)}
|
|
50
|
-
{...props}
|
|
51
|
-
/>
|
|
52
|
-
);
|
|
53
|
-
},
|
|
54
|
-
);
|
|
55
|
-
Stack.displayName = "Stack";
|
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import { cn } from "../../lib/utils";
|
|
3
|
-
|
|
4
|
-
export type StatusTone = "success" | "warning" | "danger" | "muted";
|
|
5
|
-
|
|
6
|
-
const STATUS_TONE_STYLES: Record<StatusTone, { badge: string; dot: string }> = {
|
|
7
|
-
success: {
|
|
8
|
-
badge: "text-ok border-ok/30 bg-ok/10",
|
|
9
|
-
dot: "bg-ok",
|
|
10
|
-
},
|
|
11
|
-
warning: {
|
|
12
|
-
badge: "text-warn border-warn/30 bg-warn/10",
|
|
13
|
-
dot: "bg-warn",
|
|
14
|
-
},
|
|
15
|
-
danger: {
|
|
16
|
-
badge: "text-destructive border-destructive/30 bg-destructive/10",
|
|
17
|
-
dot: "bg-destructive",
|
|
18
|
-
},
|
|
19
|
-
muted: {
|
|
20
|
-
badge: "text-muted border-border bg-bg",
|
|
21
|
-
dot: "bg-muted",
|
|
22
|
-
},
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
export function statusToneForBoolean(
|
|
26
|
-
condition: boolean,
|
|
27
|
-
onTone: StatusTone = "success",
|
|
28
|
-
offTone: StatusTone = "muted",
|
|
29
|
-
): StatusTone {
|
|
30
|
-
return condition ? onTone : offTone;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/* ── StatusBadge ─────────────────────────────────────────────────────── */
|
|
34
|
-
|
|
35
|
-
export interface StatusBadgeProps
|
|
36
|
-
extends React.HTMLAttributes<HTMLSpanElement> {
|
|
37
|
-
label: string;
|
|
38
|
-
tone: StatusTone;
|
|
39
|
-
withDot?: boolean;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export const StatusBadge = React.forwardRef<HTMLSpanElement, StatusBadgeProps>(
|
|
43
|
-
({ label, tone, withDot = false, className, ...props }, ref) => {
|
|
44
|
-
const styles = STATUS_TONE_STYLES[tone];
|
|
45
|
-
return (
|
|
46
|
-
<span
|
|
47
|
-
ref={ref}
|
|
48
|
-
className={cn(
|
|
49
|
-
"inline-flex items-center gap-1 rounded-sm border px-2 py-0.5 text-[10px] font-bold uppercase",
|
|
50
|
-
styles.badge,
|
|
51
|
-
className,
|
|
52
|
-
)}
|
|
53
|
-
{...props}
|
|
54
|
-
>
|
|
55
|
-
{withDot && (
|
|
56
|
-
<span className={cn("h-1.5 w-1.5 rounded-full", styles.dot)} />
|
|
57
|
-
)}
|
|
58
|
-
{label}
|
|
59
|
-
</span>
|
|
60
|
-
);
|
|
61
|
-
},
|
|
62
|
-
);
|
|
63
|
-
StatusBadge.displayName = "StatusBadge";
|
|
64
|
-
|
|
65
|
-
/* ── StatusDot ───────────────────────────────────────────────────────── */
|
|
66
|
-
|
|
67
|
-
export interface StatusDotProps extends React.HTMLAttributes<HTMLSpanElement> {
|
|
68
|
-
status: string;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
export const StatusDot = React.forwardRef<HTMLSpanElement, StatusDotProps>(
|
|
72
|
-
({ status, className, ...props }, ref) => {
|
|
73
|
-
const tone: StatusTone =
|
|
74
|
-
status === "success" || status === "completed" || status === "connected"
|
|
75
|
-
? "success"
|
|
76
|
-
: status === "error" || status === "failed" || status === "denied"
|
|
77
|
-
? "danger"
|
|
78
|
-
: "muted";
|
|
79
|
-
|
|
80
|
-
const styles = STATUS_TONE_STYLES[tone];
|
|
81
|
-
return (
|
|
82
|
-
<span
|
|
83
|
-
ref={ref}
|
|
84
|
-
className={cn(
|
|
85
|
-
"inline-block h-2 w-2 rounded-full",
|
|
86
|
-
styles.dot,
|
|
87
|
-
className,
|
|
88
|
-
)}
|
|
89
|
-
{...props}
|
|
90
|
-
/>
|
|
91
|
-
);
|
|
92
|
-
},
|
|
93
|
-
);
|
|
94
|
-
StatusDot.displayName = "StatusDot";
|
|
95
|
-
|
|
96
|
-
/* ── StatCard ────────────────────────────────────────────────────────── */
|
|
97
|
-
|
|
98
|
-
export interface StatCardProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
99
|
-
label: string;
|
|
100
|
-
value: React.ReactNode;
|
|
101
|
-
accent?: boolean;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
export const StatCard = React.forwardRef<HTMLDivElement, StatCardProps>(
|
|
105
|
-
({ label, value, accent = false, className, ...props }, ref) => (
|
|
106
|
-
<div
|
|
107
|
-
ref={ref}
|
|
108
|
-
className={cn(
|
|
109
|
-
"flex flex-col items-center justify-center border border-border bg-bg p-3 min-w-[80px]",
|
|
110
|
-
className,
|
|
111
|
-
)}
|
|
112
|
-
{...props}
|
|
113
|
-
>
|
|
114
|
-
<div
|
|
115
|
-
className={cn(
|
|
116
|
-
"text-lg font-bold tabular-nums",
|
|
117
|
-
accent && "text-accent",
|
|
118
|
-
)}
|
|
119
|
-
>
|
|
120
|
-
{value}
|
|
121
|
-
</div>
|
|
122
|
-
<div className="mt-0.5 text-[10px] uppercase tracking-wide text-muted">
|
|
123
|
-
{label}
|
|
124
|
-
</div>
|
|
125
|
-
</div>
|
|
126
|
-
),
|
|
127
|
-
);
|
|
128
|
-
StatCard.displayName = "StatCard";
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import * as SwitchPrimitives from "@radix-ui/react-switch";
|
|
2
|
-
import * as React from "react";
|
|
3
|
-
|
|
4
|
-
import { cn } from "../../lib/utils";
|
|
5
|
-
|
|
6
|
-
const Switch = React.forwardRef<
|
|
7
|
-
React.ElementRef<typeof SwitchPrimitives.Root>,
|
|
8
|
-
React.ComponentPropsWithoutRef<typeof SwitchPrimitives.Root>
|
|
9
|
-
>(({ className, ...props }, ref) => (
|
|
10
|
-
<SwitchPrimitives.Root
|
|
11
|
-
className={cn(
|
|
12
|
-
"peer inline-flex h-[24px] w-[44px] shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-bg disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input",
|
|
13
|
-
className,
|
|
14
|
-
)}
|
|
15
|
-
{...props}
|
|
16
|
-
ref={ref}
|
|
17
|
-
>
|
|
18
|
-
<SwitchPrimitives.Thumb
|
|
19
|
-
className={cn(
|
|
20
|
-
"pointer-events-none block h-5 w-5 rounded-full bg-bg shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0",
|
|
21
|
-
)}
|
|
22
|
-
/>
|
|
23
|
-
</SwitchPrimitives.Root>
|
|
24
|
-
));
|
|
25
|
-
Switch.displayName = SwitchPrimitives.Root.displayName;
|
|
26
|
-
|
|
27
|
-
export { Switch };
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import * as TabsPrimitive from "@radix-ui/react-tabs";
|
|
2
|
-
import * as React from "react";
|
|
3
|
-
|
|
4
|
-
import { cn } from "../../lib/utils";
|
|
5
|
-
|
|
6
|
-
const Tabs = TabsPrimitive.Root;
|
|
7
|
-
|
|
8
|
-
const TabsList = React.forwardRef<
|
|
9
|
-
React.ElementRef<typeof TabsPrimitive.List>,
|
|
10
|
-
React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>
|
|
11
|
-
>(({ className, ...props }, ref) => (
|
|
12
|
-
<TabsPrimitive.List
|
|
13
|
-
ref={ref}
|
|
14
|
-
className={cn(
|
|
15
|
-
"inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-fg",
|
|
16
|
-
className,
|
|
17
|
-
)}
|
|
18
|
-
{...props}
|
|
19
|
-
/>
|
|
20
|
-
));
|
|
21
|
-
TabsList.displayName = TabsPrimitive.List.displayName;
|
|
22
|
-
|
|
23
|
-
const TabsTrigger = React.forwardRef<
|
|
24
|
-
React.ElementRef<typeof TabsPrimitive.Trigger>,
|
|
25
|
-
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>
|
|
26
|
-
>(({ className, ...props }, ref) => (
|
|
27
|
-
<TabsPrimitive.Trigger
|
|
28
|
-
ref={ref}
|
|
29
|
-
className={cn(
|
|
30
|
-
"inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-bg transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-bg data-[state=active]:text-txt data-[state=active]:shadow-sm",
|
|
31
|
-
className,
|
|
32
|
-
)}
|
|
33
|
-
{...props}
|
|
34
|
-
/>
|
|
35
|
-
));
|
|
36
|
-
TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;
|
|
37
|
-
|
|
38
|
-
const TabsContent = React.forwardRef<
|
|
39
|
-
React.ElementRef<typeof TabsPrimitive.Content>,
|
|
40
|
-
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>
|
|
41
|
-
>(({ className, ...props }, ref) => (
|
|
42
|
-
<TabsPrimitive.Content
|
|
43
|
-
ref={ref}
|
|
44
|
-
className={cn(
|
|
45
|
-
"mt-2 ring-offset-bg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
46
|
-
className,
|
|
47
|
-
)}
|
|
48
|
-
{...props}
|
|
49
|
-
/>
|
|
50
|
-
));
|
|
51
|
-
TabsContent.displayName = TabsPrimitive.Content.displayName;
|
|
52
|
-
|
|
53
|
-
export { Tabs, TabsContent, TabsList, TabsTrigger };
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* TagEditor — add/remove string tags with chip display.
|
|
3
|
-
*
|
|
4
|
-
* Fully generic; no app-context dependency. Callers pass translated labels
|
|
5
|
-
* via props (with English defaults so the component works out-of-the-box).
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { useState } from "react";
|
|
9
|
-
import { cn } from "../../lib/utils";
|
|
10
|
-
import { Button } from "./button";
|
|
11
|
-
import { Input } from "./input";
|
|
12
|
-
|
|
13
|
-
export interface TagEditorProps {
|
|
14
|
-
label: string;
|
|
15
|
-
items: string[];
|
|
16
|
-
onChange: (items: string[]) => void;
|
|
17
|
-
placeholder?: string;
|
|
18
|
-
/** Label for the Add button. Defaults to "Add". */
|
|
19
|
-
addLabel?: string;
|
|
20
|
-
/** Label for the remove button. Defaults to "×". */
|
|
21
|
-
removeLabel?: string;
|
|
22
|
-
/** Optional class for the root container. */
|
|
23
|
-
className?: string;
|
|
24
|
-
/** Optional class for the input row. */
|
|
25
|
-
inputRowClassName?: string;
|
|
26
|
-
/** Optional class for the scrollable tag list. */
|
|
27
|
-
listClassName?: string;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export function TagEditor({
|
|
31
|
-
label,
|
|
32
|
-
items,
|
|
33
|
-
onChange,
|
|
34
|
-
placeholder = "add item...",
|
|
35
|
-
addLabel = "+",
|
|
36
|
-
removeLabel = "×",
|
|
37
|
-
className,
|
|
38
|
-
inputRowClassName,
|
|
39
|
-
listClassName,
|
|
40
|
-
}: TagEditorProps) {
|
|
41
|
-
const [inputValue, setInputValue] = useState("");
|
|
42
|
-
|
|
43
|
-
const addItem = () => {
|
|
44
|
-
const trimmed = inputValue.trim();
|
|
45
|
-
if (trimmed && !items.includes(trimmed)) {
|
|
46
|
-
onChange([...items, trimmed]);
|
|
47
|
-
}
|
|
48
|
-
setInputValue("");
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
const removeItem = (index: number) => {
|
|
52
|
-
const updated = [...items];
|
|
53
|
-
updated.splice(index, 1);
|
|
54
|
-
onChange(updated);
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
return (
|
|
58
|
-
<div className={cn("flex min-h-0 flex-col gap-1.5", className)}>
|
|
59
|
-
<span className="font-semibold text-xs">{label}</span>
|
|
60
|
-
<div className={cn("flex items-center gap-1.5", inputRowClassName)}>
|
|
61
|
-
<Input
|
|
62
|
-
type="text"
|
|
63
|
-
value={inputValue}
|
|
64
|
-
placeholder={placeholder}
|
|
65
|
-
onChange={(e) => setInputValue(e.target.value)}
|
|
66
|
-
onKeyDown={(e) => {
|
|
67
|
-
if (e.key === "Enter") {
|
|
68
|
-
e.preventDefault();
|
|
69
|
-
addItem();
|
|
70
|
-
}
|
|
71
|
-
}}
|
|
72
|
-
className="h-7 px-2 border-border bg-card text-[11px] focus-visible:ring-1 focus-visible:ring-accent flex-1 min-w-0 shadow-sm"
|
|
73
|
-
/>
|
|
74
|
-
<Button
|
|
75
|
-
variant="ghost"
|
|
76
|
-
size="sm"
|
|
77
|
-
className="h-7 w-7 text-[14px] p-0 text-accent border-none hover:bg-transparent hover:text-accent/80 font-bold"
|
|
78
|
-
onClick={addItem}
|
|
79
|
-
>
|
|
80
|
-
{addLabel}
|
|
81
|
-
</Button>
|
|
82
|
-
</div>
|
|
83
|
-
<div
|
|
84
|
-
className={cn(
|
|
85
|
-
"min-h-0 overflow-y-auto rounded-xl border border-border/40 bg-bg/50 p-2 backdrop-blur-sm",
|
|
86
|
-
"flex flex-wrap content-start items-start gap-x-1.5 gap-y-1",
|
|
87
|
-
listClassName,
|
|
88
|
-
)}
|
|
89
|
-
>
|
|
90
|
-
{items.map((item, i) => (
|
|
91
|
-
<span
|
|
92
|
-
key={item}
|
|
93
|
-
className="inline-flex items-center justify-between gap-1 px-2 py-0.5 border border-border/50 bg-black/10 rounded text-[11px] h-fit text-txt font-medium"
|
|
94
|
-
>
|
|
95
|
-
<span className="truncate max-w-[200px]" title={item}>
|
|
96
|
-
{item}
|
|
97
|
-
</span>
|
|
98
|
-
<Button
|
|
99
|
-
variant="ghost"
|
|
100
|
-
size="icon"
|
|
101
|
-
className="h-4 w-4 p-0 text-danger/80 hover:text-danger hover:bg-transparent"
|
|
102
|
-
onClick={() => removeItem(i)}
|
|
103
|
-
>
|
|
104
|
-
{removeLabel}
|
|
105
|
-
</Button>
|
|
106
|
-
</span>
|
|
107
|
-
))}
|
|
108
|
-
</div>
|
|
109
|
-
</div>
|
|
110
|
-
);
|
|
111
|
-
}
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
import { X } from "lucide-react";
|
|
2
|
-
import * as React from "react";
|
|
3
|
-
import { cn } from "../../lib/utils";
|
|
4
|
-
|
|
5
|
-
export interface TagInputProps
|
|
6
|
-
extends Omit<React.HTMLAttributes<HTMLDivElement>, "onChange"> {
|
|
7
|
-
/** Label shown above the input */
|
|
8
|
-
label?: string;
|
|
9
|
-
/** Current list of tags */
|
|
10
|
-
items: string[];
|
|
11
|
-
/** Called with the updated tag list */
|
|
12
|
-
onChange: (items: string[]) => void;
|
|
13
|
-
/** Placeholder text for the input */
|
|
14
|
-
placeholder?: string;
|
|
15
|
-
/** Maximum number of tags */
|
|
16
|
-
maxItems?: number;
|
|
17
|
-
/** Label for the explicit add button */
|
|
18
|
-
addLabel?: string;
|
|
19
|
-
/** Aria-label template for the remove button */
|
|
20
|
-
removeLabel?: string;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export const TagInput = React.forwardRef<HTMLDivElement, TagInputProps>(
|
|
24
|
-
(
|
|
25
|
-
{
|
|
26
|
-
label,
|
|
27
|
-
items,
|
|
28
|
-
onChange,
|
|
29
|
-
placeholder = "Add item…",
|
|
30
|
-
maxItems,
|
|
31
|
-
addLabel = "Add",
|
|
32
|
-
removeLabel = "Remove",
|
|
33
|
-
className,
|
|
34
|
-
...props
|
|
35
|
-
},
|
|
36
|
-
ref,
|
|
37
|
-
) => {
|
|
38
|
-
const [inputValue, setInputValue] = React.useState("");
|
|
39
|
-
|
|
40
|
-
const addItem = React.useCallback(() => {
|
|
41
|
-
const trimmed = inputValue.trim();
|
|
42
|
-
if (!trimmed || items.includes(trimmed)) return;
|
|
43
|
-
if (maxItems != null && items.length >= maxItems) return;
|
|
44
|
-
onChange([...items, trimmed]);
|
|
45
|
-
setInputValue("");
|
|
46
|
-
}, [inputValue, items, onChange, maxItems]);
|
|
47
|
-
|
|
48
|
-
const removeItem = React.useCallback(
|
|
49
|
-
(index: number) => {
|
|
50
|
-
const updated = [...items];
|
|
51
|
-
updated.splice(index, 1);
|
|
52
|
-
onChange(updated);
|
|
53
|
-
},
|
|
54
|
-
[items, onChange],
|
|
55
|
-
);
|
|
56
|
-
|
|
57
|
-
return (
|
|
58
|
-
<div
|
|
59
|
-
ref={ref}
|
|
60
|
-
className={cn("flex flex-col gap-1.5", className)}
|
|
61
|
-
{...props}
|
|
62
|
-
>
|
|
63
|
-
{label && <span className="text-xs font-semibold">{label}</span>}
|
|
64
|
-
<div className="flex items-center gap-1.5">
|
|
65
|
-
<input
|
|
66
|
-
type="text"
|
|
67
|
-
value={inputValue}
|
|
68
|
-
placeholder={placeholder}
|
|
69
|
-
onChange={(e) => setInputValue(e.target.value)}
|
|
70
|
-
onKeyDown={(e) => {
|
|
71
|
-
if (e.key === "Enter") {
|
|
72
|
-
e.preventDefault();
|
|
73
|
-
addItem();
|
|
74
|
-
}
|
|
75
|
-
}}
|
|
76
|
-
className="flex-1 min-w-0 rounded-md border border-input bg-bg px-2 py-1 text-[11px] placeholder:text-muted focus-visible:outline-none focus-visible:border-ring"
|
|
77
|
-
/>
|
|
78
|
-
<button
|
|
79
|
-
type="button"
|
|
80
|
-
className="rounded-md border border-input bg-bg px-1.5 py-0.5 text-[10px] text-muted transition-colors hover:border-accent hover:text-accent"
|
|
81
|
-
onClick={addItem}
|
|
82
|
-
>
|
|
83
|
-
{addLabel}
|
|
84
|
-
</button>
|
|
85
|
-
</div>
|
|
86
|
-
<div className="flex flex-wrap gap-1.5 rounded-md border border-border bg-bg-accent p-1.5 min-h-[60px] content-start">
|
|
87
|
-
{items.map((item, i) => (
|
|
88
|
-
<span
|
|
89
|
-
key={item}
|
|
90
|
-
className="inline-flex items-center gap-1 rounded-sm border border-border bg-bg px-2 py-0.5 text-[11px]"
|
|
91
|
-
>
|
|
92
|
-
{item}
|
|
93
|
-
<button
|
|
94
|
-
type="button"
|
|
95
|
-
className="text-muted hover:text-destructive transition-colors"
|
|
96
|
-
onClick={() => removeItem(i)}
|
|
97
|
-
aria-label={`${removeLabel} ${item}`}
|
|
98
|
-
>
|
|
99
|
-
<X className="h-3 w-3" />
|
|
100
|
-
</button>
|
|
101
|
-
</span>
|
|
102
|
-
))}
|
|
103
|
-
</div>
|
|
104
|
-
</div>
|
|
105
|
-
);
|
|
106
|
-
},
|
|
107
|
-
);
|
|
108
|
-
TagInput.displayName = "TagInput";
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
|
|
3
|
-
import { cn } from "../../lib/utils";
|
|
4
|
-
|
|
5
|
-
export interface TextareaProps
|
|
6
|
-
extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {}
|
|
7
|
-
|
|
8
|
-
const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
|
|
9
|
-
({ className, ...props }, ref) => {
|
|
10
|
-
return (
|
|
11
|
-
<textarea
|
|
12
|
-
className={cn(
|
|
13
|
-
"flex min-h-[80px] w-full rounded-md border border-input bg-bg px-3 py-2 text-sm ring-offset-bg placeholder:text-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
|
14
|
-
className,
|
|
15
|
-
)}
|
|
16
|
-
ref={ref}
|
|
17
|
-
{...props}
|
|
18
|
-
/>
|
|
19
|
-
);
|
|
20
|
-
},
|
|
21
|
-
);
|
|
22
|
-
Textarea.displayName = "Textarea";
|
|
23
|
-
|
|
24
|
-
export { Textarea };
|