UNPKG

@rohitkvs/ai-assistant-widget

Version:

A React/Next.js library for AI assistant widget with floating button, voice call, and chat functionality

676 lines (675 loc) 24.3 kB
import ne, { useState as k, useRef as U, useEffect as B } from "react"; import { motion as f, AnimatePresence as I } from "framer-motion"; import E from "clsx"; var L = { exports: {} }, R = {}; /** * @license React * react-jsx-runtime.production.js * * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ var W; function le() { if (W) return R; W = 1; var r = Symbol.for("react.transitional.element"), c = Symbol.for("react.fragment"); function d(o, l, i) { var h = null; if (i !== void 0 && (h = "" + i), l.key !== void 0 && (h = "" + l.key), "key" in l) { i = {}; for (var p in l) p !== "key" && (i[p] = l[p]); } else i = l; return l = i.ref, { $$typeof: r, type: o, key: h, ref: l !== void 0 ? l : null, props: i }; } return R.Fragment = c, R.jsx = d, R.jsxs = d, R; } var C = {}; /** * @license React * react-jsx-runtime.development.js * * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ var q; function oe() { return q || (q = 1, process.env.NODE_ENV !== "production" && function() { function r(e) { if (e == null) return null; if (typeof e == "function") return e.$$typeof === re ? null : e.displayName || e.name || null; if (typeof e == "string") return e; switch (e) { case _: return "Fragment"; case J: return "Profiler"; case G: return "StrictMode"; case K: return "Suspense"; case ee: return "SuspenseList"; case ae: return "Activity"; } if (typeof e == "object") switch (typeof e.tag == "number" && console.error( "Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue." ), e.$$typeof) { case N: return "Portal"; case Z: return (e.displayName || "Context") + ".Provider"; case X: return (e._context.displayName || "Context") + ".Consumer"; case Q: var a = e.render; return e = e.displayName, e || (e = a.displayName || a.name || "", e = e !== "" ? "ForwardRef(" + e + ")" : "ForwardRef"), e; case te: return a = e.displayName || null, a !== null ? a : r(e.type) || "Memo"; case $: a = e._payload, e = e._init; try { return r(e(a)); } catch { } } return null; } function c(e) { return "" + e; } function d(e) { try { c(e); var a = !1; } catch { a = !0; } if (a) { a = console; var n = a.error, u = typeof Symbol == "function" && Symbol.toStringTag && e[Symbol.toStringTag] || e.constructor.name || "Object"; return n.call( a, "The provided key is an unsupported type %s. This value must be coerced to a string before using it here.", u ), c(e); } } function o(e) { if (e === _) return "<>"; if (typeof e == "object" && e !== null && e.$$typeof === $) return "<...>"; try { var a = r(e); return a ? "<" + a + ">" : "<...>"; } catch { return "<...>"; } } function l() { var e = S.A; return e === null ? null : e.getOwner(); } function i() { return Error("react-stack-top-frame"); } function h(e) { if (z.call(e, "key")) { var a = Object.getOwnPropertyDescriptor(e, "key").get; if (a && a.isReactWarning) return !1; } return e.key !== void 0; } function p(e, a) { function n() { H || (H = !0, console.error( "%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)", a )); } n.isReactWarning = !0, Object.defineProperty(e, "key", { get: n, configurable: !0 }); } function g() { var e = r(this.type); return Y[e] || (Y[e] = !0, console.error( "Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release." )), e = this.props.ref, e !== void 0 ? e : null; } function w(e, a, n, u, v, x, A, P) { return n = x.ref, e = { $$typeof: j, type: e, key: a, props: x, _owner: v }, (n !== void 0 ? n : null) !== null ? Object.defineProperty(e, "ref", { enumerable: !1, get: g }) : Object.defineProperty(e, "ref", { enumerable: !1, value: null }), e._store = {}, Object.defineProperty(e._store, "validated", { configurable: !1, enumerable: !1, writable: !0, value: 0 }), Object.defineProperty(e, "_debugInfo", { configurable: !1, enumerable: !1, writable: !0, value: null }), Object.defineProperty(e, "_debugStack", { configurable: !1, enumerable: !1, writable: !0, value: A }), Object.defineProperty(e, "_debugTask", { configurable: !1, enumerable: !1, writable: !0, value: P }), Object.freeze && (Object.freeze(e.props), Object.freeze(e)), e; } function b(e, a, n, u, v, x, A, P) { var m = a.children; if (m !== void 0) if (u) if (ie(m)) { for (u = 0; u < m.length; u++) T(m[u]); Object.freeze && Object.freeze(m); } else console.error( "React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead." ); else T(m); if (z.call(a, "key")) { m = r(e); var y = Object.keys(a).filter(function(se) { return se !== "key"; }); u = 0 < y.length ? "{key: someKey, " + y.join(": ..., ") + ": ...}" : "{key: someKey}", V[m + u] || (y = 0 < y.length ? "{" + y.join(": ..., ") + ": ...}" : "{}", console.error( `A props object containing a "key" prop is being spread into JSX: let props = %s; <%s {...props} /> React keys must be passed directly to JSX without using spread: let props = %s; <%s key={someKey} {...props} />`, u, m, y, m ), V[m + u] = !0); } if (m = null, n !== void 0 && (d(n), m = "" + n), h(a) && (d(a.key), m = "" + a.key), "key" in a) { n = {}; for (var M in a) M !== "key" && (n[M] = a[M]); } else n = a; return m && p( n, typeof e == "function" ? e.displayName || e.name || "Unknown" : e ), w( e, m, x, v, l(), n, A, P ); } function T(e) { typeof e == "object" && e !== null && e.$$typeof === j && e._store && (e._store.validated = 1); } var s = ne, j = Symbol.for("react.transitional.element"), N = Symbol.for("react.portal"), _ = Symbol.for("react.fragment"), G = Symbol.for("react.strict_mode"), J = Symbol.for("react.profiler"), X = Symbol.for("react.consumer"), Z = Symbol.for("react.context"), Q = Symbol.for("react.forward_ref"), K = Symbol.for("react.suspense"), ee = Symbol.for("react.suspense_list"), te = Symbol.for("react.memo"), $ = Symbol.for("react.lazy"), ae = Symbol.for("react.activity"), re = Symbol.for("react.client.reference"), S = s.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, z = Object.prototype.hasOwnProperty, ie = Array.isArray, O = console.createTask ? console.createTask : function() { return null; }; s = { "react-stack-bottom-frame": function(e) { return e(); } }; var H, Y = {}, D = s["react-stack-bottom-frame"].bind( s, i )(), F = O(o(i)), V = {}; C.Fragment = _, C.jsx = function(e, a, n, u, v) { var x = 1e4 > S.recentlyCreatedOwnerStacks++; return b( e, a, n, !1, u, v, x ? Error("react-stack-top-frame") : D, x ? O(o(e)) : F ); }, C.jsxs = function(e, a, n, u, v) { var x = 1e4 > S.recentlyCreatedOwnerStacks++; return b( e, a, n, !0, u, v, x ? Error("react-stack-top-frame") : D, x ? O(o(e)) : F ); }; }()), C; } process.env.NODE_ENV === "production" ? L.exports = le() : L.exports = oe(); var t = L.exports; const ce = ({ onClick: r, className: c, position: d = { bottom: "24px", right: "24px" } }) => /* @__PURE__ */ t.jsx( f.button, { onClick: r, className: E("ai-widget-floating-btn", c), style: d, whileHover: { scale: 1.05 }, whileTap: { scale: 0.95 }, initial: { scale: 0 }, animate: { scale: 1 }, transition: { type: "spring", stiffness: 260, damping: 20 }, children: /* @__PURE__ */ t.jsx( "svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ t.jsx( "path", { d: "M20 2H4C2.9 2 2 2.9 2 4V16C2 17.1 2.9 18 4 18H6L10 22L14 18H20C21.1 18 22 17.1 22 16V4C22 2.9 21.1 2 20 2Z", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", fill: "none" } ) } ) } ), de = ({ isOpen: r, onClose: c, onStartCall: d, onStartChat: o, position: l = { bottom: "100px", right: "24px" } }) => /* @__PURE__ */ t.jsx(I, { children: r && /* @__PURE__ */ t.jsxs(t.Fragment, { children: [ /* @__PURE__ */ t.jsx( f.div, { className: "ai-widget-backdrop", initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, onClick: c } ), /* @__PURE__ */ t.jsxs( f.div, { className: "ai-widget-modal", style: l, initial: { opacity: 0, scale: 0.8, y: 20 }, animate: { opacity: 1, scale: 1, y: 0 }, exit: { opacity: 0, scale: 0.8, y: 20 }, transition: { type: "spring", stiffness: 300, damping: 30 }, children: [ /* @__PURE__ */ t.jsxs("div", { className: "ai-widget-modal-header", children: [ /* @__PURE__ */ t.jsx("h2", { className: "ai-widget-modal-title", children: "AI Assistant" }), /* @__PURE__ */ t.jsx( "button", { onClick: c, className: "ai-widget-close-btn", children: /* @__PURE__ */ t.jsx("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "currentColor", children: /* @__PURE__ */ t.jsx("path", { fillRule: "evenodd", d: "M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z", clipRule: "evenodd" }) }) } ) ] }), /* @__PURE__ */ t.jsxs("div", { className: "ai-widget-options", children: [ /* @__PURE__ */ t.jsxs( f.button, { onClick: d, className: "ai-widget-option-btn", whileHover: { scale: 1.02 }, whileTap: { scale: 0.98 }, children: [ /* @__PURE__ */ t.jsx("div", { className: "ai-widget-option-icon", children: /* @__PURE__ */ t.jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ t.jsx("path", { d: "M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z" }) }) }), /* @__PURE__ */ t.jsx("span", { className: "ai-widget-option-text", children: "Start Call" }) ] } ), /* @__PURE__ */ t.jsxs( f.button, { onClick: o, className: "ai-widget-option-btn", whileHover: { scale: 1.02 }, whileTap: { scale: 0.98 }, children: [ /* @__PURE__ */ t.jsx("div", { className: "ai-widget-option-icon", children: /* @__PURE__ */ t.jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ t.jsx("path", { d: "M20 2H4C2.9 2 2 2.9 2 4V16C2 17.1 2.9 18 4 18H6L10 22L14 18H20C21.1 18 22 17.1 22 16V4C22 2.9 21.1 2 20 2Z" }) }) }), /* @__PURE__ */ t.jsx("span", { className: "ai-widget-option-text", children: "Start Chat" }) ] } ) ] }) ] } ) ] }) }), ue = ({ isOpen: r, onClose: c, position: d = { bottom: "100px", right: "24px" } }) => { const [o, l] = k(!1), [i, h] = k(!0), p = () => { l(!o); }, g = () => { h(!1), c(); }; return /* @__PURE__ */ t.jsx(I, { children: r && /* @__PURE__ */ t.jsxs(t.Fragment, { children: [ /* @__PURE__ */ t.jsx( f.div, { className: "ai-widget-backdrop", initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, onClick: c } ), /* @__PURE__ */ t.jsxs( f.div, { className: "ai-widget-modal ai-widget-voice-modal", style: d, initial: { opacity: 0, scale: 0.8, y: 20 }, animate: { opacity: 1, scale: 1, y: 0 }, exit: { opacity: 0, scale: 0.8, y: 20 }, transition: { type: "spring", stiffness: 300, damping: 30 }, children: [ /* @__PURE__ */ t.jsxs("div", { className: "ai-widget-modal-header", children: [ /* @__PURE__ */ t.jsx("h2", { className: "ai-widget-modal-title", children: "Voice Call" }), /* @__PURE__ */ t.jsx( "button", { onClick: c, className: "ai-widget-close-btn", children: /* @__PURE__ */ t.jsx("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "currentColor", children: /* @__PURE__ */ t.jsx("path", { fillRule: "evenodd", d: "M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z", clipRule: "evenodd" }) }) } ) ] }), /* @__PURE__ */ t.jsxs("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", marginBottom: "2rem" }, children: [ /* @__PURE__ */ t.jsx( f.div, { className: E("ai-widget-avatar", { "ai-widget-pulse": i }), animate: i ? { scale: [1, 1.05, 1] } : {}, transition: { duration: 2, repeat: 1 / 0 }, children: /* @__PURE__ */ t.jsx("div", { className: "ai-widget-avatar-dot" }) } ), /* @__PURE__ */ t.jsx("span", { className: "ai-widget-status", children: i ? "Connected" : "Connecting..." }) ] }), /* @__PURE__ */ t.jsxs("div", { className: "ai-widget-controls", children: [ /* @__PURE__ */ t.jsx( f.button, { onClick: p, className: E("ai-widget-control-btn ai-widget-mute-btn", { muted: o }), whileHover: { scale: 1.05 }, whileTap: { scale: 0.95 }, children: o ? /* @__PURE__ */ t.jsx("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ t.jsx("path", { d: "M16.5 12c0-1.77-1.02-3.29-2.5-4.03v2.21l2.45 2.45c.03-.2.05-.41.05-.63zm2.5 0c0 .94-.2 1.82-.54 2.64l1.51 1.51C20.63 14.91 21 13.5 21 12c0-4.28-2.99-7.86-7-8.77v2.06c2.89.86 5 3.54 5 6.71zM4.27 3L3 4.27 7.73 9H3v6h4l5 5v-6.73l4.25 4.25c-.67.52-1.42.93-2.25 1.18v2.06c1.38-.31 2.63-.95 3.69-1.81L19.73 21 21 19.73l-9-9L4.27 3zM12 4L9.91 6.09 12 8.18V4z" }) }) : /* @__PURE__ */ t.jsx("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ t.jsx("path", { d: "M12 2c1.1 0 2 .9 2 2v6c0 1.1-.9 2-2 2s-2-.9-2-2V4c0-1.1.9-2 2-2zm6 6c0 4.28-2.99 7.86-7 8.77v2.06c5.93-.94 10.5-6.13 10.5-12.17h-1.5c0 0 0 0 0 0zm-12 0H4.5c0 6.04 4.57 11.23 10.5 12.17v-2.06C10.99 15.86 8 12.28 8 8H6z" }) }) } ), /* @__PURE__ */ t.jsx( f.button, { onClick: g, className: "ai-widget-control-btn ai-widget-end-btn", whileHover: { scale: 1.05 }, whileTap: { scale: 0.95 }, children: /* @__PURE__ */ t.jsxs("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "currentColor", children: [ /* @__PURE__ */ t.jsx("path", { d: "M19.23 15.26l-2.54-.29c-.61-.07-1.21.14-1.64.57l-1.84 1.84c-2.83-1.44-5.15-3.75-6.59-6.59l1.85-1.85c.43-.43.64-1.03.57-1.64l-.29-2.52c-.12-1.01-.97-1.77-1.99-1.77H5.03c-1.13 0-2.07.94-2 2.07.53 8.54 7.36 15.36 15.89 15.89 1.13.07 2.07-.87 2.07-2v-1.73c.01-1.01-.75-1.86-1.76-1.98z" }), /* @__PURE__ */ t.jsx("path", { d: "M16 4h4v4l-6-6v4c0 1.1.9 2 2 2z" }) ] }) } ) ] }) ] } ) ] }) }); }, me = ({ isOpen: r, onClose: c, position: d = { bottom: "100px", right: "24px" } }) => { const [o, l] = k([ { id: "1", text: "Hello! How can I help you today?", isUser: !1, timestamp: /* @__PURE__ */ new Date() } ]), [i, h] = k(""), p = U(null), g = U(null), w = () => { var s; (s = p.current) == null || s.scrollIntoView({ behavior: "smooth" }); }; B(() => { w(); }, [o]), B(() => { r && g.current && setTimeout(() => { var s; return (s = g.current) == null ? void 0 : s.focus(); }, 100); }, [r]); const b = () => { if (i.trim()) { const s = { id: Date.now().toString(), text: i, isUser: !0, timestamp: /* @__PURE__ */ new Date() }; l((j) => [...j, s]), h(""), setTimeout(() => { const j = { id: (Date.now() + 1).toString(), text: "I understand. Let me help you with that.", isUser: !1, timestamp: /* @__PURE__ */ new Date() }; l((N) => [...N, j]); }, 1e3); } }, T = (s) => { s.key === "Enter" && b(); }; return /* @__PURE__ */ t.jsx(I, { children: r && /* @__PURE__ */ t.jsxs(t.Fragment, { children: [ /* @__PURE__ */ t.jsx( f.div, { className: "ai-widget-backdrop", initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, onClick: c } ), /* @__PURE__ */ t.jsxs( f.div, { className: "ai-widget-modal ai-widget-chat-modal", style: d, initial: { opacity: 0, scale: 0.8, y: 20 }, animate: { opacity: 1, scale: 1, y: 0 }, exit: { opacity: 0, scale: 0.8, y: 20 }, transition: { type: "spring", stiffness: 300, damping: 30 }, children: [ /* @__PURE__ */ t.jsxs("div", { className: "ai-widget-chat-header", children: [ /* @__PURE__ */ t.jsx("h2", { className: "ai-widget-modal-title", children: "Chat" }), /* @__PURE__ */ t.jsx( "button", { onClick: c, className: "ai-widget-close-btn", children: /* @__PURE__ */ t.jsx("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "currentColor", children: /* @__PURE__ */ t.jsx("path", { fillRule: "evenodd", d: "M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z", clipRule: "evenodd" }) }) } ) ] }), /* @__PURE__ */ t.jsxs("div", { className: "ai-widget-messages", children: [ o.map((s) => /* @__PURE__ */ t.jsx( f.div, { initial: { opacity: 0, y: 10 }, animate: { opacity: 1, y: 0 }, className: E("ai-widget-message", { user: s.isUser, assistant: !s.isUser }), children: /* @__PURE__ */ t.jsx( "div", { className: E("ai-widget-message-bubble", { user: s.isUser, assistant: !s.isUser }), children: s.text } ) }, s.id )), /* @__PURE__ */ t.jsx("div", { ref: p }) ] }), /* @__PURE__ */ t.jsx("div", { className: "ai-widget-chat-input", children: /* @__PURE__ */ t.jsxs("div", { className: "ai-widget-input-container", children: [ /* @__PURE__ */ t.jsx( "input", { ref: g, type: "text", value: i, onChange: (s) => h(s.target.value), onKeyPress: T, placeholder: "Type your message...", className: "ai-widget-input" } ), /* @__PURE__ */ t.jsx( f.button, { onClick: b, disabled: !i.trim(), className: E("ai-widget-send-btn", { active: i.trim(), disabled: !i.trim() }), whileHover: i.trim() ? { scale: 1.05 } : {}, whileTap: i.trim() ? { scale: 0.95 } : {}, children: /* @__PURE__ */ t.jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ t.jsx("path", { d: "M2.01 21L23 12 2.01 3 2 10l15 2-15 2z" }) }) } ) ] }) }) ] } ) ] }) }); }, xe = ({ position: r = { bottom: "24px", right: "24px" }, className: c }) => { const [d, o] = k("closed"), l = () => { o("assistant"); }, i = () => { o("closed"); }, h = () => { o("voice"); }, p = () => { o("chat"); }, w = r.bottom && r.right ? { bottom: `calc(${r.bottom} + 100px)`, right: r.right } : r.bottom && r.left ? { bottom: `calc(${r.bottom} + 100px)`, left: r.left } : r.top && r.right ? { top: `calc(${r.top} + 100px)`, right: r.right } : r.top && r.left ? { top: `calc(${r.top} + 100px)`, left: r.left } : { bottom: `calc(${r.bottom || "24px"} + 100px)`, right: r.right || "24px" }; return /* @__PURE__ */ t.jsxs("div", { className: "ai-widget-container", children: [ /* @__PURE__ */ t.jsx( ce, { onClick: l, position: r, className: c } ), /* @__PURE__ */ t.jsx( de, { isOpen: d === "assistant", onClose: i, onStartCall: h, onStartChat: p, position: w } ), /* @__PURE__ */ t.jsx( ue, { isOpen: d === "voice", onClose: i, position: w } ), /* @__PURE__ */ t.jsx( me, { isOpen: d === "chat", onClose: i, position: w } ) ] }); }; export { de as AIAssistantModal, xe as AIWidget, me as ChatModal, ce as FloatingButton, ue as VoiceCallModal };