@moontra/moonui 2.0.7 → 2.0.9
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/package.json +26 -19
- package/src/__tests__/use-intersection-observer.test.tsx +216 -0
- package/src/__tests__/use-local-storage.test.tsx +174 -0
- package/src/__tests__/use-pro-access.test.tsx +183 -0
- package/src/components/ui/__tests__/accordion.test.tsx +571 -0
- package/src/components/ui/__tests__/alert.test.tsx +484 -0
- package/src/components/ui/__tests__/aspect-ratio.test.tsx +492 -0
- package/src/components/ui/__tests__/avatar.test.tsx +382 -0
- package/src/components/ui/__tests__/badge.test.tsx +364 -0
- package/src/components/ui/__tests__/breadcrumb.test.tsx +687 -0
- package/src/components/ui/__tests__/button.test.tsx +91 -0
- package/src/components/ui/__tests__/card.test.tsx +104 -0
- package/src/components/ui/__tests__/checkbox.test.tsx +591 -0
- package/src/components/ui/__tests__/collapsible.test.tsx +592 -0
- package/src/components/ui/__tests__/color-picker.test.tsx +365 -0
- package/src/components/ui/__tests__/command.test.tsx +677 -0
- package/src/components/ui/__tests__/data-table.test.tsx +256 -0
- package/src/components/ui/__tests__/date-picker.test.tsx +320 -0
- package/src/components/ui/__tests__/dialog.test.tsx +764 -0
- package/src/components/ui/__tests__/input.test.tsx +318 -0
- package/src/components/ui/__tests__/label.test.tsx +103 -0
- package/src/components/ui/__tests__/popover.test.tsx +637 -0
- package/src/components/ui/__tests__/progress.test.tsx +382 -0
- package/src/components/ui/__tests__/radio-group.test.tsx +555 -0
- package/src/components/ui/__tests__/select.test.tsx +705 -0
- package/src/components/ui/__tests__/skeleton.test.tsx +253 -0
- package/src/components/ui/__tests__/slider.test.tsx +493 -0
- package/src/components/ui/__tests__/switch.test.tsx +372 -0
- package/src/components/ui/__tests__/table.test.tsx +824 -0
- package/src/components/ui/__tests__/tabs.test.tsx +887 -0
- package/src/components/ui/__tests__/toast.test.tsx +458 -0
- package/src/components/ui/__tests__/tooltip.test.tsx +583 -0
- package/src/components/ui/accordion.tsx +63 -0
- package/src/components/ui/alert.tsx +130 -0
- package/src/components/ui/aspect-ratio.tsx +72 -0
- package/src/components/ui/avatar.tsx +135 -0
- package/src/components/ui/badge.tsx +225 -0
- package/src/components/ui/breadcrumb.tsx +207 -0
- package/src/components/ui/button.stories.tsx +162 -0
- package/src/components/ui/button.tsx +221 -0
- package/src/components/ui/calendar.tsx +262 -0
- package/src/components/ui/card.stories.tsx +208 -0
- package/src/components/ui/card.tsx +141 -0
- package/src/components/ui/checkbox.tsx +256 -0
- package/src/components/ui/collapsible.tsx +129 -0
- package/src/components/ui/color-picker.tsx +664 -0
- package/src/components/ui/command.tsx +218 -0
- package/src/components/ui/data-table.stories.tsx +509 -0
- package/src/components/ui/data-table.tsx +623 -0
- package/src/components/ui/date-picker.stories.tsx +321 -0
- package/src/components/ui/date-picker.tsx +603 -0
- package/src/components/ui/dialog.tsx +332 -0
- package/src/components/ui/dropdown-menu.tsx +200 -0
- package/src/components/ui/file-upload.tsx +400 -0
- package/src/components/ui/github-stars.tsx +201 -0
- package/src/components/ui/index.ts +12 -0
- package/src/components/ui/input.stories.tsx +255 -0
- package/src/components/ui/input.tsx +219 -0
- package/src/components/ui/label.tsx +26 -0
- package/src/components/ui/locked-component.tsx +215 -0
- package/src/components/ui/moon-logo.tsx +97 -0
- package/src/components/ui/pagination.tsx +116 -0
- package/src/components/ui/popover.tsx +183 -0
- package/src/components/ui/progress.tsx +182 -0
- package/src/components/ui/radio-group.tsx +243 -0
- package/src/components/ui/select.tsx +273 -0
- package/src/components/ui/separator.tsx +140 -0
- package/src/components/ui/simple-editor.tsx +652 -0
- package/src/components/ui/skeleton.tsx +351 -0
- package/src/components/ui/slider.tsx +351 -0
- package/src/components/ui/switch.tsx +83 -0
- package/src/components/ui/table.tsx +322 -0
- package/src/components/ui/tabs.tsx +195 -0
- package/src/components/ui/textarea.tsx +46 -0
- package/src/components/ui/toast.tsx +313 -0
- package/src/components/ui/toggle.tsx +47 -0
- package/src/components/ui/tooltip.tsx +152 -0
- package/src/docs/theme-system.md +1194 -0
- package/src/index.tsx +39 -0
- package/src/lib/micro-interactions.ts +255 -0
- package/src/lib/theme.tsx +398 -0
- package/src/lib/utils.ts +69 -0
- package/src/styles/design-system.css +365 -0
- package/src/styles/index.css +4 -0
- package/src/styles/tailwind.css +6 -0
- package/src/styles/tokens.css +453 -0
- package/src/use-intersection-observer.tsx +154 -0
- package/src/use-local-storage.tsx +71 -0
- package/src/use-paddle.ts +138 -0
- package/src/use-performance-optimizer.ts +379 -0
- package/src/use-pro-access.ts +141 -0
- package/src/use-scroll-animation.ts +221 -0
- package/src/use-subscription.ts +37 -0
- package/src/use-toast.ts +32 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import * as SwitchPrimitives from "@radix-ui/react-switch"
|
|
5
|
+
|
|
6
|
+
import { cn } from "../../lib/utils"
|
|
7
|
+
|
|
8
|
+
type SwitchSize = "sm" | "md" | "lg";
|
|
9
|
+
type SwitchVariant = "primary" | "success" | "warning" | "danger" | "secondary";
|
|
10
|
+
|
|
11
|
+
export interface SwitchProps extends React.ComponentPropsWithoutRef<typeof SwitchPrimitives.Root> {
|
|
12
|
+
/** Switch boyutu */
|
|
13
|
+
size?: SwitchSize;
|
|
14
|
+
/** Switch renk varyantı */
|
|
15
|
+
variant?: SwitchVariant;
|
|
16
|
+
/** Yükleniyor durumunu gösterir */
|
|
17
|
+
loading?: boolean;
|
|
18
|
+
/** Sol tarafta gösterilecek ikon */
|
|
19
|
+
leftIcon?: React.ReactNode;
|
|
20
|
+
/** Sağ tarafta gösterilecek ikon */
|
|
21
|
+
rightIcon?: React.ReactNode;
|
|
22
|
+
/** Switch açıklaması */
|
|
23
|
+
description?: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const Switch = React.forwardRef<
|
|
27
|
+
React.ElementRef<typeof SwitchPrimitives.Root>,
|
|
28
|
+
SwitchProps
|
|
29
|
+
>(({ className, size = "md", variant = "primary", loading, leftIcon, rightIcon, description, ...props }, ref) => (
|
|
30
|
+
<div className="inline-flex items-center gap-2">
|
|
31
|
+
{leftIcon && <span className="text-muted-foreground">{leftIcon}</span>}
|
|
32
|
+
<SwitchPrimitives.Root
|
|
33
|
+
className={cn(
|
|
34
|
+
"peer relative inline-flex 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-background disabled:cursor-not-allowed disabled:opacity-50 dark:data-[state=unchecked]:bg-gray-700/70 dark:focus-visible:ring-primary/40 dark:focus-visible:ring-offset-gray-950",
|
|
35
|
+
|
|
36
|
+
// Boyutlar
|
|
37
|
+
size === "sm" && "h-4 w-8",
|
|
38
|
+
size === "md" && "h-6 w-11",
|
|
39
|
+
size === "lg" && "h-7 w-14",
|
|
40
|
+
|
|
41
|
+
// Varyantlar (checked durumunda)
|
|
42
|
+
variant === "primary" && "data-[state=checked]:bg-primary",
|
|
43
|
+
variant === "success" && "data-[state=checked]:bg-success",
|
|
44
|
+
variant === "warning" && "data-[state=checked]:bg-warning",
|
|
45
|
+
variant === "danger" && "data-[state=checked]:bg-error",
|
|
46
|
+
variant === "secondary" && "data-[state=checked]:bg-accent",
|
|
47
|
+
|
|
48
|
+
// Unchecked durumu
|
|
49
|
+
"data-[state=unchecked]:bg-input",
|
|
50
|
+
|
|
51
|
+
// Loading durumu
|
|
52
|
+
loading && "opacity-80 cursor-wait",
|
|
53
|
+
|
|
54
|
+
className
|
|
55
|
+
)}
|
|
56
|
+
disabled={loading || props.disabled}
|
|
57
|
+
{...props}
|
|
58
|
+
ref={ref}
|
|
59
|
+
>
|
|
60
|
+
{loading ? (
|
|
61
|
+
<div className="absolute inset-0 flex items-center justify-center">
|
|
62
|
+
<div className="h-3 w-3 animate-spin rounded-full border-2 border-gray-300 border-t-primary"></div>
|
|
63
|
+
</div>
|
|
64
|
+
) : null}
|
|
65
|
+
|
|
66
|
+
<SwitchPrimitives.Thumb
|
|
67
|
+
className={cn(
|
|
68
|
+
"pointer-events-none block rounded-full bg-background shadow-lg ring-0 transition-transform",
|
|
69
|
+
// Boyuta göre thumb boyutları
|
|
70
|
+
size === "sm" && "h-3 w-3 data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0",
|
|
71
|
+
size === "md" && "h-5 w-5 data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0",
|
|
72
|
+
size === "lg" && "h-6 w-6 data-[state=checked]:translate-x-7 data-[state=unchecked]:translate-x-0",
|
|
73
|
+
)}
|
|
74
|
+
/>
|
|
75
|
+
</SwitchPrimitives.Root>
|
|
76
|
+
{rightIcon && <span className="text-muted-foreground">{rightIcon}</span>}
|
|
77
|
+
{description && <span className="text-sm text-muted-foreground">{description}</span>}
|
|
78
|
+
</div>
|
|
79
|
+
))
|
|
80
|
+
Switch.displayName = SwitchPrimitives.Root.displayName
|
|
81
|
+
|
|
82
|
+
export { Switch }
|
|
83
|
+
export type { SwitchSize, SwitchVariant }
|
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
3
|
+
|
|
4
|
+
import { cn } from "../../lib/utils";
|
|
5
|
+
|
|
6
|
+
export type SortDirection = "asc" | "desc" | null;
|
|
7
|
+
|
|
8
|
+
const tableVariants = cva(
|
|
9
|
+
"w-full caption-bottom text-sm",
|
|
10
|
+
{
|
|
11
|
+
variants: {
|
|
12
|
+
variant: {
|
|
13
|
+
default: "dark:text-gray-200",
|
|
14
|
+
bordered: "border border-border dark:border-gray-700",
|
|
15
|
+
striped: "dark:text-gray-200",
|
|
16
|
+
card: "border border-border dark:border-gray-700 rounded-md shadow-sm dark:shadow-gray-900/20",
|
|
17
|
+
minimal: "border-none dark:text-gray-200",
|
|
18
|
+
},
|
|
19
|
+
size: {
|
|
20
|
+
sm: "text-xs",
|
|
21
|
+
default: "text-sm",
|
|
22
|
+
lg: "text-base",
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
defaultVariants: {
|
|
26
|
+
variant: "default",
|
|
27
|
+
size: "default",
|
|
28
|
+
},
|
|
29
|
+
}
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
export interface ColumnDefinition<T> {
|
|
33
|
+
id: string;
|
|
34
|
+
header: React.ReactNode;
|
|
35
|
+
accessorKey?: keyof T;
|
|
36
|
+
cell?: (row: T) => React.ReactNode;
|
|
37
|
+
sortable?: boolean;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
interface TableProps<T>
|
|
41
|
+
extends React.HTMLAttributes<HTMLTableElement>,
|
|
42
|
+
VariantProps<typeof tableVariants> {
|
|
43
|
+
/** Veri yükleniyor durumunu gösterir */
|
|
44
|
+
loading?: boolean;
|
|
45
|
+
/** Sıralama için kullanılan sütun */
|
|
46
|
+
sortColumn?: string;
|
|
47
|
+
/** Sıralama yönü */
|
|
48
|
+
sortDirection?: SortDirection;
|
|
49
|
+
/** Sıralama değiştiğinde çağrılacak fonksiyon */
|
|
50
|
+
onSortChange?: (column: string, direction: SortDirection) => void;
|
|
51
|
+
/** Boş durum için özel içerik */
|
|
52
|
+
emptyContent?: React.ReactNode;
|
|
53
|
+
/** Seçili satır id'leri */
|
|
54
|
+
selectedRowIds?: string[];
|
|
55
|
+
/** Satır seçim değiştiğinde çağrılacak fonksiyon */
|
|
56
|
+
onRowSelectionChange?: (selectedRowIds: string[]) => void;
|
|
57
|
+
/** Satır seçim devre dışı */
|
|
58
|
+
disableRowSelection?: boolean;
|
|
59
|
+
/** Her satır için benzersiz id çıkarma fonksiyonu */
|
|
60
|
+
getRowId?: (row: T) => string;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Tip parametresiz Table bileşeni için varsayılan tip, herhangi bir veri tipini kabul edebilmesi için
|
|
64
|
+
const Table = React.forwardRef<
|
|
65
|
+
HTMLTableElement,
|
|
66
|
+
TableProps<unknown>
|
|
67
|
+
>(({
|
|
68
|
+
className,
|
|
69
|
+
variant,
|
|
70
|
+
size,
|
|
71
|
+
loading,
|
|
72
|
+
emptyContent,
|
|
73
|
+
// Kullanılmayan özellikleri yoruma alarak lint uyarılarını önlüyoruz
|
|
74
|
+
// sortColumn,
|
|
75
|
+
// sortDirection,
|
|
76
|
+
// onSortChange,
|
|
77
|
+
// selectedRowIds,
|
|
78
|
+
// onRowSelectionChange,
|
|
79
|
+
// disableRowSelection,
|
|
80
|
+
// getRowId,
|
|
81
|
+
...props
|
|
82
|
+
}, ref) => {
|
|
83
|
+
// Apply striped styles to the tbody via a class name
|
|
84
|
+
const striped = variant === "striped";
|
|
85
|
+
|
|
86
|
+
// Çocukları güvenli bir şekilde işle ve tip kontrollerini doğru yap
|
|
87
|
+
const childrenWithProps = React.Children.map(props.children, (child) => {
|
|
88
|
+
if (React.isValidElement(child)) {
|
|
89
|
+
if (child.type === "tbody") {
|
|
90
|
+
// Tip güvenliği için props'ları düzgün şekilde ele alıyoruz
|
|
91
|
+
const tbodyProps = child.props as Record<string, unknown>;
|
|
92
|
+
return React.cloneElement(child as React.ReactElement<React.HTMLAttributes<HTMLTableSectionElement>>, {
|
|
93
|
+
className: cn(tbodyProps.className as string | undefined, striped && "even:[&>tr]:bg-muted/50")
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return child;
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
return (
|
|
101
|
+
<div className="relative w-full overflow-auto">
|
|
102
|
+
{/* Yükleniyor durumu için overlay */}
|
|
103
|
+
{loading && (
|
|
104
|
+
<div className="absolute inset-0 bg-background/60 flex items-center justify-center z-10">
|
|
105
|
+
<div className="h-8 w-8 animate-spin rounded-full border-2 border-primary border-t-transparent"></div>
|
|
106
|
+
</div>
|
|
107
|
+
)}
|
|
108
|
+
|
|
109
|
+
<table
|
|
110
|
+
ref={ref}
|
|
111
|
+
className={cn(
|
|
112
|
+
tableVariants({ variant, size }),
|
|
113
|
+
loading && "opacity-70",
|
|
114
|
+
className
|
|
115
|
+
)}
|
|
116
|
+
{...props}
|
|
117
|
+
>
|
|
118
|
+
{childrenWithProps}
|
|
119
|
+
</table>
|
|
120
|
+
|
|
121
|
+
</div>
|
|
122
|
+
);
|
|
123
|
+
});
|
|
124
|
+
Table.displayName = "Table";
|
|
125
|
+
|
|
126
|
+
const TableHeader = React.forwardRef<
|
|
127
|
+
HTMLTableSectionElement,
|
|
128
|
+
React.HTMLAttributes<HTMLTableSectionElement>
|
|
129
|
+
>(({ className, ...props }, ref) => (
|
|
130
|
+
<thead ref={ref} className={cn("[&_tr]:border-b", className)} {...props} />
|
|
131
|
+
));
|
|
132
|
+
TableHeader.displayName = "TableHeader";
|
|
133
|
+
|
|
134
|
+
interface TableBodyProps extends React.HTMLAttributes<HTMLTableSectionElement> {
|
|
135
|
+
/** Veri yoksa gösterilecek boş durum içeriği */
|
|
136
|
+
emptyContent?: React.ReactNode;
|
|
137
|
+
/** Varsayılan boş durum mesajı */
|
|
138
|
+
emptyMessage?: string;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const TableBody = React.forwardRef<
|
|
142
|
+
HTMLTableSectionElement,
|
|
143
|
+
TableBodyProps
|
|
144
|
+
>(({ className, emptyContent, emptyMessage = "No data available", children, ...props }, ref) => {
|
|
145
|
+
// Çocuk elementlerin varlığını kontrol et
|
|
146
|
+
const hasChildren = React.Children.count(children) > 0;
|
|
147
|
+
|
|
148
|
+
return (
|
|
149
|
+
<tbody
|
|
150
|
+
ref={ref}
|
|
151
|
+
className={cn("[&_tr:last-child]:border-0", className)}
|
|
152
|
+
{...props}
|
|
153
|
+
>
|
|
154
|
+
{hasChildren ? (
|
|
155
|
+
children
|
|
156
|
+
) : (
|
|
157
|
+
<tr>
|
|
158
|
+
<td colSpan={100} className="h-24 text-center">
|
|
159
|
+
{emptyContent || (
|
|
160
|
+
<div className="py-6 text-muted-foreground">
|
|
161
|
+
<div className="text-sm">
|
|
162
|
+
{emptyMessage}
|
|
163
|
+
</div>
|
|
164
|
+
</div>
|
|
165
|
+
)}
|
|
166
|
+
</td>
|
|
167
|
+
</tr>
|
|
168
|
+
)}
|
|
169
|
+
</tbody>
|
|
170
|
+
)
|
|
171
|
+
});
|
|
172
|
+
TableBody.displayName = "TableBody";
|
|
173
|
+
|
|
174
|
+
const TableFooter = React.forwardRef<
|
|
175
|
+
HTMLTableSectionElement,
|
|
176
|
+
React.HTMLAttributes<HTMLTableSectionElement>
|
|
177
|
+
>(({ className, ...props }, ref) => (
|
|
178
|
+
<tfoot
|
|
179
|
+
ref={ref}
|
|
180
|
+
className={cn("bg-primary text-primary-foreground font-medium", className)}
|
|
181
|
+
{...props}
|
|
182
|
+
/>
|
|
183
|
+
));
|
|
184
|
+
TableFooter.displayName = "TableFooter";
|
|
185
|
+
|
|
186
|
+
const TableRow = React.forwardRef<
|
|
187
|
+
HTMLTableRowElement,
|
|
188
|
+
React.HTMLAttributes<HTMLTableRowElement>
|
|
189
|
+
>(({ className, ...props }, ref) => (
|
|
190
|
+
<tr
|
|
191
|
+
ref={ref}
|
|
192
|
+
className={cn(
|
|
193
|
+
"border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted",
|
|
194
|
+
className
|
|
195
|
+
)}
|
|
196
|
+
{...props}
|
|
197
|
+
/>
|
|
198
|
+
));
|
|
199
|
+
TableRow.displayName = "TableRow";
|
|
200
|
+
|
|
201
|
+
interface TableHeadProps extends React.ThHTMLAttributes<HTMLTableCellElement> {
|
|
202
|
+
/** Bu sütun için sıralama durumu */
|
|
203
|
+
sortable?: boolean;
|
|
204
|
+
/** Bu sütunun sıralanma durumu */
|
|
205
|
+
sorted?: SortDirection;
|
|
206
|
+
/** Sıralama değiştiğinde çağrılacak fonksiyon */
|
|
207
|
+
onSort?: () => void;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const TableHead = React.forwardRef<HTMLTableCellElement, TableHeadProps>(
|
|
211
|
+
({ className, sortable, sorted, onSort, children, ...props }, ref) => {
|
|
212
|
+
// Sıralama için simgeler
|
|
213
|
+
const renderSortIcon = () => {
|
|
214
|
+
if (!sortable) return null;
|
|
215
|
+
|
|
216
|
+
if (sorted === "asc") {
|
|
217
|
+
return (
|
|
218
|
+
<svg
|
|
219
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
220
|
+
className="ml-1 h-4 w-4 inline-block"
|
|
221
|
+
viewBox="0 0 20 20"
|
|
222
|
+
fill="currentColor"
|
|
223
|
+
>
|
|
224
|
+
<path
|
|
225
|
+
fillRule="evenodd"
|
|
226
|
+
d="M14.707 10.293a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 111.414-1.414L9 12.586V5a1 1 0 012 0v7.586l2.293-2.293a1 1 0 011.414 0z"
|
|
227
|
+
clipRule="evenodd"
|
|
228
|
+
/>
|
|
229
|
+
</svg>
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
if (sorted === "desc") {
|
|
234
|
+
return (
|
|
235
|
+
<svg
|
|
236
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
237
|
+
className="ml-1 h-4 w-4 inline-block"
|
|
238
|
+
viewBox="0 0 20 20"
|
|
239
|
+
fill="currentColor"
|
|
240
|
+
>
|
|
241
|
+
<path
|
|
242
|
+
fillRule="evenodd"
|
|
243
|
+
d="M5.293 9.707a1 1 0 010-1.414l4-4a1 1 0 011.414 0l4 4a1 1 0 01-1.414 1.414L11 7.414V15a1 1 0 11-2 0V7.414L6.707 9.707a1 1 0 01-1.414 0z"
|
|
244
|
+
clipRule="evenodd"
|
|
245
|
+
/>
|
|
246
|
+
</svg>
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
return (
|
|
251
|
+
<svg
|
|
252
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
253
|
+
className="ml-1 h-4 w-4 inline-block opacity-30"
|
|
254
|
+
viewBox="0 0 20 20"
|
|
255
|
+
fill="currentColor"
|
|
256
|
+
>
|
|
257
|
+
<path
|
|
258
|
+
fillRule="evenodd"
|
|
259
|
+
d="M10 3a1 1 0 01.707.293l3 3a1 1 0 01-1.414 1.414L10 5.414 7.707 7.707a1 1 0 01-1.414-1.414l3-3A1 1 0 0110 3zm-3.707 9.293a1 1 0 011.414 0L10 14.586l2.293-2.293a1 1 0 011.414 1.414l-3 3a1 1 0 01-1.414 0l-3-3a1 1 0 010-1.414z"
|
|
260
|
+
clipRule="evenodd"
|
|
261
|
+
/>
|
|
262
|
+
</svg>
|
|
263
|
+
);
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
return (
|
|
267
|
+
<th
|
|
268
|
+
ref={ref}
|
|
269
|
+
className={cn(
|
|
270
|
+
"h-10 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0",
|
|
271
|
+
sortable && "cursor-pointer hover:text-foreground select-none",
|
|
272
|
+
className
|
|
273
|
+
)}
|
|
274
|
+
onClick={sortable ? onSort : undefined}
|
|
275
|
+
{...props}
|
|
276
|
+
>
|
|
277
|
+
<div className="flex items-center">
|
|
278
|
+
{children}
|
|
279
|
+
{sortable && renderSortIcon()}
|
|
280
|
+
</div>
|
|
281
|
+
</th>
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
);
|
|
285
|
+
TableHead.displayName = "TableHead";
|
|
286
|
+
|
|
287
|
+
const TableCell = React.forwardRef<
|
|
288
|
+
HTMLTableCellElement,
|
|
289
|
+
React.TdHTMLAttributes<HTMLTableCellElement>
|
|
290
|
+
>(({ className, ...props }, ref) => (
|
|
291
|
+
<td
|
|
292
|
+
ref={ref}
|
|
293
|
+
className={cn("p-4 align-middle [&:has([role=checkbox])]:pr-0", className)}
|
|
294
|
+
{...props}
|
|
295
|
+
/>
|
|
296
|
+
));
|
|
297
|
+
TableCell.displayName = "TableCell";
|
|
298
|
+
|
|
299
|
+
const TableCaption = React.forwardRef<
|
|
300
|
+
HTMLTableCaptionElement,
|
|
301
|
+
React.HTMLAttributes<HTMLTableCaptionElement>
|
|
302
|
+
>(({ className, ...props }, ref) => (
|
|
303
|
+
<caption
|
|
304
|
+
ref={ref}
|
|
305
|
+
className={cn("mt-4 text-sm text-muted-foreground", className)}
|
|
306
|
+
{...props}
|
|
307
|
+
/>
|
|
308
|
+
));
|
|
309
|
+
TableCaption.displayName = "TableCaption";
|
|
310
|
+
|
|
311
|
+
export {
|
|
312
|
+
Table,
|
|
313
|
+
TableHeader,
|
|
314
|
+
TableBody,
|
|
315
|
+
TableFooter,
|
|
316
|
+
TableHead,
|
|
317
|
+
TableRow,
|
|
318
|
+
TableCell,
|
|
319
|
+
TableCaption,
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
export type { TableBodyProps };
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as TabsPrimitive from "@radix-ui/react-tabs";
|
|
3
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
4
|
+
|
|
5
|
+
import { cn } from "../../lib/utils";
|
|
6
|
+
|
|
7
|
+
/* -------------------------------------------------------------------------------------------------
|
|
8
|
+
* Tabs Root
|
|
9
|
+
* -----------------------------------------------------------------------------------------------*/
|
|
10
|
+
interface TabsProps extends React.ComponentPropsWithoutRef<typeof TabsPrimitive.Root> {
|
|
11
|
+
/** Mobil görünümde dikey düzen için */
|
|
12
|
+
vertical?: boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const Tabs = React.forwardRef<
|
|
16
|
+
React.ElementRef<typeof TabsPrimitive.Root>,
|
|
17
|
+
TabsProps
|
|
18
|
+
>(({ vertical = false, ...props }, ref) => (
|
|
19
|
+
<TabsPrimitive.Root
|
|
20
|
+
ref={ref}
|
|
21
|
+
orientation={vertical ? "vertical" : "horizontal"}
|
|
22
|
+
{...props}
|
|
23
|
+
/>
|
|
24
|
+
));
|
|
25
|
+
|
|
26
|
+
Tabs.displayName = TabsPrimitive.Root.displayName;
|
|
27
|
+
|
|
28
|
+
/* -------------------------------------------------------------------------------------------------
|
|
29
|
+
* TabsList
|
|
30
|
+
* -----------------------------------------------------------------------------------------------*/
|
|
31
|
+
const tabsListVariants = cva(
|
|
32
|
+
"flex items-center justify-start transition-all duration-200",
|
|
33
|
+
{
|
|
34
|
+
variants: {
|
|
35
|
+
variant: {
|
|
36
|
+
default: "bg-muted rounded-md p-1 text-muted-foreground dark:bg-gray-800/80 dark:text-gray-400",
|
|
37
|
+
pills: "bg-transparent gap-2 p-0 dark:text-gray-400",
|
|
38
|
+
underline: "bg-transparent border-b border-border dark:border-gray-700 gap-4 dark:text-gray-400",
|
|
39
|
+
cards: "bg-transparent gap-2 p-0 dark:text-gray-400",
|
|
40
|
+
minimal: "bg-transparent gap-1 p-0 dark:text-gray-400",
|
|
41
|
+
},
|
|
42
|
+
orientation: {
|
|
43
|
+
horizontal: "flex-row",
|
|
44
|
+
vertical: "flex-col items-start gap-1"
|
|
45
|
+
},
|
|
46
|
+
fullWidth: {
|
|
47
|
+
true: "w-full"
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
defaultVariants: {
|
|
51
|
+
variant: "default",
|
|
52
|
+
orientation: "horizontal",
|
|
53
|
+
fullWidth: false
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
interface TabsListProps
|
|
59
|
+
extends React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>,
|
|
60
|
+
VariantProps<typeof tabsListVariants> {
|
|
61
|
+
/** Dikey düzende göster */
|
|
62
|
+
orientation?: "horizontal" | "vertical";
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const TabsList = React.forwardRef<
|
|
66
|
+
React.ElementRef<typeof TabsPrimitive.List>,
|
|
67
|
+
TabsListProps
|
|
68
|
+
>(({ className, variant, orientation, fullWidth, ...props }, ref) => (
|
|
69
|
+
<TabsPrimitive.List
|
|
70
|
+
ref={ref}
|
|
71
|
+
className={cn(tabsListVariants({ variant, orientation, fullWidth, className }))}
|
|
72
|
+
{...props}
|
|
73
|
+
/>
|
|
74
|
+
));
|
|
75
|
+
|
|
76
|
+
TabsList.displayName = TabsPrimitive.List.displayName;
|
|
77
|
+
|
|
78
|
+
/* -------------------------------------------------------------------------------------------------
|
|
79
|
+
* TabsTrigger
|
|
80
|
+
* -----------------------------------------------------------------------------------------------*/
|
|
81
|
+
const tabsTriggerVariants = cva(
|
|
82
|
+
"inline-flex items-center justify-center whitespace-nowrap font-medium ring-offset-background transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
|
|
83
|
+
{
|
|
84
|
+
variants: {
|
|
85
|
+
variant: {
|
|
86
|
+
default: "rounded-md data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm dark:data-[state=active]:bg-gray-900 dark:data-[state=active]:text-gray-100 dark:data-[state=active]:shadow-gray-950/10",
|
|
87
|
+
underline: "rounded-none border-b-2 border-transparent pb-2 data-[state=active]:border-primary data-[state=active]:bg-transparent data-[state=active]:text-foreground dark:data-[state=active]:border-primary/80 dark:data-[state=active]:text-gray-100",
|
|
88
|
+
pills: "rounded-full bg-muted hover:bg-muted/80 data-[state=active]:bg-primary data-[state=active]:text-primary-foreground dark:bg-gray-800 dark:hover:bg-gray-700 dark:data-[state=active]:bg-primary/90 dark:data-[state=active]:text-white",
|
|
89
|
+
cards: "rounded-md bg-muted/50 hover:bg-muted data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-md dark:bg-gray-800/50 dark:hover:bg-gray-700/50 dark:data-[state=active]:bg-gray-900 dark:data-[state=active]:text-gray-100 dark:data-[state=active]:shadow-gray-950/20",
|
|
90
|
+
minimal: "rounded-sm bg-transparent hover:bg-muted/30 data-[state=active]:bg-transparent data-[state=active]:text-foreground data-[state=active]:underline data-[state=active]:underline-offset-4 dark:hover:bg-gray-800/30 dark:data-[state=active]:text-gray-200",
|
|
91
|
+
},
|
|
92
|
+
size: {
|
|
93
|
+
sm: "h-7 px-2 text-xs",
|
|
94
|
+
md: "h-9 px-3 py-1.5 text-sm",
|
|
95
|
+
lg: "h-10 px-4 py-2 text-base",
|
|
96
|
+
},
|
|
97
|
+
orientation: {
|
|
98
|
+
horizontal: "",
|
|
99
|
+
vertical: "justify-start w-full text-left"
|
|
100
|
+
},
|
|
101
|
+
fullWidth: {
|
|
102
|
+
true: "w-full"
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
defaultVariants: {
|
|
106
|
+
variant: "default",
|
|
107
|
+
size: "md",
|
|
108
|
+
orientation: "horizontal",
|
|
109
|
+
fullWidth: false
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
interface TabsTriggerProps
|
|
115
|
+
extends React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>,
|
|
116
|
+
VariantProps<typeof tabsTriggerVariants> {
|
|
117
|
+
/** İkon konumu */
|
|
118
|
+
iconPosition?: "left" | "right" | "none";
|
|
119
|
+
/** İkon */
|
|
120
|
+
icon?: React.ReactNode;
|
|
121
|
+
/** Badge içeriği */
|
|
122
|
+
badge?: React.ReactNode;
|
|
123
|
+
/** Aktif olmayan durumda yarı saydam */
|
|
124
|
+
fadeTabs?: boolean;
|
|
125
|
+
/** Dikey düzende göster */
|
|
126
|
+
orientation?: "horizontal" | "vertical";
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const TabsTrigger = React.forwardRef<
|
|
130
|
+
React.ElementRef<typeof TabsPrimitive.Trigger>,
|
|
131
|
+
TabsTriggerProps
|
|
132
|
+
>(({
|
|
133
|
+
className,
|
|
134
|
+
variant,
|
|
135
|
+
size,
|
|
136
|
+
icon,
|
|
137
|
+
iconPosition = "left",
|
|
138
|
+
badge,
|
|
139
|
+
fadeTabs = false,
|
|
140
|
+
orientation,
|
|
141
|
+
fullWidth,
|
|
142
|
+
children,
|
|
143
|
+
...props
|
|
144
|
+
}, ref) => (
|
|
145
|
+
<TabsPrimitive.Trigger
|
|
146
|
+
ref={ref}
|
|
147
|
+
className={cn(
|
|
148
|
+
tabsTriggerVariants({ variant, size, orientation, fullWidth }),
|
|
149
|
+
fadeTabs && "data-[state=inactive]:opacity-60",
|
|
150
|
+
className
|
|
151
|
+
)}
|
|
152
|
+
{...props}
|
|
153
|
+
>
|
|
154
|
+
{icon && iconPosition === "left" && (
|
|
155
|
+
<span className="mr-2">{icon}</span>
|
|
156
|
+
)}
|
|
157
|
+
{children}
|
|
158
|
+
{icon && iconPosition === "right" && (
|
|
159
|
+
<span className="ml-2">{icon}</span>
|
|
160
|
+
)}
|
|
161
|
+
{badge && (
|
|
162
|
+
<span className="ml-2">{badge}</span>
|
|
163
|
+
)}
|
|
164
|
+
</TabsPrimitive.Trigger>
|
|
165
|
+
));
|
|
166
|
+
|
|
167
|
+
TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;
|
|
168
|
+
|
|
169
|
+
/* -------------------------------------------------------------------------------------------------
|
|
170
|
+
* TabsContent
|
|
171
|
+
* -----------------------------------------------------------------------------------------------*/
|
|
172
|
+
interface TabsContentProps
|
|
173
|
+
extends React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content> {
|
|
174
|
+
/** İçerik animasyonu */
|
|
175
|
+
animated?: boolean;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const TabsContent = React.forwardRef<
|
|
179
|
+
React.ElementRef<typeof TabsPrimitive.Content>,
|
|
180
|
+
TabsContentProps
|
|
181
|
+
>(({ className, animated = false, ...props }, ref) => (
|
|
182
|
+
<TabsPrimitive.Content
|
|
183
|
+
ref={ref}
|
|
184
|
+
className={cn(
|
|
185
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
186
|
+
animated && "data-[state=active]:animate-fadeIn data-[state=inactive]:animate-fadeOut",
|
|
187
|
+
className
|
|
188
|
+
)}
|
|
189
|
+
{...props}
|
|
190
|
+
/>
|
|
191
|
+
));
|
|
192
|
+
|
|
193
|
+
TabsContent.displayName = TabsPrimitive.Content.displayName;
|
|
194
|
+
|
|
195
|
+
export { Tabs, TabsList, TabsTrigger, TabsContent };
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
|
|
3
|
+
import { cn } from "../../lib/utils"
|
|
4
|
+
|
|
5
|
+
export interface TextareaProps
|
|
6
|
+
extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
|
|
7
|
+
// Enhanced props that shouldn't be passed to DOM
|
|
8
|
+
variant?: "default" | "outline" | "ghost" | "underline"
|
|
9
|
+
size?: "sm" | "md" | "lg"
|
|
10
|
+
error?: boolean | string
|
|
11
|
+
success?: boolean
|
|
12
|
+
loading?: boolean
|
|
13
|
+
autoResize?: boolean
|
|
14
|
+
maxHeight?: number
|
|
15
|
+
characterCount?: boolean
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
|
|
19
|
+
({
|
|
20
|
+
className,
|
|
21
|
+
// Extract enhanced props to prevent them from being passed to DOM
|
|
22
|
+
variant,
|
|
23
|
+
size,
|
|
24
|
+
error,
|
|
25
|
+
success,
|
|
26
|
+
loading,
|
|
27
|
+
autoResize,
|
|
28
|
+
maxHeight,
|
|
29
|
+
characterCount,
|
|
30
|
+
...props
|
|
31
|
+
}, ref) => {
|
|
32
|
+
return (
|
|
33
|
+
<textarea
|
|
34
|
+
className={cn(
|
|
35
|
+
"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
|
+
className
|
|
37
|
+
)}
|
|
38
|
+
ref={ref}
|
|
39
|
+
{...props}
|
|
40
|
+
/>
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
)
|
|
44
|
+
Textarea.displayName = "Textarea"
|
|
45
|
+
|
|
46
|
+
export { Textarea }
|