@moontra/moonui 2.2.0 → 2.2.2
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/dist/index.d.mts +91 -14
- package/dist/index.d.ts +91 -14
- package/dist/index.js +1714 -369
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1546 -371
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/src/components/ui/alert.tsx +123 -93
- package/src/components/ui/avatar.tsx +2 -0
- package/src/components/ui/badge.tsx +19 -17
- package/src/components/ui/breadcrumb.tsx +2 -0
- package/src/components/ui/button.stories.tsx +4 -2
- package/src/components/ui/button.tsx +39 -33
- package/src/components/ui/calendar.tsx +1 -1
- package/src/components/ui/card-input.tsx +231 -0
- package/src/components/ui/card.stories.tsx +2 -0
- package/src/components/ui/card.tsx +2 -0
- package/src/components/ui/data-table.stories.tsx +4 -2
- package/src/components/ui/data-table.tsx +7 -7
- package/src/components/ui/date-picker.stories.tsx +2 -0
- package/src/components/ui/date-picker.tsx +18 -9
- package/src/components/ui/draggable-list.tsx +2 -0
- package/src/components/ui/index.ts +357 -44
- package/src/components/ui/input.stories.tsx +2 -0
- package/src/components/ui/input.tsx +2 -0
- package/src/components/ui/locked-component.tsx +222 -0
- package/src/components/ui/pagination.tsx +2 -0
- package/src/components/ui/phone-input.tsx +172 -0
- package/src/components/ui/popover-pro.tsx +424 -0
- package/src/components/ui/rich-text-editor/index.tsx +2 -1
- package/src/components/ui/scroll-area.tsx +48 -0
- package/src/components/ui/select.tsx +5 -1
- package/src/components/ui/separator.tsx +2 -2
- package/src/components/ui/swipeable-card.tsx +2 -0
- package/src/components/ui/table.tsx +2 -0
- package/src/components/ui/tabs.tsx +2 -0
- package/src/components/ui/tags-input.tsx +130 -0
- package/src/components/ui/textarea.tsx +2 -0
- package/src/components/ui/toast.tsx +2 -0
- package/src/index.tsx +4 -46
- package/src/lib/performance-profiler.ts +79 -0
- package/src/styles/index.css +315 -2
- package/src/use-performance-optimizer.ts +26 -26
- package/src/use-scroll-animation.ts +5 -7
|
@@ -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 };
|
package/src/index.tsx
CHANGED
|
@@ -1,47 +1,5 @@
|
|
|
1
|
-
//
|
|
2
|
-
|
|
1
|
+
// Export all components with MoonUI prefix
|
|
2
|
+
export * from "./components/ui";
|
|
3
3
|
|
|
4
|
-
//
|
|
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";
|
|
@@ -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();
|
package/src/styles/index.css
CHANGED
|
@@ -1,4 +1,317 @@
|
|
|
1
1
|
/* MoonUI - Complete CSS System */
|
|
2
|
-
@
|
|
2
|
+
@tailwind base;
|
|
3
|
+
@tailwind components;
|
|
4
|
+
@tailwind utilities;
|
|
5
|
+
|
|
3
6
|
@import "./tokens.css";
|
|
4
|
-
@import "./design-system.css";
|
|
7
|
+
@import "./design-system.css";
|
|
8
|
+
|
|
9
|
+
/* ======================
|
|
10
|
+
MOONUI COMPONENT STYLES
|
|
11
|
+
====================== */
|
|
12
|
+
|
|
13
|
+
@layer components {
|
|
14
|
+
/* ======================
|
|
15
|
+
BUTTON COMPONENT
|
|
16
|
+
====================== */
|
|
17
|
+
.moonui-button-base {
|
|
18
|
+
@apply inline-flex items-center justify-center rounded-md text-sm font-medium;
|
|
19
|
+
@apply ring-offset-background transition-colors duration-200;
|
|
20
|
+
@apply focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2;
|
|
21
|
+
@apply disabled:pointer-events-none disabled:opacity-50;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/* ======================
|
|
25
|
+
CARD COMPONENT
|
|
26
|
+
====================== */
|
|
27
|
+
.moonui-card-base {
|
|
28
|
+
@apply rounded-lg border bg-card text-card-foreground shadow-sm;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.moonui-card-header {
|
|
32
|
+
@apply flex flex-col space-y-1.5 p-6;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.moonui-card-title {
|
|
36
|
+
@apply text-2xl font-semibold leading-none tracking-tight;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.moonui-card-description {
|
|
40
|
+
@apply text-sm text-muted-foreground;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.moonui-card-content {
|
|
44
|
+
@apply p-6 pt-0;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.moonui-card-footer {
|
|
48
|
+
@apply flex items-center p-6 pt-0;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/* ======================
|
|
52
|
+
INPUT COMPONENT
|
|
53
|
+
====================== */
|
|
54
|
+
.moonui-input-base {
|
|
55
|
+
@apply flex h-10 w-full rounded-md border border-input bg-background px-3 py-2;
|
|
56
|
+
@apply text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium;
|
|
57
|
+
@apply placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2;
|
|
58
|
+
@apply focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/* ======================
|
|
62
|
+
LABEL COMPONENT
|
|
63
|
+
====================== */
|
|
64
|
+
.moonui-label-base {
|
|
65
|
+
@apply text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/* ======================
|
|
69
|
+
DIALOG COMPONENT
|
|
70
|
+
====================== */
|
|
71
|
+
.moonui-dialog-overlay {
|
|
72
|
+
@apply fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out;
|
|
73
|
+
@apply data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.moonui-dialog-content {
|
|
77
|
+
@apply fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%];
|
|
78
|
+
@apply gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in;
|
|
79
|
+
@apply data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0;
|
|
80
|
+
@apply data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2;
|
|
81
|
+
@apply data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2;
|
|
82
|
+
@apply data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/* ======================
|
|
86
|
+
ALERT COMPONENT
|
|
87
|
+
====================== */
|
|
88
|
+
.moonui-alert-base {
|
|
89
|
+
@apply relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute;
|
|
90
|
+
@apply [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.moonui-alert-destructive {
|
|
94
|
+
@apply border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/* ======================
|
|
98
|
+
BADGE COMPONENT
|
|
99
|
+
====================== */
|
|
100
|
+
.moonui-badge-base {
|
|
101
|
+
@apply inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold;
|
|
102
|
+
@apply transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.moonui-badge-default {
|
|
106
|
+
@apply border-transparent bg-primary text-primary-foreground hover:bg-primary/80;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.moonui-badge-secondary {
|
|
110
|
+
@apply border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.moonui-badge-destructive {
|
|
114
|
+
@apply border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.moonui-badge-outline {
|
|
118
|
+
@apply text-foreground;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/* ======================
|
|
122
|
+
TABLE COMPONENT
|
|
123
|
+
====================== */
|
|
124
|
+
.moonui-table-base {
|
|
125
|
+
@apply w-full caption-bottom text-sm;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.moonui-table-header {
|
|
129
|
+
@apply [&_tr]:border-b;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.moonui-table-body {
|
|
133
|
+
@apply [&_tr:last-child]:border-0;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.moonui-table-footer {
|
|
137
|
+
@apply border-t bg-muted/50 font-medium [&>tr]:last:border-b-0;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.moonui-table-row {
|
|
141
|
+
@apply border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.moonui-table-head {
|
|
145
|
+
@apply h-12 px-4 text-left align-middle font-medium text-muted-foreground;
|
|
146
|
+
@apply [&:has([role=checkbox])]:pr-0;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.moonui-table-cell {
|
|
150
|
+
@apply p-4 align-middle [&:has([role=checkbox])]:pr-0;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/* ======================
|
|
154
|
+
TOGGLE COMPONENT
|
|
155
|
+
====================== */
|
|
156
|
+
.moonui-toggle-base {
|
|
157
|
+
@apply inline-flex items-center justify-center rounded-md text-sm font-medium;
|
|
158
|
+
@apply ring-offset-background transition-all duration-200;
|
|
159
|
+
@apply focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2;
|
|
160
|
+
@apply disabled:pointer-events-none disabled:opacity-50;
|
|
161
|
+
color: hsl(var(--foreground));
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/* ======================
|
|
165
|
+
SWITCH COMPONENT
|
|
166
|
+
====================== */
|
|
167
|
+
.moonui-switch-base {
|
|
168
|
+
@apply peer inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border-2;
|
|
169
|
+
@apply border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2;
|
|
170
|
+
@apply focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background;
|
|
171
|
+
@apply disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary;
|
|
172
|
+
@apply data-[state=unchecked]:bg-input;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.moonui-switch-thumb {
|
|
176
|
+
@apply pointer-events-none block h-5 w-5 rounded-full bg-background shadow-lg ring-0;
|
|
177
|
+
@apply transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/* ======================
|
|
181
|
+
CHECKBOX COMPONENT
|
|
182
|
+
====================== */
|
|
183
|
+
.moonui-checkbox-base {
|
|
184
|
+
@apply peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background;
|
|
185
|
+
@apply focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2;
|
|
186
|
+
@apply disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary;
|
|
187
|
+
@apply data-[state=checked]:text-primary-foreground;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/* ======================
|
|
191
|
+
RADIO GROUP COMPONENT
|
|
192
|
+
====================== */
|
|
193
|
+
.moonui-radio-base {
|
|
194
|
+
@apply aspect-square h-4 w-4 rounded-full border border-primary text-primary ring-offset-background;
|
|
195
|
+
@apply focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2;
|
|
196
|
+
@apply disabled:cursor-not-allowed disabled:opacity-50;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/* ======================
|
|
200
|
+
SELECT COMPONENT
|
|
201
|
+
====================== */
|
|
202
|
+
.moonui-select-trigger {
|
|
203
|
+
@apply flex h-10 w-full items-center justify-between rounded-md border border-input;
|
|
204
|
+
@apply bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground;
|
|
205
|
+
@apply focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2;
|
|
206
|
+
@apply disabled:cursor-not-allowed disabled:opacity-50;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
.moonui-select-content {
|
|
210
|
+
@apply relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover;
|
|
211
|
+
@apply text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out;
|
|
212
|
+
@apply data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95;
|
|
213
|
+
@apply data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/* ======================
|
|
217
|
+
TOOLTIP COMPONENT
|
|
218
|
+
====================== */
|
|
219
|
+
.moonui-tooltip-content {
|
|
220
|
+
@apply z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground;
|
|
221
|
+
@apply shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out;
|
|
222
|
+
@apply data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95;
|
|
223
|
+
@apply data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2;
|
|
224
|
+
@apply data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/* ======================
|
|
228
|
+
SKELETON COMPONENT
|
|
229
|
+
====================== */
|
|
230
|
+
.moonui-skeleton-base {
|
|
231
|
+
@apply animate-pulse rounded-md bg-muted;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/* ======================
|
|
235
|
+
AVATAR COMPONENT
|
|
236
|
+
====================== */
|
|
237
|
+
.moonui-avatar-base {
|
|
238
|
+
@apply relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
.moonui-avatar-image {
|
|
242
|
+
@apply aspect-square h-full w-full;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
.moonui-avatar-fallback {
|
|
246
|
+
@apply flex h-full w-full items-center justify-center rounded-full bg-muted;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/* ======================
|
|
250
|
+
ACCORDION COMPONENT
|
|
251
|
+
====================== */
|
|
252
|
+
.moonui-accordion-item {
|
|
253
|
+
@apply border-b;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
.moonui-accordion-trigger {
|
|
257
|
+
@apply flex flex-1 items-center justify-between py-4 font-medium transition-all;
|
|
258
|
+
@apply hover:underline [&[data-state=open]>svg]:rotate-180;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
.moonui-accordion-content {
|
|
262
|
+
@apply overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up;
|
|
263
|
+
@apply data-[state=open]:animate-accordion-down;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/* ======================
|
|
267
|
+
TABS COMPONENT
|
|
268
|
+
====================== */
|
|
269
|
+
.moonui-tabs-list {
|
|
270
|
+
@apply inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
.moonui-tabs-trigger {
|
|
274
|
+
@apply inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5;
|
|
275
|
+
@apply text-sm font-medium ring-offset-background transition-all focus-visible:outline-none;
|
|
276
|
+
@apply focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2;
|
|
277
|
+
@apply disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background;
|
|
278
|
+
@apply data-[state=active]:text-foreground data-[state=active]:shadow-sm;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
.moonui-tabs-content {
|
|
282
|
+
@apply mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2;
|
|
283
|
+
@apply focus-visible:ring-ring focus-visible:ring-offset-2;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/* ======================
|
|
287
|
+
PROGRESS COMPONENT
|
|
288
|
+
====================== */
|
|
289
|
+
.moonui-progress-base {
|
|
290
|
+
@apply relative h-4 w-full overflow-hidden rounded-full bg-secondary;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
.moonui-progress-indicator {
|
|
294
|
+
@apply h-full w-full flex-1 bg-primary transition-all;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/* ======================
|
|
298
|
+
SLIDER COMPONENT
|
|
299
|
+
====================== */
|
|
300
|
+
.moonui-slider-base {
|
|
301
|
+
@apply relative flex w-full touch-none select-none items-center;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
.moonui-slider-track {
|
|
305
|
+
@apply relative h-2 w-full grow overflow-hidden rounded-full bg-secondary;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
.moonui-slider-range {
|
|
309
|
+
@apply absolute h-full bg-primary;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
.moonui-slider-thumb {
|
|
313
|
+
@apply block h-5 w-5 rounded-full border-2 border-primary bg-background ring-offset-background;
|
|
314
|
+
@apply transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring;
|
|
315
|
+
@apply focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50;
|
|
316
|
+
}
|
|
317
|
+
}
|