@gentleduck/registry-ui 0.2.1

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 (175) hide show
  1. package/CHANGELOG.md +62 -0
  2. package/index.css +3 -0
  3. package/package.json +59 -0
  4. package/src/_old/_table/index.ts +5 -0
  5. package/src/_old/_table/table-advanced.constants.tsx +24 -0
  6. package/src/_old/_table/table-advanced.tsx +311 -0
  7. package/src/_old/_table/table-advanced.types.ts +272 -0
  8. package/src/_old/_table/table.constants.ts +2 -0
  9. package/src/_old/_table/table.hook.tsx +115 -0
  10. package/src/_old/_table/table.lib.ts +85 -0
  11. package/src/_old/_table/table.tsx +916 -0
  12. package/src/_old/_table/table.types.ts +118 -0
  13. package/src/_old/_table/todo.md +11 -0
  14. package/src/_old/_upload/index.ts +9 -0
  15. package/src/_old/_upload/todo.md +38 -0
  16. package/src/_old/_upload/upload-advanced-chunks.tsx +1624 -0
  17. package/src/_old/_upload/upload-advanced.tsx +507 -0
  18. package/src/_old/_upload/upload-sonner.tsx +58 -0
  19. package/src/_old/_upload/upload.assets.tsx +239 -0
  20. package/src/_old/_upload/upload.constants.tsx +75 -0
  21. package/src/_old/_upload/upload.dto.ts +19 -0
  22. package/src/_old/_upload/upload.lib.tsx +630 -0
  23. package/src/_old/_upload/upload.tsx +491 -0
  24. package/src/_old/_upload/upload.types.ts +436 -0
  25. package/src/accordion/accordion.tsx +247 -0
  26. package/src/accordion/index.ts +1 -0
  27. package/src/alert/alert.constants.ts +17 -0
  28. package/src/alert/alert.tsx +52 -0
  29. package/src/alert/index.ts +2 -0
  30. package/src/alert-dialog/alert-dialog.tsx +107 -0
  31. package/src/alert-dialog/index.ts +1 -0
  32. package/src/aspect-ratio/aspect-ratio.tsx +33 -0
  33. package/src/aspect-ratio/index.ts +1 -0
  34. package/src/audio/audio-record.tsx +776 -0
  35. package/src/audio/audio-visualizer.tsx +377 -0
  36. package/src/audio/audio.libs.ts +5 -0
  37. package/src/audio/audio.types.ts +50 -0
  38. package/src/audio/index.ts +2 -0
  39. package/src/avatar/avatar.tsx +78 -0
  40. package/src/avatar/index.ts +1 -0
  41. package/src/badge/badge.constants.ts +38 -0
  42. package/src/badge/badge.tsx +19 -0
  43. package/src/badge/index.ts +2 -0
  44. package/src/breadcrumb/breadcrumb.tsx +119 -0
  45. package/src/breadcrumb/index.ts +1 -0
  46. package/src/button/button.constants.ts +44 -0
  47. package/src/button/button.tsx +79 -0
  48. package/src/button/button.types.ts +38 -0
  49. package/src/button/index.ts +3 -0
  50. package/src/button-group/button-group.constants.ts +26 -0
  51. package/src/button-group/button-group.tsx +65 -0
  52. package/src/button-group/index.ts +2 -0
  53. package/src/calendar/calendar.tsx +191 -0
  54. package/src/calendar/index.ts +1 -0
  55. package/src/card/card.tsx +81 -0
  56. package/src/card/index.ts +1 -0
  57. package/src/carousel/carousel.tsx +211 -0
  58. package/src/carousel/carousel.types.ts +23 -0
  59. package/src/carousel/index.ts +2 -0
  60. package/src/chart/chart.libs.ts +27 -0
  61. package/src/chart/chart.tsx +260 -0
  62. package/src/chart/chart.types.ts +38 -0
  63. package/src/chart/index.ts +3 -0
  64. package/src/checkbox/checkbox.tsx +144 -0
  65. package/src/checkbox/checkbox.types.ts +24 -0
  66. package/src/checkbox/index.ts +2 -0
  67. package/src/collapsible/collapsible.tsx +151 -0
  68. package/src/collapsible/index.ts +1 -0
  69. package/src/combobox/combobox.tsx +132 -0
  70. package/src/combobox/index.ts +1 -0
  71. package/src/command/command.tsx +192 -0
  72. package/src/command/command.types.ts +11 -0
  73. package/src/command/index.ts +2 -0
  74. package/src/context-menu/context-menu.tsx +178 -0
  75. package/src/context-menu/index.ts +1 -0
  76. package/src/dialog/dialog-responsive.tsx +137 -0
  77. package/src/dialog/dialog.tsx +97 -0
  78. package/src/dialog/index.ts +2 -0
  79. package/src/direction/direction.tsx +13 -0
  80. package/src/direction/index.ts +1 -0
  81. package/src/drawer/drawer.tsx +185 -0
  82. package/src/drawer/index.ts +1 -0
  83. package/src/dropdown-menu/dropdown-menu.tsx +181 -0
  84. package/src/dropdown-menu/index.ts +1 -0
  85. package/src/empty/empty.constants.ts +15 -0
  86. package/src/empty/empty.tsx +73 -0
  87. package/src/empty/index.ts +2 -0
  88. package/src/field/field.constants.ts +22 -0
  89. package/src/field/field.tsx +203 -0
  90. package/src/field/index.ts +2 -0
  91. package/src/hover-card/hover-card.tsx +79 -0
  92. package/src/hover-card/index.ts +1 -0
  93. package/src/input/index.ts +1 -0
  94. package/src/input/input.tsx +45 -0
  95. package/src/input-group/index.ts +1 -0
  96. package/src/input-group/input-group.tsx +170 -0
  97. package/src/input-otp/index.ts +1 -0
  98. package/src/input-otp/input-otp.tsx +66 -0
  99. package/src/item/index.ts +2 -0
  100. package/src/item/item.constants.ts +22 -0
  101. package/src/item/item.tsx +185 -0
  102. package/src/json-editor/index.ts +4 -0
  103. package/src/json-editor/json-editor.hooks.ts +21 -0
  104. package/src/json-editor/json-editor.libs.ts +34 -0
  105. package/src/json-editor/json-editor.tsx +425 -0
  106. package/src/json-editor/json-editor.types.ts +80 -0
  107. package/src/json-editor/json-editor.view.tsx +110 -0
  108. package/src/json-editor/json-text-area.tsx +7 -0
  109. package/src/kbd/index.ts +1 -0
  110. package/src/kbd/kbd.tsx +39 -0
  111. package/src/label/index.ts +1 -0
  112. package/src/label/label.tsx +28 -0
  113. package/src/menubar/index.ts +1 -0
  114. package/src/menubar/menubar.tsx +213 -0
  115. package/src/navigation-menu/index.ts +1 -0
  116. package/src/navigation-menu/navigation-menu.tsx +152 -0
  117. package/src/pagination/index.ts +2 -0
  118. package/src/pagination/pagination.tsx +191 -0
  119. package/src/pagination/pagination.types.ts +17 -0
  120. package/src/popover/index.ts +1 -0
  121. package/src/popover/popover.tsx +35 -0
  122. package/src/preview-panel/index.ts +3 -0
  123. package/src/preview-panel/preview-panel-dialog.tsx +99 -0
  124. package/src/preview-panel/preview-panel.tsx +389 -0
  125. package/src/preview-panel/preview-panel.types.ts +49 -0
  126. package/src/progress/index.ts +1 -0
  127. package/src/progress/progress.tsx +32 -0
  128. package/src/radio-group/index.ts +1 -0
  129. package/src/radio-group/radio-group.tsx +92 -0
  130. package/src/resizable/index.ts +1 -0
  131. package/src/resizable/resizable.tsx +52 -0
  132. package/src/scroll-area/index.ts +1 -0
  133. package/src/scroll-area/scroll-area.tsx +30 -0
  134. package/src/select/index.ts +1 -0
  135. package/src/select/select.tsx +138 -0
  136. package/src/separator/index.ts +1 -0
  137. package/src/separator/separator.tsx +28 -0
  138. package/src/sheet/index.ts +2 -0
  139. package/src/sheet/sheet.constants.tsx +20 -0
  140. package/src/sheet/sheet.tsx +92 -0
  141. package/src/sidebar/index.ts +4 -0
  142. package/src/sidebar/sidebar.constants.ts +30 -0
  143. package/src/sidebar/sidebar.hooks.ts +13 -0
  144. package/src/sidebar/sidebar.tsx +676 -0
  145. package/src/sidebar/sidebar.types.ts +28 -0
  146. package/src/skeleton/index.ts +1 -0
  147. package/src/skeleton/skeleton.tsx +22 -0
  148. package/src/slider/index.ts +1 -0
  149. package/src/slider/slider.tsx +57 -0
  150. package/src/sonner/index.ts +4 -0
  151. package/src/sonner/sonner.chunks.tsx +80 -0
  152. package/src/sonner/sonner.libs.ts +13 -0
  153. package/src/sonner/sonner.tsx +31 -0
  154. package/src/sonner/sonner.types.ts +9 -0
  155. package/src/switch/index.ts +1 -0
  156. package/src/switch/switch.tsx +63 -0
  157. package/src/table/index.ts +1 -0
  158. package/src/table/table.tsx +95 -0
  159. package/src/tabs/index.ts +1 -0
  160. package/src/tabs/tabs.tsx +151 -0
  161. package/src/textarea/index.ts +1 -0
  162. package/src/textarea/textarea.tsx +24 -0
  163. package/src/toggle/index.ts +2 -0
  164. package/src/toggle/toggle.constants.ts +22 -0
  165. package/src/toggle/toggle.tsx +24 -0
  166. package/src/toggle-group/index.ts +1 -0
  167. package/src/toggle-group/toggle-group.tsx +69 -0
  168. package/src/tooltip/index.ts +1 -0
  169. package/src/tooltip/tooltip.tsx +32 -0
  170. package/src/upload/index.ts +1 -0
  171. package/src/upload/upload.constants.tsx +19 -0
  172. package/src/upload/upload.libs.ts +97 -0
  173. package/src/upload/upload.tsx +340 -0
  174. package/src/upload/upload.types.ts +44 -0
  175. package/tsconfig.json +25 -0
@@ -0,0 +1,213 @@
1
+ 'use client'
2
+
3
+ import { cn } from '@gentleduck/libs/cn'
4
+ import { AnimVariants } from '@gentleduck/motion/anim'
5
+ import * as MenubarPrimitive from '@gentleduck/primitives/menubar'
6
+ import { Check, ChevronRight, Circle } from 'lucide-react'
7
+ import * as React from 'react'
8
+
9
+ const MenubarMenu: typeof MenubarPrimitive.Menu = MenubarPrimitive.Menu
10
+
11
+ const MenubarGroup = MenubarPrimitive.Group
12
+
13
+ const MenubarPortal = MenubarPrimitive.Portal
14
+
15
+ function MenubarRadioGroup({ ...props }: React.ComponentProps<typeof MenubarPrimitive.RadioGroup>) {
16
+ return <MenubarPrimitive.RadioGroup {...props} />
17
+ }
18
+
19
+ function MenubarSub({ ...props }: React.ComponentProps<typeof MenubarPrimitive.Sub>) {
20
+ return <MenubarPrimitive.Sub data-slot="menubar-sub" {...props} />
21
+ }
22
+
23
+ const Menubar = React.forwardRef<
24
+ React.ComponentRef<typeof MenubarPrimitive.Root>,
25
+ React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Root>
26
+ >(({ className, ...props }, ref) => (
27
+ <MenubarPrimitive.Root
28
+ ref={ref}
29
+ className={cn('flex h-9 items-center space-x-1 rounded-md border bg-background p-1 shadow-sm', className)}
30
+ {...props}
31
+ />
32
+ ))
33
+ Menubar.displayName = MenubarPrimitive.Root.displayName
34
+
35
+ const MenubarTrigger = React.forwardRef<
36
+ React.ComponentRef<typeof MenubarPrimitive.Trigger>,
37
+ React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Trigger>
38
+ >(({ className, ...props }, ref) => (
39
+ <MenubarPrimitive.Trigger
40
+ ref={ref}
41
+ className={cn(
42
+ 'flex cursor-default select-none items-center rounded-sm px-3 py-1 font-medium text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground',
43
+ className,
44
+ )}
45
+ {...props}
46
+ />
47
+ ))
48
+
49
+ MenubarTrigger.displayName = MenubarPrimitive.Trigger.displayName
50
+
51
+ const MenubarSubTrigger = React.forwardRef<
52
+ React.ComponentRef<typeof MenubarPrimitive.SubTrigger>,
53
+ React.ComponentPropsWithoutRef<typeof MenubarPrimitive.SubTrigger> & {
54
+ inset?: boolean
55
+ }
56
+ >(({ className, inset, children, ...props }, ref) => (
57
+ <MenubarPrimitive.SubTrigger
58
+ ref={ref}
59
+ className={cn(
60
+ 'flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground',
61
+ inset && 'ps-8',
62
+ className,
63
+ )}
64
+ {...props}>
65
+ {children}
66
+ <ChevronRight aria-hidden="true" className="ms-auto h-4 w-4 rtl:rotate-180" />
67
+ </MenubarPrimitive.SubTrigger>
68
+ ))
69
+ MenubarSubTrigger.displayName = MenubarPrimitive.SubTrigger.displayName
70
+
71
+ const MenubarSubContent = React.forwardRef<
72
+ React.ComponentRef<typeof MenubarPrimitive.SubContent>,
73
+ React.ComponentPropsWithoutRef<typeof MenubarPrimitive.SubContent>
74
+ >(({ className, ...props }, ref) => (
75
+ <MenubarPrimitive.SubContent
76
+ ref={ref}
77
+ className={cn(
78
+ 'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]: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 z-50 min-w-32 origin-(--gentleduck-menubar-content-transform-origin) overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=closed]:animate-out data-[state=open]:animate-in',
79
+ AnimVariants(),
80
+ className,
81
+ )}
82
+ {...props}
83
+ />
84
+ ))
85
+ MenubarSubContent.displayName = MenubarPrimitive.SubContent.displayName
86
+
87
+ const MenubarContent = React.forwardRef<
88
+ React.ComponentRef<typeof MenubarPrimitive.Content>,
89
+ React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Content>
90
+ >(({ className, align = 'start', alignOffset = -4, sideOffset = 8, ...props }, ref) => (
91
+ <MenubarPrimitive.Portal>
92
+ <MenubarPrimitive.Content
93
+ ref={ref}
94
+ align={align}
95
+ alignOffset={alignOffset}
96
+ sideOffset={sideOffset}
97
+ className={cn(
98
+ 'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]: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 z-50 min-w-48 origin-(--gentleduck-menubar-content-transform-origin) overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in',
99
+ AnimVariants(),
100
+ className,
101
+ )}
102
+ {...props}
103
+ />
104
+ </MenubarPrimitive.Portal>
105
+ ))
106
+ MenubarContent.displayName = MenubarPrimitive.Content.displayName
107
+
108
+ const MenubarItem = React.forwardRef<
109
+ React.ComponentRef<typeof MenubarPrimitive.Item>,
110
+ React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Item> & {
111
+ inset?: boolean
112
+ }
113
+ >(({ className, inset, ...props }, ref) => (
114
+ <MenubarPrimitive.Item
115
+ ref={ref}
116
+ className={cn(
117
+ 'relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50',
118
+ inset && 'ps-8',
119
+ className,
120
+ )}
121
+ {...props}
122
+ />
123
+ ))
124
+ MenubarItem.displayName = MenubarPrimitive.Item.displayName
125
+
126
+ const MenubarCheckboxItem = React.forwardRef<
127
+ React.ComponentRef<typeof MenubarPrimitive.CheckboxItem>,
128
+ React.ComponentPropsWithoutRef<typeof MenubarPrimitive.CheckboxItem>
129
+ >(({ className, children, checked, ...props }, ref) => (
130
+ <MenubarPrimitive.CheckboxItem
131
+ ref={ref}
132
+ className={cn(
133
+ 'relative flex cursor-default select-none items-center rounded-sm py-1.5 ps-8 pe-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50',
134
+ className,
135
+ )}
136
+ checked={checked}
137
+ {...props}>
138
+ <span className="absolute start-2 flex h-3.5 w-3.5 items-center justify-center">
139
+ <MenubarPrimitive.ItemIndicator>
140
+ <Check aria-hidden="true" className="h-4 w-4" />
141
+ </MenubarPrimitive.ItemIndicator>
142
+ </span>
143
+ {children}
144
+ </MenubarPrimitive.CheckboxItem>
145
+ ))
146
+ MenubarCheckboxItem.displayName = MenubarPrimitive.CheckboxItem.displayName
147
+
148
+ const MenubarRadioItem = React.forwardRef<
149
+ React.ComponentRef<typeof MenubarPrimitive.RadioItem>,
150
+ React.ComponentPropsWithoutRef<typeof MenubarPrimitive.RadioItem>
151
+ >(({ className, children, ...props }, ref) => (
152
+ <MenubarPrimitive.RadioItem
153
+ ref={ref}
154
+ className={cn(
155
+ 'relative flex cursor-default select-none items-center rounded-sm py-1.5 ps-8 pe-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50',
156
+ className,
157
+ )}
158
+ {...props}>
159
+ <span className="absolute start-2 flex h-3.5 w-3.5 items-center justify-center">
160
+ <MenubarPrimitive.ItemIndicator>
161
+ <Circle aria-hidden="true" className="size-2 fill-current" />
162
+ </MenubarPrimitive.ItemIndicator>
163
+ </span>
164
+ {children}
165
+ </MenubarPrimitive.RadioItem>
166
+ ))
167
+ MenubarRadioItem.displayName = MenubarPrimitive.RadioItem.displayName
168
+
169
+ const MenubarLabel = React.forwardRef<
170
+ React.ComponentRef<typeof MenubarPrimitive.Label>,
171
+ React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Label> & {
172
+ inset?: boolean
173
+ }
174
+ >(({ className, inset, ...props }, ref) => (
175
+ <MenubarPrimitive.Label
176
+ ref={ref}
177
+ className={cn('px-2 py-1.5 font-semibold text-sm', inset && 'ps-8', className)}
178
+ {...props}
179
+ />
180
+ ))
181
+ MenubarLabel.displayName = MenubarPrimitive.Label.displayName
182
+
183
+ const MenubarSeparator = React.forwardRef<
184
+ React.ComponentRef<typeof MenubarPrimitive.Separator>,
185
+ React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Separator>
186
+ >(({ className, ...props }, ref) => (
187
+ <MenubarPrimitive.Separator ref={ref} className={cn('-mx-1 my-1 h-px bg-muted', className)} {...props} />
188
+ ))
189
+ MenubarSeparator.displayName = MenubarPrimitive.Separator.displayName
190
+
191
+ const MenubarShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => {
192
+ return <span className={cn('ms-auto text-muted-foreground text-xs tracking-widest', className)} {...props} />
193
+ }
194
+ MenubarShortcut.displayName = 'MenubarShortcut'
195
+
196
+ export {
197
+ Menubar,
198
+ MenubarMenu,
199
+ MenubarTrigger,
200
+ MenubarContent,
201
+ MenubarItem,
202
+ MenubarSeparator,
203
+ MenubarLabel,
204
+ MenubarCheckboxItem,
205
+ MenubarRadioGroup,
206
+ MenubarRadioItem,
207
+ MenubarPortal,
208
+ MenubarSubContent,
209
+ MenubarSubTrigger,
210
+ MenubarGroup,
211
+ MenubarSub,
212
+ MenubarShortcut,
213
+ }
@@ -0,0 +1 @@
1
+ export * from './navigation-menu'
@@ -0,0 +1,152 @@
1
+ import { cn } from '@gentleduck/libs/cn'
2
+ import * as NavigationMenuPrimitive from '@gentleduck/primitives/navigation-menu'
3
+ import { cva } from '@gentleduck/variants'
4
+ import { ChevronDown } from 'lucide-react'
5
+ import * as React from 'react'
6
+
7
+ const NavigationMenu = React.forwardRef<
8
+ React.ComponentRef<typeof NavigationMenuPrimitive.Root>,
9
+ React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Root> & {
10
+ viewport?: boolean
11
+ }
12
+ >(({ className, children, viewport = true, ...props }, ref) => (
13
+ <NavigationMenuPrimitive.Root
14
+ ref={ref}
15
+ className={cn('group/navigation-menu relative flex max-w-max flex-1 items-center justify-center', className)}
16
+ data-slot="navigation-menu"
17
+ data-viewport={viewport}
18
+ {...props}>
19
+ {children}
20
+ {viewport && <NavigationMenuViewport />}
21
+ </NavigationMenuPrimitive.Root>
22
+ ))
23
+ NavigationMenu.displayName = NavigationMenuPrimitive.Root.displayName
24
+
25
+ const NavigationMenuList = React.forwardRef<
26
+ React.ComponentRef<typeof NavigationMenuPrimitive.List>,
27
+ React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.List>
28
+ >(({ className, ...props }, ref) => (
29
+ <NavigationMenuPrimitive.List
30
+ ref={ref}
31
+ className={cn('group flex flex-1 list-none items-center justify-center gap-1', className)}
32
+ data-slot="navigation-menu-list"
33
+ {...props}
34
+ />
35
+ ))
36
+ NavigationMenuList.displayName = NavigationMenuPrimitive.List.displayName
37
+
38
+ const NavigationMenuItem = React.forwardRef<
39
+ React.ComponentRef<typeof NavigationMenuPrimitive.Item>,
40
+ React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Item>
41
+ >(({ className, ...props }, ref) => (
42
+ <NavigationMenuPrimitive.Item
43
+ ref={ref}
44
+ className={cn('relative', className)}
45
+ data-slot="navigation-menu-item"
46
+ {...props}
47
+ />
48
+ ))
49
+ NavigationMenuItem.displayName = NavigationMenuPrimitive.Item.displayName
50
+
51
+ const navigationMenuTriggerStyle = cva(
52
+ 'group inline-flex h-9 w-max items-center justify-center rounded-md bg-background px-4 py-2 font-medium text-sm outline-none transition-all hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus-visible:outline-1 focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 data-[state=open]:bg-accent/50 data-[state=open]:text-accent-foreground data-[state=open]:focus:bg-accent data-[state=open]:hover:bg-accent',
53
+ )
54
+
55
+ const NavigationMenuTrigger = React.forwardRef<
56
+ React.ComponentRef<typeof NavigationMenuPrimitive.Trigger>,
57
+ React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Trigger>
58
+ >(({ className, children, ...props }, ref) => (
59
+ <NavigationMenuPrimitive.Trigger
60
+ ref={ref}
61
+ className={cn(navigationMenuTriggerStyle(), 'group', className)}
62
+ data-slot="navigation-menu-trigger"
63
+ {...props}>
64
+ {children}
65
+ <ChevronDown
66
+ aria-hidden="true"
67
+ className="relative top-[1px] ms-1 size-4 transition duration-300 group-data-[state=open]:rotate-180"
68
+ />
69
+ </NavigationMenuPrimitive.Trigger>
70
+ ))
71
+ NavigationMenuTrigger.displayName = NavigationMenuPrimitive.Trigger.displayName
72
+
73
+ const NavigationMenuContent = React.forwardRef<
74
+ React.ComponentRef<typeof NavigationMenuPrimitive.Content>,
75
+ React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Content>
76
+ >(({ className, ...props }, ref) => (
77
+ <NavigationMenuPrimitive.Content
78
+ ref={ref}
79
+ className={cn(
80
+ 'data-[motion^=from-]:fade-in data-[motion^=to-]:fade-out 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 group-data-[viewport=false]/navigation-menu:data-[state=closed]:zoom-out-95 group-data-[viewport=false]/navigation-menu:data-[state=open]:zoom-in-95 group-data-[viewport=false]/navigation-menu:data-[state=open]:fade-in-0 group-data-[viewport=false]/navigation-menu:data-[state=closed]:fade-out-0 start-0 top-0 w-full p-2 pe-2.5 data-[motion^=from-]:animate-in data-[motion^=to-]:animate-out **:data-[slot=navigation-menu-link]:focus:outline-none **:data-[slot=navigation-menu-link]:focus:ring-0 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 group-data-[viewport=false]/navigation-menu:data-[state=closed]:animate-out group-data-[viewport=false]/navigation-menu:data-[state=open]:animate-in md:absolute md:w-auto',
81
+ 'transition-all transition-discrete duration-[200ms,150ms] ease-(--duck-motion-ease)',
82
+ className,
83
+ )}
84
+ data-slot="navigation-menu-content"
85
+ {...props}
86
+ />
87
+ ))
88
+ NavigationMenuContent.displayName = NavigationMenuPrimitive.Content.displayName
89
+
90
+ const NavigationMenuViewport = React.forwardRef<
91
+ React.ComponentRef<typeof NavigationMenuPrimitive.Viewport>,
92
+ React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Viewport>
93
+ >(({ className, ...props }, ref) => (
94
+ <div className={cn('absolute start-0 top-full isolate flex justify-center')}>
95
+ <NavigationMenuPrimitive.Viewport
96
+ ref={ref}
97
+ className={cn(
98
+ 'data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-90 relative mt-1.5 h-(--radix-navigation-menu-viewport-height) w-full origin-top-center overflow-hidden rounded-md border bg-popover text-popover-foreground shadow data-[state=closed]:animate-out data-[state=open]:animate-in md:w-(--radix-navigation-menu-viewport-width)',
99
+ 'transition-all transition-discrete duration-[200ms,150ms] ease-(--duck-motion-ease)',
100
+ className,
101
+ )}
102
+ data-slot="navigation-menu-viewport"
103
+ {...props}
104
+ />
105
+ </div>
106
+ ))
107
+ NavigationMenuViewport.displayName = NavigationMenuPrimitive.Viewport.displayName
108
+
109
+ const NavigationMenuLink = React.forwardRef<
110
+ React.ComponentRef<typeof NavigationMenuPrimitive.Link>,
111
+ React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Link>
112
+ >(({ className, ...props }, ref) => (
113
+ <NavigationMenuPrimitive.Link
114
+ ref={ref}
115
+ className={cn(
116
+ "flex flex-col gap-1 rounded-sm p-2 text-sm outline-none transition-all hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus-visible:outline-1 focus-visible:ring-[3px] focus-visible:ring-ring/50 data-[active=true]:bg-accent/50 data-[active=true]:text-accent-foreground data-[active=true]:focus:bg-accent data-[active=true]:hover:bg-accent [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground",
117
+ className,
118
+ )}
119
+ data-slot="navigation-menu-link"
120
+ {...props}
121
+ />
122
+ ))
123
+ NavigationMenuLink.displayName = NavigationMenuPrimitive.Link.displayName
124
+
125
+ const NavigationMenuIndicator = React.forwardRef<
126
+ React.ComponentRef<typeof NavigationMenuPrimitive.Indicator>,
127
+ React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Indicator>
128
+ >(({ className, ...props }, ref) => (
129
+ <NavigationMenuPrimitive.Indicator
130
+ ref={ref}
131
+ className={cn(
132
+ 'data-[state=hidden]:fade-out data-[state=visible]:fade-in top-full z-1 flex h-1.5 items-end justify-center overflow-hidden data-[state=hidden]:animate-out data-[state=visible]:animate-in',
133
+ className,
134
+ )}
135
+ data-slot="navigation-menu-indicator"
136
+ {...props}>
137
+ <div className="relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm bg-border shadow-md" />
138
+ </NavigationMenuPrimitive.Indicator>
139
+ ))
140
+ NavigationMenuIndicator.displayName = NavigationMenuPrimitive.Indicator.displayName
141
+
142
+ export {
143
+ NavigationMenu,
144
+ NavigationMenuList,
145
+ NavigationMenuItem,
146
+ NavigationMenuContent,
147
+ NavigationMenuTrigger,
148
+ NavigationMenuLink,
149
+ NavigationMenuIndicator,
150
+ NavigationMenuViewport,
151
+ navigationMenuTriggerStyle,
152
+ }
@@ -0,0 +1,2 @@
1
+ export * from './pagination'
2
+ export * from './pagination.types'
@@ -0,0 +1,191 @@
1
+ import { cn } from '@gentleduck/libs/cn'
2
+ import { type Direction, useDirection } from '@gentleduck/primitives/direction'
3
+ import * as PaginationPrimitive from '@gentleduck/primitives/pagination'
4
+ import {
5
+ ChevronLeft,
6
+ ChevronLeftIcon,
7
+ ChevronRight,
8
+ ChevronRightIcon,
9
+ ChevronsLeftIcon,
10
+ ChevronsRightIcon,
11
+ MoreHorizontal,
12
+ } from 'lucide-react'
13
+ import * as React from 'react'
14
+ import { Button, buttonVariants } from '../button'
15
+ import type { DuckPaginationProps, PaginationLinkProps } from './pagination.types'
16
+
17
+ const Pagination = React.forwardRef<
18
+ React.ComponentRef<typeof PaginationPrimitive.Root>,
19
+ React.ComponentPropsWithoutRef<typeof PaginationPrimitive.Root>
20
+ >(({ className, ...props }, ref) => (
21
+ <PaginationPrimitive.Root
22
+ className={cn('mx-auto flex w-full justify-center', className)}
23
+ data-slot="pagination"
24
+ ref={ref}
25
+ {...props}
26
+ />
27
+ ))
28
+ Pagination.displayName = 'Pagination'
29
+
30
+ const PaginationContent = React.forwardRef<
31
+ React.ComponentRef<typeof PaginationPrimitive.Content>,
32
+ React.ComponentPropsWithoutRef<typeof PaginationPrimitive.Content>
33
+ >(({ className, ...props }, ref) => (
34
+ <PaginationPrimitive.Content
35
+ className={cn('flex flex-row items-center gap-1', className)}
36
+ data-slot="pagination-content"
37
+ ref={ref}
38
+ {...props}
39
+ />
40
+ ))
41
+ PaginationContent.displayName = 'PaginationContent'
42
+
43
+ const PaginationItem = React.forwardRef<
44
+ React.ComponentRef<typeof PaginationPrimitive.Item>,
45
+ React.ComponentPropsWithoutRef<typeof PaginationPrimitive.Item>
46
+ >(({ className, ...props }, ref) => (
47
+ <PaginationPrimitive.Item className={cn(className)} data-slot="pagination-item" ref={ref} {...props} />
48
+ ))
49
+ PaginationItem.displayName = 'PaginationItem'
50
+
51
+ const PaginationLink = React.forwardRef<HTMLAnchorElement, PaginationLinkProps>(
52
+ ({ className, isActive, size = 'icon', ...props }, ref) => (
53
+ <a
54
+ aria-current={isActive ? 'page' : undefined}
55
+ className={cn(
56
+ buttonVariants({
57
+ size,
58
+ variant: isActive ? 'outline' : 'ghost',
59
+ }),
60
+ className,
61
+ )}
62
+ data-slot="pagination-link"
63
+ ref={ref}
64
+ {...props}
65
+ />
66
+ ),
67
+ )
68
+ PaginationLink.displayName = 'PaginationLink'
69
+
70
+ const PaginationPrevious = React.forwardRef<
71
+ HTMLAnchorElement,
72
+ React.ComponentPropsWithoutRef<typeof PaginationLink> & { text?: string }
73
+ >(({ className, text = 'Previous', ...props }, ref) => (
74
+ <PaginationLink
75
+ aria-label="Go to previous page"
76
+ className={cn('gap-1 ps-2.5', className)}
77
+ data-slot="pagination-previous"
78
+ ref={ref}
79
+ size="default"
80
+ {...props}>
81
+ <ChevronLeft aria-hidden="true" className="h-4 w-4 rtl:rotate-180" />
82
+ <span className="hidden sm:block">{text}</span>
83
+ </PaginationLink>
84
+ ))
85
+ PaginationPrevious.displayName = 'PaginationPrevious'
86
+
87
+ const PaginationNext = React.forwardRef<
88
+ HTMLAnchorElement,
89
+ React.ComponentPropsWithoutRef<typeof PaginationLink> & { text?: string }
90
+ >(({ className, text = 'Next', ...props }, ref) => (
91
+ <PaginationLink
92
+ aria-label="Go to next page"
93
+ className={cn('gap-1 pe-2.5', className)}
94
+ data-slot="pagination-next"
95
+ ref={ref}
96
+ size="default"
97
+ {...props}>
98
+ <span className="hidden sm:block">{text}</span>
99
+ <ChevronRight aria-hidden="true" className="h-4 w-4 rtl:rotate-180" />
100
+ </PaginationLink>
101
+ ))
102
+ PaginationNext.displayName = 'PaginationNext'
103
+
104
+ const PaginationEllipsis = React.forwardRef<
105
+ HTMLSpanElement,
106
+ React.ComponentPropsWithoutRef<'span'> & { text?: string }
107
+ >(({ className, text = 'More pages', ...props }, ref) => (
108
+ <span
109
+ role="img"
110
+ aria-label={text}
111
+ className={cn('flex h-9 w-9 items-center justify-center', className)}
112
+ data-slot="pagination-ellipsis"
113
+ ref={ref}
114
+ {...props}>
115
+ <MoreHorizontal aria-hidden="true" className="h-4 w-4" />
116
+ </span>
117
+ ))
118
+ PaginationEllipsis.displayName = 'PaginationEllipsis'
119
+
120
+ const PaginationWrapper = (props: DuckPaginationProps) => {
121
+ const { className: wrapperClassName, dir, ...wrapperProps } = props.wrapper ?? {}
122
+ const { className: contentClassName, ...contentProps } = props.content ?? {}
123
+ const { className: itemClassName, ...itemProps } = props.item ?? {}
124
+ const { className: rightClassName, ...rightProps } = props.right ?? {}
125
+ const { className: maxRightClassName, ...maxRightProps } = props.maxRight ?? {}
126
+ const { className: leftClassName, ...leftProps } = props.left ?? {}
127
+ const { className: maxLeftClassName, ...maxLeftProps } = props.maxLeft ?? {}
128
+ const direction = useDirection(dir as Direction)
129
+ const StartIcon = direction === 'rtl' ? ChevronRightIcon : ChevronLeftIcon
130
+ const EndIcon = direction === 'rtl' ? ChevronLeftIcon : ChevronRightIcon
131
+ const StartDoubleIcon = direction === 'rtl' ? ChevronsRightIcon : ChevronsLeftIcon
132
+ const EndDoubleIcon = direction === 'rtl' ? ChevronsLeftIcon : ChevronsRightIcon
133
+
134
+ return (
135
+ <Pagination className={cn('justify-end', wrapperClassName)} {...wrapperProps}>
136
+ <PaginationContent className={cn('gap-2', contentClassName)} {...contentProps}>
137
+ <PaginationItem className={cn(itemClassName)} {...itemProps}>
138
+ <Button
139
+ aria-label="Go to first page"
140
+ className={cn('w-[32px] p-0', maxLeftClassName)}
141
+ size="sm"
142
+ variant="outline"
143
+ {...maxLeftProps}>
144
+ <StartDoubleIcon aria-hidden="true" />
145
+ </Button>
146
+ </PaginationItem>
147
+ <PaginationItem className={cn(itemClassName)} {...itemProps}>
148
+ <Button
149
+ aria-label="Go to previous page"
150
+ className={cn('w-[32px] p-0', leftClassName)}
151
+ size="sm"
152
+ variant="outline"
153
+ {...leftProps}>
154
+ <StartIcon aria-hidden="true" />
155
+ </Button>
156
+ </PaginationItem>
157
+ <PaginationItem className={cn(itemClassName)} {...itemProps}>
158
+ <Button
159
+ aria-label="Go to next page"
160
+ className={cn('w-[32px] p-0', rightClassName)}
161
+ size="sm"
162
+ variant="outline"
163
+ {...rightProps}>
164
+ <EndIcon aria-hidden="true" />
165
+ </Button>
166
+ </PaginationItem>
167
+ <PaginationItem className={cn(itemClassName)} {...itemProps}>
168
+ <Button
169
+ aria-label="Go to last page"
170
+ className={cn('w-[32px] p-0', maxRightClassName)}
171
+ size="sm"
172
+ variant="outline"
173
+ {...maxRightProps}>
174
+ <EndDoubleIcon aria-hidden="true" />
175
+ </Button>
176
+ </PaginationItem>
177
+ </PaginationContent>
178
+ </Pagination>
179
+ )
180
+ }
181
+
182
+ export {
183
+ Pagination,
184
+ PaginationContent,
185
+ PaginationEllipsis,
186
+ PaginationItem,
187
+ PaginationLink,
188
+ PaginationNext,
189
+ PaginationPrevious,
190
+ PaginationWrapper,
191
+ }
@@ -0,0 +1,17 @@
1
+ import type { Button, ButtonProps } from '../button'
2
+ import type { Pagination, PaginationContent, PaginationItem } from './pagination'
3
+
4
+ export interface DuckPaginationProps {
5
+ wrapper?: React.ComponentPropsWithoutRef<typeof Pagination>
6
+ content?: React.ComponentPropsWithoutRef<typeof PaginationContent>
7
+ item?: React.ComponentPropsWithoutRef<typeof PaginationItem>
8
+ right?: React.ComponentPropsWithoutRef<typeof Button>
9
+ maxRight?: React.ComponentPropsWithoutRef<typeof Button>
10
+ left?: React.ComponentPropsWithoutRef<typeof Button>
11
+ maxLeft?: React.ComponentPropsWithoutRef<typeof Button>
12
+ }
13
+
14
+ export type PaginationLinkProps = {
15
+ isActive?: boolean
16
+ } & Pick<ButtonProps, 'size'> &
17
+ Omit<React.ComponentPropsWithoutRef<'a'>, 'size'>
@@ -0,0 +1 @@
1
+ export * from './popover'
@@ -0,0 +1,35 @@
1
+ 'use client'
2
+
3
+ import { cn } from '@gentleduck/libs/cn'
4
+ import * as PopoverPrimitive from '@gentleduck/primitives/popover'
5
+ import * as React from 'react'
6
+
7
+ const Popover = PopoverPrimitive.Root
8
+
9
+ const PopoverTrigger: typeof PopoverPrimitive.Trigger = PopoverPrimitive.Trigger
10
+
11
+ const PopoverAnchor: typeof PopoverPrimitive.Anchor = PopoverPrimitive.Anchor
12
+
13
+ const PopoverContent = React.forwardRef<
14
+ React.ComponentRef<typeof PopoverPrimitive.Content>,
15
+ React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>
16
+ >(({ className, align = 'center', sideOffset = 4, ...props }, ref) => (
17
+ <PopoverPrimitive.Portal>
18
+ <PopoverPrimitive.Content
19
+ ref={ref}
20
+ align={align}
21
+ sideOffset={sideOffset}
22
+ className={cn(
23
+ 'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]: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 z-50 w-72 origin-(--gentleduck-popover-content-transform-origin) rounded-md border bg-popover p-4 text-start text-popover-foreground shadow-md outline-none data-[state=closed]:animate-out data-[state=open]:animate-in',
24
+ 'transition-all transition-discrete duration-[200ms,150ms] ease-(--duck-motion-ease)',
25
+ className,
26
+ )}
27
+ {...props}
28
+ />
29
+ </PopoverPrimitive.Portal>
30
+ ))
31
+ PopoverContent.displayName = PopoverPrimitive.Content.displayName
32
+
33
+ export const PopoverClose: typeof PopoverPrimitive.Close = PopoverPrimitive.Close
34
+
35
+ export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor }
@@ -0,0 +1,3 @@
1
+ export * from './preview-panel'
2
+ export * from './preview-panel.types'
3
+ export * from './preview-panel-dialog'