UNPKG

@progress/kendo-react-conversational-ui

Version:

React Chat component allows the user to participate in chat sessions with users or chat bots. KendoReact Conversational UI components

173 lines (170 loc) 4.93 kB
/** * @license *------------------------------------------------------------------------------------------- * Copyright © 2025 Progress Software Corporation. All rights reserved. * Licensed under commercial license. See LICENSE.md in the package root for more information *------------------------------------------------------------------------------------------- */ import * as c from "react"; const A = 50, _ = 250, h = 50, m = 100, B = ({ viewItemsWrapperRef: n, isKeyboardNavigationActiveRef: S, processedMessages: a, suggestions: f }) => { const s = c.useCallback(() => { n.current && (n.current.scrollTop = n.current.scrollHeight - n.current.clientHeight); }, [n]), u = c.useCallback(() => { if (!n.current) return !0; const t = n.current, { scrollTop: e, scrollHeight: r, clientHeight: l } = t, i = A + 25; return r - e - l < i; }, [n]), b = c.useCallback((t) => t === 0 ? 16 : t <= 2 ? 32 * t : Math.min(50 * t, 200), []), C = c.useCallback( (t, e) => { const r = b(t); setTimeout(() => { !u() && n.current && e(t + 1); }, r); }, [b, u, n] ), d = c.useCallback(() => { const t = (e = 0) => { e > 5 || requestAnimationFrame(() => { s(), C(e, t); }); }; t(); }, [s, C]), y = c.useCallback(() => { s(), setTimeout(() => { !u() && n.current && s(); }, 50); }, [s, u, n]), E = c.useCallback(() => { requestAnimationFrame(() => { requestAnimationFrame(() => { requestAnimationFrame(y); }); }); }, [y]), L = c.useCallback(() => { s(), setTimeout(() => { !u() && n.current && d(); }, 25); }, [s, u, n, d]), o = c.useCallback( (t = !1) => { if (!n.current || S.current) return; u() && (t ? L() : E()); }, [ u, L, E, n, S ] ); c.useEffect(() => { const t = window.setTimeout(() => s(), _); return () => { clearTimeout(t); }; }, [s]), c.useEffect(() => { d(); }, [a.length, d]); const k = c.useRef(/* @__PURE__ */ new Map()); c.useEffect(() => { const t = /* @__PURE__ */ new Map(); let e = !1; a.forEach((r) => { if (r.id !== void 0) { const l = r.id, i = !!r.typing, T = k.current.get(l); t.set(l, i), T === !0 && i === !1 && (e = !0); } }), k.current = t, e && d(); }, [a, d]), c.useEffect(() => { const t = window.setTimeout(() => { o(); }, h); return () => { clearTimeout(t); }; }, [a, o]), c.useEffect(() => { if (a.length > 0) { const t = a[a.length - 1], e = (t == null ? void 0 : t.text) || ""; (e.includes("```") || e.includes(` `) || e.includes("<pre>") || e.includes("<code>") || e.includes("<table>") || e.length > 500) && o(!0); } }, [a, o]), c.useEffect(() => { if (f && f.length > 0) { const t = window.setTimeout(() => { o(); }, m); return () => { clearTimeout(t); }; } }, [f, o]), c.useEffect(() => { if (!n.current) return () => { }; let t; const e = new ResizeObserver(() => { t && clearTimeout(t), t = window.setTimeout(() => { o(); }, h); }), r = n.current.querySelector(".k-message-list-content"); return r && e.observe(r), () => { e.disconnect(); }; }, [o, n]); const g = c.useCallback((t) => { var r; if (t.type !== "characterData" && t.type !== "childList") return !1; const e = (r = t.target.textContent) != null ? r : ""; return e.includes("```") || e.includes(` `) || e.includes("<pre>") || e.includes("<code>") || e.includes("<table>") || t.addedNodes && t.addedNodes.length > 2; }, []), O = c.useCallback( (t) => { let e = !1, r = !1; return t.forEach((l) => { var i; (l.type === "childList" || l.type === "characterData" || l.type === "attributes" && ["class", "style"].includes((i = l.attributeName) != null ? i : "")) && (e = !0, g(l) && (r = !0)); }), { shouldScroll: e, hasSignificantChange: r }; }, [g] ), D = c.useCallback( (t, e) => { e.current && clearTimeout(e.current), t ? o(!0) : e.current = window.setTimeout(() => { o(); }, h); }, [o] ); c.useEffect(() => { if (!n.current) return () => { }; const t = { current: void 0 }; let e = 0; const r = new MutationObserver((l) => { const i = Date.now(); if (i - e < 16) return; e = i; const { shouldScroll: T, hasSignificantChange: x } = O(l); T && u() && D(x, t); }); return r.observe(n.current, { childList: !0, subtree: !0, characterData: !0, attributes: !0, attributeFilter: ["class", "style"] }), () => { r.disconnect(), t.current && clearTimeout(t.current); }; }, [u, O, D, n]); }; export { B as useChatScroll };