UNPKG

@automattic/agenttic-ui

Version:

UI components for the Agenttic framework

1,894 lines 58.7 kB
import { jsxs as I, jsx as n, Fragment as Ht } from "react/jsx-runtime"; import * as oe from "react"; import ae, { useState as k, useEffect as E, useCallback as d, useRef as L, createContext as De, useContext as Oe, useId as Ne, memo as Me, useMemo as Pe } from "react"; import { motion as P, AnimatePresence as At, useMotionValue as Mt, useDragControls as ie, animate as Pt } from "framer-motion"; import { __ as ut } from "@wordpress/i18n"; import { Slot as Ve } from "@radix-ui/react-slot"; import He from "react-markdown"; import './index.css';function U(...e) { return e.flat().filter(Boolean).map((t) => typeof t == "string" ? t : typeof t == "object" && !Array.isArray(t) && t !== null ? Object.entries(t).filter(([a, r]) => r).map(([a]) => a).join(" ") : "").join(" ").trim(); } function re(e) { const t = e || "collapsed", [a, r] = k(t); E(() => { e !== void 0 && r(e); }, [e]); const s = a !== "collapsed" && a !== "compact", i = d(() => { r("expanded"); }, []), c = d(() => { r(t); }, [t]), h = d(() => { r( (u) => u === "collapsed" ? "compact" : "collapsed" ); }, []); return { state: a, initialState: t, setState: r, isOpen: s, open: i, close: c, toggle: h }; } function se({ value: e, setValue: t, onSubmit: a, isProcessing: r }) { const s = L(null), i = d(() => { t(""), s.current && (s.current.style.height = "auto", setTimeout(() => { var u; (u = s.current) == null || u.focus(); }, 100)); }, [t]), c = d(() => { const u = s.current; if (!u) return; u.style.height = "auto"; const m = u.scrollHeight, p = 40, g = 200; u.style.height = `${Math.min( Math.max(m, p), g )}px`; }, []), h = d( (u) => { u.key === "Enter" && !u.shiftKey && !r && e.trim() && (u.preventDefault(), a(e.trim()), i()); }, [e, r, a, i] ); return E(() => { c(); }, [e, c]), { value: e, setValue: t, clear: i, textareaRef: s, handleKeyDown: h, adjustHeight: c }; } const ce = ut("Ask anything", "a8c-agenttic"), Yt = { type: "spring", stiffness: 300, damping: 30 }, dt = { type: "spring", damping: 40, stiffness: 500, mass: 0.8 }, Vt = { ...dt, stiffness: 1e3, damping: 90 }, $t = { type: "spring", damping: 40, stiffness: 500, mass: 0.8 }, le = { hidden: { opacity: 0 }, visible: { opacity: 1, transition: Yt }, exit: { opacity: 0, transition: { ...Yt, duration: 0.1 } } }, $e = () => { if (typeof window > "u") return { left: 0, right: 0, top: 0, bottom: 0 }; const e = 20; return { left: e, right: window.innerWidth - 400 - e, // Assuming max width of 400px top: e, bottom: window.innerHeight - 60 - e // Assuming collapsed height of 60px }; }, Fe = { "0%": { backgroundPosition: "-200% 0" }, "100%": { backgroundPosition: "200% 0" } }, to = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({ __proto__: null, fadeVariants: le, fastSpring: dt, fastSpringWithDelay: Vt, getDragConstraints: $e, morphSpring: $t, springConfig: Yt, thinkingGradientKeyframes: Fe }, Symbol.toStringTag, { value: "Module" })), ke = "button-module_button", Ue = "button-module_pressed", We = "button-module_primary", Be = "button-module_ghost", Ge = "button-module_outline", Ze = "button-module_transparent", Ye = "button-module_link", Ke = "button-module_icon", Xe = "button-module_sm", je = "button-module_lg", ze = "button-module_withTextAndIcon", It = { button: ke, pressed: Ue, primary: We, ghost: Be, outline: Ge, transparent: Ze, link: Ye, icon: Ke, sm: Xe, lg: je, withTextAndIcon: ze }, X = oe.forwardRef( function({ className: t, variant: a = "primary", size: r, icon: s, children: i, asChild: c = !1, pressed: h = !1, ...u }, m) { const p = c ? Ve : "button", g = !!s, w = r || (g && !i ? "icon" : void 0); return /* @__PURE__ */ I( p, { ref: m, "data-slot": "button", className: U( It.button, It[a], w && It[w], g && i ? It.withTextAndIcon : void 0, h ? It.pressed : void 0, t ), "aria-pressed": h, ...u, children: [ s, i ] } ); } ); X.displayName = "Button"; function ue({ className: e, size: t = 24 }) { return /* @__PURE__ */ n( "svg", { className: e, width: t, height: t, viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ n( "path", { d: "M19.6611 11.5224L16.3782 10.39C15.0799 9.94387 14.0561 8.92011 13.61 7.62181L12.4775 4.33887C12.3231 3.88704 11.6769 3.88704 11.5225 4.33887L10.39 7.62181C9.94388 8.92011 8.9201 9.94387 7.6218 10.39L4.33887 11.5224C3.88704 11.6768 3.88704 12.3231 4.33887 12.4776L7.6218 13.61C8.9201 14.0561 9.94388 15.0799 10.39 16.3782L11.5225 19.6611C11.6769 20.113 12.3231 20.113 12.4775 19.6611L13.61 16.3782C14.0561 15.0799 15.0799 14.0561 16.3782 13.61L19.6611 12.4776C20.113 12.3231 20.113 11.6768 19.6611 11.5224ZM15.8291 12.2431L14.1876 12.8093C13.5356 13.0323 13.0266 13.5471 12.8036 14.1934L12.2374 15.8348C12.1572 16.0636 11.837 16.0636 11.7569 15.8348L11.1907 14.1934C10.9677 13.5414 10.4529 13.0323 9.80662 12.8093L8.16515 12.2431C7.93637 12.163 7.93637 11.8427 8.16515 11.7626L9.80662 11.1964C10.4586 10.9734 10.9677 10.4586 11.1907 9.81233L11.7569 8.17087C11.837 7.94209 12.1572 7.94209 12.2374 8.17087L12.8036 9.81233C13.0266 10.4643 13.5414 10.9734 14.1876 11.1964L15.8291 11.7626C16.0579 11.8427 16.0579 12.163 15.8291 12.2431Z", fill: "currentColor" } ) } ); } const qe = "CollapsedView-module_button", Je = { button: qe }; function de({ icon: e = /* @__PURE__ */ n(ue, { size: 36 }), onClick: t, onHover: a, focusOnMount: r = !1 }) { const s = L(null), i = L(r); return E(() => { i.current && s.current && s.current.focus(), i.current = !1; }, [i, s]), /* @__PURE__ */ n( P.div, { "data-slot": "collapsed-view", layout: "preserve-aspect", layoutId: "collapsed-button", initial: { opacity: 0, scale: 0.5 }, animate: { opacity: 1, scale: 1, transition: { ...$t, delay: 0.2 } }, exit: { opacity: 0, scale: 0, transition: { duration: 0.15 } }, children: /* @__PURE__ */ n( X, { ref: s, onClick: t, onMouseEnter: a, variant: "link", className: Je.button, icon: e, "aria-label": ut("Open chat", "a8c-agenttic") } ) } ); } const Qe = "Textarea-module_textarea", tn = { textarea: Qe }, me = oe.forwardRef( ({ className: e, ...t }, a) => /* @__PURE__ */ n( "textarea", { "data-slot": "textarea", className: tn.textarea, ref: a, ...t } ) ); me.displayName = "Textarea"; function en({ className: e, size: t = 24 }) { return /* @__PURE__ */ n( "svg", { width: t, height: t, viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", className: e, children: /* @__PURE__ */ n( "path", { d: "M12.2197 5C12.4186 5 12.6094 5.07902 12.75 5.21967L17 9.46967C17.2929 9.76256 17.2929 10.2374 17 10.5303C16.7071 10.8232 16.2322 10.8232 15.9393 10.5303L12.9697 7.56067V18.25C12.9697 18.6642 12.6339 19 12.2197 19C11.8055 19 11.4697 18.6642 11.4697 18.25V7.56065L8.5 10.5303C8.2071 10.8232 7.73223 10.8232 7.43934 10.5303C7.14644 10.2374 7.14645 9.76256 7.43934 9.46967L11.6894 5.21967C11.83 5.07902 12.0208 5 12.2197 5Z", fill: "currentColor" } ) } ); } function nn({ className: e, size: t = 24 }) { return /* @__PURE__ */ n( "svg", { width: t, height: t, viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", className: e, children: /* @__PURE__ */ n( "rect", { x: "7", y: "7", width: "10", height: "10", rx: "2", fill: "currentColor" } ) } ); } const on = "ChatInput-module_container", an = "ChatInput-module_textareaContainer", rn = "ChatInput-module_actions", sn = "ChatInput-module_button", vt = { container: on, textareaContainer: an, actions: rn, button: sn }; function cn({ className: e, size: t = 24 }) { return /* @__PURE__ */ n( "svg", { className: e, width: t, height: t, viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ n( "path", { fillRule: "evenodd", clipRule: "evenodd", d: "M18.0045 13.4451L12 7.9864L5.9955 13.4451L7.00451 14.5549L12 10.0136L16.9955 14.5549L18.0045 13.4451Z", fill: "currentColor" } ) } ); } const ln = "AnimatedPlaceholder-module_container", un = { container: ln }; function dn({ texts: e, interval: t = 3e3, className: a = "" }) { const [r, s] = k(0); return E(() => { const i = setInterval(() => { s( (c) => (c + 1) % e.length ); }, t); return () => clearInterval(i); }, [e.length, t]), /* @__PURE__ */ n(At, { mode: "wait", children: /* @__PURE__ */ n( P.span, { "data-slot": "animated-placeholder", className: U(un.container, a), initial: { opacity: 0, y: 8 }, animate: { opacity: 1, y: 0 }, exit: { opacity: 0, y: -8 }, transition: { duration: 0.3, ease: [0.4, 0, 0.2, 1] // Matches --transition-colors cubic-bezier }, children: e[r] }, r ) }); } const fe = De(null); function mt() { const e = Oe(fe); if (!e) throw new Error( "useAgentUIContext must be used within an AgentUIContainer" ); return e; } function Qt({ children: e, value: t }) { return /* @__PURE__ */ n(fe.Provider, { value: t, children: e }); } function Xt({ value: e, onChange: t, onSubmit: a, onKeyDown: r, textareaRef: s, placeholder: i = ce, isProcessing: c, onBlur: h, fromCompact: u = !1, onExpand: m, showExpandButton: p = !0, focusOnMount: g = !1, customActions: w = [], actionOrder: _ = "before-submit", onStop: y, disabled: S = !1, className: O, onMouseEnter: H, onMouseLeave: A }) { const $ = Ne(), l = (e.trim() || c) && !S, { variant: N, floatingChatState: ft } = mt(), B = (T) => T.endsWith("…") ? T : `${T}…`, et = Array.isArray(i); let G; et ? G = i.map(B) : i ? G = B(i) : G = ""; const M = L(g); E(() => { M.current && s.current && s.current.focus(), M.current = !1; }, [M, s]); const nt = () => w.map((T) => /* @__PURE__ */ n( X, { className: T.className || vt.button, onClick: T.onClick, disabled: T.disabled, variant: T.variant || "ghost", icon: T.icon, "aria-label": T["aria-label"] }, T.id )), o = () => N === "embedded" || ft === "expanded" ? null : p && m ? /* @__PURE__ */ n( X, { className: vt.button, onClick: m, variant: "ghost", icon: /* @__PURE__ */ n(cn, {}), "aria-label": ut("Expand conversation", "a8c-agenttic") } ) : null, ot = () => { if (c && !y) return null; const T = () => { c && y ? y() : a(); }; return /* @__PURE__ */ n( X, { className: vt.button, onClick: T, disabled: !l, variant: "primary", icon: c ? /* @__PURE__ */ n(nn, {}) : /* @__PURE__ */ n(en, {}), "aria-label": c ? ut("Stop processing", "a8c-agenttic") : ut("Send message", "a8c-agenttic") } ); }; return /* @__PURE__ */ I( "div", { "data-slot": "chat-input", className: vt.container, onMouseEnter: H, onMouseLeave: A, children: [ /* @__PURE__ */ I( P.div, { className: vt.textareaContainer, initial: { opacity: 0 }, animate: { opacity: 1, scale: 1, transition: e.trim() ? { duration: 0 } : Vt }, children: [ !e && et && /* @__PURE__ */ n( dn, { texts: G } ), /* @__PURE__ */ n( me, { id: $, ref: s, value: e, onChange: (T) => t(T.target.value), onKeyDown: r, onBlur: h, placeholder: et ? "" : G, rows: 1 } ) ] } ), /* @__PURE__ */ I( P.div, { className: vt.actions, initial: { opacity: u ? 1 : 0, scale: u ? 1 : 0.5 }, animate: { opacity: 1, scale: 1, transition: e.trim() ? { duration: 0 } : dt }, children: [ o(), _ === "before-submit" && nt(), ot(), _ === "after-submit" && nt() ] } ) ] } ); } const mn = "Suggestions-module_container", fn = "Suggestions-module_vertical", Bt = { container: mn, vertical: fn }, jt = ({ className: e, suggestions: t, onSubmit: a, layout: r = "horizontal", visible: s = !0, onMouseEnter: i, onMouseLeave: c }) => { const h = (u) => { a && a(u.prompt); }; return !t || t.length === 0 ? null : /* @__PURE__ */ n(At, { children: t && t.length > 0 && s && /* @__PURE__ */ n( P.div, { className: U( Bt.container, r === "vertical" ? Bt.vertical : "", e ), initial: { opacity: 0, y: "-80%" }, animate: { opacity: 1, y: "-100%" }, exit: { opacity: 0, y: "-80%" }, transition: Vt, onMouseEnter: i, onMouseLeave: c, children: t.map( (u, m) => /* @__PURE__ */ n( P.div, { initial: { opacity: 0, y: 10 }, animate: { opacity: 1, y: 0 }, exit: { opacity: 0, y: 10 }, transition: { ...Vt, delay: m * 0.05 }, children: /* @__PURE__ */ n( X, { onClick: () => h(u), variant: r === "vertical" ? "transparent" : "outline", size: r === "vertical" ? "lg" : void 0, className: Bt.button, children: u.label } ) }, u.id ) ) } ) }); }; function hn() { const e = L(/* @__PURE__ */ new Map()), t = d((i) => { const c = e.current.get(i); c && (clearTimeout(c), e.current.delete(i)); }, []), a = d( (i, c, h) => { t(i); const u = setTimeout(c, h); return e.current.set(i, u), u; }, [t] ), r = d(() => { e.current.forEach((i) => { clearTimeout(i); }), e.current.clear(); }, []), s = d((i) => e.current.has(i), []); return E(() => r, [r]), { setNamedTimeout: a, clearNamedTimeout: t, clearAllTimeouts: r, hasTimeout: s }; } const pn = 4e3; function he({ value: e, onChange: t, onSubmit: a, onKeyDown: r, textareaRef: s, placeholder: i, isProcessing: c, onBlur: h, onExpand: u, showExpandButton: m = !0, focusOnMount: p = !1, customActions: g, actionOrder: w, onStop: _, suggestions: y, clearSuggestions: S, handleSuggestionSubmit: O }) { const [H, A] = k(!1), { setNamedTimeout: $, clearAllTimeouts: l } = hn(), N = d(() => { $( "hide-suggestions", () => { A(!1); }, pn ); }, [$]); return E(() => { if (l(), e) { A(!1); return; } if (!y || y.length === 0) { A(!1); return; } A(!0), N(); }, [ e, y, l, $, S, N ]), /* @__PURE__ */ I(Ht, { children: [ /* @__PURE__ */ n( Xt, { value: e, onChange: t, onSubmit: a, onKeyDown: r, textareaRef: s, placeholder: i, isProcessing: c, onBlur: h, onExpand: u, showExpandButton: m, focusOnMount: p, customActions: g, actionOrder: w, onStop: _, onMouseEnter: () => { l(), A(!0); }, onMouseLeave: () => N() } ), !e && /* @__PURE__ */ n( jt, { suggestions: y, onSubmit: O, layout: "vertical", visible: H, onMouseEnter: () => { l(), A(!0); }, onMouseLeave: () => N() } ) ] }); } function pe({ className: e, size: t = 24 }) { return /* @__PURE__ */ n( "svg", { className: e, width: t, height: t, viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ n( "path", { d: "M12.0001 13.0607L16.4697 17.5304L17.5304 16.4697L13.0607 12.0001L17.5304 7.53039L16.4697 6.46973L12.0001 10.9394L7.5304 6.46973L6.46973 7.53039L10.9394 12.0001L6.46974 16.4697L7.5304 17.5304L12.0001 13.0607Z", fill: "currentColor" } ) } ); } const Cn = "ChatHeader-module_container", gn = { container: Cn }; function Ce({ onClose: e, className: t }) { return /* @__PURE__ */ n( P.div, { "data-slot": "chat-header", "data-draggable": "true", className: gn.container, initial: { opacity: 0 }, animate: { opacity: 1 }, transition: { ...dt, delay: 0.1 }, children: e && /* @__PURE__ */ n( X, { variant: "ghost", icon: /* @__PURE__ */ n(pe, {}), onClick: e, "aria-label": ut("Close conversation", "a8c-agenttic") } ) } ); } const vn = "Notice-module_container", wn = "Notice-module_containerWithIcon", Ln = "Notice-module_content", yn = "Notice-module_actions", bn = "Notice-module_icon", In = "Notice-module_dismissible", J = { container: vn, containerWithIcon: wn, content: Ln, actions: yn, icon: bn, dismissible: In }; function ge({ icon: e, message: t, action: a, dismissible: r = !0, onDismiss: s, className: i, status: c }) { return /* @__PURE__ */ I( "div", { "data-slot": "notice", className: U( J.container, { [J.containerWithIcon]: !!e, [J.isSuccess]: c === "success", [J.isWarning]: c === "warning", [J.isError]: c === "error" }, i ), children: [ /* @__PURE__ */ I("div", { className: J.content, children: [ e && /* @__PURE__ */ n("div", { className: J.icon, children: e }), /* @__PURE__ */ n("span", { children: t }) ] }), /* @__PURE__ */ I("div", { className: J.actions, children: [ a && /* @__PURE__ */ n(X, { onClick: a.onClick, variant: "link", children: a.label }), r && s && /* @__PURE__ */ n( X, { className: J.dismissible, onClick: s, variant: "ghost", size: "sm", icon: /* @__PURE__ */ n(pe, {}) } ) ] }) ] } ); } const Tn = "ChatFooter-module_container", Kt = { container: Tn }; function _n({ inputValue: e, onInputChange: t, onSubmit: a, onKeyDown: r, textareaRef: s, placeholder: i, isProcessing: c, onStop: h, fromCompact: u = !1, onExpand: m, disabled: p, notice: g, suggestions: w, clearSuggestions: _, focusOnMount: y, customActions: S, actionOrder: O }) { const H = d( (A) => { t(A), _ == null || _(); }, [t, _] ); return /* @__PURE__ */ I( P.div, { "data-slot": "chat-footer", className: Kt.container, initial: { opacity: 0, scale: 1 }, animate: { opacity: 1, scale: 1 }, transition: { ...dt }, children: [ !e && /* @__PURE__ */ n( jt, { suggestions: w, onSubmit: H } ), g && /* @__PURE__ */ n( ge, { icon: g.icon, message: g.message, action: g.action, dismissible: g.dismissible, onDismiss: g.onDismiss } ), /* @__PURE__ */ n( Xt, { value: e, onChange: t, onSubmit: a, onKeyDown: r, textareaRef: s, placeholder: i, isProcessing: c, onStop: h, fromCompact: u, onExpand: m, showExpandButton: !1, focusOnMount: y, customActions: S, actionOrder: O, disabled: p } ) ] } ); } const Sn = "MessageActions-module_container", te = { container: Sn }; function ee({ message: e }) { return !e.actions || e.actions.length === 0 ? null : /* @__PURE__ */ n( "div", { className: te.container, "data-visible": "true", role: "toolbar", "aria-label": "Message actions", children: e.actions.map((t) => /* @__PURE__ */ n( X, { className: te.button, icon: t.icon, onClick: () => t.onClick(e), variant: "ghost", size: "sm", type: "button", disabled: t.disabled, pressed: t.pressed, title: t.tooltip || t.label, "aria-label": t.label, ...t.tooltip && { title: t.tooltip }, children: t.showLabel ? t.label : void 0 }, t.id )) } ); } const En = "Message-module_message", An = "Message-module_user", xn = "Message-module_bubble", Rn = "Message-module_error", Dn = "Message-module_content", On = "Message-module_disabled", Tt = { message: En, user: An, bubble: xn, error: Rn, content: Dn, disabled: On }, Nn = ae.forwardRef( function({ message: t, messageRenderer: a = He }, r) { const s = () => /* @__PURE__ */ n(Ht, { children: t.content.map((i, c) => { if (i.type === "text" && i.text) return /* @__PURE__ */ n(a, { children: i.text }, c); if (i.type === "component" && i.component) { const h = i.component; return /* @__PURE__ */ n( h, { ...i.componentProps || {} }, c ); } return null; }) }); return /* @__PURE__ */ I( P.div, { ref: r, variants: le, initial: "hidden", animate: "visible", "data-slot": "message", "data-role": t.role, className: U( Tt.message, Tt[t.role], t.disabled ? Tt.disabled : void 0 ), children: [ /* @__PURE__ */ I( "div", { className: Tt.content, title: t.disabled ? ut( "This action is no longer available or cannot be performed", "a8c-agenttic" ) : void 0, children: [ /* @__PURE__ */ n("div", { className: Tt.bubble, children: s() }), t.role !== "user" && /* @__PURE__ */ n(ee, { message: t }) ] } ), t.role === "user" && /* @__PURE__ */ n(ee, { message: t }) ] } ); } ), Mn = "Messages-module_container", Pn = "Messages-module_emptyState", Gt = { container: Mn, emptyState: Pn }, Vn = "Thinking-module_container", Hn = "Thinking-module_icon", $n = "Thinking-module_content", Zt = { container: Vn, icon: Hn, content: $n }, Fn = Me( ae.forwardRef( function({ content: t = "Thinking…" }, a) { const r = Pe(() => /* @__PURE__ */ n(ue, {}), []); return /* @__PURE__ */ I( "div", { ref: a, "data-slot": "thinking", className: Zt.container, children: [ /* @__PURE__ */ n("div", { className: Zt.icon, children: r }), /* @__PURE__ */ n("span", { className: Zt.content, children: t }) ] } ); } ) ); function ve({ messages: e, isProcessing: t, error: a, emptyView: r, messageRenderer: s, className: i }) { const c = L(null), h = L([]), u = L(!0), m = L(null); return E(() => { const p = e.length > h.current.length; if (u.current && e.length > 0 && c.current ? c.current.scrollTop = c.current.scrollHeight : p && !u.current && c.current && c.current.scrollTo({ top: c.current.scrollHeight, behavior: "smooth" }), p && m.current) { const w = e.slice( h.current.length ).filter( (_) => _.role === "agent" ); if (w.length > 0) { const y = w[w.length - 1].content.filter((S) => S.type === "text").map((S) => S.text).join(" "); y && (m.current.textContent = y); } } u.current && (u.current = !1), h.current = e; }, [e]), e.length === 0 ? r ? /* @__PURE__ */ n( "div", { "data-slot": "messages", className: `${Gt.container} ${Gt.emptyState}`, ref: c, children: r } ) : null : /* @__PURE__ */ I(Ht, { children: [ /* @__PURE__ */ n( "div", { ref: m, "aria-live": "polite", "aria-atomic": "true", style: { position: "absolute", left: "-10000px", width: "1px", height: "1px", overflow: "hidden" } } ), /* @__PURE__ */ n( "div", { "data-slot": "messages", className: Gt.container, ref: c, children: /* @__PURE__ */ I(At, { mode: "popLayout", children: [ e.map((p) => /* @__PURE__ */ n( Nn, { message: p, messageRenderer: s }, p.id )), t && /* @__PURE__ */ n(Fn, {}), a && /* @__PURE__ */ n( "div", { className: "error-message", style: { color: "var(--color-destructive)", padding: "1rem", textAlign: "center" }, children: a } ) ] }) } ) ] }); } const kn = "ConversationView-module_container", Un = "ConversationView-module_withHeader", Et = { container: kn, withHeader: Un }; function ne({ messages: e, error: t, inputValue: a, onInputChange: r, onSubmit: s, onKeyDown: i, textareaRef: c, placeholder: h, isProcessing: u, onStop: m, fromCompact: p = !1, showHeader: g = !1, onClose: w, onExpand: _, notice: y, emptyView: S, suggestions: O, clearSuggestions: H, messageRenderer: A, focusOnMount: $ = !1 }) { return E(() => { const l = (N) => { N.key === "Escape" && w && w(); }; return document.addEventListener("keydown", l), () => document.removeEventListener("keydown", l); }, [w]), /* @__PURE__ */ I( "div", { "data-slot": "conversation-view", className: `${Et.container}${g ? ` ${Et.withHeader}` : ""}`, children: [ g && /* @__PURE__ */ n(Ce, { onClose: w }), /* @__PURE__ */ n( ve, { messages: e, isProcessing: u, error: t, emptyView: S, messageRenderer: A } ), /* @__PURE__ */ n( _n, { inputValue: a, onInputChange: r, onSubmit: s, onKeyDown: i, textareaRef: c, placeholder: h, isProcessing: u, onStop: m, fromCompact: p, onExpand: _, notice: y, suggestions: O, clearSuggestions: H, focusOnMount: $ } ) ] } ); } const Wn = "Chat-module_container", Bn = "Chat-module_embedded", Gn = "Chat-module_floating", Zn = "Chat-module_content", K = { container: Wn, embedded: Bn, floating: Gn, content: Zn }, x = { COLLAPSED_SIZE: 56, COMPACT_WIDTH: 372, EXPANDED_HEIGHT: 520, AUTO_COLLAPSE_DELAY: 1500, BORDER_RADIUS: 24, PADDING: 16, VIEWPORT_OFFSET: 16 }, _t = { SPRING_CONFIG: { type: "spring", damping: 25, stiffness: 300 }, VELOCITY_MULTIPLIER: 0.1, NON_DRAGGABLE_SELECTORS: [ '[data-slot="message"]', '[data-slot="chat-input"]', '[data-slot="chat-footer"]' ].join(", ") }; function eo({ messages: e, isProcessing: t, error: a, onSubmit: r, variant: s = "floating", triggerIcon: i, placeholder: c = ce, notice: h, onOpen: u, onExpand: m, onClose: p, onStop: g, emptyView: w, floatingChatState: _, suggestions: y, clearSuggestions: S, messageRenderer: O, className: H }) { const [A, $] = k(""), l = re(_), N = L(!1), ft = L(!1), B = L(!1), [et, G] = k(!1); E(() => { N.current = !1, ft.current = !1, B.current = !1; }, [l.state]); const M = L(/* @__PURE__ */ new Set()), nt = d(() => { M.current.forEach((C) => { clearTimeout(C); }), M.current.clear(); }, []), o = se({ value: A, setValue: $, onSubmit: async (C) => { l.state !== "expanded" && (m == null || m()), l.setState("expanded"), await r(C); }, isProcessing: t }), [ot, T] = k(56), [at, Ft] = k( "left" ), ht = L(null), pt = L(null), Z = L(null), V = Mt(0), Q = Mt(0), v = ie(), xt = d(() => { N.current = !0, l.open(), u == null || u(); }, [l, u]), it = d(() => { var R, F, j; const C = (F = (R = Z.current) == null ? void 0 : R.ownerDocument) == null ? void 0 : F.activeElement; return !(C && ((j = Z.current) != null && j.contains(C)) || A.trim()); }, [A, Z]), wt = (C) => C === "collapsed" ? x.COLLAPSED_SIZE : C === "compact" ? ot : x.EXPANDED_HEIGHT, kt = d(() => { if (l.state === "collapsed" && (l.setState("compact"), l.initialState === "collapsed")) { const C = setTimeout(() => { l.state === "compact" && it() && l.setState("collapsed"), M.current.delete(C); }, x.AUTO_COLLAPSE_DELAY); M.current.add(C); } }, [l, it]), Ct = d(() => { if (l.initialState === "collapsed" && l.state === "compact" && it()) { const C = setTimeout(() => { l.state === "compact" && it() && l.setState("collapsed"), M.current.delete(C); }, x.AUTO_COLLAPSE_DELAY); M.current.add(C); } }, [l, it]), tt = d(async () => { if (o.value.trim()) { const C = o.value.trim(); o.clear(), l.state !== "expanded" && (m == null || m()), l.setState("expanded"), await r(C); } }, [o, r, l, m]), W = d(() => { B.current = !0, m == null || m(), l.setState("expanded"); }, [m, l]), rt = d(() => { ft.current = !0, o.clear(), l.close(), p && p(); }, [o, l, p]), Y = d( (C) => { if (!Z.current || !pt.current) return null; const R = Z.current.getBoundingClientRect(), F = pt.current.getBoundingClientRect(), j = window.getComputedStyle(Z.current), ct = new DOMMatrixReadOnly(j.transform), Dt = R.x - ct.e, z = R.y - ct.f, Ut = (C ?? at) === "left" ? F.left : F.right - x.COMPACT_WIDTH, Wt = F.bottom - x.EXPANDED_HEIGHT; return { x: Ut - Dt, y: Wt - z }; }, [at] ), Lt = d( (C) => { C.target.closest( _t.NON_DRAGGABLE_SELECTORS ) || v.start(C.nativeEvent); }, [v] ), Rt = d( (C, R) => { const F = R.point.x, j = x.COMPACT_WIDTH, ct = (window.innerWidth - j) / 2, z = F < ct ? "left" : "right"; Ft(z); const gt = Y(z); gt && (Pt(V, gt.x, { ..._t.SPRING_CONFIG, velocity: R.velocity.x * _t.VELOCITY_MULTIPLIER }), Pt(Q, gt.y, { ..._t.SPRING_CONFIG, velocity: R.velocity.y * _t.VELOCITY_MULTIPLIER })); }, [V, Q, Y] ), yt = L(l.state), st = yt.current === "compact" && l.state === "expanded"; return E(() => { nt(), yt.current = l.state; }, [l.state, nt]), E(() => { if (l.state !== "expanded") return; const C = () => { const R = Y(); R && (V.set(R.x), Q.set(R.y)); }; return window.addEventListener("resize", C), () => window.removeEventListener("resize", C); }, [l.state, V, Q, Y]), E(() => { const C = M.current; return () => { C.forEach((R) => { clearTimeout(R); }), C.clear(); }; }, []), E(() => { if (l.state === "compact" && ht.current) { const C = ht.current.scrollHeight + x.PADDING; T(C); } }, [l.state, o.value]), s === "embedded" ? /* @__PURE__ */ n( "div", { "data-slot": "chat-embedded", className: U(H, K.container, K.embedded), children: /* @__PURE__ */ n( ne, { messages: e, inputValue: o.value, onInputChange: o.setValue, onSubmit: tt, onKeyDown: o.handleKeyDown, textareaRef: o.textareaRef, placeholder: c, isProcessing: t, onStop: g, showHeader: !1, notice: h, suggestions: y, clearSuggestions: S, error: a, emptyView: w, messageRenderer: O, onExpand: W, focusOnMount: B.current } ) } ) : /* @__PURE__ */ I(Ht, { children: [ /* @__PURE__ */ n( "div", { ref: pt, style: { position: "fixed", top: x.VIEWPORT_OFFSET, left: x.VIEWPORT_OFFSET, right: x.VIEWPORT_OFFSET, bottom: x.VIEWPORT_OFFSET, pointerEvents: "none" } } ), /* @__PURE__ */ n( P.div, { ref: Z, "data-slot": "chat-floating", className: U(H, K.container, K.floating, { animating: et }), onMouseLeave: l.state === "compact" ? Ct : void 0, drag: l.state === "expanded", dragControls: v, dragListener: !1, dragConstraints: pt, dragMomentum: !1, dragElastic: 0.1, dragTransition: { power: 0.1, timeConstant: 100 }, onDragEnd: Rt, onPointerDown: Lt, style: { x: V, y: Q, bottom: x.VIEWPORT_OFFSET, left: x.VIEWPORT_OFFSET }, children: /* @__PURE__ */ n( P.div, { layout: !0, className: K.content, initial: !1, animate: { width: l.state === "collapsed" ? x.COLLAPSED_SIZE : x.COMPACT_WIDTH, height: wt(l.state), x: l.state === "collapsed" && at === "right" ? x.COMPACT_WIDTH - x.COLLAPSED_SIZE : 0, transition: o.value.trim() ? { duration: 0 } : $t }, onAnimationStart: () => G(!0), onAnimationComplete: () => G(!1), style: { borderRadius: x.BORDER_RADIUS }, children: /* @__PURE__ */ I(At, { mode: "wait", children: [ l.state === "collapsed" && /* @__PURE__ */ n( de, { icon: i, onClick: xt, onHover: kt, focusOnMount: ft.current }, "collapsed" ), l.state === "compact" && /* @__PURE__ */ n("div", { ref: ht, children: /* @__PURE__ */ n( he, { value: o.value, onChange: o.setValue, onSubmit: tt, onKeyDown: o.handleKeyDown, textareaRef: o.textareaRef, placeholder: c, isProcessing: t, onBlur: Ct, onExpand: W, showExpandButton: !o.value.trim(), focusOnMount: N.current, onStop: g, suggestions: y, clearSuggestions: S }, "compact" ) }), l.state === "expanded" && /* @__PURE__ */ n( ne, { messages: e, inputValue: o.value, onInputChange: o.setValue, onSubmit: tt, onKeyDown: o.handleKeyDown, textareaRef: o.textareaRef, placeholder: c, isProcessing: t, onStop: g, showHeader: !0, onClose: rt, fromCompact: st, notice: h, suggestions: y, clearSuggestions: S, error: a, emptyView: w, messageRenderer: O, onExpand: W, focusOnMount: B.current }, "expanded" ) ] }) } ) } ) ] }); } const D = { COLLAPSED_SIZE: 56, COMPACT_WIDTH: 372, EXPANDED_HEIGHT: 520, AUTO_COLLAPSE_DELAY: 1500, BORDER_RADIUS: 24, PADDING: 16, VIEWPORT_OFFSET: 16 }, St = { SPRING_CONFIG: { type: "spring", damping: 25, stiffness: 300 }, VELOCITY_MULTIPLIER: 0.1, NON_DRAGGABLE_SELECTORS: [ '[data-slot="message"]', '[data-slot="chat-input"]', '[data-slot="chat-footer"]' ].join(", ") }; function Yn() { return /* @__PURE__ */ n( "div", { style: { position: "fixed", top: 0, left: 0, right: 0, bottom: 0, zIndex: 9999, cursor: "grabbing", pointerEvents: "auto", userSelect: "none", WebkitUserSelect: "none", MozUserSelect: "none", msUserSelect: "none" } } ); } function we({ children: e, messages: t, isProcessing: a, error: r, onSubmit: s, variant: i = "floating", triggerIcon: c, placeholder: h, notice: u, onOpen: m, onExpand: p, onClose: g, onStop: w, emptyView: _, floatingChatState: y, suggestions: S, clearSuggestions: O, messageRenderer: H, className: A, inputValue: $, onInputChange: l, draggableStates: N = ["expanded"], // Default to only expanded for backward compatibility ...ft }) { const B = $ !== void 0, [et, G] = k(""), M = B ? $ : et, nt = B ? l : G, o = re(y), ot = L(!1), T = L(!1), at = L(!1), [Ft, ht] = k(!1), [pt, Z] = k(!1); E(() => { ot.current = !1, T.current = !1, at.current = !1; }, [o.state]); const V = L(/* @__PURE__ */ new Set()), Q = d(() => { V.current.forEach((f) => { clearTimeout(f); }), V.current.clear(); }, []), v = se({ value: M, setValue: nt, onSubmit: async (f) => { o.state !== "expanded" && (p == null || p()), o.setState("expanded"), await s(f); }, isProcessing: a }), [xt, it] = k(56), [wt, kt] = k( "left" ), Ct = L(null), tt = L(null), W = L(null), rt = Mt(0), Y = Mt(0), Lt = ie(), Rt = d( (f) => { const b = f.endsWith(" ") ? f : `${f} `; v.setValue(b), O == null || O(), v.textareaRef.current && (v.textareaRef.current.focus(), v.textareaRef.current.setSelectionRange( b.length, b.length )); }, [v.setValue, O] ), yt = d(() => { ot.current = !0, o.open(), m == null || m(); }, [o, m]), st = d(() => { var b, q, lt; const f = (q = (b = W.current) == null ? void 0 : b.ownerDocument) == null ? void 0 : q.activeElement; return !(f && ((lt = W.current) != null && lt.contains(f)) || M.trim()); }, [M, W]), C = d( (f) => f === "collapsed" ? D.COLLAPSED_SIZE : f === "compact" ? xt : D.EXPANDED_HEIGHT, [xt] ), R = d(() => { if (o.state === "collapsed" && (o.setState("compact"), o.initialState === "collapsed")) { const f = setTimeout(() => { o.state === "compact" && st() && o.setState("collapsed"), V.current.delete(f); }, D.AUTO_COLLAPSE_DELAY); V.current.add(f); } }, [o, st]), F = d(() => { if (o.initialState === "collapsed" && o.state === "compact" && st()) { const f = setTimeout(() => { o.state === "compact" && st() && o.setState("collapsed"), V.current.delete(f); }, D.AUTO_COLLAPSE_DELAY); V.current.add(f); } }, [o, st]), j = d(async () => { if (v.value.trim()) { const f = v.value.trim(); v.clear(), o.state !== "expanded" && (p == null || p()), o.setState("expanded"), await s(f); } }, [v, s, o, p]), ct = d(() => { at.current = !0, p == null || p(), o.setState("expanded"); }, [p, o]), Dt = d(() => { T.current = !0, v.clear(), o.close(), g && g(); }, [v, o, g]), z = d( (f) => { if (!W.current || !tt.current) return null; const b = W.current.getBoundingClientRect(), q = tt.current.getBoundingClientRect(), lt = window.getComputedStyle(W.current), Ot = new DOMMatrixReadOnly(lt.transform), Jt = b.x - Ot.e, Nt = b.y - Ot.f, bt = f ?? wt, Ae = C(o.state), xe = bt === "left" ? q.left : q.right - D.COMPACT_WIDTH, Re = q.bottom - Ae; return { x: xe - Jt, y: Re - Nt }; }, [wt, o.state, C] ), gt = d( (f) => { const b = f.target; if (b.ownerDocument !== document) return; b.closest( St.NON_DRAGGABLE_SELECTORS ) || (f.preventDefault(), Lt.start(f.nativeEvent)); }, [Lt] ), Ut = d(() => { Z(!0); }, []), Wt = d( (f, b) => { Z(!1); const q = b.point.x, lt = D.COMPACT_WIDTH, Ot = (window.innerWidth - lt) / 2, Nt = q < Ot ? "left" : "right"; kt(Nt); const bt = z(Nt); bt && (Pt(rt, bt.x, { ...St.SPRING_CONFIG, velocity: b.velocity.x * St.VELOCITY_MULTIPLIER }), Pt(Y, bt.y, { ...St.SPRING_CONFIG, velocity: b.velocity.y * St.VELOCITY_MULTIPLIER })); }, [rt, Y, z] ), zt = L(o.state), Ee = zt.current === "compact" && o.state === "expanded"; E(() => { Q(), zt.current = o.state; }, [o.state, Q]), E(() => { if (o.state !== "expanded") return; const f = () => { const b = z(); b && (rt.set(b.x), Y.set(b.y)); }; return window.addEventListener("resize", f), () => window.removeEventListener("resize", f); }, [o.state, rt, Y, z]), E(() => { const f = V.current; return () => { f.forEach((b) => { clearTimeout(b); }), f.clear(); }; }, []), E(() => { if (o.state === "compact" && Ct.current) { const f = Ct.current.scrollHeight + D.PADDING; it(f); } }, [o.state, v.value]); const qt = { // Core data messages: t, isProcessing: a, error: r, // Input state inputValue: v.value, setInputValue: v.setValue, clearInput: v.clear, textareaRef: v.textareaRef, handleKeyDown: v.handleKeyDown, // Actions onSubmit: s, handleSubmit: j, onStop: w, // UI state variant: i, placeholder: h, emptyView: _, messageRenderer: H, // Floating chat specific floatingChatState: o.state, triggerIcon: c, onOpen: yt, onExpand: ct, onClose: Dt, // Suggestions suggestions: S, clearSuggestions: O, handleSuggestionSubmit: Rt, // Notice notice: u, // Internal state for components focusOnMount: at.current, fromCompact: Ee, showExpandButton: !v.value.trim() }; return i === "embedded" ? /* @__PURE__ */ n(Qt, { value: qt, children: /* @__PURE__ */ n( "div", { "data-slot": "chat-embedded", className: U( A, K.container, K.embedded ), children: e } ) }) : /* @__PURE__ */ I(Qt, { value: qt, children: [ /* @__PURE__ */ n( "div", { ref: tt, style: { position: "fixed", top: D.VIEWPORT_OFFSET, left: D.VIEWPORT_OFFSET, right: D.VIEWPORT_OFFSET, bottom: D.VIEWPORT_OFFSET, pointerEvents: "none" } } ), pt && /* @__PURE__ */ n(Yn, {}), /* @__PURE__ */ n( P.div, { ref: W, "data-slot": "chat-floating", className: U(A, K.container, K.floating, { animating: Ft }), onMouseLeave: o.state === "compact" ? F : void 0, drag: N.includes(o.state), dragControls: Lt, dragListener: !1, dragConstraints: tt, dragMomentum: !1, dragElastic: 0.1, dragTransition: { power: 0.1, timeConstant: 100 }, onDragStart: Ut, onDragEnd: Wt, onPointerDown: gt, style: { x: rt, y: Y, bottom: D.VIEWPORT_OFFSET, left: D.VIEWPORT_OFFSET, cursor: N.includes(o.state) ? "grab" : "default" }, children: /* @__PURE__ */ n( P.div, { layout: !0, className: K.content, initial: !1, animate: { width: o.state === "collapsed" ? D.COLLAPSED_SIZE : D.COMPACT_WIDTH, height: C(o.state), x: o.state === "collapsed" && wt === "right" ? D.COMPACT_WIDTH - D.COLLAPSED_SIZE : 0, transition: v.value.trim() ? { duration: 0 } : $t }, onAnimationStart: () => ht(!0), onAnimationComplete: () => ht(!1), style: { borderRadius: D.BORDER_RADIUS }, children: /* @__PURE__ */ I(At, { mode: "wait", children: [ o.state === "collapsed" && /* @__PURE__ */ n( de, { icon: c, onClick: yt, onHover: R, focusOnMount: T.current }, "collapsed" ), o.state === "compact" && /* @__PURE__ */ n("div", { ref: Ct, children: /* @__PURE__ */ n( he, { value: v.value, onChange: v.setValue, onSubmit: j, onKeyDown: v.handleKeyDown, textareaRef: v.textareaRef, placeholder: h, isProcessing: a, onBlur: F, onExpand: ct, showExpandButton: !v.value.trim(), focusOnMount: ot.current, onStop: w, suggestions: S, clearSuggestions: O, handleSuggestionSubmit: Rt }, "compact" ) }), o.state === "expanded" && e ] }) } ) } ) ] }); } function Le({ className: e } = {}) { const { onClose: t } = mt(); return /* @__PURE__ */ n(Ce, { onClose: t, className: e }); } function ye({ className: e } = {}) { const { messages: t, isProcessing: a, error: r, emptyView: s, messageRenderer: i } = mt(); return /* @__PURE__ */ n( ve, { messages: t, isProcessing: a, error: r, emptyView: s, messageRenderer: i, className: e } ); } function be({ className: e, disabled: t, customActions: a, actionOrder: r } = {}) { const { inputValue: s, setInputValue: i, handleSubmit: c, handleKeyDown: h, textareaRef: u, placeholder: m, isProcessing: p, onStop: g, fromCompact: w, onExpand: _, showExpandButton: y, focusOnMount: S } = mt(); return /* @__PURE__ */ n( Xt, { value: s, onChange: i, onSubmit: c, onKeyDown: h, textareaRef: u, placeholder: m, isProcessing: p, onStop: g, fromCompact: w, onExpand: _, showExpandButton: y, focusOnMount: S, disabled: t, customActions: a, actionOrder: r, className: e } ); } function Ie({ className: e, showSuggestions: t, onSelect: a } = {}) { const { suggestions: r, handleSuggestionSubmit: s, inputValue: i } = mt(), c = d( (h) => { try { a == null || a(h); } catch (u) { console.warn("Suggestions onSelect callback failed:", u); } s(h); }, [a, s] ); return i && !t ? null : /* @__PURE__ */ n( jt, { suggestions: r, onSubmit: c, className: e } ); } function Te({ className: e } = {}) { const { notice: t } = mt(); return t ? /* @__PURE__ */ n( ge, { icon: t.icon, message: t.message, action: t.action, dismissible: t.dismissible, onDismiss: t.onDismiss, className: e } ) : null; } function _e({ children: e, className: t } = {}) { return e ? /* @__PURE__ */ n( P.div, { "data-slot": "chat-footer", className: U(Kt.container, t), initial: { opacity: 0, scale: 1 }, animate: { opacity: 1, scale: 1 }, transition: { ...dt }, children: e } ) : /* @__PURE__ */ I( P.div, { "data-slot": "chat-footer", className: U(Kt.container, t), initial: { opacity: 0, scale: 1 }, animate: { opacity: 1, scale: 1 }, transition: { ...dt }, children: [ /* @__PURE__ */ n(Ie, {}), /* @__PURE__ */ n(Te, {}), /* @__PURE__ */ n(be, {}) ] } ); } function Se({ showHeader: e = !0, children: t, className: a } = {}) { const { onClose: r } = mt(); return E(() => { const s = (i) => { i.key === "Escape" && r && r(); }; return document.addEvent