laif-ds
Version:
Design System di Laif con componenti React basati su principi di Atomic Design
229 lines (228 loc) • 6.22 kB
JavaScript
"use client";
import { jsxs as y, jsx as t, Fragment as j } from "react/jsx-runtime";
import { forwardRef as g, useRef as L, useCallback as T, useState as z } from "react";
import { cn as B } from "../../lib/utils.js";
import { useAutoScroll as D } from "../../hooks/use-auto-scroll.js";
import { Button as N } from "./button.js";
import { CopyButton as S } from "./copy-button.js";
import { MessageInput as P } from "./message-input.js";
import { MessageList as U } from "./message-list.js";
import { PromptSuggestions as E } from "./prompt-suggestions.js";
import O from "../../node_modules/lucide-react/dist/esm/icons/thumbs-up.js";
import q from "../../node_modules/lucide-react/dist/esm/icons/thumbs-down.js";
import H from "../../node_modules/lucide-react/dist/esm/icons/arrow-down.js";
function J({
messages: e,
handleSubmit: n,
input: a,
handleInputChange: u,
stop: l,
isGenerating: c,
append: f,
suggestions: d,
className: w,
onRateResponse: p,
setMessages: v,
transcribeAudio: A
}) {
const C = e.at(-1), F = e.length === 0, b = (C == null ? void 0 : C.role) === "user", x = L(e);
x.current = e;
const M = T(() => {
if (l == null || l(), !v) return;
const r = [...x.current], i = r.findLast(
(s) => s.role === "assistant"
);
if (!i) return;
let m = !1, h = { ...i };
if (i.toolInvocations) {
const s = i.toolInvocations.map(
(o) => o.state === "call" ? (m = !0, {
...o,
state: "result",
result: {
content: "Tool execution was cancelled",
__cancelled: !0
// Special marker to indicate cancellation
}
}) : o
);
m && (h = {
...h,
toolInvocations: s
});
}
if (i.parts && i.parts.length > 0) {
const s = i.parts.map((o) => o.type === "tool-invocation" && o.toolInvocation && o.toolInvocation.state === "call" ? (m = !0, {
...o,
toolInvocation: {
...o.toolInvocation,
state: "result",
result: {
content: "Tool execution was cancelled",
__cancelled: !0
}
}
}) : o);
m && (h = {
...h,
parts: s
});
}
if (m) {
const s = r.findIndex(
(o) => o.id === i.id
);
s !== -1 && (r[s] = h, v(r));
}
}, [l, v, x]), _ = T(
(r) => ({
actions: p ? /* @__PURE__ */ y(j, { children: [
/* @__PURE__ */ t("div", { className: "border-r pr-1", children: /* @__PURE__ */ t(
S,
{
content: r.content,
copyMessage: "Copied response to clipboard!"
}
) }),
/* @__PURE__ */ t(
N,
{
size: "icon",
variant: "ghost",
className: "h-6 w-6",
onClick: () => p(r.id, "thumbs-up"),
children: /* @__PURE__ */ t(O, { className: "h-4 w-4" })
}
),
/* @__PURE__ */ t(
N,
{
size: "icon",
variant: "ghost",
className: "h-6 w-6",
onClick: () => p(r.id, "thumbs-down"),
children: /* @__PURE__ */ t(q, { className: "h-4 w-4" })
}
)
] }) : /* @__PURE__ */ t(
S,
{
content: r.content,
copyMessage: "Copied response to clipboard!"
}
)
}),
[p]
);
return /* @__PURE__ */ y(I, { className: w, children: [
F && f && d ? /* @__PURE__ */ t(
E,
{
label: "Try these prompts ✨",
append: f,
suggestions: d
}
) : null,
e.length > 0 ? /* @__PURE__ */ t(K, { messages: e, children: /* @__PURE__ */ t(
U,
{
messages: e,
isTyping: b,
messageOptions: _
}
) }) : null,
/* @__PURE__ */ t(
k,
{
className: "flex-shrink-0",
isPending: c || b,
handleSubmit: n,
children: ({ files: r, setFiles: i }) => /* @__PURE__ */ t(
P,
{
value: a,
onChange: u,
allowAttachments: !0,
files: r,
setFiles: i,
stop: M,
isGenerating: c,
transcribeAudio: A
}
)
}
)
] });
}
J.displayName = "Chat";
function K({
messages: e,
children: n
}) {
const {
containerRef: a,
scrollToBottom: u,
handleScroll: l,
shouldAutoScroll: c,
handleTouchStart: f
} = D([e]);
return /* @__PURE__ */ y(
"div",
{
className: "relative flex-1 overflow-y-auto pb-4",
ref: a,
onScroll: l,
onTouchStart: f,
children: [
/* @__PURE__ */ t("div", { className: "max-w-full", children: n }),
!c && /* @__PURE__ */ t("div", { className: "pointer-events-none absolute right-0 bottom-0 left-0 flex items-end justify-end", children: /* @__PURE__ */ t("div", { className: "sticky bottom-0 left-0 flex w-full justify-end", children: /* @__PURE__ */ t(
N,
{
onClick: u,
className: "animate-in fade-in-0 slide-in-from-bottom-1 pointer-events-auto h-8 w-8 rounded-full ease-in-out",
size: "icon",
variant: "ghost",
children: /* @__PURE__ */ t(H, { className: "h-4 w-4" })
}
) }) })
]
}
);
}
const I = g(({ className: e, ...n }, a) => /* @__PURE__ */ t(
"div",
{
ref: a,
className: B("flex h-full max-h-full w-full flex-col", e),
...n
}
));
I.displayName = "ChatContainer";
const k = g(
({ children: e, handleSubmit: n, className: a }, u) => {
const [l, c] = z(null);
return /* @__PURE__ */ t("form", { ref: u, onSubmit: (d) => {
if (!l) {
n(d);
return;
}
const w = Q(l);
n(d, { experimental_attachments: w }), c(null);
}, className: a, children: e({ files: l, setFiles: c }) });
}
);
k.displayName = "ChatForm";
function Q(e) {
if (typeof window > "u")
return {};
const n = new DataTransfer();
for (const a of Array.from(e))
n.items.add(a);
return n.files;
}
export {
J as Chat,
I as ChatContainer,
k as ChatForm,
K as ChatMessages
};