@tuturuuu/ui 0.0.4
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/.checksum +1 -0
- package/README.md +46 -0
- package/components.json +20 -0
- package/eslint.config.mjs +20 -0
- package/jsr.json +10 -0
- package/package.json +120 -0
- package/postcss.config.mjs +8 -0
- package/rollup.config.js +40 -0
- package/src/components/ui/accordion.tsx +70 -0
- package/src/components/ui/alert-dialog.tsx +156 -0
- package/src/components/ui/alert.tsx +58 -0
- package/src/components/ui/aspect-ratio.tsx +11 -0
- package/src/components/ui/avatar.tsx +52 -0
- package/src/components/ui/badge.tsx +49 -0
- package/src/components/ui/breadcrumb.tsx +108 -0
- package/src/components/ui/button.tsx +61 -0
- package/src/components/ui/calendar.tsx +212 -0
- package/src/components/ui/card.tsx +74 -0
- package/src/components/ui/carousel.tsx +240 -0
- package/src/components/ui/chart.tsx +365 -0
- package/src/components/ui/checkbox.tsx +31 -0
- package/src/components/ui/codeblock.tsx +161 -0
- package/src/components/ui/collapsible.tsx +33 -0
- package/src/components/ui/color-picker.tsx +143 -0
- package/src/components/ui/command.tsx +176 -0
- package/src/components/ui/context-menu.tsx +251 -0
- package/src/components/ui/custom/autosize-textarea.tsx +111 -0
- package/src/components/ui/custom/calendar/core.tsx +61 -0
- package/src/components/ui/custom/calendar/day-cell.tsx +74 -0
- package/src/components/ui/custom/calendar/month-header.tsx +59 -0
- package/src/components/ui/custom/calendar/month-view.tsx +110 -0
- package/src/components/ui/custom/calendar/utils.ts +76 -0
- package/src/components/ui/custom/calendar/year-calendar.tsx +64 -0
- package/src/components/ui/custom/calendar/year-view.tsx +58 -0
- package/src/components/ui/custom/combobox.tsx +197 -0
- package/src/components/ui/custom/common-footer.tsx +215 -0
- package/src/components/ui/custom/compared-date-range-picker.tsx +561 -0
- package/src/components/ui/custom/date-input.tsx +279 -0
- package/src/components/ui/custom/empty-card.tsx +39 -0
- package/src/components/ui/custom/feature-summary.tsx +135 -0
- package/src/components/ui/custom/file-uploader.tsx +349 -0
- package/src/components/ui/custom/input-field.tsx +29 -0
- package/src/components/ui/custom/loading-indicator.tsx +28 -0
- package/src/components/ui/custom/modifiable-dialog-trigger.tsx +83 -0
- package/src/components/ui/custom/month-picker.tsx +157 -0
- package/src/components/ui/custom/report-preview.tsx +175 -0
- package/src/components/ui/custom/search-bar.tsx +56 -0
- package/src/components/ui/custom/select-field.tsx +78 -0
- package/src/components/ui/custom/tables/data-table-column-header.tsx +72 -0
- package/src/components/ui/custom/tables/data-table-create-button.tsx +31 -0
- package/src/components/ui/custom/tables/data-table-faceted-filter.tsx +142 -0
- package/src/components/ui/custom/tables/data-table-pagination.tsx +243 -0
- package/src/components/ui/custom/tables/data-table-refresh-button.tsx +45 -0
- package/src/components/ui/custom/tables/data-table-toolbar.tsx +133 -0
- package/src/components/ui/custom/tables/data-table-view-options.tsx +112 -0
- package/src/components/ui/custom/tables/data-table.tsx +228 -0
- package/src/components/ui/custom/uploaded-files-card.tsx +50 -0
- package/src/components/ui/dialog.tsx +137 -0
- package/src/components/ui/drawer.tsx +131 -0
- package/src/components/ui/dropdown-menu.tsx +256 -0
- package/src/components/ui/form.tsx +167 -0
- package/src/components/ui/hover-card.tsx +41 -0
- package/src/components/ui/icons.tsx +506 -0
- package/src/components/ui/input-otp.tsx +78 -0
- package/src/components/ui/input.tsx +18 -0
- package/src/components/ui/label.tsx +23 -0
- package/src/components/ui/markdown.tsx +7 -0
- package/src/components/ui/menubar.tsx +275 -0
- package/src/components/ui/navigation-menu.tsx +169 -0
- package/src/components/ui/pagination.tsx +126 -0
- package/src/components/ui/popover.tsx +47 -0
- package/src/components/ui/progress.tsx +30 -0
- package/src/components/ui/radio-group.tsx +44 -0
- package/src/components/ui/resizable.tsx +55 -0
- package/src/components/ui/scroll-area.tsx +57 -0
- package/src/components/ui/select.tsx +180 -0
- package/src/components/ui/separator.tsx +27 -0
- package/src/components/ui/sheet.tsx +138 -0
- package/src/components/ui/sidebar.tsx +734 -0
- package/src/components/ui/skeleton.tsx +13 -0
- package/src/components/ui/slider.tsx +62 -0
- package/src/components/ui/sonner.tsx +29 -0
- package/src/components/ui/switch.tsx +30 -0
- package/src/components/ui/table.tsx +112 -0
- package/src/components/ui/tabs.tsx +68 -0
- package/src/components/ui/tag-input.tsx +141 -0
- package/src/components/ui/textarea.tsx +17 -0
- package/src/components/ui/time-picker-input.tsx +117 -0
- package/src/components/ui/time-picker-utils.tsx +146 -0
- package/src/components/ui/toast.tsx +128 -0
- package/src/components/ui/toaster.tsx +35 -0
- package/src/components/ui/toggle-group.tsx +72 -0
- package/src/components/ui/toggle.tsx +46 -0
- package/src/components/ui/tooltip.tsx +60 -0
- package/src/globals.css +252 -0
- package/src/hooks/use-callback-ref.ts +28 -0
- package/src/hooks/use-controllable-state.ts +68 -0
- package/src/hooks/use-copy-to-clipboard.ts +46 -0
- package/src/hooks/use-form.ts +23 -0
- package/src/hooks/use-forwarded-ref.ts +17 -0
- package/src/hooks/use-mobile.tsx +21 -0
- package/src/hooks/use-toast.ts +191 -0
- package/src/resolvers.ts +3 -0
- package/tsconfig.json +17 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* regular expression to check for valid hour format (01-23)
|
|
3
|
+
*/
|
|
4
|
+
export function isValidHour(value: string) {
|
|
5
|
+
return /^(0[0-9]|1[0-9]|2[0-3])$/.test(value);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* regular expression to check for valid 12-hour format (01-12)
|
|
10
|
+
*/
|
|
11
|
+
export function isValid12Hour(value: string) {
|
|
12
|
+
return /^(0[1-9]|1[0-2])$/.test(value);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* regular expression to check for valid minute format (00-59)
|
|
17
|
+
*/
|
|
18
|
+
export function isValidMinuteOrSecond(value: string) {
|
|
19
|
+
return /^[0-5][0-9]$/.test(value);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
type GetValidNumberConfig = { max: number; min?: number; loop?: boolean };
|
|
23
|
+
|
|
24
|
+
export function getValidNumber(
|
|
25
|
+
value: string,
|
|
26
|
+
{ max, min = 0, loop = false }: GetValidNumberConfig
|
|
27
|
+
) {
|
|
28
|
+
let numericValue = parseInt(value, 10);
|
|
29
|
+
|
|
30
|
+
if (!isNaN(numericValue)) {
|
|
31
|
+
if (!loop) {
|
|
32
|
+
if (numericValue > max) numericValue = max;
|
|
33
|
+
if (numericValue < min) numericValue = min;
|
|
34
|
+
} else {
|
|
35
|
+
if (numericValue > max) numericValue = min;
|
|
36
|
+
if (numericValue < min) numericValue = max;
|
|
37
|
+
}
|
|
38
|
+
return numericValue.toString().padStart(2, '0');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return '00';
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function getValidHour(value: string) {
|
|
45
|
+
if (isValidHour(value)) return value;
|
|
46
|
+
return getValidNumber(value, { max: 23 });
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function getValid12Hour(value: string) {
|
|
50
|
+
if (isValid12Hour(value)) return value;
|
|
51
|
+
return getValidNumber(value, { max: 12 });
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function getValidMinuteOrSecond(value: string) {
|
|
55
|
+
if (isValidMinuteOrSecond(value)) return value;
|
|
56
|
+
return getValidNumber(value, { max: 59 });
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
type GetValidArrowNumberConfig = {
|
|
60
|
+
min: number;
|
|
61
|
+
max: number;
|
|
62
|
+
step: number;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export function getValidArrowNumber(
|
|
66
|
+
value: string,
|
|
67
|
+
{ min, max, step }: GetValidArrowNumberConfig
|
|
68
|
+
) {
|
|
69
|
+
let numericValue = parseInt(value, 10);
|
|
70
|
+
if (!isNaN(numericValue)) {
|
|
71
|
+
numericValue += step;
|
|
72
|
+
return getValidNumber(String(numericValue), { min, max, loop: true });
|
|
73
|
+
}
|
|
74
|
+
return '00';
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function getValidArrowHour(value: string, step: number) {
|
|
78
|
+
return getValidArrowNumber(value, { min: 0, max: 23, step });
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function getValidArrowMinuteOrSecond(value: string, step: number) {
|
|
82
|
+
return getValidArrowNumber(value, { min: 0, max: 59, step });
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function setMinutes(date: Date, value: string) {
|
|
86
|
+
const minutes = getValidMinuteOrSecond(value);
|
|
87
|
+
date.setMinutes(parseInt(minutes, 10));
|
|
88
|
+
return date;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function setSeconds(date: Date, value: string) {
|
|
92
|
+
const seconds = getValidMinuteOrSecond(value);
|
|
93
|
+
date.setSeconds(parseInt(seconds, 10));
|
|
94
|
+
return date;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export function setHours(date: Date, value: string) {
|
|
98
|
+
const hours = getValidHour(value);
|
|
99
|
+
date.setHours(parseInt(hours, 10));
|
|
100
|
+
return date;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export type TimePickerType = 'minutes' | 'seconds' | 'hours'; // | "12hours";
|
|
104
|
+
|
|
105
|
+
export function setDateByType(date: Date, value: string, type: TimePickerType) {
|
|
106
|
+
switch (type) {
|
|
107
|
+
case 'minutes':
|
|
108
|
+
return setMinutes(date, value);
|
|
109
|
+
case 'seconds':
|
|
110
|
+
return setSeconds(date, value);
|
|
111
|
+
case 'hours':
|
|
112
|
+
return setHours(date, value);
|
|
113
|
+
default:
|
|
114
|
+
return date;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export function getDateByType(date: Date, type: TimePickerType) {
|
|
119
|
+
switch (type) {
|
|
120
|
+
case 'minutes':
|
|
121
|
+
return getValidMinuteOrSecond(String(date.getMinutes()));
|
|
122
|
+
case 'seconds':
|
|
123
|
+
return getValidMinuteOrSecond(String(date.getSeconds()));
|
|
124
|
+
case 'hours':
|
|
125
|
+
return getValidHour(String(date.getHours()));
|
|
126
|
+
default:
|
|
127
|
+
return '00';
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function getArrowByType(
|
|
132
|
+
value: string,
|
|
133
|
+
step: number,
|
|
134
|
+
type: TimePickerType
|
|
135
|
+
) {
|
|
136
|
+
switch (type) {
|
|
137
|
+
case 'minutes':
|
|
138
|
+
return getValidArrowMinuteOrSecond(value, step);
|
|
139
|
+
case 'seconds':
|
|
140
|
+
return getValidArrowMinuteOrSecond(value, step);
|
|
141
|
+
case 'hours':
|
|
142
|
+
return getValidArrowHour(value, step);
|
|
143
|
+
default:
|
|
144
|
+
return '00';
|
|
145
|
+
}
|
|
146
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import * as ToastPrimitives from '@radix-ui/react-toast';
|
|
4
|
+
import { cn } from '@tuturuuu/utils/format';
|
|
5
|
+
import { type VariantProps, cva } from 'class-variance-authority';
|
|
6
|
+
import { X } from 'lucide-react';
|
|
7
|
+
import * as React from 'react';
|
|
8
|
+
|
|
9
|
+
const ToastProvider = ToastPrimitives.Provider;
|
|
10
|
+
|
|
11
|
+
const ToastViewport = React.forwardRef<
|
|
12
|
+
React.ComponentRef<typeof ToastPrimitives.Viewport>,
|
|
13
|
+
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Viewport>
|
|
14
|
+
>(({ className, ...props }, ref) => (
|
|
15
|
+
<ToastPrimitives.Viewport
|
|
16
|
+
ref={ref}
|
|
17
|
+
className={cn(
|
|
18
|
+
'fixed top-0 z-[100] flex max-h-screen w-full flex-col-reverse p-4 sm:top-auto sm:right-0 sm:bottom-0 sm:flex-col md:max-w-[420px]',
|
|
19
|
+
className
|
|
20
|
+
)}
|
|
21
|
+
{...props}
|
|
22
|
+
/>
|
|
23
|
+
));
|
|
24
|
+
ToastViewport.displayName = ToastPrimitives.Viewport.displayName;
|
|
25
|
+
|
|
26
|
+
const toastVariants = cva(
|
|
27
|
+
'group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 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',
|
|
28
|
+
{
|
|
29
|
+
variants: {
|
|
30
|
+
variant: {
|
|
31
|
+
default: 'border bg-background text-foreground',
|
|
32
|
+
destructive:
|
|
33
|
+
'destructive group border-destructive bg-destructive text-destructive-foreground',
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
defaultVariants: {
|
|
37
|
+
variant: 'default',
|
|
38
|
+
},
|
|
39
|
+
}
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
const Toast = React.forwardRef<
|
|
43
|
+
React.ComponentRef<typeof ToastPrimitives.Root>,
|
|
44
|
+
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Root> &
|
|
45
|
+
VariantProps<typeof toastVariants>
|
|
46
|
+
>(({ className, variant, ...props }, ref) => {
|
|
47
|
+
return (
|
|
48
|
+
<ToastPrimitives.Root
|
|
49
|
+
ref={ref}
|
|
50
|
+
className={cn(toastVariants({ variant }), className)}
|
|
51
|
+
{...props}
|
|
52
|
+
/>
|
|
53
|
+
);
|
|
54
|
+
});
|
|
55
|
+
Toast.displayName = ToastPrimitives.Root.displayName;
|
|
56
|
+
|
|
57
|
+
const ToastAction = React.forwardRef<
|
|
58
|
+
React.ComponentRef<typeof ToastPrimitives.Action>,
|
|
59
|
+
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Action>
|
|
60
|
+
>(({ className, ...props }, ref) => (
|
|
61
|
+
<ToastPrimitives.Action
|
|
62
|
+
ref={ref}
|
|
63
|
+
className={cn(
|
|
64
|
+
'inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium ring-offset-background transition-colors group-[.destructive]:border-muted/40 hover:bg-secondary group-[.destructive]:hover:border-destructive/30 group-[.destructive]:hover:bg-destructive group-[.destructive]:hover:text-destructive-foreground focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:outline-hidden group-[.destructive]:focus:ring-destructive disabled:pointer-events-none disabled:opacity-50',
|
|
65
|
+
className
|
|
66
|
+
)}
|
|
67
|
+
{...props}
|
|
68
|
+
/>
|
|
69
|
+
));
|
|
70
|
+
ToastAction.displayName = ToastPrimitives.Action.displayName;
|
|
71
|
+
|
|
72
|
+
const ToastClose = React.forwardRef<
|
|
73
|
+
React.ComponentRef<typeof ToastPrimitives.Close>,
|
|
74
|
+
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Close>
|
|
75
|
+
>(({ className, ...props }, ref) => (
|
|
76
|
+
<ToastPrimitives.Close
|
|
77
|
+
ref={ref}
|
|
78
|
+
className={cn(
|
|
79
|
+
'absolute top-2 right-2 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity group-hover:opacity-100 group-[.destructive]:text-red-300 hover:text-foreground group-[.destructive]:hover:text-red-50 focus:opacity-100 focus:ring-2 focus:outline-hidden group-[.destructive]:focus:ring-red-400 group-[.destructive]:focus:ring-offset-red-600',
|
|
80
|
+
className
|
|
81
|
+
)}
|
|
82
|
+
toast-close=""
|
|
83
|
+
{...props}
|
|
84
|
+
>
|
|
85
|
+
<X className="h-4 w-4" />
|
|
86
|
+
</ToastPrimitives.Close>
|
|
87
|
+
));
|
|
88
|
+
ToastClose.displayName = ToastPrimitives.Close.displayName;
|
|
89
|
+
|
|
90
|
+
const ToastTitle = React.forwardRef<
|
|
91
|
+
React.ComponentRef<typeof ToastPrimitives.Title>,
|
|
92
|
+
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Title>
|
|
93
|
+
>(({ className, ...props }, ref) => (
|
|
94
|
+
<ToastPrimitives.Title
|
|
95
|
+
ref={ref}
|
|
96
|
+
className={cn('text-sm font-semibold', className)}
|
|
97
|
+
{...props}
|
|
98
|
+
/>
|
|
99
|
+
));
|
|
100
|
+
ToastTitle.displayName = ToastPrimitives.Title.displayName;
|
|
101
|
+
|
|
102
|
+
const ToastDescription = React.forwardRef<
|
|
103
|
+
React.ComponentRef<typeof ToastPrimitives.Description>,
|
|
104
|
+
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Description>
|
|
105
|
+
>(({ className, ...props }, ref) => (
|
|
106
|
+
<ToastPrimitives.Description
|
|
107
|
+
ref={ref}
|
|
108
|
+
className={cn('text-sm opacity-90', className)}
|
|
109
|
+
{...props}
|
|
110
|
+
/>
|
|
111
|
+
));
|
|
112
|
+
ToastDescription.displayName = ToastPrimitives.Description.displayName;
|
|
113
|
+
|
|
114
|
+
type ToastProps = React.ComponentPropsWithoutRef<typeof Toast>;
|
|
115
|
+
|
|
116
|
+
type ToastActionElement = React.ReactElement<typeof ToastAction>;
|
|
117
|
+
|
|
118
|
+
export {
|
|
119
|
+
Toast,
|
|
120
|
+
ToastAction,
|
|
121
|
+
ToastClose,
|
|
122
|
+
ToastDescription,
|
|
123
|
+
ToastProvider,
|
|
124
|
+
ToastTitle,
|
|
125
|
+
ToastViewport,
|
|
126
|
+
type ToastActionElement,
|
|
127
|
+
type ToastProps,
|
|
128
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useToast } from '../../hooks/use-toast';
|
|
4
|
+
import {
|
|
5
|
+
Toast,
|
|
6
|
+
ToastClose,
|
|
7
|
+
ToastDescription,
|
|
8
|
+
ToastProvider,
|
|
9
|
+
ToastTitle,
|
|
10
|
+
ToastViewport,
|
|
11
|
+
} from './toast';
|
|
12
|
+
|
|
13
|
+
export function Toaster() {
|
|
14
|
+
const { toasts } = useToast();
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<ToastProvider>
|
|
18
|
+
{toasts.map(function ({ id, title, description, action, ...props }) {
|
|
19
|
+
return (
|
|
20
|
+
<Toast key={id} {...props}>
|
|
21
|
+
<div className="grid gap-1">
|
|
22
|
+
{title && <ToastTitle>{title}</ToastTitle>}
|
|
23
|
+
{description && (
|
|
24
|
+
<ToastDescription>{description}</ToastDescription>
|
|
25
|
+
)}
|
|
26
|
+
</div>
|
|
27
|
+
{action}
|
|
28
|
+
<ToastClose />
|
|
29
|
+
</Toast>
|
|
30
|
+
);
|
|
31
|
+
})}
|
|
32
|
+
<ToastViewport />
|
|
33
|
+
</ToastProvider>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { toggleVariants } from './toggle';
|
|
4
|
+
import * as ToggleGroupPrimitive from '@radix-ui/react-toggle-group';
|
|
5
|
+
import { cn } from '@tuturuuu/utils/format';
|
|
6
|
+
import { type VariantProps } from 'class-variance-authority';
|
|
7
|
+
import * as React from 'react';
|
|
8
|
+
|
|
9
|
+
const ToggleGroupContext = React.createContext<
|
|
10
|
+
VariantProps<typeof toggleVariants>
|
|
11
|
+
>({
|
|
12
|
+
size: 'default',
|
|
13
|
+
variant: 'default',
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
function ToggleGroup({
|
|
17
|
+
className,
|
|
18
|
+
variant,
|
|
19
|
+
size,
|
|
20
|
+
children,
|
|
21
|
+
...props
|
|
22
|
+
}: React.ComponentProps<typeof ToggleGroupPrimitive.Root> &
|
|
23
|
+
VariantProps<typeof toggleVariants>) {
|
|
24
|
+
return (
|
|
25
|
+
<ToggleGroupPrimitive.Root
|
|
26
|
+
data-slot="toggle-group"
|
|
27
|
+
data-variant={variant}
|
|
28
|
+
data-size={size}
|
|
29
|
+
className={cn(
|
|
30
|
+
'group/toggle-group flex items-center justify-center rounded-md data-[variant=outline]:shadow-xs',
|
|
31
|
+
className
|
|
32
|
+
)}
|
|
33
|
+
{...props}
|
|
34
|
+
>
|
|
35
|
+
<ToggleGroupContext.Provider value={{ variant, size }}>
|
|
36
|
+
{children}
|
|
37
|
+
</ToggleGroupContext.Provider>
|
|
38
|
+
</ToggleGroupPrimitive.Root>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function ToggleGroupItem({
|
|
43
|
+
className,
|
|
44
|
+
children,
|
|
45
|
+
variant,
|
|
46
|
+
size,
|
|
47
|
+
...props
|
|
48
|
+
}: React.ComponentProps<typeof ToggleGroupPrimitive.Item> &
|
|
49
|
+
VariantProps<typeof toggleVariants>) {
|
|
50
|
+
const context = React.useContext(ToggleGroupContext);
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<ToggleGroupPrimitive.Item
|
|
54
|
+
data-slot="toggle-group-item"
|
|
55
|
+
data-variant={context.variant || variant}
|
|
56
|
+
data-size={context.size || size}
|
|
57
|
+
className={cn(
|
|
58
|
+
toggleVariants({
|
|
59
|
+
variant: context.variant || variant,
|
|
60
|
+
size: context.size || size,
|
|
61
|
+
}),
|
|
62
|
+
'min-w-0 shrink-0 rounded-none shadow-none first:rounded-l-md last:rounded-r-md focus:z-10 focus-visible:z-10 data-[variant=outline]:border-l-0 data-[variant=outline]:first:border-l',
|
|
63
|
+
className
|
|
64
|
+
)}
|
|
65
|
+
{...props}
|
|
66
|
+
>
|
|
67
|
+
{children}
|
|
68
|
+
</ToggleGroupPrimitive.Item>
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export { ToggleGroup, ToggleGroupItem };
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import * as TogglePrimitive from '@radix-ui/react-toggle';
|
|
4
|
+
import { cn } from '@tuturuuu/utils/format';
|
|
5
|
+
import { type VariantProps, cva } from 'class-variance-authority';
|
|
6
|
+
import * as React from 'react';
|
|
7
|
+
|
|
8
|
+
const toggleVariants = cva(
|
|
9
|
+
"inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium transition-colors hover:bg-muted hover:text-muted-foreground disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0 ring-ring/10 dark:ring-ring/20 dark:outline-ring/40 outline-ring/50 focus-visible:ring-4 focus-visible:outline-1 aria-invalid:focus-visible:ring-0 transition-[color,box-shadow]",
|
|
10
|
+
{
|
|
11
|
+
variants: {
|
|
12
|
+
variant: {
|
|
13
|
+
default: 'bg-transparent',
|
|
14
|
+
outline:
|
|
15
|
+
'border border-input bg-transparent shadow-xs hover:bg-accent hover:text-accent-foreground',
|
|
16
|
+
},
|
|
17
|
+
size: {
|
|
18
|
+
default: 'h-9 px-2 min-w-9',
|
|
19
|
+
sm: 'h-8 px-1.5 min-w-8',
|
|
20
|
+
lg: 'h-10 px-2.5 min-w-10',
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
defaultVariants: {
|
|
24
|
+
variant: 'default',
|
|
25
|
+
size: 'default',
|
|
26
|
+
},
|
|
27
|
+
}
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
function Toggle({
|
|
31
|
+
className,
|
|
32
|
+
variant,
|
|
33
|
+
size,
|
|
34
|
+
...props
|
|
35
|
+
}: React.ComponentProps<typeof TogglePrimitive.Root> &
|
|
36
|
+
VariantProps<typeof toggleVariants>) {
|
|
37
|
+
return (
|
|
38
|
+
<TogglePrimitive.Root
|
|
39
|
+
data-slot="toggle"
|
|
40
|
+
className={cn(toggleVariants({ variant, size, className }))}
|
|
41
|
+
{...props}
|
|
42
|
+
/>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export { Toggle, toggleVariants };
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import * as TooltipPrimitive from '@radix-ui/react-tooltip';
|
|
4
|
+
import { cn } from '@tuturuuu/utils/format';
|
|
5
|
+
import * as React from 'react';
|
|
6
|
+
|
|
7
|
+
function TooltipProvider({
|
|
8
|
+
delayDuration = 0,
|
|
9
|
+
...props
|
|
10
|
+
}: React.ComponentProps<typeof TooltipPrimitive.Provider>) {
|
|
11
|
+
return (
|
|
12
|
+
<TooltipPrimitive.Provider
|
|
13
|
+
data-slot="tooltip-provider"
|
|
14
|
+
delayDuration={delayDuration}
|
|
15
|
+
{...props}
|
|
16
|
+
/>
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function Tooltip({
|
|
21
|
+
...props
|
|
22
|
+
}: React.ComponentProps<typeof TooltipPrimitive.Root>) {
|
|
23
|
+
return (
|
|
24
|
+
<TooltipProvider>
|
|
25
|
+
<TooltipPrimitive.Root data-slot="tooltip" {...props} />
|
|
26
|
+
</TooltipProvider>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function TooltipTrigger({
|
|
31
|
+
...props
|
|
32
|
+
}: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {
|
|
33
|
+
return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function TooltipContent({
|
|
37
|
+
className,
|
|
38
|
+
sideOffset = 4,
|
|
39
|
+
children,
|
|
40
|
+
...props
|
|
41
|
+
}: React.ComponentProps<typeof TooltipPrimitive.Content>) {
|
|
42
|
+
return (
|
|
43
|
+
<TooltipPrimitive.Portal>
|
|
44
|
+
<TooltipPrimitive.Content
|
|
45
|
+
data-slot="tooltip-content"
|
|
46
|
+
sideOffset={sideOffset}
|
|
47
|
+
className={cn(
|
|
48
|
+
'z-50 max-w-sm rounded-md bg-primary px-3 py-1.5 text-xs text-primary-foreground animate-in fade-in-0 zoom-in-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 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95',
|
|
49
|
+
className
|
|
50
|
+
)}
|
|
51
|
+
{...props}
|
|
52
|
+
>
|
|
53
|
+
{children}
|
|
54
|
+
{/* <TooltipPrimitive.Arrow className="z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px] bg-primary fill-primary" /> */}
|
|
55
|
+
</TooltipPrimitive.Content>
|
|
56
|
+
</TooltipPrimitive.Portal>
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger };
|