@tetrascience-npm/tetrascience-react-ui 0.5.0-beta.40.1 → 0.5.0-beta.42.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/ai/attachments.cjs +2 -0
- package/dist/components/ai/attachments.cjs.map +1 -0
- package/dist/components/ai/attachments.js +224 -0
- package/dist/components/ai/attachments.js.map +1 -0
- package/dist/components/ai/chain-of-thought.cjs +2 -0
- package/dist/components/ai/chain-of-thought.cjs.map +1 -0
- package/dist/components/ai/chain-of-thought.js +145 -0
- package/dist/components/ai/chain-of-thought.js.map +1 -0
- package/dist/components/ai/confirmation.cjs +2 -0
- package/dist/components/ai/confirmation.cjs.map +1 -0
- package/dist/components/ai/confirmation.js +109 -0
- package/dist/components/ai/confirmation.js.map +1 -0
- package/dist/components/ai/context.cjs +2 -0
- package/dist/components/ai/context.cjs.map +1 -0
- package/dist/components/ai/context.js +266 -0
- package/dist/components/ai/context.js.map +1 -0
- package/dist/components/ai/conversation.cjs +4 -0
- package/dist/components/ai/conversation.cjs.map +1 -0
- package/dist/components/ai/conversation.js +108 -0
- package/dist/components/ai/conversation.js.map +1 -0
- package/dist/components/ai/inline-citation.cjs +2 -0
- package/dist/components/ai/inline-citation.cjs.map +1 -0
- package/dist/components/ai/inline-citation.js +182 -0
- package/dist/components/ai/inline-citation.js.map +1 -0
- package/dist/components/ai/message.cjs +2 -0
- package/dist/components/ai/message.cjs.map +1 -0
- package/dist/components/ai/message.js +237 -0
- package/dist/components/ai/message.js.map +1 -0
- package/dist/components/ai/model-selector.cjs +2 -0
- package/dist/components/ai/model-selector.cjs.map +1 -0
- package/dist/components/ai/model-selector.js +77 -0
- package/dist/components/ai/model-selector.js.map +1 -0
- package/dist/components/ai/prompt-input.cjs +2 -0
- package/dist/components/ai/prompt-input.cjs.map +1 -0
- package/dist/components/ai/prompt-input.js +774 -0
- package/dist/components/ai/prompt-input.js.map +1 -0
- package/dist/components/ai/queue.cjs +2 -0
- package/dist/components/ai/queue.cjs.map +1 -0
- package/dist/components/ai/queue.js +209 -0
- package/dist/components/ai/queue.js.map +1 -0
- package/dist/components/ai/reasoning.cjs +2 -0
- package/dist/components/ai/reasoning.cjs.map +1 -0
- package/dist/components/ai/reasoning.js +129 -0
- package/dist/components/ai/reasoning.js.map +1 -0
- package/dist/components/ai/shimmer.cjs +2 -0
- package/dist/components/ai/shimmer.cjs.map +1 -0
- package/dist/components/ai/shimmer.js +49 -0
- package/dist/components/ai/shimmer.js.map +1 -0
- package/dist/components/ai/sources.cjs +2 -0
- package/dist/components/ai/sources.cjs.map +1 -0
- package/dist/components/ai/sources.js +54 -0
- package/dist/components/ai/sources.js.map +1 -0
- package/dist/components/ai/speech-input.cjs +2 -0
- package/dist/components/ai/speech-input.cjs.map +1 -0
- package/dist/components/ai/speech-input.js +123 -0
- package/dist/components/ai/speech-input.js.map +1 -0
- package/dist/components/ai/stream-status.cjs +2 -0
- package/dist/components/ai/stream-status.cjs.map +1 -0
- package/dist/components/ai/stream-status.js +106 -0
- package/dist/components/ai/stream-status.js.map +1 -0
- package/dist/components/ai/suggestion.cjs +2 -0
- package/dist/components/ai/suggestion.cjs.map +1 -0
- package/dist/components/ai/suggestion.js +38 -0
- package/dist/components/ai/suggestion.js.map +1 -0
- package/dist/components/ai/task.cjs +2 -0
- package/dist/components/ai/task.cjs.map +1 -0
- package/dist/components/ai/task.js +94 -0
- package/dist/components/ai/task.js.map +1 -0
- package/dist/components/ai/tool.cjs +2 -0
- package/dist/components/ai/tool.cjs.map +1 -0
- package/dist/components/ai/tool.js +143 -0
- package/dist/components/ai/tool.js.map +1 -0
- package/dist/components/composed/Chat/Chat.cjs +2 -0
- package/dist/components/composed/Chat/Chat.cjs.map +1 -0
- package/dist/components/composed/Chat/Chat.js +167 -0
- package/dist/components/composed/Chat/Chat.js.map +1 -0
- package/dist/components/ui/code-block.cjs +4 -0
- package/dist/components/ui/code-block.cjs.map +1 -0
- package/dist/components/ui/code-block.js +306 -0
- package/dist/components/ui/code-block.js.map +1 -0
- package/dist/components/ui/data-table/data-table-filter.cjs +2 -0
- package/dist/components/ui/data-table/data-table-filter.cjs.map +1 -0
- package/dist/components/ui/data-table/data-table-filter.js +178 -0
- package/dist/components/ui/data-table/data-table-filter.js.map +1 -0
- package/dist/components/ui/data-table/data-table.cjs +1 -1
- package/dist/components/ui/data-table/data-table.cjs.map +1 -1
- package/dist/components/ui/data-table/data-table.js +244 -195
- package/dist/components/ui/data-table/data-table.js.map +1 -1
- package/dist/components/ui/progress.cjs +2 -0
- package/dist/components/ui/progress.cjs.map +1 -0
- package/dist/components/ui/progress.js +32 -0
- package/dist/components/ui/progress.js.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.css +1 -1
- package/dist/index.d.ts +1182 -1
- package/dist/index.js +572 -368
- package/dist/index.js.map +1 -1
- package/dist/index.tailwind.css +1 -1
- package/package.json +12 -1
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("react/jsx-runtime"),a=require("lucide-react"),u=require("react"),A=require("../ui/button.cjs"),h=require("../ui/hover-card.cjs"),i=require("../../lib/utils.cjs"),y={audio:a.Music2Icon,document:a.FileTextIcon,image:a.ImageIcon,source:a.GlobeIcon,unknown:a.PaperclipIcon,video:a.VideoIcon},x=e=>{if(e.type==="source-document")return"source";const t=e.mediaType??"";return t.startsWith("image/")?"image":t.startsWith("video/")?"video":t.startsWith("audio/")?"audio":t.startsWith("application/")||t.startsWith("text/")?"document":"unknown"},v=e=>{if(e.type==="source-document")return e.title||e.filename||"Source";const t=x(e);return e.filename||(t==="image"?"Image":"Attachment")},j=(e,t,r)=>r?n.jsx("img",{alt:t||"Image",className:"size-full object-cover",height:96,src:e,width:96}):n.jsx("img",{alt:t||"Image",className:"size-full rounded object-cover",height:20,src:e,width:20}),p=u.createContext(null),f=u.createContext(null),b=()=>u.useContext(p)??{variant:"grid"},m=()=>{const e=u.useContext(f);if(!e)throw new Error("Attachment components must be used within <Attachment>");return e},I=({variant:e="grid",className:t,children:r,...o})=>{const s=u.useMemo(()=>({variant:e}),[e]);return n.jsx(p.Provider,{value:s,children:n.jsx("div",{className:i.cn("flex items-start",e==="list"?"flex-col gap-2":"flex-wrap gap-2",e==="grid"&&"ml-auto w-fit",t),...o,children:r})})},w=({data:e,onRemove:t,className:r,children:o,...s})=>{const{variant:c}=b(),l=x(e),d=u.useMemo(()=>({data:e,mediaCategory:l,onRemove:t,variant:c}),[e,l,t,c]);return n.jsx(f.Provider,{value:d,children:n.jsx("div",{className:i.cn("group relative",c==="grid"&&"size-24 overflow-hidden rounded-lg",c==="inline"&&["flex h-8 cursor-pointer select-none items-center gap-1.5","rounded-md border border-border px-1.5","font-medium text-sm transition-all","hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50"],c==="list"&&["flex w-full items-center gap-3 rounded-lg border p-3","hover:bg-accent/50"],r),...s,children:o})})},z=({fallbackIcon:e,className:t,...r})=>{const{data:o,mediaCategory:s,variant:c}=m(),l=c==="inline"?"size-3":"size-4",d=g=>n.jsx(g,{className:i.cn(l,"text-muted-foreground")}),C=()=>{if(s==="image"&&o.type==="file"&&o.url)return j(o.url,o.filename,c==="grid");if(s==="video"&&o.type==="file"&&o.url)return n.jsx("video",{className:"size-full object-cover",muted:!0,src:o.url});const g=y[s];return e??d(g)};return n.jsx("div",{className:i.cn("flex shrink-0 items-center justify-center overflow-hidden",c==="grid"&&"size-full bg-muted",c==="inline"&&"size-5 rounded bg-background",c==="list"&&"size-12 rounded bg-muted",t),...r,children:C()})},N=({showMediaType:e=!1,className:t,...r})=>{const{data:o,variant:s}=m(),c=v(o);return s==="grid"?null:n.jsxs("div",{className:i.cn("min-w-0 flex-1",t),...r,children:[n.jsx("span",{className:"block truncate",children:c}),e&&o.mediaType&&n.jsx("span",{className:"block truncate text-muted-foreground text-xs",children:o.mediaType})]})},k=({label:e="Remove",className:t,children:r,...o})=>{const{onRemove:s,variant:c}=m(),l=u.useCallback(d=>{d.stopPropagation(),s?.()},[s]);return s?n.jsxs(A.Button,{"aria-label":e,className:i.cn(c==="grid"&&["absolute top-2 right-2 size-6 rounded-full p-0","bg-background/80 backdrop-blur-sm","opacity-0 transition-opacity group-hover:opacity-100","hover:bg-background","[&>svg]:size-3"],c==="inline"&&["size-5 rounded p-0","opacity-0 transition-opacity group-hover:opacity-100","[&>svg]:size-2.5"],c==="list"&&["size-8 shrink-0 rounded p-0","[&>svg]:size-4"],t),onClick:l,type:"button",variant:"ghost",...o,children:[r??n.jsx(a.XIcon,{}),n.jsx("span",{className:"sr-only",children:e})]}):null},H=({openDelay:e=0,closeDelay:t=0,...r})=>n.jsx(h.HoverCard,{closeDelay:t,openDelay:e,...r}),T=e=>n.jsx(h.HoverCardTrigger,{...e}),P=({align:e="start",className:t,...r})=>n.jsx(h.HoverCardContent,{align:e,className:i.cn("w-auto p-2",t),...r}),q=({className:e,children:t,...r})=>n.jsx("div",{className:i.cn("flex items-center justify-center p-4 text-muted-foreground text-sm",e),...r,children:t??"No attachments"});exports.Attachment=w;exports.AttachmentEmpty=q;exports.AttachmentHoverCard=H;exports.AttachmentHoverCardContent=P;exports.AttachmentHoverCardTrigger=T;exports.AttachmentInfo=N;exports.AttachmentPreview=z;exports.AttachmentRemove=k;exports.Attachments=I;exports.getAttachmentLabel=v;exports.getMediaCategory=x;exports.useAttachmentContext=m;exports.useAttachmentsContext=b;
|
|
2
|
+
//# sourceMappingURL=attachments.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attachments.cjs","sources":["../../../src/components/ai/attachments.tsx"],"sourcesContent":["import {\n FileTextIcon,\n GlobeIcon,\n ImageIcon,\n Music2Icon,\n PaperclipIcon,\n VideoIcon,\n XIcon,\n} from \"lucide-react\";\nimport { createContext, useCallback, useContext, useMemo } from \"react\";\n\nimport type { FileUIPart, SourceDocumentUIPart } from \"ai\";\nimport type { ComponentProps, HTMLAttributes, ReactNode } from \"react\";\n\nimport { Button } from \"@/components/ui/button\";\nimport {\n HoverCard,\n HoverCardContent,\n HoverCardTrigger,\n} from \"@/components/ui/hover-card\";\nimport { cn } from \"@/lib/utils\";\n\n\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type AttachmentData =\n | (FileUIPart & { id: string })\n | (SourceDocumentUIPart & { id: string });\n\nexport type AttachmentMediaCategory =\n | \"image\"\n | \"video\"\n | \"audio\"\n | \"document\"\n | \"source\"\n | \"unknown\";\n\nexport type AttachmentVariant = \"grid\" | \"inline\" | \"list\";\n\nconst mediaCategoryIcons: Record<AttachmentMediaCategory, typeof ImageIcon> = {\n audio: Music2Icon,\n document: FileTextIcon,\n image: ImageIcon,\n source: GlobeIcon,\n unknown: PaperclipIcon,\n video: VideoIcon,\n};\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\nexport const getMediaCategory = (\n data: AttachmentData\n): AttachmentMediaCategory => {\n if (data.type === \"source-document\") {\n return \"source\";\n }\n\n const mediaType = data.mediaType ?? \"\";\n\n if (mediaType.startsWith(\"image/\")) {\n return \"image\";\n }\n if (mediaType.startsWith(\"video/\")) {\n return \"video\";\n }\n if (mediaType.startsWith(\"audio/\")) {\n return \"audio\";\n }\n if (mediaType.startsWith(\"application/\") || mediaType.startsWith(\"text/\")) {\n return \"document\";\n }\n\n return \"unknown\";\n};\n\nexport const getAttachmentLabel = (data: AttachmentData): string => {\n if (data.type === \"source-document\") {\n return data.title || data.filename || \"Source\";\n }\n\n const category = getMediaCategory(data);\n return data.filename || (category === \"image\" ? \"Image\" : \"Attachment\");\n};\n\nconst renderAttachmentImage = (\n url: string,\n filename: string | undefined,\n isGrid: boolean\n) =>\n isGrid ? (\n <img\n alt={filename || \"Image\"}\n className=\"size-full object-cover\"\n height={96}\n src={url}\n width={96}\n />\n ) : (\n <img\n alt={filename || \"Image\"}\n className=\"size-full rounded object-cover\"\n height={20}\n src={url}\n width={20}\n />\n );\n\n// ============================================================================\n// Contexts\n// ============================================================================\n\ninterface AttachmentsContextValue {\n variant: AttachmentVariant;\n}\n\nconst AttachmentsContext = createContext<AttachmentsContextValue | null>(null);\n\ninterface AttachmentContextValue {\n data: AttachmentData;\n mediaCategory: AttachmentMediaCategory;\n onRemove?: () => void;\n variant: AttachmentVariant;\n}\n\nconst AttachmentContext = createContext<AttachmentContextValue | null>(null);\n\n// ============================================================================\n// Hooks\n// ============================================================================\n\nexport const useAttachmentsContext = () =>\n useContext(AttachmentsContext) ?? { variant: \"grid\" as const };\n\nexport const useAttachmentContext = () => {\n const ctx = useContext(AttachmentContext);\n if (!ctx) {\n throw new Error(\"Attachment components must be used within <Attachment>\");\n }\n return ctx;\n};\n\n// ============================================================================\n// Attachments - Container\n// ============================================================================\n\nexport type AttachmentsProps = HTMLAttributes<HTMLDivElement> & {\n variant?: AttachmentVariant;\n};\n\nexport const Attachments = ({\n variant = \"grid\",\n className,\n children,\n ...props\n}: AttachmentsProps) => {\n const contextValue = useMemo(() => ({ variant }), [variant]);\n\n return (\n <AttachmentsContext.Provider value={contextValue}>\n <div\n className={cn(\n \"flex items-start\",\n variant === \"list\" ? \"flex-col gap-2\" : \"flex-wrap gap-2\",\n variant === \"grid\" && \"ml-auto w-fit\",\n className\n )}\n {...props}\n >\n {children}\n </div>\n </AttachmentsContext.Provider>\n );\n};\n\n// ============================================================================\n// Attachment - Item\n// ============================================================================\n\nexport type AttachmentProps = HTMLAttributes<HTMLDivElement> & {\n data: AttachmentData;\n onRemove?: () => void;\n};\n\nexport const Attachment = ({\n data,\n onRemove,\n className,\n children,\n ...props\n}: AttachmentProps) => {\n const { variant } = useAttachmentsContext();\n const mediaCategory = getMediaCategory(data);\n\n const contextValue = useMemo<AttachmentContextValue>(\n () => ({ data, mediaCategory, onRemove, variant }),\n [data, mediaCategory, onRemove, variant]\n );\n\n return (\n <AttachmentContext.Provider value={contextValue}>\n <div\n className={cn(\n \"group relative\",\n variant === \"grid\" && \"size-24 overflow-hidden rounded-lg\",\n variant === \"inline\" && [\n \"flex h-8 cursor-pointer select-none items-center gap-1.5\",\n \"rounded-md border border-border px-1.5\",\n \"font-medium text-sm transition-all\",\n \"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50\",\n ],\n variant === \"list\" && [\n \"flex w-full items-center gap-3 rounded-lg border p-3\",\n \"hover:bg-accent/50\",\n ],\n className\n )}\n {...props}\n >\n {children}\n </div>\n </AttachmentContext.Provider>\n );\n};\n\n// ============================================================================\n// AttachmentPreview - Media preview\n// ============================================================================\n\nexport type AttachmentPreviewProps = HTMLAttributes<HTMLDivElement> & {\n fallbackIcon?: ReactNode;\n};\n\nexport const AttachmentPreview = ({\n fallbackIcon,\n className,\n ...props\n}: AttachmentPreviewProps) => {\n const { data, mediaCategory, variant } = useAttachmentContext();\n\n const iconSize = variant === \"inline\" ? \"size-3\" : \"size-4\";\n\n const renderIcon = (Icon: typeof ImageIcon) => (\n <Icon className={cn(iconSize, \"text-muted-foreground\")} />\n );\n\n const renderContent = () => {\n if (mediaCategory === \"image\" && data.type === \"file\" && data.url) {\n return renderAttachmentImage(data.url, data.filename, variant === \"grid\");\n }\n\n if (mediaCategory === \"video\" && data.type === \"file\" && data.url) {\n return <video className=\"size-full object-cover\" muted src={data.url} />;\n }\n\n const Icon = mediaCategoryIcons[mediaCategory];\n return fallbackIcon ?? renderIcon(Icon);\n };\n\n return (\n <div\n className={cn(\n \"flex shrink-0 items-center justify-center overflow-hidden\",\n variant === \"grid\" && \"size-full bg-muted\",\n variant === \"inline\" && \"size-5 rounded bg-background\",\n variant === \"list\" && \"size-12 rounded bg-muted\",\n className\n )}\n {...props}\n >\n {renderContent()}\n </div>\n );\n};\n\n// ============================================================================\n// AttachmentInfo - Name and type display\n// ============================================================================\n\nexport type AttachmentInfoProps = HTMLAttributes<HTMLDivElement> & {\n showMediaType?: boolean;\n};\n\nexport const AttachmentInfo = ({\n showMediaType = false,\n className,\n ...props\n}: AttachmentInfoProps) => {\n const { data, variant } = useAttachmentContext();\n const label = getAttachmentLabel(data);\n\n if (variant === \"grid\") {\n return null;\n }\n\n return (\n <div className={cn(\"min-w-0 flex-1\", className)} {...props}>\n <span className=\"block truncate\">{label}</span>\n {showMediaType && data.mediaType && (\n <span className=\"block truncate text-muted-foreground text-xs\">\n {data.mediaType}\n </span>\n )}\n </div>\n );\n};\n\n// ============================================================================\n// AttachmentRemove - Remove button\n// ============================================================================\n\nexport type AttachmentRemoveProps = ComponentProps<typeof Button> & {\n label?: string;\n};\n\nexport const AttachmentRemove = ({\n label = \"Remove\",\n className,\n children,\n ...props\n}: AttachmentRemoveProps) => {\n const { onRemove, variant } = useAttachmentContext();\n\n const handleClick = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onRemove?.();\n },\n [onRemove]\n );\n\n if (!onRemove) {\n return null;\n }\n\n return (\n <Button\n aria-label={label}\n className={cn(\n variant === \"grid\" && [\n \"absolute top-2 right-2 size-6 rounded-full p-0\",\n \"bg-background/80 backdrop-blur-sm\",\n \"opacity-0 transition-opacity group-hover:opacity-100\",\n \"hover:bg-background\",\n \"[&>svg]:size-3\",\n ],\n variant === \"inline\" && [\n \"size-5 rounded p-0\",\n \"opacity-0 transition-opacity group-hover:opacity-100\",\n \"[&>svg]:size-2.5\",\n ],\n variant === \"list\" && [\"size-8 shrink-0 rounded p-0\", \"[&>svg]:size-4\"],\n className\n )}\n onClick={handleClick}\n type=\"button\"\n variant=\"ghost\"\n {...props}\n >\n {children ?? <XIcon />}\n <span className=\"sr-only\">{label}</span>\n </Button>\n );\n};\n\n// ============================================================================\n// AttachmentHoverCard - Hover preview\n// ============================================================================\n\nexport type AttachmentHoverCardProps = ComponentProps<typeof HoverCard>;\n\nexport const AttachmentHoverCard = ({\n openDelay = 0,\n closeDelay = 0,\n ...props\n}: AttachmentHoverCardProps) => (\n <HoverCard closeDelay={closeDelay} openDelay={openDelay} {...props} />\n);\n\nexport type AttachmentHoverCardTriggerProps = ComponentProps<\n typeof HoverCardTrigger\n>;\n\nexport const AttachmentHoverCardTrigger = (\n props: AttachmentHoverCardTriggerProps\n) => <HoverCardTrigger {...props} />;\n\nexport type AttachmentHoverCardContentProps = ComponentProps<\n typeof HoverCardContent\n>;\n\nexport const AttachmentHoverCardContent = ({\n align = \"start\",\n className,\n ...props\n}: AttachmentHoverCardContentProps) => (\n <HoverCardContent\n align={align}\n className={cn(\"w-auto p-2\", className)}\n {...props}\n />\n);\n\n// ============================================================================\n// AttachmentEmpty - Empty state\n// ============================================================================\n\nexport type AttachmentEmptyProps = HTMLAttributes<HTMLDivElement>;\n\nexport const AttachmentEmpty = ({\n className,\n children,\n ...props\n}: AttachmentEmptyProps) => (\n <div\n className={cn(\n \"flex items-center justify-center p-4 text-muted-foreground text-sm\",\n className\n )}\n {...props}\n >\n {children ?? \"No attachments\"}\n </div>\n);\n"],"names":["mediaCategoryIcons","Music2Icon","FileTextIcon","ImageIcon","GlobeIcon","PaperclipIcon","VideoIcon","getMediaCategory","data","mediaType","getAttachmentLabel","category","renderAttachmentImage","url","filename","isGrid","jsx","AttachmentsContext","createContext","AttachmentContext","useAttachmentsContext","useContext","useAttachmentContext","ctx","Attachments","variant","className","children","props","contextValue","useMemo","cn","Attachment","onRemove","mediaCategory","AttachmentPreview","fallbackIcon","iconSize","renderIcon","Icon","renderContent","AttachmentInfo","showMediaType","label","jsxs","AttachmentRemove","handleClick","useCallback","e","Button","XIcon","AttachmentHoverCard","openDelay","closeDelay","HoverCard","AttachmentHoverCardTrigger","HoverCardTrigger","AttachmentHoverCardContent","align","HoverCardContent","AttachmentEmpty"],"mappings":"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"}
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import { jsx as i, jsxs as m } from "react/jsx-runtime";
|
|
2
|
+
import { XIcon as y, VideoIcon as C, PaperclipIcon as A, GlobeIcon as z, ImageIcon as I, FileTextIcon as w, Music2Icon as N } from "lucide-react";
|
|
3
|
+
import { createContext as g, useMemo as h, useCallback as k, useContext as p } from "react";
|
|
4
|
+
import { Button as j } from "../ui/button.js";
|
|
5
|
+
import { HoverCard as T, HoverCardContent as H, HoverCardTrigger as P } from "../ui/hover-card.js";
|
|
6
|
+
import { cn as s } from "../../lib/utils.js";
|
|
7
|
+
const W = {
|
|
8
|
+
audio: N,
|
|
9
|
+
document: w,
|
|
10
|
+
image: I,
|
|
11
|
+
source: z,
|
|
12
|
+
unknown: A,
|
|
13
|
+
video: C
|
|
14
|
+
}, f = (e) => {
|
|
15
|
+
if (e.type === "source-document")
|
|
16
|
+
return "source";
|
|
17
|
+
const t = e.mediaType ?? "";
|
|
18
|
+
return t.startsWith("image/") ? "image" : t.startsWith("video/") ? "video" : t.startsWith("audio/") ? "audio" : t.startsWith("application/") || t.startsWith("text/") ? "document" : "unknown";
|
|
19
|
+
}, M = (e) => {
|
|
20
|
+
if (e.type === "source-document")
|
|
21
|
+
return e.title || e.filename || "Source";
|
|
22
|
+
const t = f(e);
|
|
23
|
+
return e.filename || (t === "image" ? "Image" : "Attachment");
|
|
24
|
+
}, V = (e, t, r) => r ? /* @__PURE__ */ i(
|
|
25
|
+
"img",
|
|
26
|
+
{
|
|
27
|
+
alt: t || "Image",
|
|
28
|
+
className: "size-full object-cover",
|
|
29
|
+
height: 96,
|
|
30
|
+
src: e,
|
|
31
|
+
width: 96
|
|
32
|
+
}
|
|
33
|
+
) : /* @__PURE__ */ i(
|
|
34
|
+
"img",
|
|
35
|
+
{
|
|
36
|
+
alt: t || "Image",
|
|
37
|
+
className: "size-full rounded object-cover",
|
|
38
|
+
height: 20,
|
|
39
|
+
src: e,
|
|
40
|
+
width: 20
|
|
41
|
+
}
|
|
42
|
+
), v = g(null), x = g(null), E = () => p(v) ?? { variant: "grid" }, u = () => {
|
|
43
|
+
const e = p(x);
|
|
44
|
+
if (!e)
|
|
45
|
+
throw new Error("Attachment components must be used within <Attachment>");
|
|
46
|
+
return e;
|
|
47
|
+
}, X = ({
|
|
48
|
+
variant: e = "grid",
|
|
49
|
+
className: t,
|
|
50
|
+
children: r,
|
|
51
|
+
...n
|
|
52
|
+
}) => {
|
|
53
|
+
const c = h(() => ({ variant: e }), [e]);
|
|
54
|
+
return /* @__PURE__ */ i(v.Provider, { value: c, children: /* @__PURE__ */ i(
|
|
55
|
+
"div",
|
|
56
|
+
{
|
|
57
|
+
className: s(
|
|
58
|
+
"flex items-start",
|
|
59
|
+
e === "list" ? "flex-col gap-2" : "flex-wrap gap-2",
|
|
60
|
+
e === "grid" && "ml-auto w-fit",
|
|
61
|
+
t
|
|
62
|
+
),
|
|
63
|
+
...n,
|
|
64
|
+
children: r
|
|
65
|
+
}
|
|
66
|
+
) });
|
|
67
|
+
}, q = ({
|
|
68
|
+
data: e,
|
|
69
|
+
onRemove: t,
|
|
70
|
+
className: r,
|
|
71
|
+
children: n,
|
|
72
|
+
...c
|
|
73
|
+
}) => {
|
|
74
|
+
const { variant: o } = E(), a = f(e), l = h(
|
|
75
|
+
() => ({ data: e, mediaCategory: a, onRemove: t, variant: o }),
|
|
76
|
+
[e, a, t, o]
|
|
77
|
+
);
|
|
78
|
+
return /* @__PURE__ */ i(x.Provider, { value: l, children: /* @__PURE__ */ i(
|
|
79
|
+
"div",
|
|
80
|
+
{
|
|
81
|
+
className: s(
|
|
82
|
+
"group relative",
|
|
83
|
+
o === "grid" && "size-24 overflow-hidden rounded-lg",
|
|
84
|
+
o === "inline" && [
|
|
85
|
+
"flex h-8 cursor-pointer select-none items-center gap-1.5",
|
|
86
|
+
"rounded-md border border-border px-1.5",
|
|
87
|
+
"font-medium text-sm transition-all",
|
|
88
|
+
"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50"
|
|
89
|
+
],
|
|
90
|
+
o === "list" && [
|
|
91
|
+
"flex w-full items-center gap-3 rounded-lg border p-3",
|
|
92
|
+
"hover:bg-accent/50"
|
|
93
|
+
],
|
|
94
|
+
r
|
|
95
|
+
),
|
|
96
|
+
...c,
|
|
97
|
+
children: n
|
|
98
|
+
}
|
|
99
|
+
) });
|
|
100
|
+
}, D = ({
|
|
101
|
+
fallbackIcon: e,
|
|
102
|
+
className: t,
|
|
103
|
+
...r
|
|
104
|
+
}) => {
|
|
105
|
+
const { data: n, mediaCategory: c, variant: o } = u(), a = o === "inline" ? "size-3" : "size-4", l = (d) => /* @__PURE__ */ i(d, { className: s(a, "text-muted-foreground") }), b = () => {
|
|
106
|
+
if (c === "image" && n.type === "file" && n.url)
|
|
107
|
+
return V(n.url, n.filename, o === "grid");
|
|
108
|
+
if (c === "video" && n.type === "file" && n.url)
|
|
109
|
+
return /* @__PURE__ */ i("video", { className: "size-full object-cover", muted: !0, src: n.url });
|
|
110
|
+
const d = W[c];
|
|
111
|
+
return e ?? l(d);
|
|
112
|
+
};
|
|
113
|
+
return /* @__PURE__ */ i(
|
|
114
|
+
"div",
|
|
115
|
+
{
|
|
116
|
+
className: s(
|
|
117
|
+
"flex shrink-0 items-center justify-center overflow-hidden",
|
|
118
|
+
o === "grid" && "size-full bg-muted",
|
|
119
|
+
o === "inline" && "size-5 rounded bg-background",
|
|
120
|
+
o === "list" && "size-12 rounded bg-muted",
|
|
121
|
+
t
|
|
122
|
+
),
|
|
123
|
+
...r,
|
|
124
|
+
children: b()
|
|
125
|
+
}
|
|
126
|
+
);
|
|
127
|
+
}, J = ({
|
|
128
|
+
showMediaType: e = !1,
|
|
129
|
+
className: t,
|
|
130
|
+
...r
|
|
131
|
+
}) => {
|
|
132
|
+
const { data: n, variant: c } = u(), o = M(n);
|
|
133
|
+
return c === "grid" ? null : /* @__PURE__ */ m("div", { className: s("min-w-0 flex-1", t), ...r, children: [
|
|
134
|
+
/* @__PURE__ */ i("span", { className: "block truncate", children: o }),
|
|
135
|
+
e && n.mediaType && /* @__PURE__ */ i("span", { className: "block truncate text-muted-foreground text-xs", children: n.mediaType })
|
|
136
|
+
] });
|
|
137
|
+
}, K = ({
|
|
138
|
+
label: e = "Remove",
|
|
139
|
+
className: t,
|
|
140
|
+
children: r,
|
|
141
|
+
...n
|
|
142
|
+
}) => {
|
|
143
|
+
const { onRemove: c, variant: o } = u(), a = k(
|
|
144
|
+
(l) => {
|
|
145
|
+
l.stopPropagation(), c?.();
|
|
146
|
+
},
|
|
147
|
+
[c]
|
|
148
|
+
);
|
|
149
|
+
return c ? /* @__PURE__ */ m(
|
|
150
|
+
j,
|
|
151
|
+
{
|
|
152
|
+
"aria-label": e,
|
|
153
|
+
className: s(
|
|
154
|
+
o === "grid" && [
|
|
155
|
+
"absolute top-2 right-2 size-6 rounded-full p-0",
|
|
156
|
+
"bg-background/80 backdrop-blur-sm",
|
|
157
|
+
"opacity-0 transition-opacity group-hover:opacity-100",
|
|
158
|
+
"hover:bg-background",
|
|
159
|
+
"[&>svg]:size-3"
|
|
160
|
+
],
|
|
161
|
+
o === "inline" && [
|
|
162
|
+
"size-5 rounded p-0",
|
|
163
|
+
"opacity-0 transition-opacity group-hover:opacity-100",
|
|
164
|
+
"[&>svg]:size-2.5"
|
|
165
|
+
],
|
|
166
|
+
o === "list" && ["size-8 shrink-0 rounded p-0", "[&>svg]:size-4"],
|
|
167
|
+
t
|
|
168
|
+
),
|
|
169
|
+
onClick: a,
|
|
170
|
+
type: "button",
|
|
171
|
+
variant: "ghost",
|
|
172
|
+
...n,
|
|
173
|
+
children: [
|
|
174
|
+
r ?? /* @__PURE__ */ i(y, {}),
|
|
175
|
+
/* @__PURE__ */ i("span", { className: "sr-only", children: e })
|
|
176
|
+
]
|
|
177
|
+
}
|
|
178
|
+
) : null;
|
|
179
|
+
}, O = ({
|
|
180
|
+
openDelay: e = 0,
|
|
181
|
+
closeDelay: t = 0,
|
|
182
|
+
...r
|
|
183
|
+
}) => /* @__PURE__ */ i(T, { closeDelay: t, openDelay: e, ...r }), Q = (e) => /* @__PURE__ */ i(P, { ...e }), U = ({
|
|
184
|
+
align: e = "start",
|
|
185
|
+
className: t,
|
|
186
|
+
...r
|
|
187
|
+
}) => /* @__PURE__ */ i(
|
|
188
|
+
H,
|
|
189
|
+
{
|
|
190
|
+
align: e,
|
|
191
|
+
className: s("w-auto p-2", t),
|
|
192
|
+
...r
|
|
193
|
+
}
|
|
194
|
+
), Y = ({
|
|
195
|
+
className: e,
|
|
196
|
+
children: t,
|
|
197
|
+
...r
|
|
198
|
+
}) => /* @__PURE__ */ i(
|
|
199
|
+
"div",
|
|
200
|
+
{
|
|
201
|
+
className: s(
|
|
202
|
+
"flex items-center justify-center p-4 text-muted-foreground text-sm",
|
|
203
|
+
e
|
|
204
|
+
),
|
|
205
|
+
...r,
|
|
206
|
+
children: t ?? "No attachments"
|
|
207
|
+
}
|
|
208
|
+
);
|
|
209
|
+
export {
|
|
210
|
+
q as Attachment,
|
|
211
|
+
Y as AttachmentEmpty,
|
|
212
|
+
O as AttachmentHoverCard,
|
|
213
|
+
U as AttachmentHoverCardContent,
|
|
214
|
+
Q as AttachmentHoverCardTrigger,
|
|
215
|
+
J as AttachmentInfo,
|
|
216
|
+
D as AttachmentPreview,
|
|
217
|
+
K as AttachmentRemove,
|
|
218
|
+
X as Attachments,
|
|
219
|
+
M as getAttachmentLabel,
|
|
220
|
+
f as getMediaCategory,
|
|
221
|
+
u as useAttachmentContext,
|
|
222
|
+
E as useAttachmentsContext
|
|
223
|
+
};
|
|
224
|
+
//# sourceMappingURL=attachments.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attachments.js","sources":["../../../src/components/ai/attachments.tsx"],"sourcesContent":["import {\n FileTextIcon,\n GlobeIcon,\n ImageIcon,\n Music2Icon,\n PaperclipIcon,\n VideoIcon,\n XIcon,\n} from \"lucide-react\";\nimport { createContext, useCallback, useContext, useMemo } from \"react\";\n\nimport type { FileUIPart, SourceDocumentUIPart } from \"ai\";\nimport type { ComponentProps, HTMLAttributes, ReactNode } from \"react\";\n\nimport { Button } from \"@/components/ui/button\";\nimport {\n HoverCard,\n HoverCardContent,\n HoverCardTrigger,\n} from \"@/components/ui/hover-card\";\nimport { cn } from \"@/lib/utils\";\n\n\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type AttachmentData =\n | (FileUIPart & { id: string })\n | (SourceDocumentUIPart & { id: string });\n\nexport type AttachmentMediaCategory =\n | \"image\"\n | \"video\"\n | \"audio\"\n | \"document\"\n | \"source\"\n | \"unknown\";\n\nexport type AttachmentVariant = \"grid\" | \"inline\" | \"list\";\n\nconst mediaCategoryIcons: Record<AttachmentMediaCategory, typeof ImageIcon> = {\n audio: Music2Icon,\n document: FileTextIcon,\n image: ImageIcon,\n source: GlobeIcon,\n unknown: PaperclipIcon,\n video: VideoIcon,\n};\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\nexport const getMediaCategory = (\n data: AttachmentData\n): AttachmentMediaCategory => {\n if (data.type === \"source-document\") {\n return \"source\";\n }\n\n const mediaType = data.mediaType ?? \"\";\n\n if (mediaType.startsWith(\"image/\")) {\n return \"image\";\n }\n if (mediaType.startsWith(\"video/\")) {\n return \"video\";\n }\n if (mediaType.startsWith(\"audio/\")) {\n return \"audio\";\n }\n if (mediaType.startsWith(\"application/\") || mediaType.startsWith(\"text/\")) {\n return \"document\";\n }\n\n return \"unknown\";\n};\n\nexport const getAttachmentLabel = (data: AttachmentData): string => {\n if (data.type === \"source-document\") {\n return data.title || data.filename || \"Source\";\n }\n\n const category = getMediaCategory(data);\n return data.filename || (category === \"image\" ? \"Image\" : \"Attachment\");\n};\n\nconst renderAttachmentImage = (\n url: string,\n filename: string | undefined,\n isGrid: boolean\n) =>\n isGrid ? (\n <img\n alt={filename || \"Image\"}\n className=\"size-full object-cover\"\n height={96}\n src={url}\n width={96}\n />\n ) : (\n <img\n alt={filename || \"Image\"}\n className=\"size-full rounded object-cover\"\n height={20}\n src={url}\n width={20}\n />\n );\n\n// ============================================================================\n// Contexts\n// ============================================================================\n\ninterface AttachmentsContextValue {\n variant: AttachmentVariant;\n}\n\nconst AttachmentsContext = createContext<AttachmentsContextValue | null>(null);\n\ninterface AttachmentContextValue {\n data: AttachmentData;\n mediaCategory: AttachmentMediaCategory;\n onRemove?: () => void;\n variant: AttachmentVariant;\n}\n\nconst AttachmentContext = createContext<AttachmentContextValue | null>(null);\n\n// ============================================================================\n// Hooks\n// ============================================================================\n\nexport const useAttachmentsContext = () =>\n useContext(AttachmentsContext) ?? { variant: \"grid\" as const };\n\nexport const useAttachmentContext = () => {\n const ctx = useContext(AttachmentContext);\n if (!ctx) {\n throw new Error(\"Attachment components must be used within <Attachment>\");\n }\n return ctx;\n};\n\n// ============================================================================\n// Attachments - Container\n// ============================================================================\n\nexport type AttachmentsProps = HTMLAttributes<HTMLDivElement> & {\n variant?: AttachmentVariant;\n};\n\nexport const Attachments = ({\n variant = \"grid\",\n className,\n children,\n ...props\n}: AttachmentsProps) => {\n const contextValue = useMemo(() => ({ variant }), [variant]);\n\n return (\n <AttachmentsContext.Provider value={contextValue}>\n <div\n className={cn(\n \"flex items-start\",\n variant === \"list\" ? \"flex-col gap-2\" : \"flex-wrap gap-2\",\n variant === \"grid\" && \"ml-auto w-fit\",\n className\n )}\n {...props}\n >\n {children}\n </div>\n </AttachmentsContext.Provider>\n );\n};\n\n// ============================================================================\n// Attachment - Item\n// ============================================================================\n\nexport type AttachmentProps = HTMLAttributes<HTMLDivElement> & {\n data: AttachmentData;\n onRemove?: () => void;\n};\n\nexport const Attachment = ({\n data,\n onRemove,\n className,\n children,\n ...props\n}: AttachmentProps) => {\n const { variant } = useAttachmentsContext();\n const mediaCategory = getMediaCategory(data);\n\n const contextValue = useMemo<AttachmentContextValue>(\n () => ({ data, mediaCategory, onRemove, variant }),\n [data, mediaCategory, onRemove, variant]\n );\n\n return (\n <AttachmentContext.Provider value={contextValue}>\n <div\n className={cn(\n \"group relative\",\n variant === \"grid\" && \"size-24 overflow-hidden rounded-lg\",\n variant === \"inline\" && [\n \"flex h-8 cursor-pointer select-none items-center gap-1.5\",\n \"rounded-md border border-border px-1.5\",\n \"font-medium text-sm transition-all\",\n \"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50\",\n ],\n variant === \"list\" && [\n \"flex w-full items-center gap-3 rounded-lg border p-3\",\n \"hover:bg-accent/50\",\n ],\n className\n )}\n {...props}\n >\n {children}\n </div>\n </AttachmentContext.Provider>\n );\n};\n\n// ============================================================================\n// AttachmentPreview - Media preview\n// ============================================================================\n\nexport type AttachmentPreviewProps = HTMLAttributes<HTMLDivElement> & {\n fallbackIcon?: ReactNode;\n};\n\nexport const AttachmentPreview = ({\n fallbackIcon,\n className,\n ...props\n}: AttachmentPreviewProps) => {\n const { data, mediaCategory, variant } = useAttachmentContext();\n\n const iconSize = variant === \"inline\" ? \"size-3\" : \"size-4\";\n\n const renderIcon = (Icon: typeof ImageIcon) => (\n <Icon className={cn(iconSize, \"text-muted-foreground\")} />\n );\n\n const renderContent = () => {\n if (mediaCategory === \"image\" && data.type === \"file\" && data.url) {\n return renderAttachmentImage(data.url, data.filename, variant === \"grid\");\n }\n\n if (mediaCategory === \"video\" && data.type === \"file\" && data.url) {\n return <video className=\"size-full object-cover\" muted src={data.url} />;\n }\n\n const Icon = mediaCategoryIcons[mediaCategory];\n return fallbackIcon ?? renderIcon(Icon);\n };\n\n return (\n <div\n className={cn(\n \"flex shrink-0 items-center justify-center overflow-hidden\",\n variant === \"grid\" && \"size-full bg-muted\",\n variant === \"inline\" && \"size-5 rounded bg-background\",\n variant === \"list\" && \"size-12 rounded bg-muted\",\n className\n )}\n {...props}\n >\n {renderContent()}\n </div>\n );\n};\n\n// ============================================================================\n// AttachmentInfo - Name and type display\n// ============================================================================\n\nexport type AttachmentInfoProps = HTMLAttributes<HTMLDivElement> & {\n showMediaType?: boolean;\n};\n\nexport const AttachmentInfo = ({\n showMediaType = false,\n className,\n ...props\n}: AttachmentInfoProps) => {\n const { data, variant } = useAttachmentContext();\n const label = getAttachmentLabel(data);\n\n if (variant === \"grid\") {\n return null;\n }\n\n return (\n <div className={cn(\"min-w-0 flex-1\", className)} {...props}>\n <span className=\"block truncate\">{label}</span>\n {showMediaType && data.mediaType && (\n <span className=\"block truncate text-muted-foreground text-xs\">\n {data.mediaType}\n </span>\n )}\n </div>\n );\n};\n\n// ============================================================================\n// AttachmentRemove - Remove button\n// ============================================================================\n\nexport type AttachmentRemoveProps = ComponentProps<typeof Button> & {\n label?: string;\n};\n\nexport const AttachmentRemove = ({\n label = \"Remove\",\n className,\n children,\n ...props\n}: AttachmentRemoveProps) => {\n const { onRemove, variant } = useAttachmentContext();\n\n const handleClick = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onRemove?.();\n },\n [onRemove]\n );\n\n if (!onRemove) {\n return null;\n }\n\n return (\n <Button\n aria-label={label}\n className={cn(\n variant === \"grid\" && [\n \"absolute top-2 right-2 size-6 rounded-full p-0\",\n \"bg-background/80 backdrop-blur-sm\",\n \"opacity-0 transition-opacity group-hover:opacity-100\",\n \"hover:bg-background\",\n \"[&>svg]:size-3\",\n ],\n variant === \"inline\" && [\n \"size-5 rounded p-0\",\n \"opacity-0 transition-opacity group-hover:opacity-100\",\n \"[&>svg]:size-2.5\",\n ],\n variant === \"list\" && [\"size-8 shrink-0 rounded p-0\", \"[&>svg]:size-4\"],\n className\n )}\n onClick={handleClick}\n type=\"button\"\n variant=\"ghost\"\n {...props}\n >\n {children ?? <XIcon />}\n <span className=\"sr-only\">{label}</span>\n </Button>\n );\n};\n\n// ============================================================================\n// AttachmentHoverCard - Hover preview\n// ============================================================================\n\nexport type AttachmentHoverCardProps = ComponentProps<typeof HoverCard>;\n\nexport const AttachmentHoverCard = ({\n openDelay = 0,\n closeDelay = 0,\n ...props\n}: AttachmentHoverCardProps) => (\n <HoverCard closeDelay={closeDelay} openDelay={openDelay} {...props} />\n);\n\nexport type AttachmentHoverCardTriggerProps = ComponentProps<\n typeof HoverCardTrigger\n>;\n\nexport const AttachmentHoverCardTrigger = (\n props: AttachmentHoverCardTriggerProps\n) => <HoverCardTrigger {...props} />;\n\nexport type AttachmentHoverCardContentProps = ComponentProps<\n typeof HoverCardContent\n>;\n\nexport const AttachmentHoverCardContent = ({\n align = \"start\",\n className,\n ...props\n}: AttachmentHoverCardContentProps) => (\n <HoverCardContent\n align={align}\n className={cn(\"w-auto p-2\", className)}\n {...props}\n />\n);\n\n// ============================================================================\n// AttachmentEmpty - Empty state\n// ============================================================================\n\nexport type AttachmentEmptyProps = HTMLAttributes<HTMLDivElement>;\n\nexport const AttachmentEmpty = ({\n className,\n children,\n ...props\n}: AttachmentEmptyProps) => (\n <div\n className={cn(\n \"flex items-center justify-center p-4 text-muted-foreground text-sm\",\n className\n )}\n {...props}\n >\n {children ?? \"No attachments\"}\n </div>\n);\n"],"names":["mediaCategoryIcons","Music2Icon","FileTextIcon","ImageIcon","GlobeIcon","PaperclipIcon","VideoIcon","getMediaCategory","data","mediaType","getAttachmentLabel","category","renderAttachmentImage","url","filename","isGrid","jsx","AttachmentsContext","createContext","AttachmentContext","useAttachmentsContext","useContext","useAttachmentContext","ctx","Attachments","variant","className","children","props","contextValue","useMemo","cn","Attachment","onRemove","mediaCategory","AttachmentPreview","fallbackIcon","iconSize","renderIcon","Icon","renderContent","AttachmentInfo","showMediaType","label","jsxs","AttachmentRemove","handleClick","useCallback","e","Button","XIcon","AttachmentHoverCard","openDelay","closeDelay","HoverCard","AttachmentHoverCardTrigger","HoverCardTrigger","AttachmentHoverCardContent","align","HoverCardContent","AttachmentEmpty"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),l=require("lucide-react"),i=require("../ui/collapsible.cjs"),s=require("../../lib/utils.cjs"),h=({className:t,defaultOpen:a=!0,...o})=>e.jsx(i.Collapsible,{className:s.cn("overflow-hidden rounded-lg text-sm",t),defaultOpen:a,...o}),u=({className:t,children:a,title:o="Chain of Thought",icon:r,isStreaming:n=!1,...p})=>e.jsx(i.CollapsibleTrigger,{className:s.cn("group flex w-full items-center gap-2 text-muted-foreground text-sm transition-colors hover:text-foreground",t),...p,children:a??e.jsxs(e.Fragment,{children:[r??e.jsx(l.Brain,{className:"size-4 text-muted-foreground"}),e.jsxs("span",{className:"flex-1 text-left items-center gap-2",children:[o,n&&e.jsx("span",{className:"size-1.5 animate-pulse rounded-full bg-primary"})]}),e.jsx(l.ChevronUpIcon,{className:"size-4 text-muted-foreground opacity-0 transition-all group-focus-visible:opacity-100 group-hover:opacity-100 group-data-[state=open]:opacity-100 group-data-[state=closed]:rotate-180","data-slot":"collapsible-chevron"})]})}),c=({className:t,...a})=>e.jsx(i.CollapsibleContent,{className:s.cn("flex flex-col gap-2.5 pb-4 pt-3","data-[state=closed]:animate-out data-[state=open]:animate-in","data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0","data-[state=closed]:slide-out-to-top-1 data-[state=open]:slide-in-from-top-1",t),...a}),x={bullet:e.jsx("span",{className:"mt-[7px] ml-1 size-1.5 shrink-0 rounded-full bg-muted-foreground/50"}),search:e.jsx(l.SearchIcon,{className:"mt-0.5 w-[18px] size-3.5 shrink-0 text-muted-foreground"}),image:e.jsx(l.ImageIcon,{className:"mt-0.5 size-3.5 shrink-0 text-muted-foreground"})},d=({variant:t="bullet",className:a,children:o,...r})=>{const n=typeof t=="string"?x[t]:t;return e.jsxs("div",{className:s.cn("flex items-start gap-2 text-muted-foreground",a),...r,children:[e.jsx("span",{className:"flex shrink-0",children:n}),e.jsx("span",{className:"min-w-0 flex-1 leading-relaxed",children:o})]})},g=({className:t,...a})=>e.jsx("div",{className:s.cn("ml-[6px] flex flex-wrap gap-1.5 border-l-2 border-muted-foreground/20 py-0.5 pl-3",t),...a}),m=({className:t,children:a,...o})=>e.jsx("a",{className:s.cn("inline-flex items-center rounded-full border border-border/60 bg-muted/50 px-2 py-0.5 text-xs text-muted-foreground transition-colors",o.href&&"cursor-pointer hover:bg-muted hover:text-foreground",t),rel:"noreferrer",target:"_blank",...o,children:a}),f=({src:t,alt:a="",caption:o,className:r,...n})=>e.jsxs("figure",{className:s.cn("ml-[22px] overflow-hidden rounded-lg border",r),...n,children:[e.jsx("img",{alt:a,className:"max-h-64 w-full object-cover",src:t}),o&&e.jsx("figcaption",{className:"border-t px-3 py-2 text-xs italic text-muted-foreground/70",children:o})]});h.displayName="ChainOfThought";u.displayName="ChainOfThoughtTrigger";c.displayName="ChainOfThoughtContent";d.displayName="ChainOfThoughtStep";g.displayName="ChainOfThoughtSources";m.displayName="ChainOfThoughtSource";f.displayName="ChainOfThoughtImage";exports.ChainOfThought=h;exports.ChainOfThoughtContent=c;exports.ChainOfThoughtImage=f;exports.ChainOfThoughtSource=m;exports.ChainOfThoughtSources=g;exports.ChainOfThoughtStep=d;exports.ChainOfThoughtTrigger=u;
|
|
2
|
+
//# sourceMappingURL=chain-of-thought.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chain-of-thought.cjs","sources":["../../../src/components/ai/chain-of-thought.tsx"],"sourcesContent":["import { Brain, ChevronUpIcon, ImageIcon, SearchIcon } from \"lucide-react\";\n\nimport type { ComponentProps, ReactNode } from \"react\";\n\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from \"@/components/ui/collapsible\";\nimport { cn } from \"@/lib/utils\";\n\n// ---------------------------------------------------------------------------\n// ChainOfThought (root)\n// ---------------------------------------------------------------------------\n\nexport type ChainOfThoughtProps = ComponentProps<typeof Collapsible>;\n\nexport const ChainOfThought = ({\n className,\n defaultOpen = true,\n ...props\n}: ChainOfThoughtProps) => (\n <Collapsible\n className={cn(\"overflow-hidden rounded-lg text-sm\", className)}\n defaultOpen={defaultOpen}\n {...props}\n />\n);\n\n// ---------------------------------------------------------------------------\n// ChainOfThoughtTrigger\n// ---------------------------------------------------------------------------\n\nexport type ChainOfThoughtTriggerProps = ComponentProps<typeof CollapsibleTrigger> & {\n title?: string;\n icon?: ReactNode;\n /** When true, renders a subtle animated dot next to the title. */\n isStreaming?: boolean;\n};\n\nexport const ChainOfThoughtTrigger = ({\n className,\n children,\n title = \"Chain of Thought\",\n icon,\n isStreaming = false,\n ...props\n}: ChainOfThoughtTriggerProps) => (\n <CollapsibleTrigger\n className={cn(\n \"group flex w-full items-center gap-2 text-muted-foreground text-sm transition-colors hover:text-foreground\",\n className\n )}\n {...props}\n >\n {children ?? (\n <>\n {icon ?? <Brain className=\"size-4 text-muted-foreground\" />}\n <span className=\"flex-1 text-left items-center gap-2\">\n {title}\n {isStreaming && (\n <span className=\"size-1.5 animate-pulse rounded-full bg-primary\" />\n )}\n </span>\n <ChevronUpIcon\n className=\"size-4 text-muted-foreground opacity-0 transition-all group-focus-visible:opacity-100 group-hover:opacity-100 group-data-[state=open]:opacity-100 group-data-[state=closed]:rotate-180\"\n data-slot=\"collapsible-chevron\"\n />\n </>\n )}\n </CollapsibleTrigger>\n);\n\n// ---------------------------------------------------------------------------\n// ChainOfThoughtContent\n// ---------------------------------------------------------------------------\n\nexport type ChainOfThoughtContentProps = ComponentProps<typeof CollapsibleContent>;\n\nexport const ChainOfThoughtContent = ({\n className,\n ...props\n}: ChainOfThoughtContentProps) => (\n <CollapsibleContent\n className={cn(\n \"flex flex-col gap-2.5 pb-4 pt-3\",\n \"data-[state=closed]:animate-out data-[state=open]:animate-in\",\n \"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n \"data-[state=closed]:slide-out-to-top-1 data-[state=open]:slide-in-from-top-1\",\n className\n )}\n {...props}\n />\n);\n\n// ---------------------------------------------------------------------------\n// ChainOfThoughtStep\n// ---------------------------------------------------------------------------\n\nexport type ChainOfThoughtStepVariant = \"bullet\" | \"search\" | \"image\";\n\nexport type ChainOfThoughtStepProps = ComponentProps<\"div\"> & {\n /**\n * Visual prefix for the step.\n * - `\"bullet\"` — small dot (default, plain reasoning text)\n * - `\"search\"` — magnifying-glass (web search / tool call)\n * - `\"image\"` — image icon (image fetch / vision step)\n * - ReactNode — custom icon\n */\n variant?: ChainOfThoughtStepVariant | ReactNode;\n};\n\nconst STEP_ICONS: Record<ChainOfThoughtStepVariant, ReactNode> = {\n bullet: (\n <span className=\"mt-[7px] ml-1 size-1.5 shrink-0 rounded-full bg-muted-foreground/50\" />\n ),\n search: <SearchIcon className=\"mt-0.5 w-[18px] size-3.5 shrink-0 text-muted-foreground\" />,\n image: <ImageIcon className=\"mt-0.5 size-3.5 shrink-0 text-muted-foreground\" />,\n};\n\nexport const ChainOfThoughtStep = ({\n variant = \"bullet\",\n className,\n children,\n ...props\n}: ChainOfThoughtStepProps) => {\n const icon =\n typeof variant === \"string\"\n ? STEP_ICONS[variant as ChainOfThoughtStepVariant]\n : variant;\n\n return (\n <div\n className={cn(\"flex items-start gap-2 text-muted-foreground\", className)}\n {...props}\n >\n <span className=\"flex shrink-0\">{icon}</span>\n <span className=\"min-w-0 flex-1 leading-relaxed\">{children}</span>\n </div>\n );\n};\n\n// ---------------------------------------------------------------------------\n// ChainOfThoughtSources — inline chip group with left bar\n// ---------------------------------------------------------------------------\n\nexport type ChainOfThoughtSourcesProps = ComponentProps<\"div\">;\n\nexport const ChainOfThoughtSources = ({\n className,\n ...props\n}: ChainOfThoughtSourcesProps) => (\n <div\n className={cn(\n \"ml-[6px] flex flex-wrap gap-1.5 border-l-2 border-muted-foreground/20 py-0.5 pl-3\",\n className\n )}\n {...props}\n />\n);\n\nexport type ChainOfThoughtSourceProps = ComponentProps<\"a\">;\n\nexport const ChainOfThoughtSource = ({\n className,\n children,\n ...props\n}: ChainOfThoughtSourceProps) => (\n <a\n className={cn(\n \"inline-flex items-center rounded-full border border-border/60 bg-muted/50 px-2 py-0.5 text-xs text-muted-foreground transition-colors\",\n props.href && \"cursor-pointer hover:bg-muted hover:text-foreground\",\n className\n )}\n rel=\"noreferrer\"\n target=\"_blank\"\n {...props}\n >\n {children}\n </a>\n);\n\n// ---------------------------------------------------------------------------\n// ChainOfThoughtImage — inline image with optional caption\n// ---------------------------------------------------------------------------\n\nexport type ChainOfThoughtImageProps = ComponentProps<\"figure\"> & {\n src: string;\n alt?: string;\n caption?: string;\n};\n\nexport const ChainOfThoughtImage = ({\n src,\n alt = \"\",\n caption,\n className,\n ...props\n}: ChainOfThoughtImageProps) => (\n <figure\n className={cn(\"ml-[22px] overflow-hidden rounded-lg border\", className)}\n {...props}\n >\n <img alt={alt} className=\"max-h-64 w-full object-cover\" src={src} />\n {caption && (\n <figcaption className=\"border-t px-3 py-2 text-xs italic text-muted-foreground/70\">\n {caption}\n </figcaption>\n )}\n </figure>\n);\n\nChainOfThought.displayName = \"ChainOfThought\";\nChainOfThoughtTrigger.displayName = \"ChainOfThoughtTrigger\";\nChainOfThoughtContent.displayName = \"ChainOfThoughtContent\";\nChainOfThoughtStep.displayName = \"ChainOfThoughtStep\";\nChainOfThoughtSources.displayName = \"ChainOfThoughtSources\";\nChainOfThoughtSource.displayName = \"ChainOfThoughtSource\";\nChainOfThoughtImage.displayName = \"ChainOfThoughtImage\";\n"],"names":["ChainOfThought","className","defaultOpen","props","jsx","Collapsible","cn","ChainOfThoughtTrigger","children","title","icon","isStreaming","CollapsibleTrigger","jsxs","Fragment","Brain","ChevronUpIcon","ChainOfThoughtContent","CollapsibleContent","STEP_ICONS","SearchIcon","ImageIcon","ChainOfThoughtStep","variant","ChainOfThoughtSources","ChainOfThoughtSource","ChainOfThoughtImage","src","alt","caption"],"mappings":"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"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { jsx as t, jsxs as l, Fragment as d } from "react/jsx-runtime";
|
|
2
|
+
import { Brain as m, ChevronUpIcon as u, ImageIcon as h, SearchIcon as c } from "lucide-react";
|
|
3
|
+
import { Collapsible as g, CollapsibleContent as f, CollapsibleTrigger as p } from "../ui/collapsible.js";
|
|
4
|
+
import { cn as r } from "../../lib/utils.js";
|
|
5
|
+
const x = ({
|
|
6
|
+
className: e,
|
|
7
|
+
defaultOpen: a = !0,
|
|
8
|
+
...o
|
|
9
|
+
}) => /* @__PURE__ */ t(
|
|
10
|
+
g,
|
|
11
|
+
{
|
|
12
|
+
className: r("overflow-hidden rounded-lg text-sm", e),
|
|
13
|
+
defaultOpen: a,
|
|
14
|
+
...o
|
|
15
|
+
}
|
|
16
|
+
), N = ({
|
|
17
|
+
className: e,
|
|
18
|
+
children: a,
|
|
19
|
+
title: o = "Chain of Thought",
|
|
20
|
+
icon: s,
|
|
21
|
+
isStreaming: n = !1,
|
|
22
|
+
...i
|
|
23
|
+
}) => /* @__PURE__ */ t(
|
|
24
|
+
p,
|
|
25
|
+
{
|
|
26
|
+
className: r(
|
|
27
|
+
"group flex w-full items-center gap-2 text-muted-foreground text-sm transition-colors hover:text-foreground",
|
|
28
|
+
e
|
|
29
|
+
),
|
|
30
|
+
...i,
|
|
31
|
+
children: a ?? /* @__PURE__ */ l(d, { children: [
|
|
32
|
+
s ?? /* @__PURE__ */ t(m, { className: "size-4 text-muted-foreground" }),
|
|
33
|
+
/* @__PURE__ */ l("span", { className: "flex-1 text-left items-center gap-2", children: [
|
|
34
|
+
o,
|
|
35
|
+
n && /* @__PURE__ */ t("span", { className: "size-1.5 animate-pulse rounded-full bg-primary" })
|
|
36
|
+
] }),
|
|
37
|
+
/* @__PURE__ */ t(
|
|
38
|
+
u,
|
|
39
|
+
{
|
|
40
|
+
className: "size-4 text-muted-foreground opacity-0 transition-all group-focus-visible:opacity-100 group-hover:opacity-100 group-data-[state=open]:opacity-100 group-data-[state=closed]:rotate-180",
|
|
41
|
+
"data-slot": "collapsible-chevron"
|
|
42
|
+
}
|
|
43
|
+
)
|
|
44
|
+
] })
|
|
45
|
+
}
|
|
46
|
+
), C = ({
|
|
47
|
+
className: e,
|
|
48
|
+
...a
|
|
49
|
+
}) => /* @__PURE__ */ t(
|
|
50
|
+
f,
|
|
51
|
+
{
|
|
52
|
+
className: r(
|
|
53
|
+
"flex flex-col gap-2.5 pb-4 pt-3",
|
|
54
|
+
"data-[state=closed]:animate-out data-[state=open]:animate-in",
|
|
55
|
+
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
56
|
+
"data-[state=closed]:slide-out-to-top-1 data-[state=open]:slide-in-from-top-1",
|
|
57
|
+
e
|
|
58
|
+
),
|
|
59
|
+
...a
|
|
60
|
+
}
|
|
61
|
+
), b = {
|
|
62
|
+
bullet: /* @__PURE__ */ t("span", { className: "mt-[7px] ml-1 size-1.5 shrink-0 rounded-full bg-muted-foreground/50" }),
|
|
63
|
+
search: /* @__PURE__ */ t(c, { className: "mt-0.5 w-[18px] size-3.5 shrink-0 text-muted-foreground" }),
|
|
64
|
+
image: /* @__PURE__ */ t(h, { className: "mt-0.5 size-3.5 shrink-0 text-muted-foreground" })
|
|
65
|
+
}, T = ({
|
|
66
|
+
variant: e = "bullet",
|
|
67
|
+
className: a,
|
|
68
|
+
children: o,
|
|
69
|
+
...s
|
|
70
|
+
}) => {
|
|
71
|
+
const n = typeof e == "string" ? b[e] : e;
|
|
72
|
+
return /* @__PURE__ */ l(
|
|
73
|
+
"div",
|
|
74
|
+
{
|
|
75
|
+
className: r("flex items-start gap-2 text-muted-foreground", a),
|
|
76
|
+
...s,
|
|
77
|
+
children: [
|
|
78
|
+
/* @__PURE__ */ t("span", { className: "flex shrink-0", children: n }),
|
|
79
|
+
/* @__PURE__ */ t("span", { className: "min-w-0 flex-1 leading-relaxed", children: o })
|
|
80
|
+
]
|
|
81
|
+
}
|
|
82
|
+
);
|
|
83
|
+
}, y = ({
|
|
84
|
+
className: e,
|
|
85
|
+
...a
|
|
86
|
+
}) => /* @__PURE__ */ t(
|
|
87
|
+
"div",
|
|
88
|
+
{
|
|
89
|
+
className: r(
|
|
90
|
+
"ml-[6px] flex flex-wrap gap-1.5 border-l-2 border-muted-foreground/20 py-0.5 pl-3",
|
|
91
|
+
e
|
|
92
|
+
),
|
|
93
|
+
...a
|
|
94
|
+
}
|
|
95
|
+
), O = ({
|
|
96
|
+
className: e,
|
|
97
|
+
children: a,
|
|
98
|
+
...o
|
|
99
|
+
}) => /* @__PURE__ */ t(
|
|
100
|
+
"a",
|
|
101
|
+
{
|
|
102
|
+
className: r(
|
|
103
|
+
"inline-flex items-center rounded-full border border-border/60 bg-muted/50 px-2 py-0.5 text-xs text-muted-foreground transition-colors",
|
|
104
|
+
o.href && "cursor-pointer hover:bg-muted hover:text-foreground",
|
|
105
|
+
e
|
|
106
|
+
),
|
|
107
|
+
rel: "noreferrer",
|
|
108
|
+
target: "_blank",
|
|
109
|
+
...o,
|
|
110
|
+
children: a
|
|
111
|
+
}
|
|
112
|
+
), v = ({
|
|
113
|
+
src: e,
|
|
114
|
+
alt: a = "",
|
|
115
|
+
caption: o,
|
|
116
|
+
className: s,
|
|
117
|
+
...n
|
|
118
|
+
}) => /* @__PURE__ */ l(
|
|
119
|
+
"figure",
|
|
120
|
+
{
|
|
121
|
+
className: r("ml-[22px] overflow-hidden rounded-lg border", s),
|
|
122
|
+
...n,
|
|
123
|
+
children: [
|
|
124
|
+
/* @__PURE__ */ t("img", { alt: a, className: "max-h-64 w-full object-cover", src: e }),
|
|
125
|
+
o && /* @__PURE__ */ t("figcaption", { className: "border-t px-3 py-2 text-xs italic text-muted-foreground/70", children: o })
|
|
126
|
+
]
|
|
127
|
+
}
|
|
128
|
+
);
|
|
129
|
+
x.displayName = "ChainOfThought";
|
|
130
|
+
N.displayName = "ChainOfThoughtTrigger";
|
|
131
|
+
C.displayName = "ChainOfThoughtContent";
|
|
132
|
+
T.displayName = "ChainOfThoughtStep";
|
|
133
|
+
y.displayName = "ChainOfThoughtSources";
|
|
134
|
+
O.displayName = "ChainOfThoughtSource";
|
|
135
|
+
v.displayName = "ChainOfThoughtImage";
|
|
136
|
+
export {
|
|
137
|
+
x as ChainOfThought,
|
|
138
|
+
C as ChainOfThoughtContent,
|
|
139
|
+
v as ChainOfThoughtImage,
|
|
140
|
+
O as ChainOfThoughtSource,
|
|
141
|
+
y as ChainOfThoughtSources,
|
|
142
|
+
T as ChainOfThoughtStep,
|
|
143
|
+
N as ChainOfThoughtTrigger
|
|
144
|
+
};
|
|
145
|
+
//# sourceMappingURL=chain-of-thought.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chain-of-thought.js","sources":["../../../src/components/ai/chain-of-thought.tsx"],"sourcesContent":["import { Brain, ChevronUpIcon, ImageIcon, SearchIcon } from \"lucide-react\";\n\nimport type { ComponentProps, ReactNode } from \"react\";\n\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from \"@/components/ui/collapsible\";\nimport { cn } from \"@/lib/utils\";\n\n// ---------------------------------------------------------------------------\n// ChainOfThought (root)\n// ---------------------------------------------------------------------------\n\nexport type ChainOfThoughtProps = ComponentProps<typeof Collapsible>;\n\nexport const ChainOfThought = ({\n className,\n defaultOpen = true,\n ...props\n}: ChainOfThoughtProps) => (\n <Collapsible\n className={cn(\"overflow-hidden rounded-lg text-sm\", className)}\n defaultOpen={defaultOpen}\n {...props}\n />\n);\n\n// ---------------------------------------------------------------------------\n// ChainOfThoughtTrigger\n// ---------------------------------------------------------------------------\n\nexport type ChainOfThoughtTriggerProps = ComponentProps<typeof CollapsibleTrigger> & {\n title?: string;\n icon?: ReactNode;\n /** When true, renders a subtle animated dot next to the title. */\n isStreaming?: boolean;\n};\n\nexport const ChainOfThoughtTrigger = ({\n className,\n children,\n title = \"Chain of Thought\",\n icon,\n isStreaming = false,\n ...props\n}: ChainOfThoughtTriggerProps) => (\n <CollapsibleTrigger\n className={cn(\n \"group flex w-full items-center gap-2 text-muted-foreground text-sm transition-colors hover:text-foreground\",\n className\n )}\n {...props}\n >\n {children ?? (\n <>\n {icon ?? <Brain className=\"size-4 text-muted-foreground\" />}\n <span className=\"flex-1 text-left items-center gap-2\">\n {title}\n {isStreaming && (\n <span className=\"size-1.5 animate-pulse rounded-full bg-primary\" />\n )}\n </span>\n <ChevronUpIcon\n className=\"size-4 text-muted-foreground opacity-0 transition-all group-focus-visible:opacity-100 group-hover:opacity-100 group-data-[state=open]:opacity-100 group-data-[state=closed]:rotate-180\"\n data-slot=\"collapsible-chevron\"\n />\n </>\n )}\n </CollapsibleTrigger>\n);\n\n// ---------------------------------------------------------------------------\n// ChainOfThoughtContent\n// ---------------------------------------------------------------------------\n\nexport type ChainOfThoughtContentProps = ComponentProps<typeof CollapsibleContent>;\n\nexport const ChainOfThoughtContent = ({\n className,\n ...props\n}: ChainOfThoughtContentProps) => (\n <CollapsibleContent\n className={cn(\n \"flex flex-col gap-2.5 pb-4 pt-3\",\n \"data-[state=closed]:animate-out data-[state=open]:animate-in\",\n \"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n \"data-[state=closed]:slide-out-to-top-1 data-[state=open]:slide-in-from-top-1\",\n className\n )}\n {...props}\n />\n);\n\n// ---------------------------------------------------------------------------\n// ChainOfThoughtStep\n// ---------------------------------------------------------------------------\n\nexport type ChainOfThoughtStepVariant = \"bullet\" | \"search\" | \"image\";\n\nexport type ChainOfThoughtStepProps = ComponentProps<\"div\"> & {\n /**\n * Visual prefix for the step.\n * - `\"bullet\"` — small dot (default, plain reasoning text)\n * - `\"search\"` — magnifying-glass (web search / tool call)\n * - `\"image\"` — image icon (image fetch / vision step)\n * - ReactNode — custom icon\n */\n variant?: ChainOfThoughtStepVariant | ReactNode;\n};\n\nconst STEP_ICONS: Record<ChainOfThoughtStepVariant, ReactNode> = {\n bullet: (\n <span className=\"mt-[7px] ml-1 size-1.5 shrink-0 rounded-full bg-muted-foreground/50\" />\n ),\n search: <SearchIcon className=\"mt-0.5 w-[18px] size-3.5 shrink-0 text-muted-foreground\" />,\n image: <ImageIcon className=\"mt-0.5 size-3.5 shrink-0 text-muted-foreground\" />,\n};\n\nexport const ChainOfThoughtStep = ({\n variant = \"bullet\",\n className,\n children,\n ...props\n}: ChainOfThoughtStepProps) => {\n const icon =\n typeof variant === \"string\"\n ? STEP_ICONS[variant as ChainOfThoughtStepVariant]\n : variant;\n\n return (\n <div\n className={cn(\"flex items-start gap-2 text-muted-foreground\", className)}\n {...props}\n >\n <span className=\"flex shrink-0\">{icon}</span>\n <span className=\"min-w-0 flex-1 leading-relaxed\">{children}</span>\n </div>\n );\n};\n\n// ---------------------------------------------------------------------------\n// ChainOfThoughtSources — inline chip group with left bar\n// ---------------------------------------------------------------------------\n\nexport type ChainOfThoughtSourcesProps = ComponentProps<\"div\">;\n\nexport const ChainOfThoughtSources = ({\n className,\n ...props\n}: ChainOfThoughtSourcesProps) => (\n <div\n className={cn(\n \"ml-[6px] flex flex-wrap gap-1.5 border-l-2 border-muted-foreground/20 py-0.5 pl-3\",\n className\n )}\n {...props}\n />\n);\n\nexport type ChainOfThoughtSourceProps = ComponentProps<\"a\">;\n\nexport const ChainOfThoughtSource = ({\n className,\n children,\n ...props\n}: ChainOfThoughtSourceProps) => (\n <a\n className={cn(\n \"inline-flex items-center rounded-full border border-border/60 bg-muted/50 px-2 py-0.5 text-xs text-muted-foreground transition-colors\",\n props.href && \"cursor-pointer hover:bg-muted hover:text-foreground\",\n className\n )}\n rel=\"noreferrer\"\n target=\"_blank\"\n {...props}\n >\n {children}\n </a>\n);\n\n// ---------------------------------------------------------------------------\n// ChainOfThoughtImage — inline image with optional caption\n// ---------------------------------------------------------------------------\n\nexport type ChainOfThoughtImageProps = ComponentProps<\"figure\"> & {\n src: string;\n alt?: string;\n caption?: string;\n};\n\nexport const ChainOfThoughtImage = ({\n src,\n alt = \"\",\n caption,\n className,\n ...props\n}: ChainOfThoughtImageProps) => (\n <figure\n className={cn(\"ml-[22px] overflow-hidden rounded-lg border\", className)}\n {...props}\n >\n <img alt={alt} className=\"max-h-64 w-full object-cover\" src={src} />\n {caption && (\n <figcaption className=\"border-t px-3 py-2 text-xs italic text-muted-foreground/70\">\n {caption}\n </figcaption>\n )}\n </figure>\n);\n\nChainOfThought.displayName = \"ChainOfThought\";\nChainOfThoughtTrigger.displayName = \"ChainOfThoughtTrigger\";\nChainOfThoughtContent.displayName = \"ChainOfThoughtContent\";\nChainOfThoughtStep.displayName = \"ChainOfThoughtStep\";\nChainOfThoughtSources.displayName = \"ChainOfThoughtSources\";\nChainOfThoughtSource.displayName = \"ChainOfThoughtSource\";\nChainOfThoughtImage.displayName = \"ChainOfThoughtImage\";\n"],"names":["ChainOfThought","className","defaultOpen","props","jsx","Collapsible","cn","ChainOfThoughtTrigger","children","title","icon","isStreaming","CollapsibleTrigger","jsxs","Fragment","Brain","ChevronUpIcon","ChainOfThoughtContent","CollapsibleContent","STEP_ICONS","SearchIcon","ImageIcon","ChainOfThoughtStep","variant","ChainOfThoughtSources","ChainOfThoughtSource","ChainOfThoughtImage","src","alt","caption"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("react/jsx-runtime"),l=require("motion/react"),i=require("react"),b=require("../ui/button.cjs"),j=require("../ui/code-block.cjs"),v=require("../ui/kbd.cjs"),r=require("../../lib/utils.cjs"),d=i.createContext(null),a=()=>{const e=i.useContext(d);if(!e)throw new Error("Confirmation components must be used within Confirmation");return e},g=1500,h=({className:e,approval:n,state:t,children:m,...c})=>{const f=i.useMemo(()=>({approval:n,state:t}),[n,t]),[p,C]=i.useState(!0),u=n?.approved===!0&&(t==="approval-responded"||t==="output-available"||t==="output-denied");if(i.useEffect(()=>{if(u){const s=setTimeout(()=>C(!1),g);return()=>clearTimeout(s)}},[u]),!n||t==="input-streaming"||t==="input-available")return null;const x=Object.fromEntries(Object.entries(c).filter(([s])=>s.startsWith("data-")||s.startsWith("aria-")));return o.jsx(d.Provider,{value:f,children:o.jsx(l.AnimatePresence,{children:p&&o.jsx(l.motion.div,{...x,className:r.cn("flex flex-col gap-4 rounded-xl border bg-card p-5 shadow-sm",e),exit:{opacity:0,scale:.96},id:c.id,style:c.style,transition:{duration:.5,ease:"easeOut"},children:m})})})},q=({className:e,children:n,...t})=>o.jsx("h3",{className:r.cn("font-semibold text-base text-foreground",e),...t,children:n}),A=({className:e,children:n,...t})=>o.jsx(j.CodeBlock,{className:r.cn(e),...t,language:"bash",code:n?.toString()??""}),y=({children:e})=>{const{state:n}=a();return n!=="approval-requested"?null:o.jsx(o.Fragment,{children:e})},E=({children:e})=>{const{approval:n,state:t}=a();return!n?.approved||t!=="approval-responded"&&t!=="output-denied"&&t!=="output-available"?null:o.jsx(o.Fragment,{children:e})},N=({children:e})=>{const{approval:n,state:t}=a();return n?.approved!==!1||t!=="approval-responded"&&t!=="output-denied"&&t!=="output-available"?null:o.jsx(o.Fragment,{children:e})},R=({className:e,...n})=>{const{state:t}=a();return t!=="approval-requested"?null:o.jsx("div",{className:r.cn("flex items-center justify-between gap-2",e),...n})},S=({className:e,size:n="sm",...t})=>o.jsx(b.Button,{className:r.cn("gap-1.5",e),size:n,type:"button",...t}),T=({className:e,...n})=>o.jsx(v.Kbd,{className:r.cn("ml-0.5",e),...n});exports.Confirmation=h;exports.ConfirmationAccepted=E;exports.ConfirmationAction=S;exports.ConfirmationActions=R;exports.ConfirmationCode=A;exports.ConfirmationRejected=N;exports.ConfirmationRequest=y;exports.ConfirmationShortcut=T;exports.ConfirmationTitle=q;
|
|
2
|
+
//# sourceMappingURL=confirmation.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"confirmation.cjs","sources":["../../../src/components/ai/confirmation.tsx"],"sourcesContent":["import { AnimatePresence, motion } from \"motion/react\";\nimport { createContext, useContext, useEffect, useMemo, useState } from \"react\";\n\n\nimport type { ToolUIPart } from \"ai\";\nimport type { ComponentProps, PropsWithChildren, ReactNode } from \"react\";\n\nimport { Button } from \"@/components/ui/button\";\nimport { CodeBlock } from \"@/components/ui/code-block\";\nimport { Kbd } from \"@/components/ui/kbd\";\nimport { cn } from \"@/lib/utils\";\n\n\ntype ToolUIPartApproval =\n | { id: string; approved?: never; reason?: never }\n | { id: string; approved: boolean; reason?: string }\n | { id: string; approved: true; reason?: string }\n | { id: string; approved: false; reason?: string }\n | undefined;\n\ninterface ConfirmationContextValue {\n approval: ToolUIPartApproval;\n state: ToolUIPart[\"state\"];\n}\n\nconst ConfirmationContext = createContext<ConfirmationContextValue | null>(null);\n\nconst useConfirmation = () => {\n const context = useContext(ConfirmationContext);\n if (!context) {\n throw new Error(\"Confirmation components must be used within Confirmation\");\n }\n return context;\n};\n\n// ---------------------------------------------------------------------------\n// Confirmation (root)\n// ---------------------------------------------------------------------------\n\nexport type ConfirmationProps = ComponentProps<\"div\"> & {\n approval?: ToolUIPartApproval;\n state: ToolUIPart[\"state\"];\n};\n\nconst ACCEPTED_HIDE_DELAY = 1500;\n\nexport const Confirmation = ({\n className,\n approval,\n state,\n children,\n ...props\n}: ConfirmationProps) => {\n const contextValue = useMemo(() => ({ approval, state }), [approval, state]);\n const [visible, setVisible] = useState(true);\n\n const isAccepted =\n approval?.approved === true &&\n (state === \"approval-responded\" ||\n state === \"output-available\" ||\n state === \"output-denied\");\n\n useEffect(() => {\n if (isAccepted) {\n const timer = setTimeout(() => setVisible(false), ACCEPTED_HIDE_DELAY);\n return () => clearTimeout(timer);\n }\n }, [isAccepted]);\n\n if (!approval || state === \"input-streaming\" || state === \"input-available\") {\n return null;\n }\n\n // Pass through data-* and aria-* only; drop event handlers to avoid\n // onDrag type conflict between React and framer-motion.\n const passthroughProps = Object.fromEntries(\n Object.entries(props).filter(([k]) => k.startsWith(\"data-\") || k.startsWith(\"aria-\"))\n );\n\n return (\n <ConfirmationContext.Provider value={contextValue}>\n <AnimatePresence>\n {visible && (\n <motion.div\n {...passthroughProps}\n className={cn(\n \"flex flex-col gap-4 rounded-xl border bg-card p-5 shadow-sm\",\n className\n )}\n exit={{ opacity: 0, scale: 0.96 }}\n id={props.id}\n style={props.style}\n transition={{ duration: 0.5, ease: \"easeOut\" }}\n >\n {children}\n </motion.div>\n )}\n </AnimatePresence>\n </ConfirmationContext.Provider>\n );\n};\n\n// ---------------------------------------------------------------------------\n// ConfirmationTitle\n// ---------------------------------------------------------------------------\n\nexport type ConfirmationTitleProps = PropsWithChildren<ComponentProps<\"h3\">>;\n\nexport const ConfirmationTitle = ({\n className,\n children,\n ...props\n}: ConfirmationTitleProps) => (\n <h3\n className={cn(\"font-semibold text-base text-foreground\", className)}\n {...props}\n >\n {children}\n </h3>\n);\n\n// ---------------------------------------------------------------------------\n// ConfirmationCode — monospace command/code block\n// ---------------------------------------------------------------------------\n\nexport type ConfirmationCodeProps = ComponentProps<typeof CodeBlock>;\n\nexport const ConfirmationCode = ({\n className,\n children,\n ...props\n}: ConfirmationCodeProps) => (\n <CodeBlock className={cn(className)} {...props} language=\"bash\" code={children?.toString() ?? ''} />\n);\n\n// ---------------------------------------------------------------------------\n// ConfirmationRequest / Accepted / Rejected — conditional renderers\n// ---------------------------------------------------------------------------\n\nexport const ConfirmationRequest = ({ children }: { children?: ReactNode }) => {\n const { state } = useConfirmation();\n if (state !== \"approval-requested\") return null;\n return <>{children}</>;\n};\n\nexport const ConfirmationAccepted = ({ children }: { children?: ReactNode }) => {\n const { approval, state } = useConfirmation();\n if (\n !approval?.approved ||\n (state !== \"approval-responded\" &&\n state !== \"output-denied\" &&\n state !== \"output-available\")\n ) {\n return null;\n }\n return <>{children}</>;\n};\n\nexport const ConfirmationRejected = ({ children }: { children?: ReactNode }) => {\n const { approval, state } = useConfirmation();\n if (\n approval?.approved !== false ||\n (state !== \"approval-responded\" &&\n state !== \"output-denied\" &&\n state !== \"output-available\")\n ) {\n return null;\n }\n return <>{children}</>;\n};\n\n// ---------------------------------------------------------------------------\n// ConfirmationActions — deny left, allow buttons right\n// ---------------------------------------------------------------------------\n\nexport type ConfirmationActionsProps = ComponentProps<\"div\">;\n\nexport const ConfirmationActions = ({\n className,\n ...props\n}: ConfirmationActionsProps) => {\n const { state } = useConfirmation();\n if (state !== \"approval-requested\") return null;\n return (\n <div\n className={cn(\"flex items-center justify-between gap-2\", className)}\n {...props}\n />\n );\n};\n\n// ---------------------------------------------------------------------------\n// ConfirmationAction — individual button\n// ---------------------------------------------------------------------------\n\nexport type ConfirmationActionProps = ComponentProps<typeof Button>;\n\nexport const ConfirmationAction = ({\n className,\n size = \"sm\",\n ...props\n}: ConfirmationActionProps) => (\n <Button\n className={cn(\"gap-1.5\", className)}\n size={size}\n type=\"button\"\n {...props}\n />\n);\n\n// ---------------------------------------------------------------------------\n// ConfirmationShortcut — keyboard shortcut label inside a button\n// ---------------------------------------------------------------------------\n\nexport type ConfirmationShortcutProps = ComponentProps<typeof Kbd>;\n\nexport const ConfirmationShortcut = ({\n className,\n ...props\n}: ConfirmationShortcutProps) => (\n <Kbd className={cn(\"ml-0.5\", className)} {...props} />\n);\n"],"names":["ConfirmationContext","createContext","useConfirmation","context","useContext","ACCEPTED_HIDE_DELAY","Confirmation","className","approval","state","children","props","contextValue","useMemo","visible","setVisible","useState","isAccepted","useEffect","timer","passthroughProps","k","jsx","AnimatePresence","motion","cn","ConfirmationTitle","ConfirmationCode","CodeBlock","ConfirmationRequest","ConfirmationAccepted","ConfirmationRejected","ConfirmationActions","ConfirmationAction","size","Button","ConfirmationShortcut","Kbd"],"mappings":"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"}
|