@hanzo/ui 5.0.2 → 5.1.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 (371) hide show
  1. package/dist/accordion.js +1 -0
  2. package/dist/accordion.mjs +1 -0
  3. package/dist/alert-dialog.js +1 -0
  4. package/dist/alert-dialog.mjs +1 -0
  5. package/dist/alert.js +1 -0
  6. package/dist/alert.mjs +1 -0
  7. package/dist/avatar.js +1 -0
  8. package/dist/avatar.mjs +1 -0
  9. package/dist/badge.js +1 -0
  10. package/dist/badge.mjs +1 -0
  11. package/dist/breadcrumb.js +1 -0
  12. package/dist/breadcrumb.mjs +1 -0
  13. package/dist/calendar.js +1 -0
  14. package/dist/calendar.mjs +1 -0
  15. package/dist/carousel.js +1 -0
  16. package/dist/carousel.mjs +1 -0
  17. package/dist/checkbox.js +1 -0
  18. package/dist/checkbox.mjs +1 -0
  19. package/dist/chunk-3H5S2OQ3.mjs +1 -0
  20. package/dist/chunk-5GRJ7UQX.js +1 -0
  21. package/dist/chunk-63HNMH7C.js +1 -0
  22. package/dist/chunk-72TOQ4DM.mjs +1 -0
  23. package/dist/chunk-7AEFTV5R.mjs +1 -0
  24. package/dist/chunk-7M4AVV2R.js +1 -0
  25. package/dist/chunk-DKPVJSBC.js +1 -0
  26. package/dist/chunk-EI7MMDWY.js +1 -0
  27. package/dist/chunk-GANGDIZG.mjs +1 -0
  28. package/dist/chunk-GRGT2Z4K.js +1 -0
  29. package/dist/chunk-JCUUC6NY.mjs +1 -0
  30. package/dist/chunk-JUQMWLIN.js +1 -0
  31. package/dist/chunk-PRVEIITE.js +1 -0
  32. package/dist/chunk-SH52AKNZ.js +1 -0
  33. package/dist/chunk-TU67EJEW.mjs +1 -0
  34. package/dist/chunk-WN5KN73U.mjs +1 -0
  35. package/dist/chunk-YSXGDEY5.mjs +1 -0
  36. package/dist/chunk-Z76OOVUE.mjs +1 -0
  37. package/dist/collapsible.js +1 -0
  38. package/dist/collapsible.mjs +1 -0
  39. package/dist/command.js +1 -0
  40. package/dist/command.mjs +1 -0
  41. package/dist/context-menu.js +1 -0
  42. package/dist/context-menu.mjs +1 -0
  43. package/dist/dialog.js +1 -0
  44. package/dist/dialog.mjs +1 -0
  45. package/dist/drawer.js +1 -0
  46. package/dist/drawer.mjs +1 -0
  47. package/dist/dropdown-menu.js +1 -0
  48. package/dist/dropdown-menu.mjs +1 -0
  49. package/dist/form.js +1 -0
  50. package/dist/form.mjs +1 -0
  51. package/dist/hover-card.js +1 -0
  52. package/dist/hover-card.mjs +1 -0
  53. package/dist/index.js +1 -9079
  54. package/dist/index.mjs +1 -8700
  55. package/dist/input-otp.js +1 -0
  56. package/dist/input-otp.mjs +1 -0
  57. package/dist/lib/utils.js +1 -0
  58. package/dist/lib/utils.mjs +1 -0
  59. package/dist/navigation-menu.js +1 -0
  60. package/dist/navigation-menu.mjs +1 -0
  61. package/dist/popover.js +1 -0
  62. package/dist/popover.mjs +1 -0
  63. package/dist/progress.js +1 -0
  64. package/dist/progress.mjs +1 -0
  65. package/dist/radio-group.js +1 -0
  66. package/dist/radio-group.mjs +1 -0
  67. package/dist/resizable.js +1 -0
  68. package/dist/resizable.mjs +1 -0
  69. package/dist/scroll-area.js +1 -0
  70. package/dist/scroll-area.mjs +1 -0
  71. package/dist/select.js +1 -0
  72. package/dist/select.mjs +1 -0
  73. package/dist/separator.js +1 -0
  74. package/dist/separator.mjs +1 -0
  75. package/dist/sheet.js +1 -0
  76. package/dist/sheet.mjs +1 -0
  77. package/dist/skeleton.js +1 -0
  78. package/dist/skeleton.mjs +1 -0
  79. package/dist/slider.js +1 -0
  80. package/dist/slider.mjs +1 -0
  81. package/dist/sonner.js +1 -0
  82. package/dist/sonner.mjs +1 -0
  83. package/dist/src/utils.js +1 -0
  84. package/dist/src/utils.mjs +1 -0
  85. package/dist/switch.js +1 -0
  86. package/dist/switch.mjs +1 -0
  87. package/dist/table.js +1 -0
  88. package/dist/table.mjs +1 -0
  89. package/dist/tabs.js +1 -0
  90. package/dist/tabs.mjs +1 -0
  91. package/dist/tailwind/index.js +1 -0
  92. package/dist/tailwind/index.mjs +1 -0
  93. package/dist/textarea.js +1 -0
  94. package/dist/textarea.mjs +1 -0
  95. package/dist/toggle-group.js +1 -0
  96. package/dist/toggle-group.mjs +1 -0
  97. package/dist/toggle.js +1 -0
  98. package/dist/toggle.mjs +1 -0
  99. package/dist/tooltip.js +1 -0
  100. package/dist/tooltip.mjs +1 -0
  101. package/dist/types/index.js +1 -0
  102. package/dist/types/index.mjs +1 -0
  103. package/package.json +110 -81
  104. package/assets/ai-icons.tsx +0 -207
  105. package/assets/crypto.tsx +0 -33
  106. package/assets/file-type-icon.tsx +0 -66
  107. package/assets/file.tsx +0 -45
  108. package/assets/general.tsx +0 -2318
  109. package/assets/hanzo-logo.svg +0 -9
  110. package/assets/hanzo-logo.tsx +0 -17
  111. package/assets/index.ts +0 -122
  112. package/assets/index.tsx +0 -4
  113. package/assets/llm-provider.tsx +0 -1094
  114. package/blocks/auth/index.ts +0 -6
  115. package/blocks/auth/login-2fa.tsx +0 -165
  116. package/blocks/auth/login-basic.tsx +0 -94
  117. package/blocks/auth/login-social.tsx +0 -148
  118. package/blocks/auth/magic-link.tsx +0 -129
  119. package/blocks/auth/password-reset.tsx +0 -97
  120. package/blocks/auth/signup.tsx +0 -157
  121. package/blocks/components/accordian-block.tsx +0 -48
  122. package/blocks/components/block-component-props.ts +0 -11
  123. package/blocks/components/bullet-cards-block.tsx +0 -46
  124. package/blocks/components/card-block/index.tsx +0 -171
  125. package/blocks/components/card-block/link-out-button.tsx +0 -20
  126. package/blocks/components/card-block/util.ts +0 -28
  127. package/blocks/components/carte-blanche-block/index.tsx +0 -127
  128. package/blocks/components/carte-blanche-block/variant-content-left.tsx +0 -49
  129. package/blocks/components/content.tsx +0 -70
  130. package/blocks/components/cta-block.tsx +0 -115
  131. package/blocks/components/enh-heading-block.tsx +0 -204
  132. package/blocks/components/grid-block/grid-block-mutator.ts +0 -12
  133. package/blocks/components/grid-block/index.tsx +0 -83
  134. package/blocks/components/grid-block/mutator-registry.ts +0 -10
  135. package/blocks/components/grid-block/table-borders.mutator.ts +0 -47
  136. package/blocks/components/group-block.tsx +0 -83
  137. package/blocks/components/heading-block.tsx +0 -88
  138. package/blocks/components/image-block.tsx +0 -111
  139. package/blocks/components/index.ts +0 -30
  140. package/blocks/components/screenful-block/content.tsx +0 -123
  141. package/blocks/components/screenful-block/index.tsx +0 -107
  142. package/blocks/components/screenful-block/poster-background.tsx +0 -34
  143. package/blocks/components/screenful-block/video-background.tsx +0 -45
  144. package/blocks/components/space-block.tsx +0 -66
  145. package/blocks/components/video-block.tsx +0 -138
  146. package/blocks/data-display/activity-feed.tsx +0 -242
  147. package/blocks/data-display/data-table.tsx +0 -235
  148. package/blocks/data-display/stats-grid.tsx +0 -194
  149. package/blocks/def/accordian-block.ts +0 -14
  150. package/blocks/def/block.ts +0 -7
  151. package/blocks/def/bullet-cards-block.ts +0 -22
  152. package/blocks/def/card-block.ts +0 -22
  153. package/blocks/def/carte-blanche-block.ts +0 -21
  154. package/blocks/def/cta-block.ts +0 -19
  155. package/blocks/def/element-block.ts +0 -11
  156. package/blocks/def/enh-heading-block.ts +0 -44
  157. package/blocks/def/grid-block.ts +0 -16
  158. package/blocks/def/group-block.ts +0 -11
  159. package/blocks/def/heading-block.ts +0 -15
  160. package/blocks/def/image-block.ts +0 -31
  161. package/blocks/def/index.ts +0 -35
  162. package/blocks/def/screenful-block.ts +0 -54
  163. package/blocks/def/space-block.ts +0 -64
  164. package/blocks/def/video-block.ts +0 -9
  165. package/blocks/ecommerce/checkout.tsx +0 -242
  166. package/blocks/ecommerce/index.ts +0 -7
  167. package/blocks/ecommerce/product-detail.tsx +0 -257
  168. package/blocks/ecommerce/product-grid.tsx +0 -148
  169. package/blocks/ecommerce/shopping-cart.tsx +0 -181
  170. package/blocks/index.ts +0 -2
  171. package/blocks/marketing/cta-section.tsx +0 -207
  172. package/blocks/marketing/faq.tsx +0 -159
  173. package/blocks/marketing/features-grid.tsx +0 -156
  174. package/blocks/marketing/hero-section.tsx +0 -192
  175. package/blocks/marketing/index.ts +0 -6
  176. package/blocks/marketing/pricing-table.tsx +0 -121
  177. package/blocks/marketing/testimonials.tsx +0 -196
  178. package/components/index.ts +0 -9
  179. package/dist/index.js.map +0 -1
  180. package/dist/index.mjs.map +0 -1
  181. package/dist/tailwind.js +0 -2025
  182. package/dist/tailwind.js.map +0 -1
  183. package/dist/tailwind.mjs +0 -2013
  184. package/dist/tailwind.mjs.map +0 -1
  185. package/dist/types.js +0 -59
  186. package/dist/types.js.map +0 -1
  187. package/dist/types.mjs +0 -53
  188. package/dist/types.mjs.map +0 -1
  189. package/dist/utils.js +0 -30
  190. package/dist/utils.js.map +0 -1
  191. package/dist/utils.mjs +0 -26
  192. package/dist/utils.mjs.map +0 -1
  193. package/frameworks/core/index.ts +0 -6
  194. package/frameworks/core/utils/index.ts +0 -64
  195. package/frameworks/react/components/button.tsx +0 -26
  196. package/frameworks/react/components/index.ts +0 -5
  197. package/frameworks/react/hooks/index.ts +0 -5
  198. package/frameworks/react/index.ts +0 -9
  199. package/frameworks/react/package.json +0 -8
  200. package/frameworks/react/utils/index.ts +0 -2
  201. package/frameworks/react-native/index.ts +0 -9
  202. package/frameworks/react-native/package.json +0 -8
  203. package/frameworks/registry.json +0 -371
  204. package/frameworks/setup.sh +0 -69
  205. package/frameworks/svelte/index.ts +0 -9
  206. package/frameworks/svelte/package.json +0 -8
  207. package/frameworks/tracker.json +0 -1854
  208. package/frameworks/vue/index.ts +0 -9
  209. package/frameworks/vue/package.json +0 -8
  210. package/helpers/file.ts +0 -33
  211. package/helpers/memoization.ts +0 -40
  212. package/primitives/accordion.tsx +0 -74
  213. package/primitives/action-button.tsx +0 -42
  214. package/primitives/alert-dialog.tsx +0 -185
  215. package/primitives/alert.tsx +0 -74
  216. package/primitives/apply-typography.tsx +0 -55
  217. package/primitives/aspect-ratio.tsx +0 -5
  218. package/primitives/avatar.tsx +0 -57
  219. package/primitives/background-beams.tsx +0 -142
  220. package/primitives/badge.tsx +0 -45
  221. package/primitives/breadcrumb.tsx +0 -130
  222. package/primitives/breakpoint-indicator.tsx +0 -19
  223. package/primitives/button.tsx +0 -72
  224. package/primitives/calendar.tsx +0 -72
  225. package/primitives/card.tsx +0 -97
  226. package/primitives/carousel.tsx +0 -238
  227. package/primitives/chat/chat-input-area.tsx +0 -88
  228. package/primitives/chat/chat-input.tsx +0 -71
  229. package/primitives/chat/files-preview.tsx +0 -331
  230. package/primitives/chat/index.ts +0 -6
  231. package/primitives/chat/json-form.tsx +0 -8
  232. package/primitives/chat/message-list.tsx +0 -308
  233. package/primitives/chat/message.tsx +0 -569
  234. package/primitives/chat/sqlite-preview.tsx +0 -215
  235. package/primitives/checkbox.tsx +0 -32
  236. package/primitives/collapsible.tsx +0 -9
  237. package/primitives/combobox.tsx +0 -239
  238. package/primitives/command.tsx +0 -151
  239. package/primitives/context-menu.tsx +0 -206
  240. package/primitives/copy-to-clipboard-icon.tsx +0 -60
  241. package/primitives/dialog-video-controller.tsx +0 -38
  242. package/primitives/dialog.tsx +0 -128
  243. package/primitives/dot-pattern.tsx +0 -57
  244. package/primitives/dots-loader.tsx +0 -13
  245. package/primitives/drawer.tsx +0 -113
  246. package/primitives/dropdown-menu.tsx +0 -199
  247. package/primitives/error-message.tsx +0 -19
  248. package/primitives/file-uploader.tsx +0 -203
  249. package/primitives/form.tsx +0 -185
  250. package/primitives/hover-card.tsx +0 -28
  251. package/primitives/icons/github.tsx +0 -14
  252. package/primitives/icons/index.ts +0 -18
  253. package/primitives/icons/youtube-logo.tsx +0 -59
  254. package/primitives/index-client.ts +0 -4
  255. package/primitives/index-common.ts +0 -304
  256. package/primitives/index-next.ts +0 -4
  257. package/primitives/input-otp.tsx +0 -65
  258. package/primitives/input.tsx +0 -128
  259. package/primitives/label.tsx +0 -21
  260. package/primitives/list-adaptor.ts +0 -12
  261. package/primitives/list-box.tsx +0 -74
  262. package/primitives/loading-spinner.tsx +0 -33
  263. package/primitives/markdown-preview.tsx +0 -612
  264. package/primitives/mermaid.tsx +0 -196
  265. package/primitives/navigation-menu.tsx +0 -147
  266. package/primitives/next/image.tsx +0 -91
  267. package/primitives/next/index.ts +0 -7
  268. package/primitives/next/inline-icon.tsx +0 -36
  269. package/primitives/next/link-element.tsx +0 -109
  270. package/primitives/next/mdx-link.tsx +0 -22
  271. package/primitives/next/media-stack.tsx +0 -52
  272. package/primitives/next/nav-items.tsx +0 -45
  273. package/primitives/next/youtube-embed.tsx +0 -83
  274. package/primitives/pagination.tsx +0 -117
  275. package/primitives/popover.tsx +0 -34
  276. package/primitives/pretty-json-print.tsx +0 -28
  277. package/primitives/progress.tsx +0 -27
  278. package/primitives/prompt-textarea.tsx +0 -72
  279. package/primitives/qr-code.tsx +0 -112
  280. package/primitives/radio-group.tsx +0 -42
  281. package/primitives/resizable.tsx +0 -47
  282. package/primitives/scroll-area.tsx +0 -57
  283. package/primitives/search-input.tsx +0 -66
  284. package/primitives/select.tsx +0 -122
  285. package/primitives/separator.tsx +0 -26
  286. package/primitives/sheet.tsx +0 -139
  287. package/primitives/skeleton.tsx +0 -18
  288. package/primitives/slider.tsx +0 -63
  289. package/primitives/sonner.tsx +0 -35
  290. package/primitives/step-indicator.tsx +0 -69
  291. package/primitives/stepper.tsx +0 -272
  292. package/primitives/switch.tsx +0 -27
  293. package/primitives/table.tsx +0 -105
  294. package/primitives/tabs.tsx +0 -50
  295. package/primitives/text-area.tsx +0 -26
  296. package/primitives/text-link.tsx +0 -27
  297. package/primitives/textarea.tsx +0 -64
  298. package/primitives/textfield.tsx +0 -78
  299. package/primitives/toast.tsx +0 -30
  300. package/primitives/toggle-group.tsx +0 -63
  301. package/primitives/toggle.tsx +0 -44
  302. package/primitives/tooltip.tsx +0 -47
  303. package/primitives/video-player.tsx +0 -23
  304. package/src/button.ts +0 -1
  305. package/src/hooks/index.ts +0 -7
  306. package/src/hooks/use-click-away.ts +0 -31
  307. package/src/hooks/use-combined-refs.ts +0 -22
  308. package/src/hooks/use-copy-clipboard.ts +0 -30
  309. package/src/hooks/use-debounce.ts +0 -17
  310. package/src/hooks/use-fill-ids.ts +0 -25
  311. package/src/hooks/use-map.ts +0 -26
  312. package/src/hooks/use-measure.ts +0 -42
  313. package/src/hooks/use-reverse-video-playback.ts +0 -43
  314. package/src/hooks/use-scroll-restoration.ts +0 -50
  315. package/src/index-lean.ts +0 -87
  316. package/src/index.ts +0 -54
  317. package/src/mcp/README.md +0 -141
  318. package/src/mcp/enhanced-server.ts +0 -1208
  319. package/src/mcp/index.ts +0 -518
  320. package/src/mcp/package.json +0 -10
  321. package/src/registry/api.ts +0 -164
  322. package/src/registry/index.ts +0 -60
  323. package/src/registry/package.json +0 -10
  324. package/src/utils.ts +0 -19
  325. package/tailwind/colors.tailwind.js +0 -53
  326. package/tailwind/fontFamily.tailwind.ts +0 -7
  327. package/tailwind/fontSize.tailwind.ts +0 -13
  328. package/tailwind/index.ts +0 -7
  329. package/tailwind/safelist.tailwind.js +0 -26
  330. package/tailwind/screens.tailwind.js +0 -8
  331. package/tailwind/spacing.tailwind.js +0 -65
  332. package/tailwind/tailwind.config.hanzo-preset.d.ts +0 -5
  333. package/tailwind/tailwind.config.hanzo-preset.js +0 -915
  334. package/tailwind/tw-font-desc.ts +0 -15
  335. package/tailwind/typo-plugin/get-plugin-styles.js +0 -679
  336. package/tailwind/typo-plugin/index.d.ts +0 -9
  337. package/tailwind/typo-plugin/index.js +0 -141
  338. package/tailwind/typo-plugin/utils.js +0 -60
  339. package/tailwind/typography-test.mdx +0 -35
  340. package/tailwind/z-index.tailwind.js +0 -71
  341. package/types/animation-def.ts +0 -3
  342. package/types/breakpoints.ts +0 -11
  343. package/types/bullet-item.ts +0 -10
  344. package/types/button-def.ts +0 -39
  345. package/types/dimensions.ts +0 -8
  346. package/types/grid-def.ts +0 -56
  347. package/types/image-def.ts +0 -32
  348. package/types/index.ts +0 -30
  349. package/types/link-def.ts +0 -56
  350. package/types/media-stack-def.ts +0 -31
  351. package/types/t-shirt-size.ts +0 -5
  352. package/types/tshirt-dimensions.ts +0 -20
  353. package/types/video-def.ts +0 -25
  354. package/util/blob.ts +0 -33
  355. package/util/copy-to-clipboard.ts +0 -17
  356. package/util/create-shadow-root.ts +0 -22
  357. package/util/date.ts +0 -84
  358. package/util/debounce.ts +0 -11
  359. package/util/file.ts +0 -15
  360. package/util/format-and-abbreviate-as-currency.ts +0 -125
  361. package/util/format-text.ts +0 -34
  362. package/util/format-to-max-char.ts +0 -68
  363. package/util/index-client.ts +0 -3
  364. package/util/index.ts +0 -112
  365. package/util/number-abbreviate.ts +0 -49
  366. package/util/specifier.ts +0 -43
  367. package/util/spread-to-transform.ts +0 -25
  368. package/util/step-animation.ts +0 -90
  369. package/util/timing.ts +0 -3
  370. package/util/toasts.tsx +0 -17
  371. package/util/two-way-map.ts +0 -19
@@ -1,331 +0,0 @@
1
- import { DialogClose } from '@radix-ui/react-dialog';
2
- import {
3
- type Attachment,
4
- FileTypeSupported,
5
- } from '@hanzo_network/hanzo-node-state/v2/queries/getChatConversation/types';
6
- // import { save } from '@tauri-apps/plugin-dialog'; // Not available in web environment
7
- // import * as fs from '@tauri-apps/plugin-fs'; // Not available in web environment
8
- // import { BaseDirectory } from '@tauri-apps/plugin-fs'; // Not available in web environment
9
- // import { partial } from 'filesize';
10
- const partial = () => (bytes) => `${(bytes / 1024 / 1024).toFixed(2)} MB`;
11
- import { AnimatePresence, motion } from 'framer-motion';
12
- import { CircleSlashIcon, XIcon } from 'lucide-react';
13
- import React, { useState } from 'react';
14
- import { toast } from 'sonner';
15
-
16
- import { fileIconMap, FileTypeIcon, PaperClipIcon } from '../../assets';
17
- import { getFileExt } from '../../helpers/file';
18
- import { cn } from '../../src/utils';
19
- import { Avatar, AvatarFallback, AvatarImage } from '../avatar';
20
- import { Button } from '../button';
21
- import { Dialog, DialogContent } from '../dialog';
22
- import {
23
- Tooltip,
24
- TooltipContent,
25
- TooltipPortal,
26
- TooltipTrigger,
27
- } from '../tooltip';
28
- import { SqlitePreview } from './sqlite-preview';
29
-
30
- export type FileListProps = {
31
- files: Attachment[];
32
- className?: string;
33
- };
34
-
35
- export const isImageFile = (file: string) => {
36
- return file.match(/\.(jpg|jpeg|png|gif)$/i);
37
- };
38
-
39
- const size = partial({ standard: 'jedec' });
40
-
41
- const ImagePreview = ({
42
- name,
43
- size,
44
- url,
45
- onFullscreen,
46
- }: Pick<Attachment, 'name' | 'size' | 'url'> & {
47
- onFullscreen: (open: boolean) => void;
48
- }) => (
49
- <button
50
- className="border-divider hover:bg-bg-secondary flex h-14 w-full max-w-[210px] min-w-[210px] shrink-0 cursor-pointer items-center gap-2 rounded-md border py-1.5 pr-1.5 pl-2 text-left"
51
- onClick={() => onFullscreen(true)}
52
- >
53
- <Avatar className="bg-bg-quaternary text-text-default flex size-10 shrink-0 items-center justify-center overflow-hidden rounded-xs transition-colors">
54
- <AvatarImage
55
- alt={name}
56
- className="border-divider aspect-square h-full w-full rounded-xs border object-cover"
57
- src={url}
58
- />
59
- <AvatarFallback>
60
- <CircleSlashIcon className="text-text-secondary h-4 w-4" />
61
- </AvatarFallback>
62
- </Avatar>
63
- <FileInfo fileName={name} fileSize={size} />
64
- </button>
65
- );
66
-
67
- const FileInfo = ({
68
- fileSize,
69
- fileName,
70
- }: {
71
- fileSize?: number;
72
- fileName: string;
73
- }) => (
74
- <div className="text-text-secondary text-em-sm grid flex-1 -translate-x-px gap-1 py-0.5 leading-none">
75
- <div className="text-text-default truncate overflow-hidden font-medium">
76
- {decodeURIComponent(fileName.split('/').at(-1) ?? '')}
77
- </div>
78
- {fileSize && (
79
- <div className="text-text-secondary line-clamp-1 aspect-auto font-normal">
80
- {size(fileSize)}
81
- </div>
82
- )}
83
- </div>
84
- );
85
-
86
- type FileContentViewerProps = Pick<
87
- Attachment,
88
- 'name' | 'url' | 'content' | 'type'
89
- >;
90
-
91
- export const FileContentViewer: React.FC<FileContentViewerProps> = ({
92
- name,
93
- content,
94
- url,
95
- type,
96
- }) => {
97
- switch (type) {
98
- case FileTypeSupported.Text: {
99
- return (
100
- <pre className="bg-bg-dark h-full overflow-auto p-4 pt-10 font-mono text-xs break-words whitespace-pre-wrap">
101
- {content}
102
- </pre>
103
- );
104
- }
105
- case FileTypeSupported.Image: {
106
- return (
107
- <div className="flex h-full w-full items-center justify-center">
108
- <img
109
- alt={name}
110
- className="max-h-full max-w-full object-contain"
111
- src={url}
112
- />
113
- </div>
114
- );
115
- }
116
- case FileTypeSupported.Video: {
117
- return (
118
- <div className="flex h-full w-full items-center justify-center">
119
- <video className="max-h-full max-w-full" controls src={url}>
120
- Your browser does not support the video tag.
121
- </video>
122
- </div>
123
- );
124
- }
125
- case FileTypeSupported.Audio: {
126
- return (
127
- <div className="flex h-full w-full items-center justify-center">
128
- <audio className="w-full" controls src={url}>
129
- Your browser does not support the audio tag.
130
- </audio>
131
- </div>
132
- );
133
- }
134
- case FileTypeSupported.Html: {
135
- return (
136
- <div className="flex h-full w-full items-center justify-center">
137
- <iframe
138
- className="h-full w-full bg-gray-100"
139
- sandbox="allow-same-origin"
140
- src={url}
141
- title={name}
142
- />
143
- </div>
144
- );
145
- }
146
- case FileTypeSupported.SqliteDatabase: {
147
- return <SqlitePreview url={url || ''} />;
148
- }
149
- default:
150
- return (
151
- <div className="text-text-secondary flex h-full flex-col items-center justify-center gap-6">
152
- <span>Preview not available for this file type</span>
153
- </div>
154
- );
155
- }
156
- };
157
-
158
- const FullscreenDialog = ({
159
- open,
160
- name,
161
- type,
162
- url,
163
- content,
164
- setOpen,
165
- onDownload,
166
- }: Pick<Attachment, 'name' | 'url' | 'content' | 'type'> & {
167
- open: boolean;
168
- setOpen: (open: boolean) => void;
169
- onDownload?: () => void;
170
- }) => (
171
- <Dialog onOpenChange={setOpen} open={open}>
172
- <DialogContent className="flex size-full max-h-[99vh] max-w-[99vw] flex-col gap-2 bg-transparent p-1 py-8">
173
- <div className="flex w-full items-center justify-between gap-16 px-10">
174
- <div className="text-text-default max-w-3xl truncate text-left text-sm">
175
- {name}
176
- </div>
177
- <div className="flex items-center gap-4">
178
- <Button onClick={onDownload} size="xs" variant="outline">
179
- Download
180
- </Button>
181
- <DialogClose>
182
- <XIcon className="text-text-secondary h-6 w-6" />
183
- <span className="sr-only">Close</span>
184
- </DialogClose>
185
- </div>
186
- </div>
187
- <div className="text-text-default flex size-full flex-col overflow-hidden rounded-l-xl p-10">
188
- <FileContentViewer
189
- content={content}
190
- name={name}
191
- type={type}
192
- url={url}
193
- />
194
- </div>
195
- </DialogContent>
196
- </Dialog>
197
- );
198
- const FileButton = ({
199
- name,
200
- size,
201
- onFullscreen,
202
- }: Pick<Attachment, 'name' | 'size'> & {
203
- onFullscreen: (open: boolean) => void;
204
- }) => (
205
- <button
206
- className="border-divider hover:bg-bg-secondary flex h-14 w-full max-w-[210px] min-w-[210px] shrink-0 cursor-pointer items-center gap-2 rounded-md border py-1.5 pr-1.5 pl-2 text-left"
207
- onClick={() => onFullscreen(true)}
208
- >
209
- <span className="bg-bg-quaternary text-text-default flex size-10 shrink-0 items-center justify-center overflow-hidden rounded-xs transition-colors">
210
- {fileIconMap[getFileExt(name)] ? (
211
- <FileTypeIcon
212
- className="text-text-secondary h-5 w-5"
213
- type={getFileExt(name)}
214
- />
215
- ) : (
216
- <PaperClipIcon className="text-text-secondary h-4 w-4" />
217
- )}
218
- </span>
219
- <FileInfo fileName={name} fileSize={size} />
220
- </button>
221
- );
222
-
223
- export const FilePreview = ({
224
- name,
225
- url,
226
- size,
227
- content,
228
- blob,
229
- type,
230
- }: Attachment) => {
231
- const [open, setOpen] = useState(false);
232
-
233
- const fileName = decodeURIComponent(name).split('/').at(-1) ?? '';
234
-
235
- const children = isImageFile(name) ? (
236
- <ImagePreview name={name} onFullscreen={setOpen} size={size} url={url} />
237
- ) : (
238
- <FileButton name={name} onFullscreen={setOpen} size={size} />
239
- );
240
-
241
- return (
242
- <Tooltip>
243
- <TooltipTrigger asChild>
244
- <div>{children}</div>
245
- </TooltipTrigger>
246
- <TooltipPortal>
247
- <TooltipContent className="container break-words" side="top">
248
- <p>{fileName}</p>
249
- </TooltipContent>
250
- </TooltipPortal>
251
- <FullscreenDialog
252
- content={content}
253
- name={fileName}
254
- onDownload={async () => {
255
- const currentFile =
256
- blob ??
257
- new Blob([content || url || ''], {
258
- type: 'application/octet-stream',
259
- });
260
- const arrayBuffer = await currentFile.arrayBuffer();
261
- const currentContent = new Uint8Array(arrayBuffer);
262
- const savePath = await save({
263
- defaultPath: fileName,
264
- filters: [
265
- {
266
- name: 'File',
267
- extensions: [getFileExt(name)],
268
- },
269
- ],
270
- });
271
- if (!savePath) {
272
- toast.info('File saving cancelled');
273
- return;
274
- }
275
-
276
- await fs.writeFile(savePath, currentContent, {
277
- baseDir: BaseDirectory.Download,
278
- });
279
-
280
- toast.success(`${fileName} downloaded successfully`);
281
- }}
282
- open={open}
283
- setOpen={setOpen}
284
- type={type}
285
- url={url}
286
- />
287
- </Tooltip>
288
- );
289
- };
290
-
291
- const animations = {
292
- initial: { scale: 0.97, opacity: 0, y: 10 },
293
- animate: {
294
- scale: 1,
295
- opacity: 1,
296
- y: 0,
297
- transition: {
298
- type: 'spring',
299
- stiffness: 200,
300
- damping: 20,
301
- mass: 0.8,
302
- velocity: 1,
303
- duration: 0.6,
304
- },
305
- },
306
- exit: {
307
- scale: 0.97,
308
- opacity: 0,
309
- y: -10,
310
- transition: {
311
- type: 'spring',
312
- stiffness: 150,
313
- damping: 15,
314
- duration: 0.4,
315
- },
316
- },
317
- };
318
-
319
- export const FileList = ({ files, className }: FileListProps) => {
320
- return (
321
- <ul className={cn('flex flex-wrap gap-3', className)}>
322
- <AnimatePresence>
323
- {files?.map((file, index) => (
324
- <motion.li {...animations} key={index}>
325
- <FilePreview {...file} />
326
- </motion.li>
327
- ))}
328
- </AnimatePresence>
329
- </ul>
330
- );
331
- };
@@ -1,6 +0,0 @@
1
- export * from './message';
2
- export * from './message-list';
3
- export * from './files-preview';
4
- export * from './chat-input-area';
5
- export * from './chat-input';
6
- export * from './sqlite-preview';
@@ -1,8 +0,0 @@
1
- import React from 'react';
2
-
3
- // Temporary stub for JsonForm - will be replaced with actual implementation
4
- const JsonForm: React.FC<any> = (props) => {
5
- return <div>JsonForm Component - To be implemented</div>;
6
- };
7
-
8
- export default JsonForm;
@@ -1,308 +0,0 @@
1
- // import { ChatConversationInfiniteData } from '@hanzo_network/hanzo-node-state/v2/queries/getChatConversation/types';
2
- type ChatConversationInfiniteData = any;
3
- import {
4
- type FetchPreviousPageOptions,
5
- type InfiniteQueryObserverResult,
6
- } from '@tanstack/react-query';
7
- import React, {
8
- Fragment,
9
- memo,
10
- type RefObject,
11
- useCallback,
12
- useEffect,
13
- useLayoutEffect,
14
- useRef,
15
- useState,
16
- } from 'react';
17
- import { useInView } from 'react-intersection-observer';
18
-
19
- import { getRelativeDateLabel, groupMessagesByDate } from '../../helpers';
20
- import { cn } from '../src/utils';
21
- import { Skeleton } from '../skeleton';
22
- import { Message } from './message';
23
-
24
- function useScrollToBottom(
25
- scrollRef: RefObject<HTMLDivElement | null>,
26
- detach = false,
27
- ) {
28
- const [autoScroll, setAutoScroll] = useState(true);
29
- function scrollDomToBottom() {
30
- const scrollContainer = scrollRef.current;
31
- if (scrollContainer) {
32
- requestAnimationFrame(() => {
33
- setAutoScroll(true);
34
- scrollContainer.scrollTo(0, scrollContainer.scrollHeight);
35
- });
36
- }
37
- }
38
-
39
- useEffect(() => {
40
- if (autoScroll && !detach) {
41
- scrollDomToBottom();
42
- }
43
- });
44
-
45
- return {
46
- scrollRef,
47
- autoScroll,
48
- setAutoScroll,
49
- scrollDomToBottom,
50
- };
51
- }
52
-
53
- export const MessageList = ({
54
- noMoreMessageLabel,
55
- paginatedMessages,
56
- isSuccess,
57
- isLoading,
58
- isFetchingPreviousPage,
59
- hasPreviousPage,
60
- fetchPreviousPage,
61
- containerClassName,
62
- lastMessageContent,
63
- editAndRegenerateMessage,
64
- regenerateMessage,
65
- disabledRetryAndEdit,
66
- messageExtra,
67
- hidePythonExecution,
68
- }: {
69
- noMoreMessageLabel: string;
70
- isSuccess: boolean;
71
- isLoading: boolean;
72
- isFetchingPreviousPage: boolean;
73
- hasPreviousPage: boolean;
74
- paginatedMessages: ChatConversationInfiniteData | undefined;
75
- fetchPreviousPage: (
76
- options?: FetchPreviousPageOptions | undefined,
77
- ) => Promise<
78
- InfiniteQueryObserverResult<ChatConversationInfiniteData, Error>
79
- >;
80
- regenerateMessage?: (messageId: string) => void;
81
- editAndRegenerateMessage?: (content: string, messageHash: string) => void;
82
- containerClassName?: string;
83
- lastMessageContent?: React.ReactNode;
84
- disabledRetryAndEdit?: boolean;
85
- messageExtra?: React.ReactNode;
86
- hidePythonExecution?: boolean;
87
- }) => {
88
- const chatContainerRef = useRef<HTMLDivElement>(null);
89
- const previousChatHeightRef = useRef<number>(0);
90
- const { ref, inView } = useInView();
91
- const messageList = paginatedMessages?.pages.flat() ?? [];
92
-
93
- const { autoScroll, setAutoScroll, scrollDomToBottom } =
94
- useScrollToBottom(chatContainerRef);
95
-
96
- const fetchPreviousMessages = useCallback(async () => {
97
- setAutoScroll(false);
98
- await fetchPreviousPage();
99
- }, [fetchPreviousPage]);
100
-
101
- useEffect(() => {
102
- if (hasPreviousPage && inView) {
103
- void fetchPreviousMessages();
104
- }
105
- }, [hasPreviousPage, inView]);
106
-
107
- // adjust the scroll position of a chat container after new messages are fetched
108
- useLayoutEffect(() => {
109
- if (!isFetchingPreviousPage && inView) {
110
- const chatContainerElement = chatContainerRef.current;
111
- if (!chatContainerElement) return;
112
- const currentHeight = chatContainerElement.scrollHeight;
113
- const previousHeight = previousChatHeightRef.current;
114
-
115
- if (!autoScroll) {
116
- chatContainerElement.scrollTop =
117
- currentHeight - previousHeight + chatContainerElement.scrollTop;
118
- } else {
119
- scrollDomToBottom();
120
- }
121
-
122
- chatContainerElement.scrollTop = currentHeight - previousHeight;
123
- }
124
- }, [paginatedMessages, isFetchingPreviousPage, inView]);
125
-
126
- useEffect(() => {
127
- const chatContainerElement = chatContainerRef.current;
128
- if (!chatContainerElement) return;
129
- const handleScroll = async () => {
130
- const currentHeight = chatContainerElement.scrollHeight;
131
- const currentScrollTop = chatContainerElement.scrollTop;
132
- previousChatHeightRef.current = currentHeight;
133
- const scrollThreshold = 100;
134
- const isNearBottom =
135
- currentScrollTop + chatContainerElement.clientHeight >=
136
- currentHeight - scrollThreshold;
137
-
138
- setAutoScroll(isNearBottom);
139
-
140
- if (inView && hasPreviousPage && !isFetchingPreviousPage) {
141
- previousChatHeightRef.current = currentHeight - currentScrollTop;
142
- }
143
- };
144
-
145
- chatContainerElement.addEventListener('scroll', handleScroll, {
146
- passive: true,
147
- });
148
- return () => {
149
- chatContainerElement.removeEventListener('scroll', handleScroll);
150
- };
151
- }, [
152
- fetchPreviousMessages,
153
- hasPreviousPage,
154
- inView,
155
- isFetchingPreviousPage,
156
- paginatedMessages?.pages?.length,
157
- ]);
158
-
159
- useEffect(() => {
160
- if (messageList?.length % 2 === 1) {
161
- scrollDomToBottom();
162
- }
163
- }, [messageList?.length]);
164
-
165
- useEffect(() => {
166
- if (isSuccess) {
167
- scrollDomToBottom();
168
- }
169
- }, [isSuccess]);
170
-
171
- return (
172
- <div
173
- className={cn(
174
- 'scroll flex-1 overflow-y-auto overscroll-none will-change-scroll',
175
- 'flex-1 overflow-y-auto',
176
- containerClassName,
177
- )}
178
- id="chat-container-scroll"
179
- ref={chatContainerRef}
180
- >
181
- {isSuccess &&
182
- !isFetchingPreviousPage &&
183
- !hasPreviousPage &&
184
- (paginatedMessages?.pages ?? [])?.length > 1 && (
185
- <div className="text-text-secondary py-2 text-center text-xs">
186
- {noMoreMessageLabel}
187
- </div>
188
- )}
189
- <div className="">
190
- {isLoading && (
191
- <div className="flex flex-col space-y-8">
192
- {[...Array(10).keys()].map((index) => (
193
- <div
194
- className={cn(
195
- 'flex w-[85%] gap-2',
196
- index % 2 === 0
197
- ? 'mr-auto ml-0 flex-row items-end'
198
- : 'mr-0 ml-auto flex-row-reverse items-start',
199
- )}
200
- key={`${index}`}
201
- >
202
- <Skeleton
203
- className="h-8 w-8 shrink-0 rounded-full bg-gray-300"
204
- key={index}
205
- />
206
- <Skeleton
207
- className={cn(
208
- 'w-full rounded-lg px-2.5 py-3',
209
- index % 2 === 0
210
- ? 'h-24 rounded-bl-none bg-gray-300'
211
- : 'h-16 rounded-tr-none bg-gray-200',
212
- index % 3 === 0 && 'h-32',
213
- )}
214
- />
215
- </div>
216
- ))}
217
- </div>
218
- )}
219
- {(hasPreviousPage || isFetchingPreviousPage) && (
220
- <div className="flex flex-col space-y-3" ref={ref}>
221
- {[...Array(4).keys()].map((index) => (
222
- <div
223
- className={cn(
224
- 'flex w-[85%] gap-2',
225
- index % 2 === 0
226
- ? 'mr-auto ml-0 flex-row items-end'
227
- : 'mr-0 ml-auto flex-row-reverse items-start',
228
- )}
229
- key={`${index}`}
230
- >
231
- <Skeleton
232
- className="h-8 w-8 shrink-0 rounded-full bg-gray-300"
233
- key={index}
234
- />
235
- <Skeleton
236
- className={cn(
237
- 'w-full rounded-lg px-2.5 py-3',
238
- index % 2 === 0
239
- ? 'h-24 rounded-bl-none bg-gray-300'
240
- : 'h-16 rounded-tr-none bg-gray-200',
241
- index % 3 === 0 && 'h-32',
242
- )}
243
- />
244
- </div>
245
- ))}
246
- </div>
247
- )}
248
- {isSuccess && messageList?.length > 0 && (
249
- <Fragment>
250
- {Object.entries(groupMessagesByDate(messageList)).map(
251
- ([date, messages]) => {
252
- return (
253
- <div key={date}>
254
- <div
255
- className={cn(
256
- 'relative z-10 m-auto my-2 flex h-[26px] w-fit min-w-[100px] items-center justify-center rounded-xl bg-gray-400 px-2.5 capitalize',
257
- 'sticky top-5',
258
- )}
259
- >
260
- <span className="text-text-secondary text-xs font-medium">
261
- {getRelativeDateLabel(
262
- new Date(messages[0].createdAt || ''),
263
- )}
264
- </span>
265
- </div>
266
- <div className="flex flex-col">
267
- {messages.map((message, messageIndex) => {
268
- const previousMessage = messages[messageIndex - 1];
269
-
270
- const disabledRetryAndEditValue =
271
- disabledRetryAndEdit ?? messageIndex === 0;
272
-
273
- const handleRetryMessage = () => {
274
- regenerateMessage?.(message?.messageId ?? '');
275
- };
276
-
277
- const handleEditMessage = (message: string) => {
278
- editAndRegenerateMessage?.(
279
- message,
280
- previousMessage?.messageId ?? '',
281
- );
282
- };
283
-
284
- return (
285
- <Message
286
- disabledEdit={disabledRetryAndEditValue}
287
- handleEditMessage={handleEditMessage}
288
- handleRetryMessage={handleRetryMessage}
289
- hidePythonExecution={hidePythonExecution}
290
- key={`${message.messageId}::${messageIndex}`}
291
- message={message}
292
- messageId={message.messageId}
293
- />
294
- );
295
- })}
296
- </div>
297
- </div>
298
- );
299
- },
300
- )}
301
- {messageExtra}
302
- {lastMessageContent}
303
- </Fragment>
304
- )}
305
- </div>
306
- </div>
307
- );
308
- };