@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.
Files changed (104) hide show
  1. package/.checksum +1 -0
  2. package/README.md +46 -0
  3. package/components.json +20 -0
  4. package/eslint.config.mjs +20 -0
  5. package/jsr.json +10 -0
  6. package/package.json +120 -0
  7. package/postcss.config.mjs +8 -0
  8. package/rollup.config.js +40 -0
  9. package/src/components/ui/accordion.tsx +70 -0
  10. package/src/components/ui/alert-dialog.tsx +156 -0
  11. package/src/components/ui/alert.tsx +58 -0
  12. package/src/components/ui/aspect-ratio.tsx +11 -0
  13. package/src/components/ui/avatar.tsx +52 -0
  14. package/src/components/ui/badge.tsx +49 -0
  15. package/src/components/ui/breadcrumb.tsx +108 -0
  16. package/src/components/ui/button.tsx +61 -0
  17. package/src/components/ui/calendar.tsx +212 -0
  18. package/src/components/ui/card.tsx +74 -0
  19. package/src/components/ui/carousel.tsx +240 -0
  20. package/src/components/ui/chart.tsx +365 -0
  21. package/src/components/ui/checkbox.tsx +31 -0
  22. package/src/components/ui/codeblock.tsx +161 -0
  23. package/src/components/ui/collapsible.tsx +33 -0
  24. package/src/components/ui/color-picker.tsx +143 -0
  25. package/src/components/ui/command.tsx +176 -0
  26. package/src/components/ui/context-menu.tsx +251 -0
  27. package/src/components/ui/custom/autosize-textarea.tsx +111 -0
  28. package/src/components/ui/custom/calendar/core.tsx +61 -0
  29. package/src/components/ui/custom/calendar/day-cell.tsx +74 -0
  30. package/src/components/ui/custom/calendar/month-header.tsx +59 -0
  31. package/src/components/ui/custom/calendar/month-view.tsx +110 -0
  32. package/src/components/ui/custom/calendar/utils.ts +76 -0
  33. package/src/components/ui/custom/calendar/year-calendar.tsx +64 -0
  34. package/src/components/ui/custom/calendar/year-view.tsx +58 -0
  35. package/src/components/ui/custom/combobox.tsx +197 -0
  36. package/src/components/ui/custom/common-footer.tsx +215 -0
  37. package/src/components/ui/custom/compared-date-range-picker.tsx +561 -0
  38. package/src/components/ui/custom/date-input.tsx +279 -0
  39. package/src/components/ui/custom/empty-card.tsx +39 -0
  40. package/src/components/ui/custom/feature-summary.tsx +135 -0
  41. package/src/components/ui/custom/file-uploader.tsx +349 -0
  42. package/src/components/ui/custom/input-field.tsx +29 -0
  43. package/src/components/ui/custom/loading-indicator.tsx +28 -0
  44. package/src/components/ui/custom/modifiable-dialog-trigger.tsx +83 -0
  45. package/src/components/ui/custom/month-picker.tsx +157 -0
  46. package/src/components/ui/custom/report-preview.tsx +175 -0
  47. package/src/components/ui/custom/search-bar.tsx +56 -0
  48. package/src/components/ui/custom/select-field.tsx +78 -0
  49. package/src/components/ui/custom/tables/data-table-column-header.tsx +72 -0
  50. package/src/components/ui/custom/tables/data-table-create-button.tsx +31 -0
  51. package/src/components/ui/custom/tables/data-table-faceted-filter.tsx +142 -0
  52. package/src/components/ui/custom/tables/data-table-pagination.tsx +243 -0
  53. package/src/components/ui/custom/tables/data-table-refresh-button.tsx +45 -0
  54. package/src/components/ui/custom/tables/data-table-toolbar.tsx +133 -0
  55. package/src/components/ui/custom/tables/data-table-view-options.tsx +112 -0
  56. package/src/components/ui/custom/tables/data-table.tsx +228 -0
  57. package/src/components/ui/custom/uploaded-files-card.tsx +50 -0
  58. package/src/components/ui/dialog.tsx +137 -0
  59. package/src/components/ui/drawer.tsx +131 -0
  60. package/src/components/ui/dropdown-menu.tsx +256 -0
  61. package/src/components/ui/form.tsx +167 -0
  62. package/src/components/ui/hover-card.tsx +41 -0
  63. package/src/components/ui/icons.tsx +506 -0
  64. package/src/components/ui/input-otp.tsx +78 -0
  65. package/src/components/ui/input.tsx +18 -0
  66. package/src/components/ui/label.tsx +23 -0
  67. package/src/components/ui/markdown.tsx +7 -0
  68. package/src/components/ui/menubar.tsx +275 -0
  69. package/src/components/ui/navigation-menu.tsx +169 -0
  70. package/src/components/ui/pagination.tsx +126 -0
  71. package/src/components/ui/popover.tsx +47 -0
  72. package/src/components/ui/progress.tsx +30 -0
  73. package/src/components/ui/radio-group.tsx +44 -0
  74. package/src/components/ui/resizable.tsx +55 -0
  75. package/src/components/ui/scroll-area.tsx +57 -0
  76. package/src/components/ui/select.tsx +180 -0
  77. package/src/components/ui/separator.tsx +27 -0
  78. package/src/components/ui/sheet.tsx +138 -0
  79. package/src/components/ui/sidebar.tsx +734 -0
  80. package/src/components/ui/skeleton.tsx +13 -0
  81. package/src/components/ui/slider.tsx +62 -0
  82. package/src/components/ui/sonner.tsx +29 -0
  83. package/src/components/ui/switch.tsx +30 -0
  84. package/src/components/ui/table.tsx +112 -0
  85. package/src/components/ui/tabs.tsx +68 -0
  86. package/src/components/ui/tag-input.tsx +141 -0
  87. package/src/components/ui/textarea.tsx +17 -0
  88. package/src/components/ui/time-picker-input.tsx +117 -0
  89. package/src/components/ui/time-picker-utils.tsx +146 -0
  90. package/src/components/ui/toast.tsx +128 -0
  91. package/src/components/ui/toaster.tsx +35 -0
  92. package/src/components/ui/toggle-group.tsx +72 -0
  93. package/src/components/ui/toggle.tsx +46 -0
  94. package/src/components/ui/tooltip.tsx +60 -0
  95. package/src/globals.css +252 -0
  96. package/src/hooks/use-callback-ref.ts +28 -0
  97. package/src/hooks/use-controllable-state.ts +68 -0
  98. package/src/hooks/use-copy-to-clipboard.ts +46 -0
  99. package/src/hooks/use-form.ts +23 -0
  100. package/src/hooks/use-forwarded-ref.ts +17 -0
  101. package/src/hooks/use-mobile.tsx +21 -0
  102. package/src/hooks/use-toast.ts +191 -0
  103. package/src/resolvers.ts +3 -0
  104. package/tsconfig.json +17 -0
@@ -0,0 +1,275 @@
1
+ 'use client';
2
+
3
+ import * as MenubarPrimitive from '@radix-ui/react-menubar';
4
+ import { cn } from '@tuturuuu/utils/format';
5
+ import { CheckIcon, ChevronRightIcon, CircleIcon } from 'lucide-react';
6
+ import * as React from 'react';
7
+
8
+ function Menubar({
9
+ className,
10
+ ...props
11
+ }: React.ComponentProps<typeof MenubarPrimitive.Root>) {
12
+ return (
13
+ <MenubarPrimitive.Root
14
+ data-slot="menubar"
15
+ className={cn(
16
+ 'flex h-9 items-center gap-1 rounded-md border bg-background p-1 shadow-xs',
17
+ className
18
+ )}
19
+ {...props}
20
+ />
21
+ );
22
+ }
23
+
24
+ function MenubarMenu({
25
+ ...props
26
+ }: React.ComponentProps<typeof MenubarPrimitive.Menu>) {
27
+ return <MenubarPrimitive.Menu data-slot="menubar-menu" {...props} />;
28
+ }
29
+
30
+ function MenubarGroup({
31
+ ...props
32
+ }: React.ComponentProps<typeof MenubarPrimitive.Group>) {
33
+ return <MenubarPrimitive.Group data-slot="menubar-group" {...props} />;
34
+ }
35
+
36
+ function MenubarPortal({
37
+ ...props
38
+ }: React.ComponentProps<typeof MenubarPrimitive.Portal>) {
39
+ return <MenubarPrimitive.Portal data-slot="menubar-portal" {...props} />;
40
+ }
41
+
42
+ function MenubarRadioGroup({
43
+ ...props
44
+ }: React.ComponentProps<typeof MenubarPrimitive.RadioGroup>) {
45
+ return (
46
+ <MenubarPrimitive.RadioGroup data-slot="menubar-radio-group" {...props} />
47
+ );
48
+ }
49
+
50
+ function MenubarTrigger({
51
+ className,
52
+ ...props
53
+ }: React.ComponentProps<typeof MenubarPrimitive.Trigger>) {
54
+ return (
55
+ <MenubarPrimitive.Trigger
56
+ data-slot="menubar-trigger"
57
+ className={cn(
58
+ 'flex items-center rounded-sm px-2 py-1 text-sm font-medium outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground',
59
+ className
60
+ )}
61
+ {...props}
62
+ />
63
+ );
64
+ }
65
+
66
+ function MenubarContent({
67
+ className,
68
+ align = 'start',
69
+ alignOffset = -4,
70
+ sideOffset = 8,
71
+ ...props
72
+ }: React.ComponentProps<typeof MenubarPrimitive.Content>) {
73
+ return (
74
+ <MenubarPortal>
75
+ <MenubarPrimitive.Content
76
+ data-slot="menubar-content"
77
+ align={align}
78
+ alignOffset={alignOffset}
79
+ sideOffset={sideOffset}
80
+ className={cn(
81
+ 'z-50 min-w-[12rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md 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]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95',
82
+ className
83
+ )}
84
+ {...props}
85
+ />
86
+ </MenubarPortal>
87
+ );
88
+ }
89
+
90
+ function MenubarItem({
91
+ className,
92
+ inset,
93
+ variant = 'default',
94
+ ...props
95
+ }: React.ComponentProps<typeof MenubarPrimitive.Item> & {
96
+ inset?: boolean;
97
+ variant?: 'default' | 'destructive';
98
+ }) {
99
+ return (
100
+ <MenubarPrimitive.Item
101
+ data-slot="menubar-item"
102
+ data-inset={inset}
103
+ data-variant={variant}
104
+ className={cn(
105
+ "relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground data-[variant=destructive]:*:[svg]:!text-destructive",
106
+ className
107
+ )}
108
+ {...props}
109
+ />
110
+ );
111
+ }
112
+
113
+ function MenubarCheckboxItem({
114
+ className,
115
+ children,
116
+ checked,
117
+ ...props
118
+ }: React.ComponentProps<typeof MenubarPrimitive.CheckboxItem>) {
119
+ return (
120
+ <MenubarPrimitive.CheckboxItem
121
+ data-slot="menubar-checkbox-item"
122
+ className={cn(
123
+ "relative flex cursor-default items-center gap-2 rounded-xs py-1.5 pr-2 pl-8 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
124
+ className
125
+ )}
126
+ checked={checked}
127
+ {...props}
128
+ >
129
+ <span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
130
+ <MenubarPrimitive.ItemIndicator>
131
+ <CheckIcon className="size-4" />
132
+ </MenubarPrimitive.ItemIndicator>
133
+ </span>
134
+ {children}
135
+ </MenubarPrimitive.CheckboxItem>
136
+ );
137
+ }
138
+
139
+ function MenubarRadioItem({
140
+ className,
141
+ children,
142
+ ...props
143
+ }: React.ComponentProps<typeof MenubarPrimitive.RadioItem>) {
144
+ return (
145
+ <MenubarPrimitive.RadioItem
146
+ data-slot="menubar-radio-item"
147
+ className={cn(
148
+ "relative flex cursor-default items-center gap-2 rounded-xs py-1.5 pr-2 pl-8 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
149
+ className
150
+ )}
151
+ {...props}
152
+ >
153
+ <span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
154
+ <MenubarPrimitive.ItemIndicator>
155
+ <CircleIcon className="size-2 fill-current" />
156
+ </MenubarPrimitive.ItemIndicator>
157
+ </span>
158
+ {children}
159
+ </MenubarPrimitive.RadioItem>
160
+ );
161
+ }
162
+
163
+ function MenubarLabel({
164
+ className,
165
+ inset,
166
+ ...props
167
+ }: React.ComponentProps<typeof MenubarPrimitive.Label> & {
168
+ inset?: boolean;
169
+ }) {
170
+ return (
171
+ <MenubarPrimitive.Label
172
+ data-slot="menubar-label"
173
+ data-inset={inset}
174
+ className={cn(
175
+ 'px-2 py-1.5 text-sm font-semibold data-[inset]:pl-8',
176
+ className
177
+ )}
178
+ {...props}
179
+ />
180
+ );
181
+ }
182
+
183
+ function MenubarSeparator({
184
+ className,
185
+ ...props
186
+ }: React.ComponentProps<typeof MenubarPrimitive.Separator>) {
187
+ return (
188
+ <MenubarPrimitive.Separator
189
+ data-slot="menubar-separator"
190
+ className={cn('-mx-1 my-1 h-px bg-border', className)}
191
+ {...props}
192
+ />
193
+ );
194
+ }
195
+
196
+ function MenubarShortcut({
197
+ className,
198
+ ...props
199
+ }: React.ComponentProps<'span'>) {
200
+ return (
201
+ <span
202
+ data-slot="menubar-shortcut"
203
+ className={cn(
204
+ 'ml-auto text-xs tracking-widest text-muted-foreground',
205
+ className
206
+ )}
207
+ {...props}
208
+ />
209
+ );
210
+ }
211
+
212
+ function MenubarSub({
213
+ ...props
214
+ }: React.ComponentProps<typeof MenubarPrimitive.Sub>) {
215
+ return <MenubarPrimitive.Sub data-slot="menubar-sub" {...props} />;
216
+ }
217
+
218
+ function MenubarSubTrigger({
219
+ className,
220
+ inset,
221
+ children,
222
+ ...props
223
+ }: React.ComponentProps<typeof MenubarPrimitive.SubTrigger> & {
224
+ inset?: boolean;
225
+ }) {
226
+ return (
227
+ <MenubarPrimitive.SubTrigger
228
+ data-slot="menubar-sub-trigger"
229
+ data-inset={inset}
230
+ className={cn(
231
+ 'flex cursor-default items-center rounded-sm px-2 py-1.5 text-sm outline-none select-none focus:bg-accent focus:text-accent-foreground data-[inset]:pl-8 data-[state=open]:bg-accent data-[state=open]:text-accent-foreground',
232
+ className
233
+ )}
234
+ {...props}
235
+ >
236
+ {children}
237
+ <ChevronRightIcon className="ml-auto h-4 w-4" />
238
+ </MenubarPrimitive.SubTrigger>
239
+ );
240
+ }
241
+
242
+ function MenubarSubContent({
243
+ className,
244
+ ...props
245
+ }: React.ComponentProps<typeof MenubarPrimitive.SubContent>) {
246
+ return (
247
+ <MenubarPrimitive.SubContent
248
+ data-slot="menubar-sub-content"
249
+ className={cn(
250
+ 'z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg 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 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95',
251
+ className
252
+ )}
253
+ {...props}
254
+ />
255
+ );
256
+ }
257
+
258
+ export {
259
+ Menubar,
260
+ MenubarCheckboxItem,
261
+ MenubarContent,
262
+ MenubarGroup,
263
+ MenubarItem,
264
+ MenubarLabel,
265
+ MenubarMenu,
266
+ MenubarPortal,
267
+ MenubarRadioGroup,
268
+ MenubarRadioItem,
269
+ MenubarSeparator,
270
+ MenubarShortcut,
271
+ MenubarSub,
272
+ MenubarSubContent,
273
+ MenubarSubTrigger,
274
+ MenubarTrigger,
275
+ };
@@ -0,0 +1,169 @@
1
+ 'use client';
2
+
3
+ import * as NavigationMenuPrimitive from '@radix-ui/react-navigation-menu';
4
+ import { cn } from '@tuturuuu/utils/format';
5
+ import { cva } from 'class-variance-authority';
6
+ import { ChevronDownIcon } from 'lucide-react';
7
+ import * as React from 'react';
8
+
9
+ function NavigationMenu({
10
+ className,
11
+ children,
12
+ viewport = true,
13
+ ...props
14
+ }: React.ComponentProps<typeof NavigationMenuPrimitive.Root> & {
15
+ viewport?: boolean;
16
+ }) {
17
+ return (
18
+ <NavigationMenuPrimitive.Root
19
+ data-slot="navigation-menu"
20
+ data-viewport={viewport}
21
+ className={cn(
22
+ 'group/navigation-menu relative flex max-w-max flex-1 items-center justify-center',
23
+ className
24
+ )}
25
+ {...props}
26
+ >
27
+ {children}
28
+ {viewport && <NavigationMenuViewport />}
29
+ </NavigationMenuPrimitive.Root>
30
+ );
31
+ }
32
+
33
+ function NavigationMenuList({
34
+ className,
35
+ ...props
36
+ }: React.ComponentProps<typeof NavigationMenuPrimitive.List>) {
37
+ return (
38
+ <NavigationMenuPrimitive.List
39
+ data-slot="navigation-menu-list"
40
+ className={cn(
41
+ 'group flex flex-1 list-none items-center justify-center gap-1',
42
+ className
43
+ )}
44
+ {...props}
45
+ />
46
+ );
47
+ }
48
+
49
+ function NavigationMenuItem({
50
+ className,
51
+ ...props
52
+ }: React.ComponentProps<typeof NavigationMenuPrimitive.Item>) {
53
+ return (
54
+ <NavigationMenuPrimitive.Item
55
+ data-slot="navigation-menu-item"
56
+ className={cn('relative', className)}
57
+ {...props}
58
+ />
59
+ );
60
+ }
61
+
62
+ const navigationMenuTriggerStyle = cva(
63
+ 'group inline-flex h-9 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground disabled:pointer-events-none disabled:opacity-50 data-[active=true]:bg-accent/50 data-[state=open]:bg-accent/50 data-[active=true]:text-accent-foreground ring-ring/10 dark:ring-ring/20 dark:outline-ring/40 outline-ring/50 transition-[color,box-shadow] focus-visible:ring-4 focus-visible:outline-1'
64
+ );
65
+
66
+ function NavigationMenuTrigger({
67
+ className,
68
+ children,
69
+ ...props
70
+ }: React.ComponentProps<typeof NavigationMenuPrimitive.Trigger>) {
71
+ return (
72
+ <NavigationMenuPrimitive.Trigger
73
+ data-slot="navigation-menu-trigger"
74
+ className={cn(navigationMenuTriggerStyle(), 'group', className)}
75
+ {...props}
76
+ >
77
+ {children}{' '}
78
+ <ChevronDownIcon
79
+ className="relative top-[1px] ml-1 size-3 transition duration-300 group-data-[state=open]:rotate-180"
80
+ aria-hidden="true"
81
+ />
82
+ </NavigationMenuPrimitive.Trigger>
83
+ );
84
+ }
85
+
86
+ function NavigationMenuContent({
87
+ className,
88
+ ...props
89
+ }: React.ComponentProps<typeof NavigationMenuPrimitive.Content>) {
90
+ return (
91
+ <NavigationMenuPrimitive.Content
92
+ data-slot="navigation-menu-content"
93
+ className={cn(
94
+ 'top-0 left-0 w-full p-2 pr-2.5 data-[motion=from-end]:slide-in-from-right-52 data-[motion=from-start]:slide-in-from-left-52 data-[motion=to-end]:slide-out-to-right-52 data-[motion=to-start]:slide-out-to-left-52 data-[motion^=from-]:animate-in data-[motion^=from-]:fade-in data-[motion^=to-]:animate-out data-[motion^=to-]:fade-out md:absolute md:w-auto',
95
+ 'group-data-[viewport=false]/navigation-menu:top-full group-data-[viewport=false]/navigation-menu:mt-1.5 group-data-[viewport=false]/navigation-menu:overflow-hidden group-data-[viewport=false]/navigation-menu:rounded-md group-data-[viewport=false]/navigation-menu:border group-data-[viewport=false]/navigation-menu:bg-popover group-data-[viewport=false]/navigation-menu:text-popover-foreground group-data-[viewport=false]/navigation-menu:shadow group-data-[viewport=false]/navigation-menu:duration-200 **:data-[slot=navigation-menu-link]:focus:ring-0 **:data-[slot=navigation-menu-link]:focus:outline-none group-data-[viewport=false]/navigation-menu:data-[state=closed]:animate-out group-data-[viewport=false]/navigation-menu:data-[state=closed]:fade-out-0 group-data-[viewport=false]/navigation-menu:data-[state=closed]:zoom-out-95 group-data-[viewport=false]/navigation-menu:data-[state=open]:animate-in group-data-[viewport=false]/navigation-menu:data-[state=open]:fade-in-0 group-data-[viewport=false]/navigation-menu:data-[state=open]:zoom-in-95',
96
+ className
97
+ )}
98
+ {...props}
99
+ />
100
+ );
101
+ }
102
+
103
+ function NavigationMenuViewport({
104
+ className,
105
+ ...props
106
+ }: React.ComponentProps<typeof NavigationMenuPrimitive.Viewport>) {
107
+ return (
108
+ <div
109
+ className={cn(
110
+ 'absolute top-full left-0 isolate z-50 flex justify-center'
111
+ )}
112
+ >
113
+ <NavigationMenuPrimitive.Viewport
114
+ data-slot="navigation-menu-viewport"
115
+ className={cn(
116
+ 'origin-top-center relative mt-1.5 h-[var(--radix-navigation-menu-viewport-height)] w-full overflow-hidden rounded-md border bg-popover text-popover-foreground shadow data-[state=closed]:animate-out data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:zoom-in-90 md:w-[var(--radix-navigation-menu-viewport-width)]',
117
+ className
118
+ )}
119
+ {...props}
120
+ />
121
+ </div>
122
+ );
123
+ }
124
+
125
+ function NavigationMenuLink({
126
+ className,
127
+ ...props
128
+ }: React.ComponentProps<typeof NavigationMenuPrimitive.Link>) {
129
+ return (
130
+ <NavigationMenuPrimitive.Link
131
+ data-slot="navigation-menu-link"
132
+ className={cn(
133
+ "flex flex-col gap-1 rounded-sm p-2 text-sm ring-ring/10 outline-ring/50 transition-[color,box-shadow] hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus-visible:ring-4 focus-visible:outline-1 data-[active=true]:bg-accent/50 data-[active=true]:text-accent-foreground dark:ring-ring/20 dark:outline-ring/40 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground",
134
+ className
135
+ )}
136
+ {...props}
137
+ />
138
+ );
139
+ }
140
+
141
+ function NavigationMenuIndicator({
142
+ className,
143
+ ...props
144
+ }: React.ComponentProps<typeof NavigationMenuPrimitive.Indicator>) {
145
+ return (
146
+ <NavigationMenuPrimitive.Indicator
147
+ data-slot="navigation-menu-indicator"
148
+ className={cn(
149
+ 'top-full z-[1] flex h-1.5 items-end justify-center overflow-hidden data-[state=hidden]:animate-out data-[state=hidden]:fade-out data-[state=visible]:animate-in data-[state=visible]:fade-in',
150
+ className
151
+ )}
152
+ {...props}
153
+ >
154
+ <div className="relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm bg-border shadow-md" />
155
+ </NavigationMenuPrimitive.Indicator>
156
+ );
157
+ }
158
+
159
+ export {
160
+ NavigationMenu,
161
+ NavigationMenuContent,
162
+ NavigationMenuIndicator,
163
+ NavigationMenuItem,
164
+ NavigationMenuLink,
165
+ NavigationMenuList,
166
+ NavigationMenuTrigger,
167
+ navigationMenuTriggerStyle,
168
+ NavigationMenuViewport,
169
+ };
@@ -0,0 +1,126 @@
1
+ import { type Button, buttonVariants } from './button';
2
+ import { cn } from '@tuturuuu/utils/format';
3
+ import {
4
+ ChevronLeftIcon,
5
+ ChevronRightIcon,
6
+ MoreHorizontalIcon,
7
+ } from 'lucide-react';
8
+ import * as React from 'react';
9
+
10
+ function Pagination({ className, ...props }: React.ComponentProps<'nav'>) {
11
+ return (
12
+ <nav
13
+ role="navigation"
14
+ aria-label="pagination"
15
+ data-slot="pagination"
16
+ className={cn('mx-auto flex w-full justify-center', className)}
17
+ {...props}
18
+ />
19
+ );
20
+ }
21
+
22
+ function PaginationContent({
23
+ className,
24
+ ...props
25
+ }: React.ComponentProps<'ul'>) {
26
+ return (
27
+ <ul
28
+ data-slot="pagination-content"
29
+ className={cn('flex flex-row items-center gap-1', className)}
30
+ {...props}
31
+ />
32
+ );
33
+ }
34
+
35
+ function PaginationItem({ ...props }: React.ComponentProps<'li'>) {
36
+ return <li data-slot="pagination-item" {...props} />;
37
+ }
38
+
39
+ type PaginationLinkProps = {
40
+ isActive?: boolean;
41
+ } & Pick<React.ComponentProps<typeof Button>, 'size'> &
42
+ React.ComponentProps<'a'>;
43
+
44
+ function PaginationLink({
45
+ className,
46
+ isActive,
47
+ size = 'icon',
48
+ ...props
49
+ }: PaginationLinkProps) {
50
+ return (
51
+ <a
52
+ aria-current={isActive ? 'page' : undefined}
53
+ data-slot="pagination-link"
54
+ data-active={isActive}
55
+ className={cn(
56
+ buttonVariants({
57
+ variant: isActive ? 'outline' : 'ghost',
58
+ size,
59
+ }),
60
+ className
61
+ )}
62
+ {...props}
63
+ />
64
+ );
65
+ }
66
+
67
+ function PaginationPrevious({
68
+ className,
69
+ ...props
70
+ }: React.ComponentProps<typeof PaginationLink>) {
71
+ return (
72
+ <PaginationLink
73
+ aria-label="Go to previous page"
74
+ size="default"
75
+ className={cn('gap-1 px-2.5 sm:pl-2.5', className)}
76
+ {...props}
77
+ >
78
+ <ChevronLeftIcon />
79
+ <span className="hidden sm:block">Previous</span>
80
+ </PaginationLink>
81
+ );
82
+ }
83
+
84
+ function PaginationNext({
85
+ className,
86
+ ...props
87
+ }: React.ComponentProps<typeof PaginationLink>) {
88
+ return (
89
+ <PaginationLink
90
+ aria-label="Go to next page"
91
+ size="default"
92
+ className={cn('gap-1 px-2.5 sm:pr-2.5', className)}
93
+ {...props}
94
+ >
95
+ <span className="hidden sm:block">Next</span>
96
+ <ChevronRightIcon />
97
+ </PaginationLink>
98
+ );
99
+ }
100
+
101
+ function PaginationEllipsis({
102
+ className,
103
+ ...props
104
+ }: React.ComponentProps<'span'>) {
105
+ return (
106
+ <span
107
+ aria-hidden
108
+ data-slot="pagination-ellipsis"
109
+ className={cn('flex size-9 items-center justify-center', className)}
110
+ {...props}
111
+ >
112
+ <MoreHorizontalIcon className="size-4" />
113
+ <span className="sr-only">More pages</span>
114
+ </span>
115
+ );
116
+ }
117
+
118
+ export {
119
+ Pagination,
120
+ PaginationContent,
121
+ PaginationEllipsis,
122
+ PaginationItem,
123
+ PaginationLink,
124
+ PaginationNext,
125
+ PaginationPrevious,
126
+ };
@@ -0,0 +1,47 @@
1
+ 'use client';
2
+
3
+ import * as PopoverPrimitive from '@radix-ui/react-popover';
4
+ import { cn } from '@tuturuuu/utils/format';
5
+ import * as React from 'react';
6
+
7
+ function Popover({
8
+ ...props
9
+ }: React.ComponentProps<typeof PopoverPrimitive.Root>) {
10
+ return <PopoverPrimitive.Root data-slot="popover" {...props} />;
11
+ }
12
+
13
+ function PopoverTrigger({
14
+ ...props
15
+ }: React.ComponentProps<typeof PopoverPrimitive.Trigger>) {
16
+ return <PopoverPrimitive.Trigger data-slot="popover-trigger" {...props} />;
17
+ }
18
+
19
+ function PopoverContent({
20
+ className,
21
+ align = 'center',
22
+ sideOffset = 4,
23
+ ...props
24
+ }: React.ComponentProps<typeof PopoverPrimitive.Content>) {
25
+ return (
26
+ <PopoverPrimitive.Portal>
27
+ <PopoverPrimitive.Content
28
+ data-slot="popover-content"
29
+ align={align}
30
+ sideOffset={sideOffset}
31
+ className={cn(
32
+ 'z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-hidden 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 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95',
33
+ className
34
+ )}
35
+ {...props}
36
+ />
37
+ </PopoverPrimitive.Portal>
38
+ );
39
+ }
40
+
41
+ function PopoverAnchor({
42
+ ...props
43
+ }: React.ComponentProps<typeof PopoverPrimitive.Anchor>) {
44
+ return <PopoverPrimitive.Anchor data-slot="popover-anchor" {...props} />;
45
+ }
46
+
47
+ export { Popover, PopoverAnchor, PopoverContent, PopoverTrigger };
@@ -0,0 +1,30 @@
1
+ 'use client';
2
+
3
+ import * as ProgressPrimitive from '@radix-ui/react-progress';
4
+ import { cn } from '@tuturuuu/utils/format';
5
+ import * as React from 'react';
6
+
7
+ function Progress({
8
+ className,
9
+ value,
10
+ ...props
11
+ }: React.ComponentProps<typeof ProgressPrimitive.Root>) {
12
+ return (
13
+ <ProgressPrimitive.Root
14
+ data-slot="progress"
15
+ className={cn(
16
+ 'relative h-2 w-full overflow-hidden rounded-full bg-primary/20',
17
+ className
18
+ )}
19
+ {...props}
20
+ >
21
+ <ProgressPrimitive.Indicator
22
+ data-slot="progress-indicator"
23
+ className="h-full w-full flex-1 bg-primary transition-all"
24
+ style={{ transform: `translateX(-${100 - (value || 0)}%)` }}
25
+ />
26
+ </ProgressPrimitive.Root>
27
+ );
28
+ }
29
+
30
+ export { Progress };
@@ -0,0 +1,44 @@
1
+ 'use client';
2
+
3
+ import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
4
+ import { cn } from '@tuturuuu/utils/format';
5
+ import { CircleIcon } from 'lucide-react';
6
+ import * as React from 'react';
7
+
8
+ function RadioGroup({
9
+ className,
10
+ ...props
11
+ }: React.ComponentProps<typeof RadioGroupPrimitive.Root>) {
12
+ return (
13
+ <RadioGroupPrimitive.Root
14
+ data-slot="radio-group"
15
+ className={cn('grid gap-3', className)}
16
+ {...props}
17
+ />
18
+ );
19
+ }
20
+
21
+ function RadioGroupItem({
22
+ className,
23
+ ...props
24
+ }: React.ComponentProps<typeof RadioGroupPrimitive.Item>) {
25
+ return (
26
+ <RadioGroupPrimitive.Item
27
+ data-slot="radio-group-item"
28
+ className={cn(
29
+ 'aspect-square size-4 shrink-0 rounded-full border border-input text-primary shadow-xs ring-ring/10 outline-ring/50 transition-[color,box-shadow] focus-visible:ring-4 focus-visible:outline-1 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:focus-visible:ring-0 dark:ring-ring/20 dark:outline-ring/40',
30
+ className
31
+ )}
32
+ {...props}
33
+ >
34
+ <RadioGroupPrimitive.Indicator
35
+ data-slot="radio-group-indicator"
36
+ className="relative flex items-center justify-center"
37
+ >
38
+ <CircleIcon className="absolute top-1/2 left-1/2 size-2 -translate-x-1/2 -translate-y-1/2 fill-primary" />
39
+ </RadioGroupPrimitive.Indicator>
40
+ </RadioGroupPrimitive.Item>
41
+ );
42
+ }
43
+
44
+ export { RadioGroup, RadioGroupItem };