laif-ds
Version:
Design System di Laif con componenti React basati su principi di Atomic Design
344 lines (343 loc) • 11.4 kB
JavaScript
"use client";
import { jsxs as d, jsx as e } from "react/jsx-runtime";
import { useState as y, useEffect as C, useRef as Y } from "react";
import { AnimatePresence as v, motion as x } from "framer-motion";
import { a as I } from "../../node_modules/remeda/dist/chunk-KI5X74E2.js";
import { cn as R } from "../../lib/utils.js";
import { useAudioRecording as Z } from "../../hooks/use-audio-recording.js";
import { useAutosizeTextArea as _ } from "../../hooks/use-autosize-textarea.js";
import { AudioVisualizer as $ } from "./audio-visualizer.js";
import { Button as p } from "./button.js";
import { FilePreview as K } from "./file-preview.js";
import { InterruptPrompt as G } from "./interrupt-prompt.js";
import F from "../../node_modules/lucide-react/dist/esm/icons/paperclip.js";
import ee from "../../node_modules/lucide-react/dist/esm/icons/mic.js";
import te from "../../node_modules/lucide-react/dist/esm/icons/square.js";
import re from "../../node_modules/lucide-react/dist/esm/icons/arrow-up.js";
import ie from "../../node_modules/lucide-react/dist/esm/icons/info.js";
import ae from "../../node_modules/lucide-react/dist/esm/icons/loader-circle.js";
function ne({
placeholder: a = "Ask AI...",
className: l,
onKeyDown: o,
submitOnEnter: s = !0,
stop: u,
isGenerating: m,
enableInterrupt: A = !0,
transcribeAudio: P,
...r
}) {
var S;
const [L, w] = y(!1), [N, h] = y(!1), {
isListening: M,
isSpeechSupported: O,
isRecording: k,
isTranscribing: j,
audioStream: q,
toggleListening: E,
stopRecording: D
} = Z({
transcribeAudio: P,
onTranscriptionComplete: (t) => {
var i;
(i = r.onChange) == null || i.call(r, { target: { value: t } });
}
});
C(() => {
m || h(!1);
}, [m]);
const g = (t) => {
r.allowAttachments && r.setFiles((i) => i === null ? t : t === null ? i : [...i, ...t]);
}, H = (t) => {
r.allowAttachments === !0 && (t.preventDefault(), w(!0));
}, U = (t) => {
r.allowAttachments === !0 && (t.preventDefault(), w(!1));
}, V = (t) => {
if (w(!1), r.allowAttachments !== !0) return;
t.preventDefault();
const i = t.dataTransfer;
i.files.length && g(Array.from(i.files));
}, B = (t) => {
var T;
const i = (T = t.clipboardData) == null ? void 0 : T.items;
if (!i) return;
const n = t.clipboardData.getData("text");
if (n && n.length > 500 && r.allowAttachments) {
t.preventDefault();
const f = new Blob([n], { type: "text/plain" }), X = new File([f], "Pasted text", {
type: "text/plain",
lastModified: Date.now()
});
g([X]);
return;
}
const c = Array.from(i).map((f) => f.getAsFile()).filter((f) => f !== null);
r.allowAttachments && c.length > 0 && g(c);
}, W = (t) => {
var i, n, c;
if (s && t.key === "Enter" && !t.shiftKey) {
if (t.preventDefault(), m && u && A) {
if (N)
u(), h(!1), (i = t.currentTarget.form) == null || i.requestSubmit();
else if (r.value || r.allowAttachments && ((n = r.files) != null && n.length)) {
h(!0);
return;
}
}
(c = t.currentTarget.form) == null || c.requestSubmit();
}
o == null || o(t);
}, b = Y(
null
), [J, Q] = y(0);
C(() => {
b.current && Q(b.current.offsetHeight);
}, [r.value]);
const z = r.allowAttachments && r.files && r.files.length > 0;
return _({
ref: b,
maxHeight: 240,
borderWidth: 1,
dependencies: [r.value, z]
}), /* @__PURE__ */ d(
"div",
{
className: "relative flex w-full",
onDragOver: H,
onDragLeave: U,
onDrop: V,
children: [
A && /* @__PURE__ */ e(
G,
{
isOpen: N,
close: () => h(!1)
}
),
/* @__PURE__ */ e(
ce,
{
isVisible: k,
onStopRecording: D
}
),
/* @__PURE__ */ e("div", { className: "relative flex w-full items-center space-x-2", children: /* @__PURE__ */ d("div", { className: "relative flex-1", children: [
/* @__PURE__ */ e(
"textarea",
{
"aria-label": "Write your prompt here",
placeholder: a,
ref: b,
onPaste: B,
onKeyDown: W,
className: R(
"border-d-input bg-d-background ring-offset-d-background placeholder:text-d-secondary-foreground focus-visible:border-d-primary z-10 w-full grow resize-none rounded-xl border p-3 pr-24 text-sm transition-[border] focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50",
z && "pb-16",
l
),
...r.allowAttachments ? I(r, ["allowAttachments", "files", "setFiles"]) : I(r, ["allowAttachments"])
}
),
r.allowAttachments && /* @__PURE__ */ e("div", { className: "absolute inset-x-3 bottom-2 z-20 overflow-x-scroll py-3 [-ms-overflow-style:none] [scrollbar-width:none] [&::-webkit-scrollbar]:hidden", children: /* @__PURE__ */ e("div", { className: "flex space-x-3", children: /* @__PURE__ */ e(v, { mode: "popLayout", children: (S = r.files) == null ? void 0 : S.map((t) => /* @__PURE__ */ e(
K,
{
file: t,
onRemove: () => {
r.setFiles((i) => {
if (!i) return null;
const n = Array.from(i).filter(
(c) => c !== t
);
return n.length === 0 ? null : n;
});
}
},
t.name + String(t.lastModified)
)) }) }) })
] }) }),
/* @__PURE__ */ d("div", { className: "absolute top-3 right-3 z-20 flex gap-2", children: [
r.allowAttachments && /* @__PURE__ */ e(
p,
{
type: "button",
size: "icon",
variant: "outline",
className: "h-8 w-8",
"aria-label": "Attach a file",
onClick: async () => {
const t = await oe();
g(t);
},
children: /* @__PURE__ */ e(F, { className: "h-4 w-4" })
}
),
O && /* @__PURE__ */ e(
p,
{
type: "button",
variant: "outline",
className: R("h-8 w-8", M && "text-d-primary"),
"aria-label": "Voice input",
size: "icon",
onClick: E,
children: /* @__PURE__ */ e(ee, { className: "h-4 w-4" })
}
),
m && u ? /* @__PURE__ */ e(
p,
{
type: "button",
size: "icon",
className: "h-8 w-8",
"aria-label": "Stop generating",
onClick: u,
children: /* @__PURE__ */ e(te, { className: "h-3 w-3 animate-pulse", fill: "currentColor" })
}
) : /* @__PURE__ */ e(
p,
{
type: "submit",
size: "icon",
className: "h-8 w-8 transition-opacity",
"aria-label": "Send message",
disabled: r.value === "" || m,
children: /* @__PURE__ */ e(re, { className: "h-5 w-5" })
}
)
] }),
r.allowAttachments && /* @__PURE__ */ e(le, { isDragging: L }),
/* @__PURE__ */ e(
de,
{
isRecording: k,
isTranscribing: j,
audioStream: q,
textAreaHeight: J,
onStopRecording: D
}
)
]
}
);
}
ne.displayName = "MessageInput";
function le({ isDragging: a }) {
return /* @__PURE__ */ e(v, { children: a && /* @__PURE__ */ d(
x.div,
{
className: "border-d-border bg-d-background text-d-secondary-foreground pointer-events-none absolute inset-0 z-20 flex items-center justify-center space-x-2 rounded-xl border border-dashed text-sm",
initial: { opacity: 0 },
animate: { opacity: 1 },
exit: { opacity: 0 },
transition: { duration: 0.2 },
"aria-hidden": !0,
children: [
/* @__PURE__ */ e(F, { className: "h-4 w-4" }),
/* @__PURE__ */ e("span", { children: "Drop your files here to attach them." })
]
}
) });
}
function oe() {
if (typeof document > "u")
return Promise.resolve(null);
const a = document.createElement("input");
return a.type = "file", a.multiple = !0, a.accept = "*/*", a.click(), new Promise((l) => {
a.onchange = (o) => {
const s = o.currentTarget.files;
if (s) {
l(Array.from(s));
return;
}
l(null);
};
});
}
function se() {
return /* @__PURE__ */ d(
x.div,
{
className: "bg-d-background/80 flex h-full w-full flex-col items-center justify-center rounded-xl backdrop-blur-sm",
initial: { opacity: 0 },
animate: { opacity: 1 },
exit: { opacity: 0 },
transition: { duration: 0.2 },
children: [
/* @__PURE__ */ d("div", { className: "relative", children: [
/* @__PURE__ */ e(ae, { className: "text-d-primary h-8 w-8 animate-spin" }),
/* @__PURE__ */ e(
x.div,
{
className: "bg-d-primary/20 absolute inset-0 h-8 w-8 animate-pulse rounded-full",
initial: { scale: 0.8, opacity: 0 },
animate: { scale: 1.2, opacity: 1 },
transition: {
duration: 1,
repeat: 1 / 0,
repeatType: "reverse",
ease: "easeInOut"
}
}
)
] }),
/* @__PURE__ */ e("p", { className: "text-d-secondary-foreground mt-4 text-sm font-medium", children: "Transcribing audio..." })
]
}
);
}
function ce({ isVisible: a, onStopRecording: l }) {
return /* @__PURE__ */ e(v, { children: a && /* @__PURE__ */ e(
x.div,
{
initial: { top: 0, filter: "blur(5px)" },
animate: {
top: -40,
filter: "blur(0px)",
transition: {
type: "spring",
filter: { type: "tween" }
}
},
exit: { top: 0, filter: "blur(5px)" },
className: "bg-d-background text-d-secondary-foreground absolute left-1/2 flex -translate-x-1/2 cursor-pointer overflow-hidden rounded-full border py-1 text-center text-sm whitespace-nowrap",
onClick: l,
children: /* @__PURE__ */ d("span", { className: "mx-2.5 flex items-center", children: [
/* @__PURE__ */ e(ie, { className: "mr-2 h-3 w-3" }),
"Click to finish recording"
] })
}
) });
}
function de({
isRecording: a,
isTranscribing: l,
audioStream: o,
textAreaHeight: s,
onStopRecording: u
}) {
return a ? /* @__PURE__ */ e(
"div",
{
className: "absolute inset-[1px] z-50 overflow-hidden rounded-xl",
style: { height: s - 2 },
children: /* @__PURE__ */ e(
$,
{
stream: o,
isRecording: a,
onClick: u
}
)
}
) : l ? /* @__PURE__ */ e(
"div",
{
className: "absolute inset-[1px] z-50 overflow-hidden rounded-xl",
style: { height: s - 2 },
children: /* @__PURE__ */ e(se, {})
}
) : null;
}
export {
ne as MessageInput
};