NeoPy's picture
Upload folder using huggingface_hub
1ae64c5 verified
import {
ArrowDownIcon,
ArrowUpIcon,
CheckIcon,
ChevronLeftIcon,
ChevronRightIcon,
CopyIcon,
PencilIcon,
RefreshCwIcon,
Square,
} from "lucide-react";
import {
ActionBarPrimitive,
BranchPickerPrimitive,
ComposerPrimitive,
ErrorPrimitive,
MessagePrimitive,
ThreadPrimitive,
} from "@assistant-ui/react";
import type { FC } from "react";
import { LazyMotion, MotionConfig, domAnimation } from "motion/react";
import * as m from "motion/react-m";
import { Button } from "@/components/ui/button";
import { MarkdownText } from "@/components/assistant-ui/markdown-text";
import { Reasoning, ReasoningGroup } from "@/components/assistant-ui/reasoning";
import { ToolFallback } from "@/components/assistant-ui/tool-fallback";
import { TooltipIconButton } from "@/components/assistant-ui/tooltip-icon-button";
import {
ComposerAddAttachment,
ComposerAttachments,
UserMessageAttachments,
} from "@/components/assistant-ui/attachment";
import { cn } from "@/lib/utils";
export const Thread: FC = () => {
return (
<LazyMotion features={domAnimation}>
<MotionConfig reducedMotion="user">
<ThreadPrimitive.Root
className="aui-root aui-thread-root @container flex h-full flex-col bg-background"
style={{
["--thread-max-width" as string]: "44rem",
}}
>
<ThreadPrimitive.Viewport className="aui-thread-viewport relative flex flex-1 flex-col overflow-x-auto overflow-y-scroll px-4">
<ThreadPrimitive.If empty>
<ThreadWelcome />
</ThreadPrimitive.If>
<ThreadPrimitive.Messages
components={{
UserMessage,
EditComposer,
AssistantMessage,
}}
/>
<ThreadPrimitive.If empty={false}>
<div className="aui-thread-viewport-spacer min-h-8 grow" />
</ThreadPrimitive.If>
<Composer />
</ThreadPrimitive.Viewport>
</ThreadPrimitive.Root>
</MotionConfig>
</LazyMotion>
);
};
const ThreadScrollToBottom: FC = () => {
return (
<ThreadPrimitive.ScrollToBottom asChild>
<TooltipIconButton
tooltip="Scroll to bottom"
variant="outline"
className="aui-thread-scroll-to-bottom absolute -top-12 z-10 self-center rounded-full p-4 disabled:invisible dark:bg-background dark:hover:bg-accent"
>
<ArrowDownIcon />
</TooltipIconButton>
</ThreadPrimitive.ScrollToBottom>
);
};
const ThreadWelcome: FC = () => {
return (
<div className="aui-thread-welcome-root mx-auto my-auto flex w-full max-w-[var(--thread-max-width)] flex-grow flex-col">
<div className="aui-thread-welcome-center flex w-full flex-grow flex-col items-center justify-center">
<div className="aui-thread-welcome-message flex size-full flex-col justify-center px-8">
<m.div
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: 10 }}
className="aui-thread-welcome-message-motion-1 text-2xl font-semibold"
>
Hello there!
</m.div>
<m.div
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: 10 }}
transition={{ delay: 0.1 }}
className="aui-thread-welcome-message-motion-2 text-2xl text-muted-foreground/65"
>
How can I help you today?
</m.div>
</div>
</div>
<ThreadSuggestions />
</div>
);
};
const ThreadSuggestions: FC = () => {
return (
<div className="aui-thread-welcome-suggestions grid w-full gap-2 pb-4 @md:grid-cols-2">
{[
{
title: "What's the weather",
label: "in San Francisco?",
action: "What's the weather in San Francisco?",
},
{
title: "Explain React hooks",
label: "like useState and useEffect",
action: "Explain React hooks like useState and useEffect",
},
{
title: "Write a SQL query",
label: "to find top customers",
action: "Write a SQL query to find top customers",
},
{
title: "Create a meal plan",
label: "for healthy weight loss",
action: "Create a meal plan for healthy weight loss",
},
].map((suggestedAction, index) => (
<m.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: 20 }}
transition={{ delay: 0.05 * index }}
key={`suggested-action-${suggestedAction.title}-${index}`}
className="aui-thread-welcome-suggestion-display [&:nth-child(n+3)]:hidden @md:[&:nth-child(n+3)]:block"
>
<ThreadPrimitive.Suggestion
prompt={suggestedAction.action}
send
asChild
>
<Button
variant="ghost"
className="aui-thread-welcome-suggestion h-auto w-full flex-1 flex-wrap items-start justify-start gap-1 rounded-3xl border px-5 py-4 text-left text-sm @md:flex-col dark:hover:bg-accent/60"
aria-label={suggestedAction.action}
>
<span className="aui-thread-welcome-suggestion-text-1 font-medium">
{suggestedAction.title}
</span>
<span className="aui-thread-welcome-suggestion-text-2 text-muted-foreground">
{suggestedAction.label}
</span>
</Button>
</ThreadPrimitive.Suggestion>
</m.div>
))}
</div>
);
};
const Composer: FC = () => {
return (
<div className="aui-composer-wrapper sticky bottom-0 mx-auto flex w-full max-w-[var(--thread-max-width)] flex-col gap-4 overflow-visible rounded-t-3xl bg-background pb-4 md:pb-6">
<ThreadScrollToBottom />
<ComposerPrimitive.Root className="aui-composer-root relative flex w-full flex-col">
<ComposerPrimitive.AttachmentDropzone className="aui-composer-attachment-dropzone group/input-group flex w-full flex-col rounded-3xl border border-input bg-background px-1 pt-2 shadow-xs transition-[color,box-shadow] outline-none has-[textarea:focus-visible]:border-ring has-[textarea:focus-visible]:ring-[3px] has-[textarea:focus-visible]:ring-ring/50 data-[dragging=true]:border-dashed data-[dragging=true]:border-ring data-[dragging=true]:bg-accent/50 dark:bg-background">
<ComposerAttachments />
<ComposerPrimitive.Input
placeholder="Send a message..."
className="aui-composer-input mb-1 max-h-32 min-h-16 w-full resize-none bg-transparent px-3.5 pt-1.5 pb-3 text-base outline-none placeholder:text-muted-foreground focus-visible:ring-0"
rows={1}
autoFocus
aria-label="Message input"
/>
<ComposerAction />
</ComposerPrimitive.AttachmentDropzone>
</ComposerPrimitive.Root>
</div>
);
};
const ComposerAction: FC = () => {
return (
<div className="aui-composer-action-wrapper relative mx-1 mt-2 mb-2 flex items-center justify-between">
<ComposerAddAttachment />
<ThreadPrimitive.If running={false}>
<ComposerPrimitive.Send asChild>
<TooltipIconButton
tooltip="Send message"
side="bottom"
type="submit"
variant="default"
size="icon"
className="aui-composer-send size-[34px] rounded-full p-1"
aria-label="Send message"
>
<ArrowUpIcon className="aui-composer-send-icon size-5" />
</TooltipIconButton>
</ComposerPrimitive.Send>
</ThreadPrimitive.If>
<ThreadPrimitive.If running>
<ComposerPrimitive.Cancel asChild>
<Button
type="button"
variant="default"
size="icon"
className="aui-composer-cancel size-[34px] rounded-full border border-muted-foreground/60 hover:bg-primary/75 dark:border-muted-foreground/90"
aria-label="Stop generating"
>
<Square className="aui-composer-cancel-icon size-3.5 fill-white dark:fill-black" />
</Button>
</ComposerPrimitive.Cancel>
</ThreadPrimitive.If>
</div>
);
};
const MessageError: FC = () => {
return (
<MessagePrimitive.Error>
<ErrorPrimitive.Root className="aui-message-error-root mt-2 rounded-md border border-destructive bg-destructive/10 p-3 text-sm text-destructive dark:bg-destructive/5 dark:text-red-200">
<ErrorPrimitive.Message className="aui-message-error-message line-clamp-2" />
</ErrorPrimitive.Root>
</MessagePrimitive.Error>
);
};
const AssistantMessage: FC = () => {
return (
<MessagePrimitive.Root asChild>
<div
className="aui-assistant-message-root relative mx-auto w-full max-w-[var(--thread-max-width)] animate-in py-4 duration-150 ease-out fade-in slide-in-from-bottom-1 last:mb-24"
data-role="assistant"
>
<div className="aui-assistant-message-content mx-2 leading-7 break-words text-foreground">
<MessagePrimitive.Parts
components={{
Text: MarkdownText,
Reasoning: Reasoning,
ReasoningGroup: ReasoningGroup,
tools: { Fallback: ToolFallback },
}}
/>
<MessageError />
</div>
<div className="aui-assistant-message-footer mt-2 ml-2 flex">
<BranchPicker />
<AssistantActionBar />
</div>
</div>
</MessagePrimitive.Root>
);
};
const AssistantActionBar: FC = () => {
return (
<ActionBarPrimitive.Root
hideWhenRunning
autohide="not-last"
autohideFloat="single-branch"
className="aui-assistant-action-bar-root col-start-3 row-start-2 -ml-1 flex gap-1 text-muted-foreground data-floating:absolute data-floating:rounded-md data-floating:border data-floating:bg-background data-floating:p-1 data-floating:shadow-sm"
>
<ActionBarPrimitive.Copy asChild>
<TooltipIconButton tooltip="Copy">
<MessagePrimitive.If copied>
<CheckIcon />
</MessagePrimitive.If>
<MessagePrimitive.If copied={false}>
<CopyIcon />
</MessagePrimitive.If>
</TooltipIconButton>
</ActionBarPrimitive.Copy>
<ActionBarPrimitive.Reload asChild>
<TooltipIconButton tooltip="Refresh">
<RefreshCwIcon />
</TooltipIconButton>
</ActionBarPrimitive.Reload>
</ActionBarPrimitive.Root>
);
};
const UserMessage: FC = () => {
return (
<MessagePrimitive.Root asChild>
<div
className="aui-user-message-root mx-auto grid w-full max-w-[var(--thread-max-width)] animate-in auto-rows-auto grid-cols-[minmax(72px,1fr)_auto] gap-y-2 px-2 py-4 duration-150 ease-out fade-in slide-in-from-bottom-1 first:mt-3 last:mb-5 [&:where(>*)]:col-start-2"
data-role="user"
>
<UserMessageAttachments />
<div className="aui-user-message-content-wrapper relative col-start-2 min-w-0">
<div className="aui-user-message-content rounded-3xl bg-muted px-5 py-2.5 break-words text-foreground">
<MessagePrimitive.Parts />
</div>
<div className="aui-user-action-bar-wrapper absolute top-1/2 left-0 -translate-x-full -translate-y-1/2 pr-2">
<UserActionBar />
</div>
</div>
<BranchPicker className="aui-user-branch-picker col-span-full col-start-1 row-start-3 -mr-1 justify-end" />
</div>
</MessagePrimitive.Root>
);
};
const UserActionBar: FC = () => {
return (
<ActionBarPrimitive.Root
hideWhenRunning
autohide="not-last"
className="aui-user-action-bar-root flex flex-col items-end"
>
<ActionBarPrimitive.Edit asChild>
<TooltipIconButton tooltip="Edit" className="aui-user-action-edit p-4">
<PencilIcon />
</TooltipIconButton>
</ActionBarPrimitive.Edit>
</ActionBarPrimitive.Root>
);
};
const EditComposer: FC = () => {
return (
<div className="aui-edit-composer-wrapper mx-auto flex w-full max-w-[var(--thread-max-width)] flex-col gap-4 px-2 first:mt-4">
<ComposerPrimitive.Root className="aui-edit-composer-root ml-auto flex w-full max-w-7/8 flex-col rounded-xl bg-muted">
<ComposerPrimitive.Input
className="aui-edit-composer-input flex min-h-[60px] w-full resize-none bg-transparent p-4 text-foreground outline-none"
autoFocus
/>
<div className="aui-edit-composer-footer mx-3 mb-3 flex items-center justify-center gap-2 self-end">
<ComposerPrimitive.Cancel asChild>
<Button variant="ghost" size="sm" aria-label="Cancel edit">
Cancel
</Button>
</ComposerPrimitive.Cancel>
<ComposerPrimitive.Send asChild>
<Button size="sm" aria-label="Update message">
Update
</Button>
</ComposerPrimitive.Send>
</div>
</ComposerPrimitive.Root>
</div>
);
};
const BranchPicker: FC<BranchPickerPrimitive.Root.Props> = ({
className,
...rest
}) => {
return (
<BranchPickerPrimitive.Root
hideWhenSingleBranch
className={cn(
"aui-branch-picker-root mr-2 -ml-2 inline-flex items-center text-xs text-muted-foreground",
className,
)}
{...rest}
>
<BranchPickerPrimitive.Previous asChild>
<TooltipIconButton tooltip="Previous">
<ChevronLeftIcon />
</TooltipIconButton>
</BranchPickerPrimitive.Previous>
<span className="aui-branch-picker-state font-medium">
<BranchPickerPrimitive.Number /> / <BranchPickerPrimitive.Count />
</span>
<BranchPickerPrimitive.Next asChild>
<TooltipIconButton tooltip="Next">
<ChevronRightIcon />
</TooltipIconButton>
</BranchPickerPrimitive.Next>
</BranchPickerPrimitive.Root>
);
};