@gv-tech/ui-web 2.6.0
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 +88 -0
- package/src/accordion.tsx +58 -0
- package/src/alert-dialog.tsx +121 -0
- package/src/alert.tsx +49 -0
- package/src/aspect-ratio.tsx +7 -0
- package/src/avatar.tsx +40 -0
- package/src/badge.tsx +34 -0
- package/src/breadcrumb.tsx +105 -0
- package/src/button.tsx +47 -0
- package/src/calendar.tsx +163 -0
- package/src/card.tsx +46 -0
- package/src/carousel.tsx +234 -0
- package/src/chart.tsx +296 -0
- package/src/checkbox.tsx +31 -0
- package/src/collapsible.tsx +15 -0
- package/src/command.tsx +154 -0
- package/src/context-menu.tsx +208 -0
- package/src/dialog.tsx +95 -0
- package/src/drawer.tsx +110 -0
- package/src/dropdown-menu.tsx +212 -0
- package/src/form.tsx +160 -0
- package/src/hooks/use-theme.ts +15 -0
- package/src/hooks/use-toast.ts +189 -0
- package/src/hover-card.tsx +35 -0
- package/src/index.ts +474 -0
- package/src/input.tsx +23 -0
- package/src/label.tsx +21 -0
- package/src/lib/utils.ts +6 -0
- package/src/menubar.tsx +244 -0
- package/src/navigation-menu.tsx +143 -0
- package/src/pagination.tsx +107 -0
- package/src/popover.tsx +45 -0
- package/src/progress.tsx +28 -0
- package/src/radio-group.tsx +41 -0
- package/src/resizable.tsx +59 -0
- package/src/scroll-area.tsx +42 -0
- package/src/search.tsx +87 -0
- package/src/select.tsx +169 -0
- package/src/separator.tsx +24 -0
- package/src/setupTests.ts +114 -0
- package/src/sheet.tsx +136 -0
- package/src/skeleton.tsx +10 -0
- package/src/slider.tsx +27 -0
- package/src/sonner.tsx +32 -0
- package/src/switch.tsx +31 -0
- package/src/table.tsx +104 -0
- package/src/tabs.tsx +62 -0
- package/src/text.tsx +55 -0
- package/src/textarea.tsx +25 -0
- package/src/theme-provider.tsx +15 -0
- package/src/theme-toggle.tsx +92 -0
- package/src/toast.tsx +111 -0
- package/src/toaster.tsx +27 -0
- package/src/toggle-group.tsx +55 -0
- package/src/toggle.tsx +24 -0
- package/src/tooltip.tsx +51 -0
package/src/table.tsx
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
TableBaseProps,
|
|
7
|
+
TableBodyBaseProps,
|
|
8
|
+
TableCaptionBaseProps,
|
|
9
|
+
TableCellBaseProps,
|
|
10
|
+
TableFooterBaseProps,
|
|
11
|
+
TableHeadBaseProps,
|
|
12
|
+
TableHeaderBaseProps,
|
|
13
|
+
TableRowBaseProps,
|
|
14
|
+
} from '@gv-tech/ui-core';
|
|
15
|
+
import { cn } from './lib/utils';
|
|
16
|
+
|
|
17
|
+
const Table = React.forwardRef<HTMLTableElement, React.HTMLAttributes<HTMLTableElement> & TableBaseProps>(
|
|
18
|
+
({ className, ...props }, ref) => (
|
|
19
|
+
<div className="relative w-full overflow-auto">
|
|
20
|
+
<table ref={ref} className={cn('w-full caption-bottom text-sm', className)} {...props} />
|
|
21
|
+
</div>
|
|
22
|
+
),
|
|
23
|
+
);
|
|
24
|
+
Table.displayName = 'Table';
|
|
25
|
+
|
|
26
|
+
const TableHeader = React.forwardRef<
|
|
27
|
+
HTMLTableSectionElement,
|
|
28
|
+
React.HTMLAttributes<HTMLTableSectionElement> & TableHeaderBaseProps
|
|
29
|
+
>(({ className, ...props }, ref) => <thead ref={ref} className={cn('[&_tr]:border-b', className)} {...props} />);
|
|
30
|
+
TableHeader.displayName = 'TableHeader';
|
|
31
|
+
|
|
32
|
+
const TableBody = React.forwardRef<
|
|
33
|
+
HTMLTableSectionElement,
|
|
34
|
+
React.HTMLAttributes<HTMLTableSectionElement> & TableBodyBaseProps
|
|
35
|
+
>(({ className, ...props }, ref) => (
|
|
36
|
+
<tbody ref={ref} className={cn('[&_tr:last-child]:border-0', className)} {...props} />
|
|
37
|
+
));
|
|
38
|
+
TableBody.displayName = 'TableBody';
|
|
39
|
+
|
|
40
|
+
const TableFooter = React.forwardRef<
|
|
41
|
+
HTMLTableSectionElement,
|
|
42
|
+
React.HTMLAttributes<HTMLTableSectionElement> & TableFooterBaseProps
|
|
43
|
+
>(({ className, ...props }, ref) => (
|
|
44
|
+
<tfoot ref={ref} className={cn('border-t bg-muted/50 font-medium [&>tr]:last:border-b-0', className)} {...props} />
|
|
45
|
+
));
|
|
46
|
+
TableFooter.displayName = 'TableFooter';
|
|
47
|
+
|
|
48
|
+
const TableRow = React.forwardRef<HTMLTableRowElement, React.HTMLAttributes<HTMLTableRowElement> & TableRowBaseProps>(
|
|
49
|
+
({ className, ...props }, ref) => (
|
|
50
|
+
<tr
|
|
51
|
+
ref={ref}
|
|
52
|
+
className={cn('border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted', className)}
|
|
53
|
+
{...props}
|
|
54
|
+
/>
|
|
55
|
+
),
|
|
56
|
+
);
|
|
57
|
+
TableRow.displayName = 'TableRow';
|
|
58
|
+
|
|
59
|
+
const TableHead = React.forwardRef<
|
|
60
|
+
HTMLTableCellElement,
|
|
61
|
+
React.ThHTMLAttributes<HTMLTableCellElement> & TableHeadBaseProps
|
|
62
|
+
>(({ className, ...props }, ref) => (
|
|
63
|
+
<th
|
|
64
|
+
ref={ref}
|
|
65
|
+
className={cn(
|
|
66
|
+
'h-10 px-2 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]',
|
|
67
|
+
className,
|
|
68
|
+
)}
|
|
69
|
+
{...props}
|
|
70
|
+
/>
|
|
71
|
+
));
|
|
72
|
+
TableHead.displayName = 'TableHead';
|
|
73
|
+
|
|
74
|
+
const TableCell = React.forwardRef<
|
|
75
|
+
HTMLTableCellElement,
|
|
76
|
+
React.TdHTMLAttributes<HTMLTableCellElement> & TableCellBaseProps
|
|
77
|
+
>(({ className, ...props }, ref) => (
|
|
78
|
+
<td
|
|
79
|
+
ref={ref}
|
|
80
|
+
className={cn('p-2 align-middle [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]', className)}
|
|
81
|
+
{...props}
|
|
82
|
+
/>
|
|
83
|
+
));
|
|
84
|
+
TableCell.displayName = 'TableCell';
|
|
85
|
+
|
|
86
|
+
const TableCaption = React.forwardRef<
|
|
87
|
+
HTMLTableCaptionElement,
|
|
88
|
+
React.HTMLAttributes<HTMLTableCaptionElement> & TableCaptionBaseProps
|
|
89
|
+
>(({ className, ...props }, ref) => (
|
|
90
|
+
<caption ref={ref} className={cn('mt-4 text-sm text-muted-foreground', className)} {...props} />
|
|
91
|
+
));
|
|
92
|
+
TableCaption.displayName = 'TableCaption';
|
|
93
|
+
|
|
94
|
+
export { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow };
|
|
95
|
+
export type {
|
|
96
|
+
TableBodyBaseProps as TableBodyProps,
|
|
97
|
+
TableCaptionBaseProps as TableCaptionProps,
|
|
98
|
+
TableCellBaseProps as TableCellProps,
|
|
99
|
+
TableFooterBaseProps as TableFooterProps,
|
|
100
|
+
TableHeaderBaseProps as TableHeaderProps,
|
|
101
|
+
TableHeadBaseProps as TableHeadProps,
|
|
102
|
+
TableBaseProps as TableProps,
|
|
103
|
+
TableRowBaseProps as TableRowProps,
|
|
104
|
+
};
|
package/src/tabs.tsx
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import * as TabsPrimitive from '@radix-ui/react-tabs';
|
|
4
|
+
import * as React from 'react';
|
|
5
|
+
|
|
6
|
+
import { TabsBaseProps, TabsContentBaseProps, TabsListBaseProps, TabsTriggerBaseProps } from '@gv-tech/ui-core';
|
|
7
|
+
import { cn } from './lib/utils';
|
|
8
|
+
|
|
9
|
+
const Tabs = TabsPrimitive.Root;
|
|
10
|
+
|
|
11
|
+
const TabsList = React.forwardRef<
|
|
12
|
+
React.ElementRef<typeof TabsPrimitive.List>,
|
|
13
|
+
React.ComponentPropsWithoutRef<typeof TabsPrimitive.List> & TabsListBaseProps
|
|
14
|
+
>(({ className, ...props }, ref) => (
|
|
15
|
+
<TabsPrimitive.List
|
|
16
|
+
ref={ref}
|
|
17
|
+
className={cn(
|
|
18
|
+
'inline-flex h-9 items-center justify-center rounded-lg bg-muted p-1 text-muted-foreground',
|
|
19
|
+
className,
|
|
20
|
+
)}
|
|
21
|
+
{...props}
|
|
22
|
+
/>
|
|
23
|
+
));
|
|
24
|
+
TabsList.displayName = TabsPrimitive.List.displayName;
|
|
25
|
+
|
|
26
|
+
const TabsTrigger = React.forwardRef<
|
|
27
|
+
React.ElementRef<typeof TabsPrimitive.Trigger>,
|
|
28
|
+
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger> & TabsTriggerBaseProps
|
|
29
|
+
>(({ className, ...props }, ref) => (
|
|
30
|
+
<TabsPrimitive.Trigger
|
|
31
|
+
ref={ref}
|
|
32
|
+
className={cn(
|
|
33
|
+
'inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow',
|
|
34
|
+
className,
|
|
35
|
+
)}
|
|
36
|
+
{...props}
|
|
37
|
+
/>
|
|
38
|
+
));
|
|
39
|
+
TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;
|
|
40
|
+
|
|
41
|
+
const TabsContent = React.forwardRef<
|
|
42
|
+
React.ElementRef<typeof TabsPrimitive.Content>,
|
|
43
|
+
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content> & TabsContentBaseProps
|
|
44
|
+
>(({ className, ...props }, ref) => (
|
|
45
|
+
<TabsPrimitive.Content
|
|
46
|
+
ref={ref}
|
|
47
|
+
className={cn(
|
|
48
|
+
'mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',
|
|
49
|
+
className,
|
|
50
|
+
)}
|
|
51
|
+
{...props}
|
|
52
|
+
/>
|
|
53
|
+
));
|
|
54
|
+
TabsContent.displayName = TabsPrimitive.Content.displayName;
|
|
55
|
+
|
|
56
|
+
export { Tabs, TabsContent, TabsList, TabsTrigger };
|
|
57
|
+
export type {
|
|
58
|
+
TabsContentBaseProps as TabsContentProps,
|
|
59
|
+
TabsListBaseProps as TabsListProps,
|
|
60
|
+
TabsBaseProps as TabsProps,
|
|
61
|
+
TabsTriggerBaseProps as TabsTriggerProps,
|
|
62
|
+
};
|
package/src/text.tsx
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { cva, type VariantProps } from 'class-variance-authority';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
|
|
4
|
+
import type { TextBaseProps } from '@gv-tech/ui-core';
|
|
5
|
+
import { cn } from './lib/utils';
|
|
6
|
+
|
|
7
|
+
const textVariants = cva('', {
|
|
8
|
+
variants: {
|
|
9
|
+
variant: {
|
|
10
|
+
h1: 'scroll-m-20 text-4xl font-extrabold tracking-tight lg:text-5xl',
|
|
11
|
+
h2: 'scroll-m-20 text-3xl font-semibold tracking-tight',
|
|
12
|
+
h3: 'scroll-m-20 text-2xl font-semibold tracking-tight',
|
|
13
|
+
h4: 'scroll-m-20 text-xl font-semibold tracking-tight',
|
|
14
|
+
body: 'leading-7',
|
|
15
|
+
bodySmall: 'text-sm leading-6',
|
|
16
|
+
caption: 'text-xs text-muted-foreground',
|
|
17
|
+
label: 'text-sm font-medium leading-none',
|
|
18
|
+
overline: 'text-xs font-semibold uppercase tracking-widest text-muted-foreground',
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
defaultVariants: {
|
|
22
|
+
variant: 'body',
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
// Map variant to the most semantic HTML element
|
|
27
|
+
const variantElementMap: Record<string, keyof React.JSX.IntrinsicElements> = {
|
|
28
|
+
h1: 'h1',
|
|
29
|
+
h2: 'h2',
|
|
30
|
+
h3: 'h3',
|
|
31
|
+
h4: 'h4',
|
|
32
|
+
body: 'p',
|
|
33
|
+
bodySmall: 'p',
|
|
34
|
+
caption: 'span',
|
|
35
|
+
label: 'label',
|
|
36
|
+
overline: 'span',
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export interface TextProps extends React.HTMLAttributes<HTMLElement>, VariantProps<typeof textVariants>, TextBaseProps {
|
|
40
|
+
as?: keyof React.JSX.IntrinsicElements;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const Text = React.forwardRef<HTMLElement, TextProps>(
|
|
44
|
+
({ className, variant = 'body', as, children, ...props }, ref) => {
|
|
45
|
+
const Comp = (as || variantElementMap[variant ?? 'body'] || 'p') as React.ElementType;
|
|
46
|
+
return (
|
|
47
|
+
<Comp ref={ref} className={cn(textVariants({ variant, className }))} {...props}>
|
|
48
|
+
{children}
|
|
49
|
+
</Comp>
|
|
50
|
+
);
|
|
51
|
+
},
|
|
52
|
+
);
|
|
53
|
+
Text.displayName = 'Text';
|
|
54
|
+
|
|
55
|
+
export { Text, textVariants };
|
package/src/textarea.tsx
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
|
|
5
|
+
import { TextareaBaseProps } from '@gv-tech/ui-core';
|
|
6
|
+
import { cn } from './lib/utils';
|
|
7
|
+
|
|
8
|
+
export interface TextareaProps
|
|
9
|
+
extends Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, keyof TextareaBaseProps>, TextareaBaseProps {}
|
|
10
|
+
|
|
11
|
+
const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(({ className, ...props }, ref) => {
|
|
12
|
+
return (
|
|
13
|
+
<textarea
|
|
14
|
+
className={cn(
|
|
15
|
+
'flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',
|
|
16
|
+
className,
|
|
17
|
+
)}
|
|
18
|
+
ref={ref}
|
|
19
|
+
{...props}
|
|
20
|
+
/>
|
|
21
|
+
);
|
|
22
|
+
});
|
|
23
|
+
Textarea.displayName = 'Textarea';
|
|
24
|
+
|
|
25
|
+
export { Textarea };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { ThemeProviderBaseProps } from '@gv-tech/ui-core';
|
|
4
|
+
import type { ThemeProviderProps as NextThemesProviderProps } from 'next-themes';
|
|
5
|
+
import { ThemeProvider as NextThemesProvider } from 'next-themes';
|
|
6
|
+
|
|
7
|
+
export type ThemeProviderProps = NextThemesProviderProps & ThemeProviderBaseProps;
|
|
8
|
+
|
|
9
|
+
export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
|
|
10
|
+
return (
|
|
11
|
+
<NextThemesProvider attribute="class" defaultTheme="system" enableSystem {...props}>
|
|
12
|
+
{children}
|
|
13
|
+
</NextThemesProvider>
|
|
14
|
+
);
|
|
15
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { ThemeToggleBaseProps } from '@gv-tech/ui-core';
|
|
4
|
+
import { Moon, Sun, SunMoon } from 'lucide-react';
|
|
5
|
+
import { Button } from './button';
|
|
6
|
+
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from './dropdown-menu';
|
|
7
|
+
import { useTheme } from './hooks/use-theme';
|
|
8
|
+
import { cn } from './lib/utils';
|
|
9
|
+
|
|
10
|
+
export type ThemeToggleProps = ThemeToggleBaseProps;
|
|
11
|
+
|
|
12
|
+
export function ThemeToggle({ variant = 'binary', onThemeChange, customTheme, className }: ThemeToggleProps) {
|
|
13
|
+
const { theme: nextTheme, setTheme: setNextTheme, resolvedTheme } = useTheme();
|
|
14
|
+
|
|
15
|
+
// Use customTheme if provided, otherwise fallback to next-themes
|
|
16
|
+
const currentTheme = customTheme ?? nextTheme;
|
|
17
|
+
|
|
18
|
+
// Determine the effective theme for icon rendering
|
|
19
|
+
const effectiveTheme = customTheme ? customTheme : resolvedTheme;
|
|
20
|
+
const isDark = effectiveTheme === 'dark';
|
|
21
|
+
const isSystem = currentTheme === 'system';
|
|
22
|
+
|
|
23
|
+
const handleThemeChange = (newTheme: string) => {
|
|
24
|
+
if (onThemeChange) {
|
|
25
|
+
onThemeChange(newTheme);
|
|
26
|
+
} else {
|
|
27
|
+
setNextTheme(newTheme);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const IconToggle = () => (
|
|
32
|
+
<>
|
|
33
|
+
<Sun
|
|
34
|
+
className={cn(
|
|
35
|
+
'h-[1.2rem] w-[1.2rem] transition-all',
|
|
36
|
+
!isSystem && !isDark ? 'rotate-0 scale-100' : '-rotate-90 scale-0',
|
|
37
|
+
)}
|
|
38
|
+
/>
|
|
39
|
+
<Moon
|
|
40
|
+
className={cn(
|
|
41
|
+
'absolute h-[1.2rem] w-[1.2rem] transition-all',
|
|
42
|
+
!isSystem && isDark ? 'rotate-0 scale-100' : 'rotate-90 scale-0',
|
|
43
|
+
)}
|
|
44
|
+
/>
|
|
45
|
+
<SunMoon
|
|
46
|
+
className={cn(
|
|
47
|
+
'absolute h-[1.2rem] w-[1.2rem] transition-all',
|
|
48
|
+
isSystem ? 'rotate-0 scale-100' : 'rotate-90 scale-0',
|
|
49
|
+
)}
|
|
50
|
+
/>
|
|
51
|
+
<span className="sr-only">Toggle theme</span>
|
|
52
|
+
</>
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
if (variant === 'ternary') {
|
|
56
|
+
return (
|
|
57
|
+
<DropdownMenu>
|
|
58
|
+
<DropdownMenuTrigger asChild>
|
|
59
|
+
<Button variant="ghost" size="icon" className={cn('relative h-9 w-9', className)}>
|
|
60
|
+
<IconToggle />
|
|
61
|
+
</Button>
|
|
62
|
+
</DropdownMenuTrigger>
|
|
63
|
+
<DropdownMenuContent align="end">
|
|
64
|
+
<DropdownMenuItem onClick={() => handleThemeChange('light')}>
|
|
65
|
+
<Sun className="mr-2 h-4 w-4" />
|
|
66
|
+
<span>Light</span>
|
|
67
|
+
</DropdownMenuItem>
|
|
68
|
+
<DropdownMenuItem onClick={() => handleThemeChange('dark')}>
|
|
69
|
+
<Moon className="mr-2 h-4 w-4" />
|
|
70
|
+
<span>Dark</span>
|
|
71
|
+
</DropdownMenuItem>
|
|
72
|
+
<DropdownMenuItem onClick={() => handleThemeChange('system')}>
|
|
73
|
+
<SunMoon className="mr-2 h-4 w-4" />
|
|
74
|
+
<span>System</span>
|
|
75
|
+
</DropdownMenuItem>
|
|
76
|
+
</DropdownMenuContent>
|
|
77
|
+
</DropdownMenu>
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return (
|
|
82
|
+
<Button
|
|
83
|
+
variant="ghost"
|
|
84
|
+
size="icon"
|
|
85
|
+
className={cn('relative h-9 w-9', className)}
|
|
86
|
+
onClick={() => handleThemeChange(currentTheme === 'dark' ? 'light' : 'dark')}
|
|
87
|
+
aria-label="Toggle theme"
|
|
88
|
+
>
|
|
89
|
+
<IconToggle />
|
|
90
|
+
</Button>
|
|
91
|
+
);
|
|
92
|
+
}
|
package/src/toast.tsx
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import * as ToastPrimitives from '@radix-ui/react-toast';
|
|
2
|
+
import { cva, type VariantProps } from 'class-variance-authority';
|
|
3
|
+
import { X } from 'lucide-react';
|
|
4
|
+
import * as React from 'react';
|
|
5
|
+
|
|
6
|
+
import { cn } from './lib/utils';
|
|
7
|
+
|
|
8
|
+
const ToastProvider = ToastPrimitives.Provider;
|
|
9
|
+
|
|
10
|
+
const ToastViewport = React.forwardRef<
|
|
11
|
+
React.ElementRef<typeof ToastPrimitives.Viewport>,
|
|
12
|
+
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Viewport>
|
|
13
|
+
>(({ className, ...props }, ref) => (
|
|
14
|
+
<ToastPrimitives.Viewport
|
|
15
|
+
ref={ref}
|
|
16
|
+
className={cn(
|
|
17
|
+
'fixed top-0 z-[100] flex max-h-screen w-full flex-col-reverse p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px]',
|
|
18
|
+
className,
|
|
19
|
+
)}
|
|
20
|
+
{...props}
|
|
21
|
+
/>
|
|
22
|
+
));
|
|
23
|
+
ToastViewport.displayName = ToastPrimitives.Viewport.displayName;
|
|
24
|
+
|
|
25
|
+
const toastVariants = cva(
|
|
26
|
+
'group pointer-events-auto relative flex w-full items-center justify-between space-x-2 overflow-hidden rounded-md border p-4 pr-6 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full',
|
|
27
|
+
{
|
|
28
|
+
variants: {
|
|
29
|
+
variant: {
|
|
30
|
+
default: 'border bg-background text-foreground',
|
|
31
|
+
destructive: 'destructive group border-destructive bg-destructive text-destructive-foreground',
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
defaultVariants: {
|
|
35
|
+
variant: 'default',
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
const Toast = React.forwardRef<
|
|
41
|
+
React.ElementRef<typeof ToastPrimitives.Root>,
|
|
42
|
+
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Root> & VariantProps<typeof toastVariants>
|
|
43
|
+
>(({ className, variant, ...props }, ref) => {
|
|
44
|
+
return <ToastPrimitives.Root ref={ref} className={cn(toastVariants({ variant }), className)} {...props} />;
|
|
45
|
+
});
|
|
46
|
+
Toast.displayName = ToastPrimitives.Root.displayName;
|
|
47
|
+
|
|
48
|
+
const ToastAction = React.forwardRef<
|
|
49
|
+
React.ElementRef<typeof ToastPrimitives.Action>,
|
|
50
|
+
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Action>
|
|
51
|
+
>(({ className, ...props }, ref) => (
|
|
52
|
+
<ToastPrimitives.Action
|
|
53
|
+
ref={ref}
|
|
54
|
+
className={cn(
|
|
55
|
+
'inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium transition-colors hover:bg-secondary focus:outline-none focus:ring-1 focus:ring-ring disabled:pointer-events-none disabled:opacity-50 group-[.destructive]:border-muted/40 group-[.destructive]:hover:border-destructive/30 group-[.destructive]:hover:bg-destructive group-[.destructive]:hover:text-destructive-foreground group-[.destructive]:focus:ring-destructive',
|
|
56
|
+
className,
|
|
57
|
+
)}
|
|
58
|
+
{...props}
|
|
59
|
+
/>
|
|
60
|
+
));
|
|
61
|
+
ToastAction.displayName = ToastPrimitives.Action.displayName;
|
|
62
|
+
|
|
63
|
+
const ToastClose = React.forwardRef<
|
|
64
|
+
React.ElementRef<typeof ToastPrimitives.Close>,
|
|
65
|
+
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Close>
|
|
66
|
+
>(({ className, ...props }, ref) => (
|
|
67
|
+
<ToastPrimitives.Close
|
|
68
|
+
ref={ref}
|
|
69
|
+
className={cn(
|
|
70
|
+
'absolute right-1 top-1 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-1 group-hover:opacity-100 group-[.destructive]:text-red-300 group-[.destructive]:hover:text-red-50 group-[.destructive]:focus:ring-red-400 group-[.destructive]:focus:ring-offset-red-600',
|
|
71
|
+
className,
|
|
72
|
+
)}
|
|
73
|
+
toast-close=""
|
|
74
|
+
{...props}
|
|
75
|
+
>
|
|
76
|
+
<X className="h-4 w-4" />
|
|
77
|
+
</ToastPrimitives.Close>
|
|
78
|
+
));
|
|
79
|
+
ToastClose.displayName = ToastPrimitives.Close.displayName;
|
|
80
|
+
|
|
81
|
+
const ToastTitle = React.forwardRef<
|
|
82
|
+
React.ElementRef<typeof ToastPrimitives.Title>,
|
|
83
|
+
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Title>
|
|
84
|
+
>(({ className, ...props }, ref) => (
|
|
85
|
+
<ToastPrimitives.Title ref={ref} className={cn('text-sm font-semibold [&+div]:text-xs', className)} {...props} />
|
|
86
|
+
));
|
|
87
|
+
ToastTitle.displayName = ToastPrimitives.Title.displayName;
|
|
88
|
+
|
|
89
|
+
const ToastDescription = React.forwardRef<
|
|
90
|
+
React.ElementRef<typeof ToastPrimitives.Description>,
|
|
91
|
+
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Description>
|
|
92
|
+
>(({ className, ...props }, ref) => (
|
|
93
|
+
<ToastPrimitives.Description ref={ref} className={cn('text-sm opacity-90', className)} {...props} />
|
|
94
|
+
));
|
|
95
|
+
ToastDescription.displayName = ToastPrimitives.Description.displayName;
|
|
96
|
+
|
|
97
|
+
type ToastProps = React.ComponentPropsWithoutRef<typeof Toast>;
|
|
98
|
+
|
|
99
|
+
type ToastActionElement = React.ReactElement<typeof ToastAction>;
|
|
100
|
+
|
|
101
|
+
export {
|
|
102
|
+
Toast,
|
|
103
|
+
ToastAction,
|
|
104
|
+
ToastClose,
|
|
105
|
+
ToastDescription,
|
|
106
|
+
ToastProvider,
|
|
107
|
+
ToastTitle,
|
|
108
|
+
ToastViewport,
|
|
109
|
+
type ToastActionElement,
|
|
110
|
+
type ToastProps,
|
|
111
|
+
};
|
package/src/toaster.tsx
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { ToasterBaseProps } from '@gv-tech/ui-core';
|
|
4
|
+
import { useToast } from './hooks/use-toast';
|
|
5
|
+
import { Toast, ToastClose, ToastDescription, ToastProvider, ToastTitle, ToastViewport } from './toast';
|
|
6
|
+
|
|
7
|
+
export function Toaster({ ...props }: ToasterBaseProps) {
|
|
8
|
+
const { toasts } = useToast();
|
|
9
|
+
|
|
10
|
+
return (
|
|
11
|
+
<ToastProvider {...props}>
|
|
12
|
+
{toasts.map(function ({ id, title, description, action, ...props }) {
|
|
13
|
+
return (
|
|
14
|
+
<Toast key={id} {...props}>
|
|
15
|
+
<div className="grid gap-1">
|
|
16
|
+
{title && <ToastTitle>{title}</ToastTitle>}
|
|
17
|
+
{description && <ToastDescription>{description}</ToastDescription>}
|
|
18
|
+
</div>
|
|
19
|
+
{action}
|
|
20
|
+
<ToastClose />
|
|
21
|
+
</Toast>
|
|
22
|
+
);
|
|
23
|
+
})}
|
|
24
|
+
<ToastViewport />
|
|
25
|
+
</ToastProvider>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import * as ToggleGroupPrimitive from '@radix-ui/react-toggle-group';
|
|
4
|
+
import { type VariantProps } from 'class-variance-authority';
|
|
5
|
+
import * as React from 'react';
|
|
6
|
+
|
|
7
|
+
import { toggleVariants } from '@gv-tech/ui-core';
|
|
8
|
+
import { cn } from './lib/utils';
|
|
9
|
+
|
|
10
|
+
const ToggleGroupContext = React.createContext<VariantProps<typeof toggleVariants>>({
|
|
11
|
+
size: 'default',
|
|
12
|
+
variant: 'default',
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
export type ToggleGroupProps = React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Root> &
|
|
16
|
+
VariantProps<typeof toggleVariants>;
|
|
17
|
+
|
|
18
|
+
const ToggleGroup = React.forwardRef<React.ElementRef<typeof ToggleGroupPrimitive.Root>, ToggleGroupProps>(
|
|
19
|
+
({ className, variant, size, children, ...props }, ref) => (
|
|
20
|
+
<ToggleGroupPrimitive.Root ref={ref} className={cn('flex items-center justify-center gap-1', className)} {...props}>
|
|
21
|
+
<ToggleGroupContext.Provider value={{ variant, size }}>{children}</ToggleGroupContext.Provider>
|
|
22
|
+
</ToggleGroupPrimitive.Root>
|
|
23
|
+
),
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
ToggleGroup.displayName = ToggleGroupPrimitive.Root.displayName;
|
|
27
|
+
|
|
28
|
+
export type ToggleGroupItemProps = React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Item> &
|
|
29
|
+
VariantProps<typeof toggleVariants>;
|
|
30
|
+
|
|
31
|
+
const ToggleGroupItem = React.forwardRef<React.ElementRef<typeof ToggleGroupPrimitive.Item>, ToggleGroupItemProps>(
|
|
32
|
+
({ className, children, variant, size, ...props }, ref) => {
|
|
33
|
+
const context = React.useContext(ToggleGroupContext);
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<ToggleGroupPrimitive.Item
|
|
37
|
+
ref={ref}
|
|
38
|
+
className={cn(
|
|
39
|
+
toggleVariants({
|
|
40
|
+
variant: context.variant || variant,
|
|
41
|
+
size: context.size || size,
|
|
42
|
+
}),
|
|
43
|
+
className,
|
|
44
|
+
)}
|
|
45
|
+
{...props}
|
|
46
|
+
>
|
|
47
|
+
{children}
|
|
48
|
+
</ToggleGroupPrimitive.Item>
|
|
49
|
+
);
|
|
50
|
+
},
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
ToggleGroupItem.displayName = ToggleGroupPrimitive.Item.displayName;
|
|
54
|
+
|
|
55
|
+
export { ToggleGroup, ToggleGroupItem };
|
package/src/toggle.tsx
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import * as TogglePrimitive from '@radix-ui/react-toggle';
|
|
4
|
+
import { VariantProps } from 'class-variance-authority';
|
|
5
|
+
import * as React from 'react';
|
|
6
|
+
|
|
7
|
+
import { ToggleBaseProps, toggleVariants } from '@gv-tech/ui-core';
|
|
8
|
+
import { cn } from './lib/utils';
|
|
9
|
+
|
|
10
|
+
export interface ToggleProps
|
|
11
|
+
extends
|
|
12
|
+
React.ComponentPropsWithoutRef<typeof TogglePrimitive.Root>,
|
|
13
|
+
Omit<VariantProps<typeof toggleVariants>, 'size' | 'variant'>,
|
|
14
|
+
ToggleBaseProps {}
|
|
15
|
+
|
|
16
|
+
const Toggle = React.forwardRef<React.ElementRef<typeof TogglePrimitive.Root>, ToggleProps>(
|
|
17
|
+
({ className, variant, size, ...props }, ref) => (
|
|
18
|
+
<TogglePrimitive.Root ref={ref} className={cn(toggleVariants({ variant, size, className }))} {...props} />
|
|
19
|
+
),
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
Toggle.displayName = TogglePrimitive.Root.displayName;
|
|
23
|
+
|
|
24
|
+
export { Toggle, toggleVariants };
|
package/src/tooltip.tsx
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import * as TooltipPrimitive from '@radix-ui/react-tooltip';
|
|
4
|
+
import * as React from 'react';
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
TooltipBaseProps,
|
|
8
|
+
TooltipContentBaseProps,
|
|
9
|
+
TooltipProviderBaseProps,
|
|
10
|
+
TooltipTriggerBaseProps,
|
|
11
|
+
} from '@gv-tech/ui-core';
|
|
12
|
+
import { cn } from './lib/utils';
|
|
13
|
+
|
|
14
|
+
export type TooltipProviderProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Provider> &
|
|
15
|
+
TooltipProviderBaseProps;
|
|
16
|
+
|
|
17
|
+
const TooltipProvider = ({ delayDuration = 0, ...props }: TooltipProviderProps) => (
|
|
18
|
+
<TooltipPrimitive.Provider delayDuration={delayDuration} {...props} />
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
export type TooltipProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Root> & TooltipBaseProps;
|
|
22
|
+
|
|
23
|
+
const Tooltip = ({ ...props }: TooltipProps) => <TooltipPrimitive.Root {...props} />;
|
|
24
|
+
|
|
25
|
+
export type TooltipTriggerProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Trigger> &
|
|
26
|
+
TooltipTriggerBaseProps;
|
|
27
|
+
|
|
28
|
+
const TooltipTrigger = React.forwardRef<React.ElementRef<typeof TooltipPrimitive.Trigger>, TooltipTriggerProps>(
|
|
29
|
+
({ className, ...props }, ref) => <TooltipPrimitive.Trigger ref={ref} className={className} {...props} />,
|
|
30
|
+
);
|
|
31
|
+
TooltipTrigger.displayName = TooltipPrimitive.Trigger.displayName;
|
|
32
|
+
|
|
33
|
+
export type TooltipContentProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content> &
|
|
34
|
+
TooltipContentBaseProps;
|
|
35
|
+
|
|
36
|
+
const TooltipContent = React.forwardRef<React.ElementRef<typeof TooltipPrimitive.Content>, TooltipContentProps>(
|
|
37
|
+
({ className, sideOffset = 4, ...props }, ref) => (
|
|
38
|
+
<TooltipPrimitive.Content
|
|
39
|
+
ref={ref}
|
|
40
|
+
sideOffset={sideOffset}
|
|
41
|
+
className={cn(
|
|
42
|
+
'z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground 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',
|
|
43
|
+
className,
|
|
44
|
+
)}
|
|
45
|
+
{...props}
|
|
46
|
+
/>
|
|
47
|
+
),
|
|
48
|
+
);
|
|
49
|
+
TooltipContent.displayName = TooltipPrimitive.Content.displayName;
|
|
50
|
+
|
|
51
|
+
export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger };
|