@hanzo/ui 4.5.4 → 4.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.
Files changed (156) hide show
  1. package/README-MCP.md +3 -3
  2. package/README.md +229 -0
  3. package/assets/ai-icons.tsx +207 -0
  4. package/assets/crypto.tsx +33 -0
  5. package/assets/file-type-icon.tsx +66 -0
  6. package/assets/file.tsx +45 -0
  7. package/assets/general.tsx +2318 -0
  8. package/assets/hanzo-logo.svg +9 -0
  9. package/assets/hanzo-logo.tsx +15 -0
  10. package/assets/index.ts +8 -0
  11. package/assets/index.tsx +4 -0
  12. package/assets/llm-provider.tsx +1094 -0
  13. package/bin/create-registry.js +1 -1
  14. package/bin/test-mcp.sh +1 -1
  15. package/bin/update-registry.js +2 -2
  16. package/blocks/components/content.tsx +1 -1
  17. package/blocks/components/grid-block/index.tsx +1 -1
  18. package/blocks/components/screenful-block/content.tsx +1 -1
  19. package/blocks/components/screenful-block/poster-background.tsx +1 -1
  20. package/components/index.ts +56 -0
  21. package/dist/button.d.ts +1 -0
  22. package/dist/button.js +1 -0
  23. package/dist/hooks/index.d.ts +7 -0
  24. package/dist/hooks/index.js +7 -0
  25. package/dist/hooks/use-click-away.d.ts +2 -0
  26. package/dist/hooks/use-click-away.js +23 -0
  27. package/dist/hooks/use-combined-refs.d.ts +3 -0
  28. package/dist/hooks/use-combined-refs.js +18 -0
  29. package/dist/hooks/use-copy-clipboard.d.ts +9 -0
  30. package/dist/hooks/use-copy-clipboard.js +21 -0
  31. package/dist/hooks/use-debounce.d.ts +1 -0
  32. package/dist/hooks/use-debounce.js +13 -0
  33. package/dist/hooks/use-fill-ids.d.ts +8 -0
  34. package/dist/hooks/use-fill-ids.js +20 -0
  35. package/dist/hooks/use-map.d.ts +1 -0
  36. package/dist/hooks/use-map.js +20 -0
  37. package/dist/hooks/use-measure.d.ts +8 -0
  38. package/dist/hooks/use-measure.js +25 -0
  39. package/dist/hooks/use-reverse-video-playback.d.ts +1 -0
  40. package/dist/hooks/use-reverse-video-playback.js +41 -0
  41. package/dist/hooks/use-scroll-restoration.d.ts +8 -0
  42. package/dist/hooks/use-scroll-restoration.js +36 -0
  43. package/dist/mcp/enhanced-server.js +2 -2
  44. package/dist/registry/api.d.ts +1 -1
  45. package/dist/registry/api.js +3 -3
  46. package/dist/registry/index.d.ts +48 -48
  47. package/dist/registry/index.js +3 -3
  48. package/dist/utils.d.ts +1 -0
  49. package/dist/utils.js +1 -0
  50. package/helpers/file.ts +33 -0
  51. package/helpers/memoization.ts +40 -0
  52. package/package.json +27 -6
  53. package/primitives/accordion.tsx +53 -45
  54. package/primitives/alert-dialog.tsx +185 -0
  55. package/primitives/alert.tsx +74 -0
  56. package/primitives/apply-typography.tsx +1 -1
  57. package/primitives/avatar.tsx +37 -29
  58. package/primitives/background-beams.tsx +142 -0
  59. package/primitives/badge.tsx +27 -19
  60. package/primitives/breadcrumb.tsx +77 -62
  61. package/primitives/button.tsx +69 -72
  62. package/primitives/card.tsx +73 -59
  63. package/primitives/chat/chat-input-area.tsx +87 -0
  64. package/primitives/chat/chat-input.tsx +71 -0
  65. package/primitives/chat/files-preview.tsx +330 -0
  66. package/primitives/chat/index.ts +6 -0
  67. package/primitives/chat/json-form.tsx +8 -0
  68. package/primitives/chat/message-list.tsx +307 -0
  69. package/primitives/chat/message.tsx +569 -0
  70. package/primitives/chat/sqlite-preview.tsx +215 -0
  71. package/primitives/checkbox.tsx +18 -19
  72. package/primitives/collapsible.tsx +9 -0
  73. package/primitives/command.tsx +75 -83
  74. package/primitives/context-menu.tsx +115 -109
  75. package/primitives/copy-to-clipboard-icon.tsx +60 -0
  76. package/primitives/dialog-video-controller.tsx +1 -1
  77. package/primitives/dialog.tsx +111 -145
  78. package/primitives/dot-pattern.tsx +57 -0
  79. package/primitives/dots-loader.tsx +13 -0
  80. package/primitives/drawer.tsx +59 -87
  81. package/primitives/dropdown-menu.tsx +199 -0
  82. package/primitives/error-message.tsx +19 -0
  83. package/primitives/file-uploader.tsx +200 -0
  84. package/primitives/form.tsx +92 -87
  85. package/primitives/hover-card.tsx +28 -0
  86. package/primitives/icons/github.tsx +1 -1
  87. package/primitives/icons/youtube-logo.tsx +1 -1
  88. package/primitives/index-common.ts +121 -42
  89. package/primitives/index-next.ts +3 -1
  90. package/primitives/input.tsx +115 -20
  91. package/primitives/label.tsx +15 -23
  92. package/primitives/loading-spinner.tsx +1 -1
  93. package/primitives/markdown-preview.tsx +609 -0
  94. package/primitives/mermaid.tsx +196 -0
  95. package/primitives/next/link-element.tsx +1 -1
  96. package/primitives/next/mdx-link.tsx +1 -1
  97. package/primitives/pagination.tsx +117 -0
  98. package/primitives/popover.tsx +20 -25
  99. package/primitives/pretty-json-print.tsx +28 -0
  100. package/primitives/progress.tsx +14 -15
  101. package/primitives/prompt-textarea.tsx +72 -0
  102. package/primitives/qr-code.tsx +112 -0
  103. package/primitives/radio-group.tsx +25 -39
  104. package/primitives/resizable.tsx +47 -0
  105. package/primitives/scroll-area.tsx +35 -25
  106. package/primitives/search-input.tsx +66 -0
  107. package/primitives/select.tsx +62 -109
  108. package/primitives/separator.tsx +22 -26
  109. package/primitives/sheet.tsx +78 -117
  110. package/primitives/skeleton.tsx +13 -16
  111. package/primitives/slider.tsx +50 -60
  112. package/primitives/stepper.tsx +272 -0
  113. package/primitives/switch.tsx +14 -23
  114. package/primitives/table.tsx +65 -77
  115. package/primitives/tabs.tsx +29 -39
  116. package/primitives/text-link.tsx +25 -0
  117. package/primitives/textarea.tsx +61 -0
  118. package/primitives/textfield.tsx +75 -0
  119. package/primitives/toast.tsx +30 -0
  120. package/primitives/toggle-group.tsx +33 -33
  121. package/primitives/toggle.tsx +22 -51
  122. package/primitives/tooltip.tsx +37 -38
  123. package/registry.json +1 -1
  124. package/src/button.ts +1 -0
  125. package/src/hooks/index.ts +7 -0
  126. package/src/hooks/use-click-away.ts +31 -0
  127. package/src/hooks/use-combined-refs.ts +22 -0
  128. package/src/hooks/use-copy-clipboard.ts +30 -0
  129. package/src/hooks/use-debounce.ts +17 -0
  130. package/src/hooks/use-fill-ids.ts +25 -0
  131. package/src/hooks/use-map.ts +26 -0
  132. package/src/hooks/use-measure.ts +42 -0
  133. package/src/hooks/use-reverse-video-playback.ts +43 -0
  134. package/src/hooks/use-scroll-restoration.ts +50 -0
  135. package/src/mcp/README.md +1 -1
  136. package/src/mcp/enhanced-server.ts +2 -2
  137. package/src/registry/api.ts +3 -3
  138. package/src/registry/index.ts +3 -3
  139. package/src/utils.ts +1 -0
  140. package/style/theme-provider.tsx +1 -1
  141. package/test-imports.mjs +19 -0
  142. package/types/animation-def.ts +1 -1
  143. package/types/button-def.ts +1 -1
  144. package/types/index.ts +1 -1
  145. package/util/blob.ts +28 -0
  146. package/util/copy-to-clipboard.ts +17 -0
  147. package/util/create-shadow-root.ts +22 -0
  148. package/util/date.ts +83 -0
  149. package/util/debounce.ts +11 -0
  150. package/util/file.ts +15 -0
  151. package/util/format-and-abbreviate-as-currency.ts +1 -1
  152. package/util/format-text.ts +33 -0
  153. package/util/index.ts +9 -78
  154. package/util/timing.ts +3 -0
  155. package/util/toasts.tsx +17 -0
  156. package/utils.ts +9 -0
@@ -1,105 +1,112 @@
1
- "use client"
2
-
3
- import * as React from "react"
4
- import * as ContextMenuPrimitive from "@radix-ui/react-context-menu"
5
- import { Check, ChevronRight, Circle } from "lucide-react"
6
-
7
- import { cn } from "../util"
8
-
9
- const ContextMenu = ContextMenuPrimitive.Root
10
- const ContextMenuTrigger = ContextMenuPrimitive.Trigger
11
- const ContextMenuGroup = ContextMenuPrimitive.Group
12
- const ContextMenuPortal = ContextMenuPrimitive.Portal
13
- const ContextMenuSub = ContextMenuPrimitive.Sub
14
- const ContextMenuRadioGroup = ContextMenuPrimitive.RadioGroup
15
-
16
- const ContextMenuSubTrigger = React.forwardRef<
17
- React.ElementRef<typeof ContextMenuPrimitive.SubTrigger>,
18
- React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.SubTrigger> & {
19
- inset?: boolean
20
- }
21
- >(({ className, inset, children, ...props }, ref) => (
1
+ import * as ContextMenuPrimitive from '@radix-ui/react-context-menu';
2
+ import { Check, ChevronRight, Circle } from 'lucide-react';
3
+ import * as React from 'react';
4
+
5
+ import { cn } from '../src/utils';
6
+
7
+ const ContextMenu = ContextMenuPrimitive.Root;
8
+
9
+ const ContextMenuTrigger = ContextMenuPrimitive.Trigger;
10
+
11
+ const ContextMenuGroup = ContextMenuPrimitive.Group;
12
+
13
+ const ContextMenuPortal = ContextMenuPrimitive.Portal;
14
+
15
+ const ContextMenuSub = ContextMenuPrimitive.Sub;
16
+
17
+ const ContextMenuRadioGroup = ContextMenuPrimitive.RadioGroup;
18
+
19
+ type ContextMenuSubTriggerProps = React.ComponentPropsWithoutRef<
20
+ typeof ContextMenuPrimitive.SubTrigger
21
+ > & {
22
+ inset?: boolean;
23
+ ref?: React.RefObject<
24
+ React.ComponentRef<typeof ContextMenuPrimitive.SubTrigger>
25
+ >;
26
+ };
27
+
28
+ const ContextMenuSubTrigger = ({
29
+ className,
30
+ inset,
31
+ children,
32
+ ref,
33
+ ...props
34
+ }: ContextMenuSubTriggerProps) => (
22
35
  <ContextMenuPrimitive.SubTrigger
23
- ref={ref}
24
36
  className={cn(
25
- 'flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none ' +
26
- 'focus:bg-level-1 focus:text-accent data-[state=open]:bg-level-1 data-[state=open]:text-accent',
27
- inset && "pl-8",
28
- className
37
+ 'focus:bg-accent data-[state=open]:bg-accent data-[state=open]:text-accent-foreground flex cursor-default items-center rounded-xs px-2 py-1.5 text-sm outline-hidden select-none focus:text-white',
38
+ inset && 'pl-8',
39
+ className,
29
40
  )}
41
+ ref={ref}
30
42
  {...props}
31
43
  >
32
44
  {children}
33
45
  <ChevronRight className="ml-auto h-4 w-4" />
34
46
  </ContextMenuPrimitive.SubTrigger>
35
- ))
36
- ContextMenuSubTrigger.displayName = ContextMenuPrimitive.SubTrigger.displayName
47
+ );
48
+ ContextMenuSubTrigger.displayName = ContextMenuPrimitive.SubTrigger.displayName;
37
49
 
38
- const ContextMenuSubContent = React.forwardRef<
39
- React.ElementRef<typeof ContextMenuPrimitive.SubContent>,
40
- React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.SubContent>
41
- >(({ className, ...props }, ref) => (
50
+ const ContextMenuSubContent = ({
51
+ className,
52
+ ...props
53
+ }: React.ComponentProps<typeof ContextMenuPrimitive.SubContent>) => (
42
54
  <ContextMenuPrimitive.SubContent
43
- ref={ref}
44
55
  className={cn(
45
- 'z-popup min-w-[8rem] overflow-hidden rounded-md border bg-background p-1 text-foreground shadow-md ' +
46
- 'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 ' +
47
- 'data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 ' +
48
- 'data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 ' +
49
- 'data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
50
- className
56
+ 'data-[state=open]:animate-in data-[state=closed]:animate-out 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-[8rem] overflow-hidden rounded-md border bg-gray-300 p-1 text-white shadow-md',
57
+ className,
51
58
  )}
52
59
  {...props}
53
60
  />
54
- ))
55
- ContextMenuSubContent.displayName = ContextMenuPrimitive.SubContent.displayName
61
+ );
62
+ ContextMenuSubContent.displayName = ContextMenuPrimitive.SubContent.displayName;
56
63
 
57
- const ContextMenuContent = React.forwardRef<
58
- React.ElementRef<typeof ContextMenuPrimitive.Content>,
59
- React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Content>
60
- >(({ className, ...props }, ref) => (
64
+ const ContextMenuContent = ({
65
+ className,
66
+ ...props
67
+ }: React.ComponentProps<typeof ContextMenuPrimitive.Content>) => (
61
68
  <ContextMenuPrimitive.Portal>
62
69
  <ContextMenuPrimitive.Content
63
- ref={ref}
64
70
  className={cn(
65
- "z-popup min-w-[8rem] overflow-hidden rounded-md border bg-background p-1 text-foreground shadow-md animate-in fade-in-80 data-[state=open]:animate-in data-[state=closed]:animate-out 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",
66
- className
71
+ 'animate-in fade-in-80 data-[state=open]:animate-in data-[state=closed]:animate-out 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-[8rem] overflow-hidden rounded-md border border-gray-600 bg-gray-300 p-1 text-gray-50 shadow-md',
72
+ className,
67
73
  )}
68
74
  {...props}
69
75
  />
70
76
  </ContextMenuPrimitive.Portal>
71
- ))
72
- ContextMenuContent.displayName = ContextMenuPrimitive.Content.displayName
73
-
74
- const ContextMenuItem = React.forwardRef<
75
- React.ElementRef<typeof ContextMenuPrimitive.Item>,
76
- React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Item> & {
77
- inset?: boolean
78
- }
79
- >(({ className, inset, ...props }, ref) => (
77
+ );
78
+ ContextMenuContent.displayName = ContextMenuPrimitive.Content.displayName;
79
+
80
+ const ContextMenuItem = ({
81
+ className,
82
+ inset,
83
+ ...props
84
+ }: React.ComponentProps<typeof ContextMenuPrimitive.Item> & {
85
+ inset?: boolean;
86
+ }) => (
80
87
  <ContextMenuPrimitive.Item
81
- ref={ref}
82
88
  className={cn(
83
- "relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-level-1 focus:text-accent data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
84
- inset && "pl-8",
85
- className
89
+ 'relative flex cursor-default items-center rounded-xs px-2 py-1.5 text-sm outline-hidden select-none focus:bg-gray-200 focus:text-white data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
90
+ inset && 'pl-8',
91
+ className,
86
92
  )}
87
93
  {...props}
88
94
  />
89
- ))
90
- ContextMenuItem.displayName = ContextMenuPrimitive.Item.displayName
95
+ );
96
+ ContextMenuItem.displayName = ContextMenuPrimitive.Item.displayName;
91
97
 
92
- const ContextMenuCheckboxItem = React.forwardRef<
93
- React.ElementRef<typeof ContextMenuPrimitive.CheckboxItem>,
94
- React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.CheckboxItem>
95
- >(({ className, children, checked, ...props }, ref) => (
98
+ const ContextMenuCheckboxItem = ({
99
+ className,
100
+ children,
101
+ checked,
102
+ ...props
103
+ }: React.ComponentProps<typeof ContextMenuPrimitive.CheckboxItem>) => (
96
104
  <ContextMenuPrimitive.CheckboxItem
97
- ref={ref}
105
+ checked={checked}
98
106
  className={cn(
99
- "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-level-1 focus:text-accent data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
100
- className
107
+ 'focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center rounded-xs py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
108
+ className,
101
109
  )}
102
- checked={checked}
103
110
  {...props}
104
111
  >
105
112
  <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
@@ -109,19 +116,19 @@ const ContextMenuCheckboxItem = React.forwardRef<
109
116
  </span>
110
117
  {children}
111
118
  </ContextMenuPrimitive.CheckboxItem>
112
- ))
119
+ );
113
120
  ContextMenuCheckboxItem.displayName =
114
- ContextMenuPrimitive.CheckboxItem.displayName
121
+ ContextMenuPrimitive.CheckboxItem.displayName;
115
122
 
116
- const ContextMenuRadioItem = React.forwardRef<
117
- React.ElementRef<typeof ContextMenuPrimitive.RadioItem>,
118
- React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.RadioItem>
119
- >(({ className, children, ...props }, ref) => (
123
+ const ContextMenuRadioItem = ({
124
+ className,
125
+ children,
126
+ ...props
127
+ }: React.ComponentProps<typeof ContextMenuPrimitive.RadioItem>) => (
120
128
  <ContextMenuPrimitive.RadioItem
121
- ref={ref}
122
129
  className={cn(
123
- "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-level-1 focus:text-accent data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
124
- className
130
+ 'focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center rounded-xs py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
131
+ className,
125
132
  )}
126
133
  {...props}
127
134
  >
@@ -132,38 +139,37 @@ const ContextMenuRadioItem = React.forwardRef<
132
139
  </span>
133
140
  {children}
134
141
  </ContextMenuPrimitive.RadioItem>
135
- ))
136
- ContextMenuRadioItem.displayName = ContextMenuPrimitive.RadioItem.displayName
137
-
138
- const ContextMenuLabel = React.forwardRef<
139
- React.ElementRef<typeof ContextMenuPrimitive.Label>,
140
- React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Label> & {
141
- inset?: boolean
142
- }
143
- >(({ className, inset, ...props }, ref) => (
142
+ );
143
+ ContextMenuRadioItem.displayName = ContextMenuPrimitive.RadioItem.displayName;
144
+
145
+ const ContextMenuLabel = ({
146
+ className,
147
+ inset,
148
+ ...props
149
+ }: React.ComponentProps<typeof ContextMenuPrimitive.Label> & {
150
+ inset?: boolean;
151
+ }) => (
144
152
  <ContextMenuPrimitive.Label
145
- ref={ref}
146
153
  className={cn(
147
- "px-2 py-1.5 text-sm font-semibold text-foreground",
148
- inset && "pl-8",
149
- className
154
+ 'text-text-default px-2 py-1.5 text-sm font-semibold',
155
+ inset && 'pl-8',
156
+ className,
150
157
  )}
151
158
  {...props}
152
159
  />
153
- ))
154
- ContextMenuLabel.displayName = ContextMenuPrimitive.Label.displayName
160
+ );
161
+ ContextMenuLabel.displayName = ContextMenuPrimitive.Label.displayName;
155
162
 
156
- const ContextMenuSeparator = React.forwardRef<
157
- React.ElementRef<typeof ContextMenuPrimitive.Separator>,
158
- React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Separator>
159
- >(({ className, ...props }, ref) => (
163
+ const ContextMenuSeparator = ({
164
+ className,
165
+ ...props
166
+ }: React.ComponentProps<typeof ContextMenuPrimitive.Separator>) => (
160
167
  <ContextMenuPrimitive.Separator
161
- ref={ref}
162
- className={cn("-mx-1 my-1 h-px bg-border", className)}
168
+ className={cn('bg-border -mx-1 my-1 h-px', className)}
163
169
  {...props}
164
170
  />
165
- ))
166
- ContextMenuSeparator.displayName = ContextMenuPrimitive.Separator.displayName
171
+ );
172
+ ContextMenuSeparator.displayName = ContextMenuPrimitive.Separator.displayName;
167
173
 
168
174
  const ContextMenuShortcut = ({
169
175
  className,
@@ -172,14 +178,14 @@ const ContextMenuShortcut = ({
172
178
  return (
173
179
  <span
174
180
  className={cn(
175
- "ml-auto text-xs tracking-widest text-muted",
176
- className
181
+ 'text-text-secondary ml-auto text-xs tracking-widest',
182
+ className,
177
183
  )}
178
184
  {...props}
179
185
  />
180
- )
181
- }
182
- ContextMenuShortcut.displayName = "ContextMenuShortcut"
186
+ );
187
+ };
188
+ ContextMenuShortcut.displayName = 'ContextMenuShortcut';
183
189
 
184
190
  export {
185
191
  ContextMenu,
@@ -197,4 +203,4 @@ export {
197
203
  ContextMenuSubContent,
198
204
  ContextMenuSubTrigger,
199
205
  ContextMenuRadioGroup,
200
- }
206
+ };
@@ -0,0 +1,60 @@
1
+ import { CheckCircle2, CopyIcon } from 'lucide-react';
2
+ import React, { cloneElement, type ReactElement } from 'react';
3
+
4
+ import { useCopyClipboard } from '../src/hooks';
5
+ import { cn } from '../src/utils';
6
+ import { Button } from './button';
7
+
8
+ type CopyToClipboardIconProps = {
9
+ string?: string;
10
+ children?: ReactElement<{
11
+ className?: string;
12
+ onClick?: () => void;
13
+ }>;
14
+ className?: string;
15
+ onCopyClipboard?: () => void;
16
+ asChild?: boolean;
17
+ };
18
+
19
+ const CopyToClipboardIcon = ({
20
+ string,
21
+ children,
22
+ className,
23
+ onCopyClipboard,
24
+ asChild = false,
25
+ }: CopyToClipboardIconProps) => {
26
+ const { isCopied, onCopy } = useCopyClipboard({
27
+ string,
28
+ onCopyClipboard,
29
+ });
30
+
31
+ const ClipboardIcon = isCopied ? CheckCircle2 : CopyIcon;
32
+
33
+ if (asChild && children) {
34
+ return cloneElement(children, {
35
+ onClick: onCopy,
36
+ className: cn(children.props?.className, className),
37
+ });
38
+ }
39
+
40
+ return (
41
+ <Button
42
+ className={cn(
43
+ 'text-text-secondary hover:bg-bg-tertiary bg-bg-tertiary flex h-8 w-8 gap-2 rounded-lg text-xs font-normal transition-colors hover:text-white',
44
+ className,
45
+ )}
46
+ disabled={!string}
47
+ onClick={onCopy}
48
+ size={'icon'}
49
+ type="button"
50
+ variant="tertiary"
51
+ >
52
+ <ClipboardIcon
53
+ className={cn('h-3.5 w-3.5', isCopied && 'text-green-500')}
54
+ />
55
+ {children}
56
+ </Button>
57
+ );
58
+ };
59
+
60
+ export { CopyToClipboardIcon, useCopyClipboard };
@@ -1,6 +1,6 @@
1
1
  'use client'
2
2
 
3
- import React, { type PropsWithChildren, useState } from 'react'
3
+ import React, { PropsWithChildren, useState } from 'react'
4
4
 
5
5
  const DialogVideoController: React.FC<PropsWithChildren> = ({
6
6
  children,
@@ -1,157 +1,123 @@
1
- 'use client'
2
- import * as React from "react"
3
- import * as DialogPrimitive from "@radix-ui/react-dialog"
4
- import { X } from "lucide-react"
5
- import { cn } from "../util"
6
-
7
- const Dialog = DialogPrimitive.Root
8
-
9
- const DialogTrigger = DialogPrimitive.Trigger
10
-
11
- interface DialogPortalProps extends React.PropsWithChildren<React.ComponentPropsWithoutRef<typeof DialogPrimitive.Portal>> {
12
- className?: string;
13
- }
14
-
15
- const DialogPortal = React.forwardRef<
16
- React.ElementRef<typeof DialogPrimitive.Portal>,
17
- DialogPortalProps
18
- >(({ className, children, ...props }, ref) => (
19
- <DialogPrimitive.Portal {...props}>
20
- <div className={cn("fixed inset-0 z-50 flex items-end justify-center sm:items-center", className)}>
21
- {children}
22
- </div>
23
- </DialogPrimitive.Portal>
24
- ))
25
- DialogPortal.displayName = 'DialogPortal'
26
-
27
- interface DialogOverlayProps extends React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay> {
28
- className?: string;
29
- }
30
-
31
- const DialogOverlay = React.forwardRef<
32
- React.ElementRef<typeof DialogPrimitive.Overlay>,
33
- DialogOverlayProps
34
- >(({ className, ...props }, ref) => (
35
- <DialogPrimitive.Overlay
36
- ref={ref}
37
- className={cn(
38
- "fixed inset-0 z-50 bg-overlay backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
39
- className
40
- )}
41
- {...props}
42
- />
43
- ))
44
- DialogOverlay.displayName = DialogPrimitive.Overlay.displayName
45
-
46
-
47
- interface DialogCloseProps extends React.PropsWithChildren<React.ComponentPropsWithoutRef<typeof DialogPrimitive.Close>> {
48
- className?: string;
49
- }
50
-
51
- const DialogClose = React.forwardRef<
52
- React.ElementRef<typeof DialogPrimitive.Close>,
53
- DialogCloseProps
54
- >(({ className, ...props }, ref) => (
55
- <DialogPrimitive.Close
56
- ref={ref}
1
+ import * as DialogPrimitive from '@radix-ui/react-dialog';
2
+ import { X } from 'lucide-react';
3
+ import * as React from 'react';
4
+
5
+ import { cn } from '../src/utils';
6
+
7
+ const Dialog = DialogPrimitive.Root;
8
+
9
+ const DialogTrigger = DialogPrimitive.Trigger;
10
+
11
+ const DialogPortal = DialogPrimitive.Portal;
12
+
13
+ const DialogOverlay = ({
14
+ className,
15
+ ...props
16
+ }: React.ComponentProps<typeof DialogPrimitive.Overlay>) => (
17
+ <DialogPrimitive.Overlay
18
+ className={cn(
19
+ 'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50',
20
+ 'bg-bg-dark/90',
21
+ className,
22
+ )}
23
+ {...props}
24
+ />
25
+ );
26
+ DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
27
+
28
+ const DialogContent = ({
29
+ className,
30
+ children,
31
+ showCloseButton = false,
32
+ ...props
33
+ }: React.ComponentProps<typeof DialogPrimitive.Content> & {
34
+ showCloseButton?: boolean;
35
+ }) => (
36
+ <DialogPortal>
37
+ <DialogOverlay />
38
+ <DialogPrimitive.Content
39
+ className={cn(
40
+ 'bg-bg-default data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 border-divider fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:rounded-lg md:w-full',
41
+ className,
42
+ )}
43
+ {...props}
44
+ >
45
+ {children}
46
+ <DialogPrimitive.Close
57
47
  className={cn(
58
- "absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none",
59
- className
48
+ 'ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-text-secondary absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none',
49
+ !showCloseButton && 'hidden',
60
50
  )}
61
- {...props}
62
- >
51
+ >
63
52
  <X className="h-4 w-4" />
64
53
  <span className="sr-only">Close</span>
65
- </DialogPrimitive.Close>
66
- ))
67
-
68
- DialogClose.displayName = DialogPrimitive.Close.displayName
69
-
70
- const DialogContent = React.forwardRef<
71
- React.ElementRef<typeof DialogPrimitive.Content>,
72
- React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>
73
- >(({ className, children, ...props }, ref) => (
74
- <DialogPortal>
75
- <DialogOverlay />
76
- <DialogPrimitive.Content
77
- ref={ref}
78
- className={cn(
79
- "fixed z-50 grid w-full gap-4 rounded-t-lg bg-level-1 p-6 shadow-lg animate-in data-[state=open]:fade-in-90 data-[state=open]:slide-in-from-bottom-10 sm:max-w-lg sm:rounded-lg sm:zoom-in-90 data-[state=open]:sm:slide-in-from-bottom-0",
80
- className
81
- )}
82
- {...props}
83
- >
84
- {children}
85
- <DialogClose />
86
- </DialogPrimitive.Content>
87
- </DialogPortal>
88
- ))
89
- DialogContent.displayName = DialogPrimitive.Content.displayName
54
+ </DialogPrimitive.Close>
55
+ </DialogPrimitive.Content>
56
+ </DialogPortal>
57
+ );
58
+ DialogContent.displayName = DialogPrimitive.Content.displayName;
90
59
 
91
60
  const DialogHeader = ({
92
- className,
93
- ...props
61
+ className,
62
+ ...props
94
63
  }: React.HTMLAttributes<HTMLDivElement>) => (
95
- <div
96
- className={cn(
97
- "flex flex-col space-y-1.5 text-center sm:text-left",
98
- className
99
- )}
100
- {...props}
101
- />
102
- )
103
- DialogHeader.displayName = "DialogHeader"
64
+ <div
65
+ className={cn(
66
+ 'flex flex-col space-y-1.5 text-center sm:text-left',
67
+ className,
68
+ )}
69
+ {...props}
70
+ />
71
+ );
72
+ DialogHeader.displayName = 'DialogHeader';
104
73
 
105
74
  const DialogFooter = ({
106
- className,
107
- ...props
75
+ className,
76
+ ...props
108
77
  }: React.HTMLAttributes<HTMLDivElement>) => (
109
- <div
110
- className={cn(
111
- "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
112
- className
113
- )}
114
- {...props}
115
- />
116
- )
117
- DialogFooter.displayName = "DialogFooter"
118
-
119
- const DialogTitle = React.forwardRef<
120
- React.ElementRef<typeof DialogPrimitive.Title>,
121
- React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
122
- >(({ className, ...props }, ref) => (
123
- <DialogPrimitive.Title
124
- ref={ref}
125
- className={cn(
126
- "text-lg font-semibold leading-none tracking-tight text-foreground",
127
- className
128
- )}
129
- {...props}
130
- />
131
- ))
132
- DialogTitle.displayName = DialogPrimitive.Title.displayName
133
-
134
- const DialogDescription = React.forwardRef<
135
- React.ElementRef<typeof DialogPrimitive.Description>,
136
- React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>
137
- >(({ className, ...props }, ref) => (
138
- <DialogPrimitive.Description
139
- ref={ref}
140
- className={cn("text-sm text-muted-1", className)}
141
- {...props}
142
- />
143
- ))
144
- DialogDescription.displayName = DialogPrimitive.Description.displayName
78
+ <div
79
+ className={cn(
80
+ 'flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2',
81
+ className,
82
+ )}
83
+ {...props}
84
+ />
85
+ );
86
+ DialogFooter.displayName = 'DialogFooter';
87
+
88
+ const DialogTitle = ({
89
+ className,
90
+ ...props
91
+ }: React.ComponentProps<typeof DialogPrimitive.Title>) => (
92
+ <DialogPrimitive.Title
93
+ className={cn(
94
+ 'text-lg leading-none font-semibold tracking-tight',
95
+ className,
96
+ )}
97
+ {...props}
98
+ />
99
+ );
100
+ DialogTitle.displayName = DialogPrimitive.Title.displayName;
101
+
102
+ const DialogDescription = ({
103
+ className,
104
+ ...props
105
+ }: React.ComponentProps<typeof DialogPrimitive.Description>) => (
106
+ <DialogPrimitive.Description
107
+ className={cn('text-text-secondary text-sm', className)}
108
+ {...props}
109
+ />
110
+ );
111
+ DialogDescription.displayName = DialogPrimitive.Description.displayName;
145
112
 
146
113
  export {
147
- Dialog,
148
- DialogTrigger,
149
- DialogOverlay,
150
- DialogClose,
151
- DialogPortal,
152
- DialogContent,
153
- DialogHeader,
154
- DialogFooter,
155
- DialogTitle,
156
- DialogDescription,
157
- }
114
+ Dialog,
115
+ DialogPortal,
116
+ DialogOverlay,
117
+ DialogTrigger,
118
+ DialogContent,
119
+ DialogHeader,
120
+ DialogFooter,
121
+ DialogTitle,
122
+ DialogDescription,
123
+ };