@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.
- package/dist/accordion.js +1 -0
- package/dist/accordion.mjs +1 -0
- package/dist/alert-dialog.js +1 -0
- package/dist/alert-dialog.mjs +1 -0
- package/dist/alert.js +1 -0
- package/dist/alert.mjs +1 -0
- package/dist/avatar.js +1 -0
- package/dist/avatar.mjs +1 -0
- package/dist/badge.js +1 -0
- package/dist/badge.mjs +1 -0
- package/dist/breadcrumb.js +1 -0
- package/dist/breadcrumb.mjs +1 -0
- package/dist/calendar.js +1 -0
- package/dist/calendar.mjs +1 -0
- package/dist/carousel.js +1 -0
- package/dist/carousel.mjs +1 -0
- package/dist/checkbox.js +1 -0
- package/dist/checkbox.mjs +1 -0
- package/dist/chunk-3H5S2OQ3.mjs +1 -0
- package/dist/chunk-5GRJ7UQX.js +1 -0
- package/dist/chunk-63HNMH7C.js +1 -0
- package/dist/chunk-72TOQ4DM.mjs +1 -0
- package/dist/chunk-7AEFTV5R.mjs +1 -0
- package/dist/chunk-7M4AVV2R.js +1 -0
- package/dist/chunk-DKPVJSBC.js +1 -0
- package/dist/chunk-EI7MMDWY.js +1 -0
- package/dist/chunk-GANGDIZG.mjs +1 -0
- package/dist/chunk-GRGT2Z4K.js +1 -0
- package/dist/chunk-JCUUC6NY.mjs +1 -0
- package/dist/chunk-JUQMWLIN.js +1 -0
- package/dist/chunk-PRVEIITE.js +1 -0
- package/dist/chunk-SH52AKNZ.js +1 -0
- package/dist/chunk-TU67EJEW.mjs +1 -0
- package/dist/chunk-WN5KN73U.mjs +1 -0
- package/dist/chunk-YSXGDEY5.mjs +1 -0
- package/dist/chunk-Z76OOVUE.mjs +1 -0
- package/dist/collapsible.js +1 -0
- package/dist/collapsible.mjs +1 -0
- package/dist/command.js +1 -0
- package/dist/command.mjs +1 -0
- package/dist/context-menu.js +1 -0
- package/dist/context-menu.mjs +1 -0
- package/dist/dialog.js +1 -0
- package/dist/dialog.mjs +1 -0
- package/dist/drawer.js +1 -0
- package/dist/drawer.mjs +1 -0
- package/dist/dropdown-menu.js +1 -0
- package/dist/dropdown-menu.mjs +1 -0
- package/dist/form.js +1 -0
- package/dist/form.mjs +1 -0
- package/dist/hover-card.js +1 -0
- package/dist/hover-card.mjs +1 -0
- package/dist/index.js +1 -9079
- package/dist/index.mjs +1 -8700
- package/dist/input-otp.js +1 -0
- package/dist/input-otp.mjs +1 -0
- package/dist/lib/utils.js +1 -0
- package/dist/lib/utils.mjs +1 -0
- package/dist/navigation-menu.js +1 -0
- package/dist/navigation-menu.mjs +1 -0
- package/dist/popover.js +1 -0
- package/dist/popover.mjs +1 -0
- package/dist/progress.js +1 -0
- package/dist/progress.mjs +1 -0
- package/dist/radio-group.js +1 -0
- package/dist/radio-group.mjs +1 -0
- package/dist/resizable.js +1 -0
- package/dist/resizable.mjs +1 -0
- package/dist/scroll-area.js +1 -0
- package/dist/scroll-area.mjs +1 -0
- package/dist/select.js +1 -0
- package/dist/select.mjs +1 -0
- package/dist/separator.js +1 -0
- package/dist/separator.mjs +1 -0
- package/dist/sheet.js +1 -0
- package/dist/sheet.mjs +1 -0
- package/dist/skeleton.js +1 -0
- package/dist/skeleton.mjs +1 -0
- package/dist/slider.js +1 -0
- package/dist/slider.mjs +1 -0
- package/dist/sonner.js +1 -0
- package/dist/sonner.mjs +1 -0
- package/dist/src/utils.js +1 -0
- package/dist/src/utils.mjs +1 -0
- package/dist/switch.js +1 -0
- package/dist/switch.mjs +1 -0
- package/dist/table.js +1 -0
- package/dist/table.mjs +1 -0
- package/dist/tabs.js +1 -0
- package/dist/tabs.mjs +1 -0
- package/dist/tailwind/index.js +1 -0
- package/dist/tailwind/index.mjs +1 -0
- package/dist/textarea.js +1 -0
- package/dist/textarea.mjs +1 -0
- package/dist/toggle-group.js +1 -0
- package/dist/toggle-group.mjs +1 -0
- package/dist/toggle.js +1 -0
- package/dist/toggle.mjs +1 -0
- package/dist/tooltip.js +1 -0
- package/dist/tooltip.mjs +1 -0
- package/dist/types/index.js +1 -0
- package/dist/types/index.mjs +1 -0
- package/package.json +110 -81
- package/assets/ai-icons.tsx +0 -207
- package/assets/crypto.tsx +0 -33
- package/assets/file-type-icon.tsx +0 -66
- package/assets/file.tsx +0 -45
- package/assets/general.tsx +0 -2318
- package/assets/hanzo-logo.svg +0 -9
- package/assets/hanzo-logo.tsx +0 -17
- package/assets/index.ts +0 -122
- package/assets/index.tsx +0 -4
- package/assets/llm-provider.tsx +0 -1094
- package/blocks/auth/index.ts +0 -6
- package/blocks/auth/login-2fa.tsx +0 -165
- package/blocks/auth/login-basic.tsx +0 -94
- package/blocks/auth/login-social.tsx +0 -148
- package/blocks/auth/magic-link.tsx +0 -129
- package/blocks/auth/password-reset.tsx +0 -97
- package/blocks/auth/signup.tsx +0 -157
- package/blocks/components/accordian-block.tsx +0 -48
- package/blocks/components/block-component-props.ts +0 -11
- package/blocks/components/bullet-cards-block.tsx +0 -46
- package/blocks/components/card-block/index.tsx +0 -171
- package/blocks/components/card-block/link-out-button.tsx +0 -20
- package/blocks/components/card-block/util.ts +0 -28
- package/blocks/components/carte-blanche-block/index.tsx +0 -127
- package/blocks/components/carte-blanche-block/variant-content-left.tsx +0 -49
- package/blocks/components/content.tsx +0 -70
- package/blocks/components/cta-block.tsx +0 -115
- package/blocks/components/enh-heading-block.tsx +0 -204
- package/blocks/components/grid-block/grid-block-mutator.ts +0 -12
- package/blocks/components/grid-block/index.tsx +0 -83
- package/blocks/components/grid-block/mutator-registry.ts +0 -10
- package/blocks/components/grid-block/table-borders.mutator.ts +0 -47
- package/blocks/components/group-block.tsx +0 -83
- package/blocks/components/heading-block.tsx +0 -88
- package/blocks/components/image-block.tsx +0 -111
- package/blocks/components/index.ts +0 -30
- package/blocks/components/screenful-block/content.tsx +0 -123
- package/blocks/components/screenful-block/index.tsx +0 -107
- package/blocks/components/screenful-block/poster-background.tsx +0 -34
- package/blocks/components/screenful-block/video-background.tsx +0 -45
- package/blocks/components/space-block.tsx +0 -66
- package/blocks/components/video-block.tsx +0 -138
- package/blocks/data-display/activity-feed.tsx +0 -242
- package/blocks/data-display/data-table.tsx +0 -235
- package/blocks/data-display/stats-grid.tsx +0 -194
- package/blocks/def/accordian-block.ts +0 -14
- package/blocks/def/block.ts +0 -7
- package/blocks/def/bullet-cards-block.ts +0 -22
- package/blocks/def/card-block.ts +0 -22
- package/blocks/def/carte-blanche-block.ts +0 -21
- package/blocks/def/cta-block.ts +0 -19
- package/blocks/def/element-block.ts +0 -11
- package/blocks/def/enh-heading-block.ts +0 -44
- package/blocks/def/grid-block.ts +0 -16
- package/blocks/def/group-block.ts +0 -11
- package/blocks/def/heading-block.ts +0 -15
- package/blocks/def/image-block.ts +0 -31
- package/blocks/def/index.ts +0 -35
- package/blocks/def/screenful-block.ts +0 -54
- package/blocks/def/space-block.ts +0 -64
- package/blocks/def/video-block.ts +0 -9
- package/blocks/ecommerce/checkout.tsx +0 -242
- package/blocks/ecommerce/index.ts +0 -7
- package/blocks/ecommerce/product-detail.tsx +0 -257
- package/blocks/ecommerce/product-grid.tsx +0 -148
- package/blocks/ecommerce/shopping-cart.tsx +0 -181
- package/blocks/index.ts +0 -2
- package/blocks/marketing/cta-section.tsx +0 -207
- package/blocks/marketing/faq.tsx +0 -159
- package/blocks/marketing/features-grid.tsx +0 -156
- package/blocks/marketing/hero-section.tsx +0 -192
- package/blocks/marketing/index.ts +0 -6
- package/blocks/marketing/pricing-table.tsx +0 -121
- package/blocks/marketing/testimonials.tsx +0 -196
- package/components/index.ts +0 -9
- package/dist/index.js.map +0 -1
- package/dist/index.mjs.map +0 -1
- package/dist/tailwind.js +0 -2025
- package/dist/tailwind.js.map +0 -1
- package/dist/tailwind.mjs +0 -2013
- package/dist/tailwind.mjs.map +0 -1
- package/dist/types.js +0 -59
- package/dist/types.js.map +0 -1
- package/dist/types.mjs +0 -53
- package/dist/types.mjs.map +0 -1
- package/dist/utils.js +0 -30
- package/dist/utils.js.map +0 -1
- package/dist/utils.mjs +0 -26
- package/dist/utils.mjs.map +0 -1
- package/frameworks/core/index.ts +0 -6
- package/frameworks/core/utils/index.ts +0 -64
- package/frameworks/react/components/button.tsx +0 -26
- package/frameworks/react/components/index.ts +0 -5
- package/frameworks/react/hooks/index.ts +0 -5
- package/frameworks/react/index.ts +0 -9
- package/frameworks/react/package.json +0 -8
- package/frameworks/react/utils/index.ts +0 -2
- package/frameworks/react-native/index.ts +0 -9
- package/frameworks/react-native/package.json +0 -8
- package/frameworks/registry.json +0 -371
- package/frameworks/setup.sh +0 -69
- package/frameworks/svelte/index.ts +0 -9
- package/frameworks/svelte/package.json +0 -8
- package/frameworks/tracker.json +0 -1854
- package/frameworks/vue/index.ts +0 -9
- package/frameworks/vue/package.json +0 -8
- package/helpers/file.ts +0 -33
- package/helpers/memoization.ts +0 -40
- package/primitives/accordion.tsx +0 -74
- package/primitives/action-button.tsx +0 -42
- package/primitives/alert-dialog.tsx +0 -185
- package/primitives/alert.tsx +0 -74
- package/primitives/apply-typography.tsx +0 -55
- package/primitives/aspect-ratio.tsx +0 -5
- package/primitives/avatar.tsx +0 -57
- package/primitives/background-beams.tsx +0 -142
- package/primitives/badge.tsx +0 -45
- package/primitives/breadcrumb.tsx +0 -130
- package/primitives/breakpoint-indicator.tsx +0 -19
- package/primitives/button.tsx +0 -72
- package/primitives/calendar.tsx +0 -72
- package/primitives/card.tsx +0 -97
- package/primitives/carousel.tsx +0 -238
- package/primitives/chat/chat-input-area.tsx +0 -88
- package/primitives/chat/chat-input.tsx +0 -71
- package/primitives/chat/files-preview.tsx +0 -331
- package/primitives/chat/index.ts +0 -6
- package/primitives/chat/json-form.tsx +0 -8
- package/primitives/chat/message-list.tsx +0 -308
- package/primitives/chat/message.tsx +0 -569
- package/primitives/chat/sqlite-preview.tsx +0 -215
- package/primitives/checkbox.tsx +0 -32
- package/primitives/collapsible.tsx +0 -9
- package/primitives/combobox.tsx +0 -239
- package/primitives/command.tsx +0 -151
- package/primitives/context-menu.tsx +0 -206
- package/primitives/copy-to-clipboard-icon.tsx +0 -60
- package/primitives/dialog-video-controller.tsx +0 -38
- package/primitives/dialog.tsx +0 -128
- package/primitives/dot-pattern.tsx +0 -57
- package/primitives/dots-loader.tsx +0 -13
- package/primitives/drawer.tsx +0 -113
- package/primitives/dropdown-menu.tsx +0 -199
- package/primitives/error-message.tsx +0 -19
- package/primitives/file-uploader.tsx +0 -203
- package/primitives/form.tsx +0 -185
- package/primitives/hover-card.tsx +0 -28
- package/primitives/icons/github.tsx +0 -14
- package/primitives/icons/index.ts +0 -18
- package/primitives/icons/youtube-logo.tsx +0 -59
- package/primitives/index-client.ts +0 -4
- package/primitives/index-common.ts +0 -304
- package/primitives/index-next.ts +0 -4
- package/primitives/input-otp.tsx +0 -65
- package/primitives/input.tsx +0 -128
- package/primitives/label.tsx +0 -21
- package/primitives/list-adaptor.ts +0 -12
- package/primitives/list-box.tsx +0 -74
- package/primitives/loading-spinner.tsx +0 -33
- package/primitives/markdown-preview.tsx +0 -612
- package/primitives/mermaid.tsx +0 -196
- package/primitives/navigation-menu.tsx +0 -147
- package/primitives/next/image.tsx +0 -91
- package/primitives/next/index.ts +0 -7
- package/primitives/next/inline-icon.tsx +0 -36
- package/primitives/next/link-element.tsx +0 -109
- package/primitives/next/mdx-link.tsx +0 -22
- package/primitives/next/media-stack.tsx +0 -52
- package/primitives/next/nav-items.tsx +0 -45
- package/primitives/next/youtube-embed.tsx +0 -83
- package/primitives/pagination.tsx +0 -117
- package/primitives/popover.tsx +0 -34
- package/primitives/pretty-json-print.tsx +0 -28
- package/primitives/progress.tsx +0 -27
- package/primitives/prompt-textarea.tsx +0 -72
- package/primitives/qr-code.tsx +0 -112
- package/primitives/radio-group.tsx +0 -42
- package/primitives/resizable.tsx +0 -47
- package/primitives/scroll-area.tsx +0 -57
- package/primitives/search-input.tsx +0 -66
- package/primitives/select.tsx +0 -122
- package/primitives/separator.tsx +0 -26
- package/primitives/sheet.tsx +0 -139
- package/primitives/skeleton.tsx +0 -18
- package/primitives/slider.tsx +0 -63
- package/primitives/sonner.tsx +0 -35
- package/primitives/step-indicator.tsx +0 -69
- package/primitives/stepper.tsx +0 -272
- package/primitives/switch.tsx +0 -27
- package/primitives/table.tsx +0 -105
- package/primitives/tabs.tsx +0 -50
- package/primitives/text-area.tsx +0 -26
- package/primitives/text-link.tsx +0 -27
- package/primitives/textarea.tsx +0 -64
- package/primitives/textfield.tsx +0 -78
- package/primitives/toast.tsx +0 -30
- package/primitives/toggle-group.tsx +0 -63
- package/primitives/toggle.tsx +0 -44
- package/primitives/tooltip.tsx +0 -47
- package/primitives/video-player.tsx +0 -23
- package/src/button.ts +0 -1
- package/src/hooks/index.ts +0 -7
- package/src/hooks/use-click-away.ts +0 -31
- package/src/hooks/use-combined-refs.ts +0 -22
- package/src/hooks/use-copy-clipboard.ts +0 -30
- package/src/hooks/use-debounce.ts +0 -17
- package/src/hooks/use-fill-ids.ts +0 -25
- package/src/hooks/use-map.ts +0 -26
- package/src/hooks/use-measure.ts +0 -42
- package/src/hooks/use-reverse-video-playback.ts +0 -43
- package/src/hooks/use-scroll-restoration.ts +0 -50
- package/src/index-lean.ts +0 -87
- package/src/index.ts +0 -54
- package/src/mcp/README.md +0 -141
- package/src/mcp/enhanced-server.ts +0 -1208
- package/src/mcp/index.ts +0 -518
- package/src/mcp/package.json +0 -10
- package/src/registry/api.ts +0 -164
- package/src/registry/index.ts +0 -60
- package/src/registry/package.json +0 -10
- package/src/utils.ts +0 -19
- package/tailwind/colors.tailwind.js +0 -53
- package/tailwind/fontFamily.tailwind.ts +0 -7
- package/tailwind/fontSize.tailwind.ts +0 -13
- package/tailwind/index.ts +0 -7
- package/tailwind/safelist.tailwind.js +0 -26
- package/tailwind/screens.tailwind.js +0 -8
- package/tailwind/spacing.tailwind.js +0 -65
- package/tailwind/tailwind.config.hanzo-preset.d.ts +0 -5
- package/tailwind/tailwind.config.hanzo-preset.js +0 -915
- package/tailwind/tw-font-desc.ts +0 -15
- package/tailwind/typo-plugin/get-plugin-styles.js +0 -679
- package/tailwind/typo-plugin/index.d.ts +0 -9
- package/tailwind/typo-plugin/index.js +0 -141
- package/tailwind/typo-plugin/utils.js +0 -60
- package/tailwind/typography-test.mdx +0 -35
- package/tailwind/z-index.tailwind.js +0 -71
- package/types/animation-def.ts +0 -3
- package/types/breakpoints.ts +0 -11
- package/types/bullet-item.ts +0 -10
- package/types/button-def.ts +0 -39
- package/types/dimensions.ts +0 -8
- package/types/grid-def.ts +0 -56
- package/types/image-def.ts +0 -32
- package/types/index.ts +0 -30
- package/types/link-def.ts +0 -56
- package/types/media-stack-def.ts +0 -31
- package/types/t-shirt-size.ts +0 -5
- package/types/tshirt-dimensions.ts +0 -20
- package/types/video-def.ts +0 -25
- package/util/blob.ts +0 -33
- package/util/copy-to-clipboard.ts +0 -17
- package/util/create-shadow-root.ts +0 -22
- package/util/date.ts +0 -84
- package/util/debounce.ts +0 -11
- package/util/file.ts +0 -15
- package/util/format-and-abbreviate-as-currency.ts +0 -125
- package/util/format-text.ts +0 -34
- package/util/format-to-max-char.ts +0 -68
- package/util/index-client.ts +0 -3
- package/util/index.ts +0 -112
- package/util/number-abbreviate.ts +0 -49
- package/util/specifier.ts +0 -43
- package/util/spread-to-transform.ts +0 -25
- package/util/step-animation.ts +0 -90
- package/util/timing.ts +0 -3
- package/util/toasts.tsx +0 -17
- 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
|
-
};
|
package/primitives/chat/index.ts
DELETED
|
@@ -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
|
-
};
|