UNPKG

@assistant-ui/react

Version:

Typescript/React library for AI Chat

138 lines (137 loc) 4.81 kB
"use strict"; "use client"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/utils/smooth/useSmooth.tsx var useSmooth_exports = {}; __export(useSmooth_exports, { useSmooth: () => useSmooth }); module.exports = __toCommonJS(useSmooth_exports); var import_react = require("react"); var import_context = require("../../context/index.js"); var import_react_use_callback_ref = require("@radix-ui/react-use-callback-ref"); var import_SmoothContext = require("./SmoothContext.js"); var import_ReadonlyStore = require("../../context/ReadonlyStore.js"); var TextStreamAnimator = class { constructor(currentText, setText) { this.currentText = currentText; this.setText = setText; } animationFrameId = null; lastUpdateTime = Date.now(); targetText = ""; start() { if (this.animationFrameId !== null) return; this.lastUpdateTime = Date.now(); this.animate(); } stop() { if (this.animationFrameId !== null) { cancelAnimationFrame(this.animationFrameId); this.animationFrameId = null; } } animate = () => { const currentTime = Date.now(); const deltaTime = currentTime - this.lastUpdateTime; let timeToConsume = deltaTime; const remainingChars = this.targetText.length - this.currentText.length; const baseTimePerChar = Math.min(5, 250 / remainingChars); let charsToAdd = 0; while (timeToConsume >= baseTimePerChar && charsToAdd < remainingChars) { charsToAdd++; timeToConsume -= baseTimePerChar; } if (charsToAdd !== remainingChars) { this.animationFrameId = requestAnimationFrame(this.animate); } else { this.animationFrameId = null; } if (charsToAdd === 0) return; this.currentText = this.targetText.slice( 0, this.currentText.length + charsToAdd ); this.lastUpdateTime = currentTime - timeToConsume; this.setText(this.currentText); }; }; var SMOOTH_STATUS = Object.freeze({ type: "running" }); var useSmooth = (state, smooth = false) => { const { text } = state; const id = (0, import_context.useMessage)({ optional: true, selector: (m) => m.id }); const idRef = (0, import_react.useRef)(id); const [displayedText, setDisplayedText] = (0, import_react.useState)(text); const smoothStatusStore = (0, import_SmoothContext.useSmoothStatusStore)({ optional: true }); const setText = (0, import_react_use_callback_ref.useCallbackRef)((text2) => { setDisplayedText(text2); if (smoothStatusStore) { const target = displayedText !== text2 || state.status.type === "running" ? SMOOTH_STATUS : state.status; (0, import_ReadonlyStore.writableStore)(smoothStatusStore).setState(target, true); } }); (0, import_react.useEffect)(() => { if (smoothStatusStore) { const target = displayedText !== text || state.status.type === "running" ? SMOOTH_STATUS : state.status; (0, import_ReadonlyStore.writableStore)(smoothStatusStore).setState(target, true); } }, [smoothStatusStore, text, displayedText, state.status]); const [animatorRef] = (0, import_react.useState)( new TextStreamAnimator(text, setText) ); (0, import_react.useEffect)(() => { if (!smooth) { animatorRef.stop(); return; } if (idRef.current !== id || !text.startsWith(animatorRef.targetText)) { idRef.current = id; setText(text); animatorRef.currentText = text; animatorRef.targetText = text; animatorRef.stop(); return; } animatorRef.targetText = text; animatorRef.start(); }, [setText, animatorRef, id, smooth, text]); (0, import_react.useEffect)(() => { return () => { animatorRef.stop(); }; }, [animatorRef]); return (0, import_react.useMemo)( () => smooth ? { type: "text", text: displayedText, status: text === displayedText ? state.status : SMOOTH_STATUS } : state, [smooth, displayedText, state, text] ); }; // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { useSmooth }); //# sourceMappingURL=useSmooth.js.map