@moontra/moonui 2.1.9 → 2.2.1

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 (64) hide show
  1. package/dist/index.d.mts +1656 -0
  2. package/dist/index.d.ts +1656 -0
  3. package/dist/index.js +1847 -469
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.mjs +1679 -471
  6. package/dist/index.mjs.map +1 -1
  7. package/package.json +4 -4
  8. package/src/components/ui/accordion.tsx +1 -1
  9. package/src/components/ui/alert.tsx +123 -93
  10. package/src/components/ui/aspect-ratio.tsx +1 -1
  11. package/src/components/ui/avatar.tsx +8 -6
  12. package/src/components/ui/badge.tsx +20 -18
  13. package/src/components/ui/breadcrumb.tsx +12 -10
  14. package/src/components/ui/button.stories.tsx +4 -2
  15. package/src/components/ui/button.tsx +71 -68
  16. package/src/components/ui/calendar.tsx +2 -2
  17. package/src/components/ui/card-input.tsx +231 -0
  18. package/src/components/ui/card.stories.tsx +2 -0
  19. package/src/components/ui/card.tsx +9 -7
  20. package/src/components/ui/checkbox.tsx +1 -1
  21. package/src/components/ui/collapsible.tsx +3 -3
  22. package/src/components/ui/color-picker.tsx +2 -2
  23. package/src/components/ui/command.tsx +4 -4
  24. package/src/components/ui/data-table.stories.tsx +4 -2
  25. package/src/components/ui/data-table.tsx +8 -8
  26. package/src/components/ui/date-picker.stories.tsx +2 -0
  27. package/src/components/ui/date-picker.tsx +25 -15
  28. package/src/components/ui/dialog.tsx +2 -2
  29. package/src/components/ui/draggable-list.tsx +3 -1
  30. package/src/components/ui/dropdown-menu.tsx +2 -2
  31. package/src/components/ui/file-upload.tsx +2 -2
  32. package/src/components/ui/github-stars.tsx +1 -1
  33. package/src/components/ui/index.ts +357 -45
  34. package/src/components/ui/input.stories.tsx +2 -0
  35. package/src/components/ui/input.tsx +3 -1
  36. package/src/components/ui/locked-component.tsx +222 -0
  37. package/src/components/ui/moon-logo.tsx +1 -1
  38. package/src/components/ui/pagination.tsx +10 -8
  39. package/src/components/ui/phone-input.tsx +172 -0
  40. package/src/components/ui/popover-pro.tsx +424 -0
  41. package/src/components/ui/popover.tsx +3 -3
  42. package/src/components/ui/progress.tsx +1 -1
  43. package/src/components/ui/radio-group.tsx +1 -1
  44. package/src/components/ui/rich-text-editor/index.tsx +2 -1
  45. package/src/components/ui/scroll-area.tsx +48 -0
  46. package/src/components/ui/select.tsx +7 -3
  47. package/src/components/ui/separator.tsx +2 -2
  48. package/src/components/ui/skeleton.tsx +19 -7
  49. package/src/components/ui/slider.tsx +1 -1
  50. package/src/components/ui/swipeable-card.tsx +2 -0
  51. package/src/components/ui/switch.tsx +1 -1
  52. package/src/components/ui/table.tsx +7 -5
  53. package/src/components/ui/tabs.tsx +6 -1
  54. package/src/components/ui/tags-input.tsx +130 -0
  55. package/src/components/ui/textarea.tsx +3 -1
  56. package/src/components/ui/toast.tsx +5 -3
  57. package/src/components/ui/toggle.tsx +2 -3
  58. package/src/components/ui/tooltip.tsx +2 -5
  59. package/src/index.tsx +4 -46
  60. package/src/lib/micro-interactions.ts +2 -1
  61. package/src/lib/performance-profiler.ts +79 -0
  62. package/src/styles/index.css +315 -2
  63. package/src/use-performance-optimizer.ts +26 -26
  64. package/src/use-scroll-animation.ts +5 -7
@@ -1,3 +1,5 @@
1
+ "use client"
2
+
1
3
  import * as React from "react";
2
4
  import { cva, type VariantProps } from "class-variance-authority";
3
5
 
@@ -127,7 +129,7 @@ const TableHeader = React.forwardRef<
127
129
  HTMLTableSectionElement,
128
130
  React.HTMLAttributes<HTMLTableSectionElement>
129
131
  >(({ className, ...props }, ref) => (
130
- <thead ref={ref} className={cn("[&_tr]:border-b", className)} {...props} />
132
+ <thead ref={ref} className={cn("moonui-theme", "[&_tr]:border-b", className)} {...props} />
131
133
  ));
132
134
  TableHeader.displayName = "TableHeader";
133
135
 
@@ -148,7 +150,7 @@ const TableBody = React.forwardRef<
148
150
  return (
149
151
  <tbody
150
152
  ref={ref}
151
- className={cn("[&_tr:last-child]:border-0", className)}
153
+ className={cn("moonui-theme", "[&_tr:last-child]:border-0", className)}
152
154
  {...props}
153
155
  >
154
156
  {hasChildren ? (
@@ -177,7 +179,7 @@ const TableFooter = React.forwardRef<
177
179
  >(({ className, ...props }, ref) => (
178
180
  <tfoot
179
181
  ref={ref}
180
- className={cn("bg-primary text-primary-foreground font-medium", className)}
182
+ className={cn("moonui-theme", "bg-primary text-primary-foreground font-medium", className)}
181
183
  {...props}
182
184
  />
183
185
  ));
@@ -290,7 +292,7 @@ const TableCell = React.forwardRef<
290
292
  >(({ className, ...props }, ref) => (
291
293
  <td
292
294
  ref={ref}
293
- className={cn("p-4 align-middle [&:has([role=checkbox])]:pr-0", className)}
295
+ className={cn("moonui-theme", "p-4 align-middle [&:has([role=checkbox])]:pr-0", className)}
294
296
  {...props}
295
297
  />
296
298
  ));
@@ -302,7 +304,7 @@ const TableCaption = React.forwardRef<
302
304
  >(({ className, ...props }, ref) => (
303
305
  <caption
304
306
  ref={ref}
305
- className={cn("mt-4 text-sm text-muted-foreground", className)}
307
+ className={cn("moonui-theme", "mt-4 text-sm text-muted-foreground", className)}
306
308
  {...props}
307
309
  />
308
310
  ));
@@ -1,3 +1,5 @@
1
+ "use client"
2
+
1
3
  import * as React from "react";
2
4
  import * as TabsPrimitive from "@radix-ui/react-tabs";
3
5
  import { cva, type VariantProps } from "class-variance-authority";
@@ -18,6 +20,7 @@ const Tabs = React.forwardRef<
18
20
  >(({ vertical = false, ...props }, ref) => (
19
21
  <TabsPrimitive.Root
20
22
  ref={ref}
23
+ className={cn("moonui-theme", props.className)}
21
24
  orientation={vertical ? "vertical" : "horizontal"}
22
25
  {...props}
23
26
  />
@@ -68,7 +71,7 @@ const TabsList = React.forwardRef<
68
71
  >(({ className, variant, orientation, fullWidth, ...props }, ref) => (
69
72
  <TabsPrimitive.List
70
73
  ref={ref}
71
- className={cn(tabsListVariants({ variant, orientation, fullWidth, className }))}
74
+ className={cn("moonui-theme", tabsListVariants({ variant, orientation, fullWidth, className }))}
72
75
  {...props}
73
76
  />
74
77
  ));
@@ -145,6 +148,7 @@ const TabsTrigger = React.forwardRef<
145
148
  <TabsPrimitive.Trigger
146
149
  ref={ref}
147
150
  className={cn(
151
+ "moonui-theme",
148
152
  tabsTriggerVariants({ variant, size, orientation, fullWidth }),
149
153
  fadeTabs && "data-[state=inactive]:opacity-60",
150
154
  className
@@ -182,6 +186,7 @@ const TabsContent = React.forwardRef<
182
186
  <TabsPrimitive.Content
183
187
  ref={ref}
184
188
  className={cn(
189
+ "moonui-theme",
185
190
  "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
186
191
  animated && "data-[state=active]:animate-fadeIn data-[state=inactive]:animate-fadeOut",
187
192
  className
@@ -0,0 +1,130 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import { X } from "lucide-react";
5
+ import { cn } from "../../lib/utils";
6
+ import { Badge } from "./badge";
7
+
8
+ export interface TagsInputProps
9
+ extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "value" | "onChange"> {
10
+ value: string[];
11
+ onChange: (tags: string[]) => void;
12
+ maxTags?: number;
13
+ variant?: "primary" | "secondary" | "destructive" | "outline";
14
+ allowDuplicates?: boolean;
15
+ delimiter?: string;
16
+ }
17
+
18
+ const TagsInput = React.forwardRef<HTMLInputElement, TagsInputProps>(
19
+ (
20
+ {
21
+ value = [],
22
+ onChange,
23
+ maxTags,
24
+ variant = "primary",
25
+ allowDuplicates = false,
26
+ delimiter = ",",
27
+ placeholder = "Add tag and press Enter",
28
+ className,
29
+ disabled,
30
+ ...props
31
+ },
32
+ ref
33
+ ) => {
34
+ const [inputValue, setInputValue] = React.useState("");
35
+ const [error, setError] = React.useState("");
36
+
37
+ const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
38
+ if (e.key === "Enter" || e.key === delimiter) {
39
+ e.preventDefault();
40
+ addTag();
41
+ } else if (e.key === "Backspace" && inputValue === "" && value.length > 0) {
42
+ removeTag(value.length - 1);
43
+ }
44
+ };
45
+
46
+ const addTag = () => {
47
+ const tag = inputValue.trim();
48
+
49
+ if (!tag) return;
50
+
51
+ if (!allowDuplicates && value.includes(tag)) {
52
+ setError("This tag already exists");
53
+ setTimeout(() => setError(""), 2000);
54
+ return;
55
+ }
56
+
57
+ if (maxTags && value.length >= maxTags) {
58
+ setError(`Maximum ${maxTags} tags allowed`);
59
+ setTimeout(() => setError(""), 2000);
60
+ return;
61
+ }
62
+
63
+ onChange([...value, tag]);
64
+ setInputValue("");
65
+ setError("");
66
+ };
67
+
68
+ const removeTag = (index: number) => {
69
+ if (disabled) return;
70
+ onChange(value.filter((_, i) => i !== index));
71
+ };
72
+
73
+ return (
74
+ <div className="relative">
75
+ <div
76
+ className={cn(
77
+ "flex min-h-[2.5rem] w-full flex-wrap gap-2 rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background",
78
+ "dark:bg-zinc-950/50 dark:border-zinc-800",
79
+ "focus-within:outline-none focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2",
80
+ disabled && "cursor-not-allowed opacity-50",
81
+ className
82
+ )}
83
+ >
84
+ {value.map((tag, index) => (
85
+ <Badge
86
+ key={index}
87
+ variant={variant}
88
+ className="gap-1 pr-1.5"
89
+ >
90
+ <span className="text-xs">{tag}</span>
91
+ {!disabled && (
92
+ <button
93
+ type="button"
94
+ onClick={() => removeTag(index)}
95
+ className="ml-1 rounded-full outline-none ring-offset-background focus:ring-2 focus:ring-ring focus:ring-offset-2"
96
+ >
97
+ <X className="h-3 w-3 text-muted-foreground hover:text-foreground transition-colors" />
98
+ </button>
99
+ )}
100
+ </Badge>
101
+ ))}
102
+ <input
103
+ ref={ref}
104
+ type="text"
105
+ value={inputValue}
106
+ onChange={(e) => setInputValue(e.target.value)}
107
+ onKeyDown={handleKeyDown}
108
+ onBlur={addTag}
109
+ disabled={disabled}
110
+ placeholder={value.length === 0 ? placeholder : ""}
111
+ className={cn(
112
+ "flex-1 bg-transparent outline-none placeholder:text-muted-foreground",
113
+ "dark:placeholder:text-zinc-500",
114
+ "min-w-[120px]",
115
+ disabled && "cursor-not-allowed"
116
+ )}
117
+ {...props}
118
+ />
119
+ </div>
120
+ {error && (
121
+ <p className="mt-1 text-xs text-destructive">{error}</p>
122
+ )}
123
+ </div>
124
+ );
125
+ }
126
+ );
127
+
128
+ TagsInput.displayName = "TagsInput";
129
+
130
+ export { TagsInput };
@@ -1,3 +1,5 @@
1
+ "use client"
2
+
1
3
  import * as React from "react"
2
4
 
3
5
  import { cn } from "../../lib/utils"
@@ -31,7 +33,7 @@ const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
31
33
  }, ref) => {
32
34
  return (
33
35
  <textarea
34
- className={cn(
36
+ className={cn("moonui-theme",
35
37
  "flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
36
38
  className
37
39
  )}
@@ -57,7 +57,7 @@ const Toast = React.forwardRef<
57
57
  return (
58
58
  <ToastPrimitives.Root
59
59
  ref={ref}
60
- className={cn(toastVariants({ variant }), className)}
60
+ className={cn("moonui-theme", toastVariants({ variant }), className)}
61
61
  {...props}
62
62
  />
63
63
  );
@@ -103,7 +103,7 @@ const ToastTitle = React.forwardRef<
103
103
  >(({ className, ...props }, ref) => (
104
104
  <ToastPrimitives.Title
105
105
  ref={ref}
106
- className={cn("text-sm font-semibold [&+div]:text-xs", className)}
106
+ className={cn("moonui-theme", "text-sm font-semibold [&+div]:text-xs", className)}
107
107
  {...props}
108
108
  />
109
109
  ));
@@ -115,7 +115,7 @@ const ToastDescription = React.forwardRef<
115
115
  >(({ className, ...props }, ref) => (
116
116
  <ToastPrimitives.Description
117
117
  ref={ref}
118
- className={cn("text-sm opacity-90", className)}
118
+ className={cn("moonui-theme", "text-sm opacity-90", className)}
119
119
  {...props}
120
120
  />
121
121
  ));
@@ -207,6 +207,8 @@ const reducer = (state: State, action: any): State => {
207
207
  ...state,
208
208
  toasts: state.toasts.filter((t) => t.id !== action.toastId),
209
209
  };
210
+ default:
211
+ return state;
210
212
  }
211
213
  };
212
214
 
@@ -36,12 +36,11 @@ const Toggle = React.forwardRef<
36
36
  >(({ className, variant, size, ...props }, ref) => (
37
37
  <TogglePrimitive.Root
38
38
  ref={ref}
39
- className={cn(toggleVariants({ variant, size, className }))}
39
+ className={cn("moonui-theme", toggleVariants({ variant, size, className }))}
40
40
  {...props}
41
41
  />
42
42
  ))
43
43
 
44
44
  Toggle.displayName = TogglePrimitive.Root.displayName
45
45
 
46
- export { Toggle, toggleVariants }
47
- export type { ToggleProps }
46
+ export { Toggle, toggleVariants }
@@ -43,7 +43,7 @@ const TooltipArrow = React.forwardRef<
43
43
  >(({ className, ...props }, ref) => (
44
44
  <TooltipPrimitive.Arrow
45
45
  ref={ref}
46
- className={cn("fill-current", className)}
46
+ className={cn("moonui-theme", "fill-current", className)}
47
47
  {...props}
48
48
  />
49
49
  ))
@@ -62,7 +62,7 @@ const TooltipContent = React.forwardRef<
62
62
  <TooltipPrimitive.Content
63
63
  ref={ref}
64
64
  sideOffset={sideOffset}
65
- className={cn(tooltipVariants({ variant, size }), className)}
65
+ className={cn("moonui-theme", tooltipVariants({ variant, size }), className)}
66
66
  {...props}
67
67
  >
68
68
  {props.children}
@@ -80,7 +80,6 @@ export interface SimpleTooltipProps {
80
80
  side?: "top" | "right" | "bottom" | "left"
81
81
  align?: "start" | "center" | "end"
82
82
  delayDuration?: number
83
- skipDelayDuration?: number
84
83
  sideOffset?: number
85
84
  showArrow?: boolean
86
85
  className?: string
@@ -102,7 +101,6 @@ const SimpleTooltip = React.forwardRef<
102
101
  side = "top",
103
102
  align = "center",
104
103
  delayDuration = 400,
105
- skipDelayDuration = 300,
106
104
  sideOffset = 4,
107
105
  showArrow = false,
108
106
  className,
@@ -119,7 +117,6 @@ const SimpleTooltip = React.forwardRef<
119
117
  defaultOpen={defaultOpen}
120
118
  onOpenChange={onOpenChange}
121
119
  delayDuration={delayDuration}
122
- skipDelayDuration={skipDelayDuration}
123
120
  >
124
121
  <TooltipTrigger asChild>{children}</TooltipTrigger>
125
122
  <TooltipContent
package/src/index.tsx CHANGED
@@ -1,47 +1,5 @@
1
- // Core UI Components Export
2
- // Premium components with advanced features
1
+ // Export all components with MoonUI prefix
2
+ export * from "./components/ui";
3
3
 
4
- // Utilities
5
- export { cn } from "./lib/utils"
6
-
7
- export * from "./components/ui/accordion"
8
- export * from "./components/ui/alert"
9
- export * from "./components/ui/aspect-ratio"
10
- export * from "./components/ui/avatar"
11
- export * from "./components/ui/badge"
12
- export * from "./components/ui/breadcrumb"
13
- export * from "./components/ui/button"
14
- export * from "./components/ui/card"
15
- export * from "./components/ui/checkbox"
16
- export * from "./components/ui/collapsible"
17
- export * from "./components/ui/color-picker"
18
- export * from "./components/ui/command"
19
- export * from "./components/ui/data-table"
20
- export * from "./components/ui/date-picker"
21
- export * from "./components/ui/dialog"
22
- export * from "./components/ui/draggable-list"
23
- export * from "./components/ui/dropdown-menu"
24
- export * from "./components/ui/file-upload"
25
- export * from "./components/ui/gesture-drawer"
26
- export * from "./components/ui/github-stars"
27
- export * from "./components/ui/input"
28
- export * from "./components/ui/label"
29
- export * from "./components/ui/moon-logo"
30
- export * from "./components/ui/pagination"
31
- export * from "./components/ui/popover"
32
- export * from "./components/ui/progress"
33
- export * from "./components/ui/radio-group"
34
- export * from "./components/ui/rich-text-editor"
35
- export * from "./components/ui/select"
36
- export * from "./components/ui/separator"
37
- export * from "./components/ui/simple-editor"
38
- export * from "./components/ui/skeleton"
39
- export * from "./components/ui/slider"
40
- export * from "./components/ui/swipeable-card"
41
- export * from "./components/ui/switch"
42
- export * from "./components/ui/table"
43
- export * from "./components/ui/tabs"
44
- export * from "./components/ui/textarea"
45
- export * from "./components/ui/toast"
46
- export * from "./components/ui/toggle"
47
- export * from "./components/ui/tooltip"
4
+ // Re-export utilities
5
+ export { cn } from "./lib/utils";
@@ -252,4 +252,5 @@ export const notificationAnimation = {
252
252
  transition: springAnimations.bouncy,
253
253
  };
254
254
 
255
- export type MicroInteractionProps = VariantProps<typeof microInteractionVariants>;
255
+ export type MicroInteractionProps = VariantProps<typeof microInteractionVariants>;
256
+
@@ -0,0 +1,79 @@
1
+ export interface PerformanceMetric {
2
+ name: string;
3
+ duration: number;
4
+ timestamp: number;
5
+ }
6
+
7
+ export interface PerformanceSummary {
8
+ totalRenderTime: number;
9
+ componentCount: number;
10
+ averageRenderTime: number;
11
+ slowestComponent: string | null;
12
+ memoryUsage?: number;
13
+ }
14
+
15
+ class PerformanceProfiler {
16
+ private measurements: Map<string, PerformanceMetric[]> = new Map();
17
+
18
+ startMeasurement(category: string, name: string): () => void {
19
+ const startTime = performance.now();
20
+
21
+ return () => {
22
+ const endTime = performance.now();
23
+ const duration = endTime - startTime;
24
+
25
+ if (!this.measurements.has(category)) {
26
+ this.measurements.set(category, []);
27
+ }
28
+
29
+ this.measurements.get(category)!.push({
30
+ name,
31
+ duration,
32
+ timestamp: Date.now()
33
+ });
34
+ };
35
+ }
36
+
37
+ getMeasurements(category: string): PerformanceMetric[] {
38
+ return this.measurements.get(category) || [];
39
+ }
40
+
41
+ getPerformanceSummary(): PerformanceSummary {
42
+ const componentMetrics = this.getMeasurements('component');
43
+
44
+ if (componentMetrics.length === 0) {
45
+ return {
46
+ totalRenderTime: 0,
47
+ componentCount: 0,
48
+ averageRenderTime: 0,
49
+ slowestComponent: null
50
+ };
51
+ }
52
+
53
+ const totalRenderTime = componentMetrics.reduce((sum, m) => sum + m.duration, 0);
54
+ const slowestComponent = componentMetrics.reduce((max, m) =>
55
+ m.duration > (max?.duration || 0) ? m : max, componentMetrics[0]);
56
+
57
+ return {
58
+ totalRenderTime,
59
+ componentCount: componentMetrics.length,
60
+ averageRenderTime: totalRenderTime / componentMetrics.length,
61
+ slowestComponent: slowestComponent.name,
62
+ memoryUsage: (performance as any).memory?.usedJSHeapSize
63
+ };
64
+ }
65
+
66
+ clearMeasurements(category?: string): void {
67
+ if (category) {
68
+ this.measurements.delete(category);
69
+ } else {
70
+ this.measurements.clear();
71
+ }
72
+ }
73
+
74
+ measureComponent(componentName: string): () => void {
75
+ return this.startMeasurement('component', componentName);
76
+ }
77
+ }
78
+
79
+ export const performanceProfiler = new PerformanceProfiler();