@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.
Files changed (171) hide show
  1. package/components/ui/badge.d.ts +10 -0
  2. package/components/ui/badge.d.ts.map +1 -0
  3. package/components/ui/badge.js +20 -0
  4. package/components/ui/banner.d.ts +18 -0
  5. package/components/ui/banner.d.ts.map +1 -0
  6. package/components/ui/banner.js +27 -0
  7. package/components/ui/button.d.ts +12 -0
  8. package/components/ui/button.d.ts.map +1 -0
  9. package/components/ui/button.js +37 -0
  10. package/components/ui/card.d.ts +9 -0
  11. package/components/ui/card.d.ts.map +1 -0
  12. package/components/ui/card.js +16 -0
  13. package/components/ui/chat-atoms.d.ts +26 -0
  14. package/components/ui/chat-atoms.d.ts.map +1 -0
  15. package/components/ui/chat-atoms.js +17 -0
  16. package/components/ui/checkbox.d.ts +5 -0
  17. package/components/ui/checkbox.d.ts.map +1 -0
  18. package/components/ui/checkbox.js +8 -0
  19. package/components/ui/confirm-delete.d.ts +12 -0
  20. package/components/ui/confirm-delete.d.ts.map +1 -0
  21. package/components/ui/confirm-delete.js +13 -0
  22. package/components/ui/confirm-dialog.d.ts +24 -0
  23. package/components/ui/confirm-dialog.d.ts.map +1 -0
  24. package/components/ui/confirm-dialog.js +55 -0
  25. package/components/ui/connection-status.d.ts +9 -0
  26. package/components/ui/connection-status.d.ts.map +1 -0
  27. package/components/ui/connection-status.js +25 -0
  28. package/components/ui/copy-button.d.ts +13 -0
  29. package/components/ui/copy-button.d.ts.map +1 -0
  30. package/components/ui/copy-button.js +14 -0
  31. package/components/ui/dialog.d.ts +20 -0
  32. package/components/ui/dialog.d.ts.map +1 -0
  33. package/components/ui/dialog.js +22 -0
  34. package/components/ui/dropdown-menu.d.ts +28 -0
  35. package/components/ui/dropdown-menu.d.ts.map +1 -0
  36. package/components/ui/dropdown-menu.js +35 -0
  37. package/components/ui/empty-state.d.ts +13 -0
  38. package/components/ui/empty-state.d.ts.map +1 -0
  39. package/components/ui/empty-state.js +5 -0
  40. package/components/ui/error-boundary.d.ts +18 -0
  41. package/components/ui/error-boundary.d.ts.map +1 -0
  42. package/components/ui/error-boundary.js +27 -0
  43. package/components/ui/grid.d.ts +11 -0
  44. package/components/ui/grid.d.ts.map +1 -0
  45. package/components/ui/grid.js +30 -0
  46. package/components/ui/input.d.ts +6 -0
  47. package/components/ui/input.d.ts.map +1 -0
  48. package/components/ui/input.js +8 -0
  49. package/components/ui/label.d.ts +6 -0
  50. package/components/ui/label.d.ts.map +1 -0
  51. package/components/ui/label.js +9 -0
  52. package/components/ui/popover.d.ts +7 -0
  53. package/components/ui/popover.d.ts.map +1 -0
  54. package/components/ui/popover.js +9 -0
  55. package/components/ui/save-footer.d.ts +13 -0
  56. package/components/ui/save-footer.d.ts.map +1 -0
  57. package/components/ui/save-footer.js +9 -0
  58. package/components/ui/search-bar.d.ts +17 -0
  59. package/components/ui/search-bar.d.ts.map +1 -0
  60. package/components/ui/search-bar.js +19 -0
  61. package/components/ui/search-input.d.ts +11 -0
  62. package/components/ui/search-input.d.ts.map +1 -0
  63. package/components/ui/search-input.js +9 -0
  64. package/components/ui/section-card.d.ts +15 -0
  65. package/components/ui/section-card.d.ts.map +1 -0
  66. package/components/ui/section-card.js +9 -0
  67. package/components/ui/select.d.ts +14 -0
  68. package/components/ui/select.d.ts.map +1 -0
  69. package/components/ui/select.js +26 -0
  70. package/components/ui/separator.d.ts +5 -0
  71. package/components/ui/separator.d.ts.map +1 -0
  72. package/components/ui/separator.js +7 -0
  73. package/components/ui/skeleton.d.ts +17 -0
  74. package/components/ui/skeleton.d.ts.map +1 -0
  75. package/components/ui/skeleton.js +25 -0
  76. package/components/ui/slider.d.ts +5 -0
  77. package/components/ui/slider.d.ts.map +1 -0
  78. package/components/ui/slider.js +7 -0
  79. package/components/ui/sonner.d.ts +5 -0
  80. package/components/ui/sonner.d.ts.map +1 -0
  81. package/components/ui/sonner.js +15 -0
  82. package/components/ui/spinner.d.ts +6 -0
  83. package/components/ui/spinner.d.ts.map +1 -0
  84. package/components/ui/spinner.js +8 -0
  85. package/components/ui/stack.d.ts +13 -0
  86. package/components/ui/stack.d.ts.map +1 -0
  87. package/components/ui/stack.js +39 -0
  88. package/components/ui/status-badge.d.ts +20 -0
  89. package/components/ui/status-badge.d.ts.map +1 -0
  90. package/components/ui/status-badge.js +41 -0
  91. package/components/ui/switch.d.ts +5 -0
  92. package/components/ui/switch.d.ts.map +1 -0
  93. package/components/ui/switch.js +7 -0
  94. package/components/ui/tabs.d.ts +8 -0
  95. package/components/ui/tabs.d.ts.map +1 -0
  96. package/components/ui/tabs.js +12 -0
  97. package/components/ui/tag-editor.d.ts +24 -0
  98. package/components/ui/tag-editor.d.ts.map +1 -0
  99. package/components/ui/tag-editor.js +32 -0
  100. package/components/ui/tag-input.d.ts +19 -0
  101. package/components/ui/tag-input.d.ts.map +1 -0
  102. package/components/ui/tag-input.js +28 -0
  103. package/components/ui/textarea.d.ts +6 -0
  104. package/components/ui/textarea.d.ts.map +1 -0
  105. package/components/ui/textarea.js +8 -0
  106. package/components/ui/themed-select.d.ts +27 -0
  107. package/components/ui/themed-select.d.ts.map +1 -0
  108. package/components/ui/themed-select.js +57 -0
  109. package/components/ui/tooltip-extended.d.ts +76 -0
  110. package/components/ui/tooltip-extended.d.ts.map +1 -0
  111. package/components/ui/tooltip-extended.js +128 -0
  112. package/components/ui/tooltip.d.ts +8 -0
  113. package/components/ui/tooltip.d.ts.map +1 -0
  114. package/components/ui/tooltip.js +10 -0
  115. package/components/ui/typography.d.ts +17 -0
  116. package/components/ui/typography.d.ts.map +1 -0
  117. package/components/ui/typography.js +44 -0
  118. package/index.d.ts +42 -0
  119. package/index.d.ts.map +1 -0
  120. package/{src/index.ts → index.js} +0 -1
  121. package/lib/button-styles.d.ts +12 -0
  122. package/lib/button-styles.d.ts.map +1 -0
  123. package/lib/button-styles.js +11 -0
  124. package/lib/utils.d.ts +6 -0
  125. package/lib/utils.d.ts.map +1 -0
  126. package/{src/lib/utils.ts → lib/utils.js} +3 -4
  127. package/package.json +16 -18
  128. package/README.md +0 -6
  129. package/src/components/ui/badge.tsx +0 -35
  130. package/src/components/ui/banner.tsx +0 -81
  131. package/src/components/ui/button.tsx +0 -56
  132. package/src/components/ui/card.tsx +0 -79
  133. package/src/components/ui/chat-atoms.tsx +0 -129
  134. package/src/components/ui/checkbox.tsx +0 -28
  135. package/src/components/ui/confirm-delete.tsx +0 -67
  136. package/src/components/ui/confirm-dialog.tsx +0 -142
  137. package/src/components/ui/connection-status.tsx +0 -54
  138. package/src/components/ui/copy-button.tsx +0 -60
  139. package/src/components/ui/dialog.tsx +0 -120
  140. package/src/components/ui/dropdown-menu.tsx +0 -198
  141. package/src/components/ui/empty-state.tsx +0 -42
  142. package/src/components/ui/error-boundary.tsx +0 -63
  143. package/src/components/ui/grid.tsx +0 -43
  144. package/src/components/ui/input.tsx +0 -25
  145. package/src/components/ui/label.tsx +0 -24
  146. package/src/components/ui/popover.tsx +0 -29
  147. package/src/components/ui/save-footer.tsx +0 -58
  148. package/src/components/ui/search-bar.tsx +0 -61
  149. package/src/components/ui/search-input.tsx +0 -56
  150. package/src/components/ui/section-card.tsx +0 -85
  151. package/src/components/ui/select.tsx +0 -158
  152. package/src/components/ui/separator.tsx +0 -29
  153. package/src/components/ui/skeleton.tsx +0 -115
  154. package/src/components/ui/slider.tsx +0 -26
  155. package/src/components/ui/sonner.tsx +0 -28
  156. package/src/components/ui/spinner.tsx +0 -21
  157. package/src/components/ui/stack.tsx +0 -55
  158. package/src/components/ui/status-badge.tsx +0 -128
  159. package/src/components/ui/switch.tsx +0 -27
  160. package/src/components/ui/tabs.tsx +0 -53
  161. package/src/components/ui/tag-editor.tsx +0 -111
  162. package/src/components/ui/tag-input.tsx +0 -108
  163. package/src/components/ui/textarea.tsx +0 -24
  164. package/src/components/ui/themed-select.tsx +0 -141
  165. package/src/components/ui/tooltip-extended.tsx +0 -340
  166. package/src/components/ui/tooltip.tsx +0 -28
  167. package/src/components/ui/typography.tsx +0 -74
  168. package/src/lib/button-styles.ts +0 -19
  169. package/tsconfig.build.json +0 -18
  170. package/tsconfig.json +0 -32
  171. /package/{src/styles → styles}/theme.css +0 -0
@@ -1,141 +0,0 @@
1
- /**
2
- * ThemedSelect — custom dropdown with grouped options.
3
- *
4
- * A generic, fully-controlled select component that supports grouped option
5
- * lists and optional hint text per item. Has no dependency on any app-level
6
- * context; all state is passed in as props.
7
- */
8
-
9
- import { useEffect, useRef, useState } from "react";
10
- import { Button } from "./button";
11
-
12
- export interface ThemedSelectGroup<T extends string = string> {
13
- label: string;
14
- items: { id: T; text: string; hint?: string }[];
15
- }
16
-
17
- export interface ThemedSelectProps<T extends string = string> {
18
- value: T | null;
19
- groups: ThemedSelectGroup<T>[];
20
- onChange: (id: T) => void;
21
- placeholder?: string;
22
- menuPlacement?: "top" | "bottom";
23
- className?: string;
24
- triggerClassName?: string;
25
- menuClassName?: string;
26
- }
27
-
28
- export function ThemedSelect<T extends string>({
29
- value,
30
- groups,
31
- onChange,
32
- placeholder = "select...",
33
- menuPlacement = "bottom",
34
- className = "",
35
- triggerClassName = "",
36
- menuClassName = "",
37
- }: ThemedSelectProps<T>) {
38
- const [open, setOpen] = useState(false);
39
- const ref = useRef<HTMLDivElement>(null);
40
-
41
- // Close on outside click
42
- useEffect(() => {
43
- if (!open) return;
44
- const handler = (e: MouseEvent) => {
45
- if (ref.current && !ref.current.contains(e.target as Node))
46
- setOpen(false);
47
- };
48
- document.addEventListener("mousedown", handler);
49
- return () => document.removeEventListener("mousedown", handler);
50
- }, [open]);
51
-
52
- // Close on Escape
53
- useEffect(() => {
54
- if (!open) return;
55
- const handler = (e: KeyboardEvent) => {
56
- if (e.key === "Escape") setOpen(false);
57
- };
58
- document.addEventListener("keydown", handler);
59
- return () => document.removeEventListener("keydown", handler);
60
- }, [open]);
61
-
62
- // Find current label
63
- let currentLabel = placeholder;
64
- for (const g of groups) {
65
- const found = g.items.find((i) => i.id === value);
66
- if (found) {
67
- currentLabel = found.hint ? `${found.text} — ${found.hint}` : found.text;
68
- break;
69
- }
70
- }
71
-
72
- const menuStyle =
73
- menuPlacement === "top"
74
- ? { bottom: "calc(100% + 0.125rem)" }
75
- : { top: "calc(100% + 0.125rem)" };
76
-
77
- return (
78
- <div
79
- ref={ref}
80
- className={`relative min-w-0 w-full ${open ? "z-[100]" : ""} ${className}`}
81
- >
82
- <Button
83
- type="button"
84
- variant="outline"
85
- size="sm"
86
- className={`flex h-12 w-full items-center justify-between border-border bg-card px-2.5 py-1.5 text-left text-xs shadow-sm hover:border-accent focus-visible:ring-1 focus-visible:ring-accent ${triggerClassName}`}
87
- onClick={() => setOpen(!open)}
88
- >
89
- <span className="truncate">{currentLabel}</span>
90
- <span
91
- className={`ml-2 text-[10px] text-muted transition-transform ${open ? "rotate-180" : ""}`}
92
- >
93
- &#9660;
94
- </span>
95
- </Button>
96
-
97
- {open && (
98
- <div
99
- className={`absolute left-0 right-0 z-50 max-h-[280px] overflow-y-auto rounded-md border border-border bg-card shadow-lg ${menuClassName}`}
100
- style={menuStyle}
101
- >
102
- {groups.map((g) => (
103
- <div key={g.label}>
104
- <div className="px-2.5 py-1 text-[10px] font-semibold text-muted bg-bg-muted sticky top-0">
105
- {g.label}
106
- </div>
107
- {g.items.map((item) => {
108
- const active = item.id === value;
109
- return (
110
- <Button
111
- key={item.id}
112
- variant="ghost"
113
- size="sm"
114
- className={`w-full justify-start text-left px-2.5 py-1.5 h-auto text-xs rounded-none ${
115
- active
116
- ? "bg-accent text-accent-foreground"
117
- : "text-txt hover:bg-bg-muted"
118
- }`}
119
- onClick={() => {
120
- onChange(item.id);
121
- setOpen(false);
122
- }}
123
- >
124
- <span className="font-semibold">{item.text}</span>
125
- {item.hint && (
126
- <span
127
- className={`ml-1.5 ${active ? "opacity-70" : "text-muted"}`}
128
- >
129
- {item.hint}
130
- </span>
131
- )}
132
- </Button>
133
- );
134
- })}
135
- </div>
136
- ))}
137
- </div>
138
- )}
139
- </div>
140
- );
141
- }
@@ -1,340 +0,0 @@
1
- /**
2
- * Extended tooltip components for contextual help, icon buttons, guided
3
- * tours, and spotlight onboarding overlays.
4
- *
5
- * All exports here are framework-agnostic (no app context dependency).
6
- *
7
- * Note: The Radix-based `Tooltip` is exported from `./tooltip`. This file
8
- * exports a custom CSS-only hover tooltip (`HoverTooltip`), `IconTooltip`,
9
- * `Spotlight`, and `useGuidedTour`.
10
- */
11
-
12
- import { X } from "lucide-react";
13
- import { useCallback, useEffect, useRef, useState } from "react";
14
-
15
- /* ── HoverTooltip ────────────────────────────────────────────────────── */
16
-
17
- /**
18
- * CSS-only hover tooltip that wraps any element in a `<button>` and shows
19
- * a floating content panel on hover/focus. Supports controlled `visible`
20
- * mode and an optional dismiss button.
21
- *
22
- * Use `IconTooltip` for a div-based (non-button) variant that is safe to
23
- * wrap interactive children.
24
- */
25
- export interface HoverTooltipProps {
26
- children: React.ReactNode;
27
- content: React.ReactNode;
28
- position?: "top" | "bottom" | "left" | "right";
29
- delay?: number;
30
- showArrow?: boolean;
31
- className?: string;
32
- visible?: boolean;
33
- onDismiss?: () => void;
34
- }
35
-
36
- export function HoverTooltip({
37
- children,
38
- content,
39
- position = "top",
40
- delay = 300,
41
- showArrow = true,
42
- className = "",
43
- visible: controlledVisible,
44
- onDismiss,
45
- }: HoverTooltipProps) {
46
- const [isVisible, setIsVisible] = useState(false);
47
- const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
48
- const containerRef = useRef<HTMLButtonElement>(null);
49
- const isVisibleState =
50
- controlledVisible !== undefined ? controlledVisible : isVisible;
51
-
52
- const show = useCallback(() => {
53
- if (timeoutRef.current) clearTimeout(timeoutRef.current);
54
- timeoutRef.current = setTimeout(() => setIsVisible(true), delay);
55
- }, [delay]);
56
-
57
- const hide = useCallback(() => {
58
- if (timeoutRef.current) clearTimeout(timeoutRef.current);
59
- timeoutRef.current = setTimeout(() => setIsVisible(false), 150);
60
- }, []);
61
-
62
- useEffect(() => {
63
- return () => {
64
- if (timeoutRef.current) clearTimeout(timeoutRef.current);
65
- };
66
- }, []);
67
-
68
- const positionClasses = {
69
- top: "bottom-full left-1/2 -translate-x-1/2 mb-2",
70
- bottom: "top-full left-1/2 -translate-x-1/2 mt-2",
71
- left: "right-full top-1/2 -translate-y-1/2 mr-2",
72
- right: "left-full top-1/2 -translate-y-1/2 ml-2",
73
- };
74
-
75
- const arrowClasses = {
76
- top: "top-full left-1/2 -translate-x-1/2 border-t-border border-l-transparent border-r-transparent border-b-transparent",
77
- bottom:
78
- "bottom-full left-1/2 -translate-x-1/2 border-b-border border-l-transparent border-r-transparent border-t-transparent",
79
- left: "left-full top-1/2 -translate-y-1/2 border-l-border border-t-transparent border-b-transparent border-r-transparent",
80
- right:
81
- "right-full top-1/2 -translate-y-1/2 border-r-border border-t-transparent border-b-transparent border-l-transparent",
82
- };
83
-
84
- return (
85
- <button
86
- type="button"
87
- ref={containerRef}
88
- className="relative inline-flex bg-transparent border-0 p-0 cursor-default"
89
- onMouseEnter={show}
90
- onMouseLeave={hide}
91
- onFocus={show}
92
- onBlur={hide}
93
- >
94
- {children}
95
-
96
- {isVisibleState && (
97
- <div
98
- className={`absolute z-50 ${positionClasses[position]} ${className}`}
99
- >
100
- <div className="relative bg-bg-elevated border border-border rounded-lg shadow-xl p-3 max-w-xs">
101
- {onDismiss && (
102
- <button
103
- type="button"
104
- onClick={onDismiss}
105
- className="absolute top-1 right-1 p-1 text-muted hover:text-txt rounded"
106
- aria-label="Dismiss tooltip"
107
- >
108
- <X className="w-3 h-3" />
109
- </button>
110
- )}
111
- {content}
112
-
113
- {showArrow && (
114
- <div
115
- className={`absolute w-0 h-0 border-4 ${arrowClasses[position]}`}
116
- />
117
- )}
118
- </div>
119
- </div>
120
- )}
121
- </button>
122
- );
123
- }
124
-
125
- /* ── IconTooltip ─────────────────────────────────────────────────────── */
126
-
127
- /**
128
- * Lightweight tooltip for icon buttons.
129
- *
130
- * Uses a `<div>` wrapper (not `<button>`) so it can safely wrap interactive
131
- * elements like icon buttons without nesting buttons.
132
- */
133
- export function IconTooltip({
134
- children,
135
- label,
136
- shortcut,
137
- position = "top",
138
- }: {
139
- children: React.ReactNode;
140
- label: string;
141
- shortcut?: string;
142
- position?: "top" | "bottom";
143
- }) {
144
- const posClass =
145
- position === "top"
146
- ? "bottom-full left-1/2 -translate-x-1/2 mb-2"
147
- : "top-full left-1/2 -translate-x-1/2 mt-2";
148
- const arrowClass =
149
- position === "top"
150
- ? "top-full left-1/2 -translate-x-1/2 -mt-1 border-4 border-transparent border-t-bg-elevated"
151
- : "bottom-full left-1/2 -translate-x-1/2 -mb-1 border-4 border-transparent border-b-bg-elevated";
152
-
153
- return (
154
- <div className="relative group">
155
- {children}
156
- <div
157
- className={`absolute ${posClass} px-2 py-1 bg-bg-elevated border border-border text-[11px] text-txt-strong rounded-md whitespace-nowrap opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all duration-200 z-50 shadow-lg pointer-events-none`}
158
- role="tooltip"
159
- >
160
- <div className="font-medium">{label}</div>
161
- {shortcut && <div className="text-muted mt-0.5">{shortcut}</div>}
162
- <div className={`absolute ${arrowClass}`} />
163
- </div>
164
- </div>
165
- );
166
- }
167
-
168
- /* ── Spotlight ───────────────────────────────────────────────────────── */
169
-
170
- export interface SpotlightProps {
171
- target: string;
172
- title: string;
173
- description: string;
174
- step: number;
175
- totalSteps: number;
176
- onNext: () => void;
177
- onPrev: () => void;
178
- onSkip: () => void;
179
- /** Labels to override defaults. */
180
- labels?: {
181
- stepOf?: string;
182
- skipTour?: string;
183
- previous?: string;
184
- finish?: string;
185
- next?: string;
186
- };
187
- }
188
-
189
- export function Spotlight({
190
- target,
191
- title,
192
- description,
193
- step,
194
- totalSteps,
195
- onNext,
196
- onPrev,
197
- onSkip,
198
- labels = {},
199
- }: SpotlightProps) {
200
- const [targetRect, setTargetRect] = useState<DOMRect | null>(null);
201
-
202
- useEffect(() => {
203
- const element = document.querySelector(target);
204
- if (element) {
205
- const rect = element.getBoundingClientRect();
206
- setTargetRect(rect);
207
- }
208
- }, [target]);
209
-
210
- if (!targetRect) return null;
211
-
212
- const padding = 8;
213
-
214
- return (
215
- <div className="fixed inset-0 z-[300] pointer-events-none">
216
- {/* Backdrop with cutout */}
217
- <div
218
- className="absolute inset-0 bg-black/60 pointer-events-auto"
219
- style={{
220
- clipPath: `polygon(
221
- 0% 0%,
222
- 0% 100%,
223
- ${targetRect.left - padding}px 100%,
224
- ${targetRect.left - padding}px ${targetRect.top - padding}px,
225
- ${targetRect.right + padding}px ${targetRect.top - padding}px,
226
- ${targetRect.right + padding}px ${targetRect.bottom + padding}px,
227
- ${targetRect.left - padding}px ${targetRect.bottom + padding}px,
228
- ${targetRect.left - padding}px 100%,
229
- 100% 100%,
230
- 100% 0%
231
- )`,
232
- }}
233
- />
234
-
235
- {/* Tooltip card */}
236
- <div
237
- className="absolute bg-card border border-border rounded-xl shadow-2xl p-5 max-w-sm pointer-events-auto"
238
- style={{
239
- top: targetRect.bottom + padding + 16,
240
- left: Math.min(targetRect.left, window.innerWidth - 340),
241
- }}
242
- >
243
- <div className="flex items-center justify-between mb-3">
244
- <span className="text-xs text-muted font-medium">
245
- {labels.stepOf ?? "Step"} {step} of {totalSteps}
246
- </span>
247
- <button
248
- type="button"
249
- onClick={onSkip}
250
- className="text-xs text-muted hover:text-txt"
251
- >
252
- {labels.skipTour ?? "Skip Tour"}
253
- </button>
254
- </div>
255
-
256
- <h3 className="text-lg font-bold text-txt-strong mb-2">{title}</h3>
257
- <p className="text-sm text-muted mb-4">{description}</p>
258
-
259
- <div className="flex items-center justify-between">
260
- <button
261
- type="button"
262
- onClick={onPrev}
263
- disabled={step === 1}
264
- className="px-4 py-2 text-sm border border-border rounded-lg disabled:opacity-40 disabled:cursor-not-allowed hover:bg-bg-hover transition-colors"
265
- >
266
- {labels.previous ?? "Previous"}
267
- </button>
268
-
269
- <div className="flex gap-1">
270
- {Array.from({ length: totalSteps }, (_, idx) => idx).map(
271
- (dotIndex) => (
272
- <div
273
- key={`step-dot-${dotIndex}`}
274
- className={`w-2 h-2 rounded-full transition-colors ${
275
- dotIndex + 1 === step ? "bg-accent" : "bg-border"
276
- }`}
277
- />
278
- ),
279
- )}
280
- </div>
281
-
282
- <button
283
- type="button"
284
- onClick={onNext}
285
- className="px-4 py-2 text-sm bg-accent text-accent-fg rounded-lg hover:opacity-90 transition-opacity"
286
- >
287
- {step === totalSteps
288
- ? (labels.finish ?? "Finish")
289
- : (labels.next ?? "Next")}
290
- </button>
291
- </div>
292
- </div>
293
- </div>
294
- );
295
- }
296
-
297
- /* ── useGuidedTour ───────────────────────────────────────────────────── */
298
-
299
- export interface TourStep {
300
- target: string;
301
- title: string;
302
- description: string;
303
- }
304
-
305
- export function useGuidedTour(steps: TourStep[]) {
306
- const [isActive, setIsActive] = useState(false);
307
- const [currentStep, setCurrentStep] = useState(0);
308
-
309
- const start = useCallback(() => {
310
- setIsActive(true);
311
- setCurrentStep(0);
312
- }, []);
313
-
314
- const next = useCallback(() => {
315
- if (currentStep < steps.length - 1) {
316
- setCurrentStep((prev) => prev + 1);
317
- } else {
318
- setIsActive(false);
319
- }
320
- }, [currentStep, steps.length]);
321
-
322
- const prev = useCallback(() => {
323
- setCurrentStep((prev) => Math.max(0, prev - 1));
324
- }, []);
325
-
326
- const skip = useCallback(() => {
327
- setIsActive(false);
328
- }, []);
329
-
330
- return {
331
- isActive,
332
- currentStep,
333
- step: steps[currentStep],
334
- start,
335
- next,
336
- prev,
337
- skip,
338
- totalSteps: steps.length,
339
- };
340
- }
@@ -1,28 +0,0 @@
1
- import * as TooltipPrimitive from "@radix-ui/react-tooltip";
2
- import * as React from "react";
3
-
4
- import { cn } from "../../lib/utils";
5
-
6
- const TooltipProvider = TooltipPrimitive.Provider;
7
-
8
- const Tooltip = TooltipPrimitive.Root;
9
-
10
- const TooltipTrigger = TooltipPrimitive.Trigger;
11
-
12
- const TooltipContent = React.forwardRef<
13
- React.ElementRef<typeof TooltipPrimitive.Content>,
14
- React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>
15
- >(({ className, sideOffset = 4, ...props }, ref) => (
16
- <TooltipPrimitive.Content
17
- ref={ref}
18
- sideOffset={sideOffset}
19
- className={cn(
20
- "z-50 overflow-hidden rounded-md border border-border bg-card px-3 py-1.5 text-sm text-txt shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
21
- className,
22
- )}
23
- {...props}
24
- />
25
- ));
26
- TooltipContent.displayName = TooltipPrimitive.Content.displayName;
27
-
28
- export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger };
@@ -1,74 +0,0 @@
1
- import { cva, type VariantProps } from "class-variance-authority";
2
- import * as React from "react";
3
-
4
- import { cn } from "../../lib/utils";
5
-
6
- const textVariants = cva("text-txt", {
7
- variants: {
8
- variant: {
9
- default: "text-base",
10
- medium: "text-sm",
11
- small: "text-xs",
12
- muted: "text-sm text-muted",
13
- lead: "text-xl text-muted",
14
- large: "text-lg font-semibold",
15
- },
16
- },
17
- defaultVariants: {
18
- variant: "default",
19
- },
20
- });
21
-
22
- export interface TextProps
23
- extends React.HTMLAttributes<HTMLParagraphElement>,
24
- VariantProps<typeof textVariants> {
25
- asChild?: boolean;
26
- }
27
-
28
- export const Text = React.forwardRef<HTMLParagraphElement, TextProps>(
29
- ({ className, variant, asChild = false, ...props }, ref) => {
30
- const Comp = asChild ? "span" : "p";
31
- return (
32
- <Comp
33
- ref={ref}
34
- className={cn(textVariants({ variant }), className)}
35
- {...props}
36
- />
37
- );
38
- },
39
- );
40
- Text.displayName = "Text";
41
-
42
- const headingVariants = cva("text-txt font-semibold tracking-tight", {
43
- variants: {
44
- level: {
45
- h1: "text-4xl font-extrabold lg:text-5xl",
46
- h2: "text-3xl",
47
- h3: "text-2xl",
48
- h4: "text-xl",
49
- h5: "text-lg",
50
- h6: "text-base",
51
- },
52
- },
53
- defaultVariants: {
54
- level: "h1",
55
- },
56
- });
57
-
58
- export interface HeadingProps
59
- extends React.HTMLAttributes<HTMLHeadingElement>,
60
- VariantProps<typeof headingVariants> {}
61
-
62
- export const Heading = React.forwardRef<HTMLHeadingElement, HeadingProps>(
63
- ({ className, level = "h1", ...props }, ref) => {
64
- const Comp = level || "h1";
65
- return (
66
- <Comp
67
- ref={ref}
68
- className={cn(headingVariants({ level }), className)}
69
- {...props}
70
- />
71
- );
72
- },
73
- );
74
- Heading.displayName = "Heading";
@@ -1,19 +0,0 @@
1
- /**
2
- * Shared button class strings for consistent styling across views.
3
- *
4
- * These CSS class strings complement the `Button` component for cases where
5
- * a plain HTML `button` element is used or Tailwind class composition is
6
- * preferred over the variant prop.
7
- */
8
-
9
- export const btnPrimary =
10
- "px-4 py-2 text-sm font-medium bg-[var(--accent)] text-[var(--accent-foreground,#1a1f26)] border border-[var(--accent)] cursor-pointer hover:opacity-90 transition-opacity disabled:opacity-40 disabled:cursor-default rounded-lg";
11
-
12
- export const btnGhost =
13
- "px-3 py-1.5 text-xs bg-transparent text-[var(--muted)] border border-[var(--border)] cursor-pointer hover:text-[var(--txt)] hover:border-[var(--txt)] transition-colors disabled:opacity-40 disabled:cursor-default rounded-lg";
14
-
15
- export const btnDanger =
16
- "px-3 py-1.5 text-xs bg-transparent text-[var(--danger,#e74c3c)] border border-[var(--danger,#e74c3c)] cursor-pointer hover:bg-[var(--danger,#e74c3c)] hover:text-white transition-colors disabled:opacity-40 disabled:cursor-default rounded-lg";
17
-
18
- export const inputCls =
19
- "flex-1 px-3 py-2 text-sm bg-[var(--card)] border border-[var(--border)] text-[var(--txt)] focus:border-[var(--accent)] focus:outline-none transition-colors rounded-lg";
@@ -1,18 +0,0 @@
1
- {
2
- "extends": "./tsconfig.json",
3
- "compilerOptions": {
4
- "declaration": true,
5
- "declarationMap": true,
6
- "noEmit": false,
7
- "outDir": "./dist",
8
- "rootDir": "./src",
9
- "tsBuildInfoFile": "./dist/.tsbuildinfo"
10
- },
11
- "exclude": [
12
- "src/**/*.stories.ts",
13
- "src/**/*.stories.tsx",
14
- "src/**/*.test.ts",
15
- "src/**/*.test.tsx"
16
- ],
17
- "include": ["src"]
18
- }
package/tsconfig.json DELETED
@@ -1,32 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ESNext",
4
- "useDefineForClassFields": true,
5
- "lib": ["DOM", "DOM.Iterable", "ESNext"],
6
- "allowJs": false,
7
- "skipLibCheck": true,
8
- "esModuleInterop": false,
9
- "allowSyntheticDefaultImports": true,
10
- "strict": true,
11
- "forceConsistentCasingInFileNames": true,
12
- "module": "ESNext",
13
- "moduleResolution": "bundler",
14
- "resolveJsonModule": true,
15
- "isolatedModules": true,
16
- "noEmit": true,
17
- "jsx": "react-jsx",
18
- "types": ["node"],
19
- "baseUrl": ".",
20
- "paths": {
21
- "@ui/*": ["./src/*"]
22
- }
23
- },
24
- "exclude": [
25
- "src/**/*.stories.ts",
26
- "src/**/*.stories.tsx",
27
- "src/**/*.test.ts",
28
- "src/**/*.test.tsx"
29
- ],
30
- "include": ["src"],
31
- "references": []
32
- }
File without changes