@assistant-ui/react 0.3.1 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -668,7 +668,7 @@ var useContentPartDisplay = () => {
668
668
  throw new Error(
669
669
  "This component can only be used inside ui content parts."
670
670
  );
671
- return c.part.display;
671
+ return c;
672
672
  });
673
673
  return display;
674
674
  };
@@ -681,7 +681,7 @@ var useContentPartImage = () => {
681
681
  throw new Error(
682
682
  "ContentPartImage can only be used inside image content parts."
683
683
  );
684
- return c.part.image;
684
+ return c;
685
685
  });
686
686
  return image;
687
687
  };
@@ -1163,13 +1163,92 @@ var ContentPartProvider = ({
1163
1163
  // src/primitives/contentPart/ContentPartText.tsx
1164
1164
  import { Primitive as Primitive4 } from "@radix-ui/react-primitive";
1165
1165
  import { forwardRef as forwardRef7 } from "react";
1166
+
1167
+ // src/utils/hooks/useSmooth.tsx
1168
+ import { useEffect as useEffect8, useState as useState5 } from "react";
1169
+ var TextStreamAnimator = class {
1170
+ constructor(setText) {
1171
+ this.setText = setText;
1172
+ }
1173
+ animationFrameId = null;
1174
+ lastUpdateTime = Date.now();
1175
+ targetText = "";
1176
+ start() {
1177
+ if (this.animationFrameId !== null) return;
1178
+ this.lastUpdateTime = Date.now();
1179
+ this.animate();
1180
+ }
1181
+ stop() {
1182
+ if (this.animationFrameId !== null) {
1183
+ cancelAnimationFrame(this.animationFrameId);
1184
+ this.animationFrameId = null;
1185
+ }
1186
+ }
1187
+ animate = () => {
1188
+ const currentTime = Date.now();
1189
+ const deltaTime = currentTime - this.lastUpdateTime;
1190
+ let timeToConsume = deltaTime;
1191
+ this.setText((currentText) => {
1192
+ const targetText = this.targetText;
1193
+ if (currentText === targetText) {
1194
+ this.animationFrameId = null;
1195
+ return currentText;
1196
+ }
1197
+ const remainingChars = targetText.length - currentText.length;
1198
+ const baseTimePerChar = Math.min(5, 250 / remainingChars);
1199
+ let charsToAdd = 0;
1200
+ while (timeToConsume >= baseTimePerChar && charsToAdd < remainingChars) {
1201
+ charsToAdd++;
1202
+ timeToConsume -= baseTimePerChar;
1203
+ }
1204
+ this.animationFrameId = requestAnimationFrame(this.animate);
1205
+ if (charsToAdd === 0) {
1206
+ return currentText;
1207
+ }
1208
+ const newText = targetText.slice(0, currentText.length + charsToAdd);
1209
+ this.lastUpdateTime = currentTime - timeToConsume;
1210
+ return newText;
1211
+ });
1212
+ };
1213
+ };
1214
+ var useSmooth = (text, smooth = false) => {
1215
+ const [displayedText, setDisplayedText] = useState5(text);
1216
+ const [animatorRef] = useState5(
1217
+ new TextStreamAnimator(setDisplayedText)
1218
+ );
1219
+ useEffect8(() => {
1220
+ console.log("smooth", smooth);
1221
+ if (!smooth) {
1222
+ animatorRef.stop();
1223
+ return;
1224
+ }
1225
+ if (!text.startsWith(animatorRef.targetText)) {
1226
+ setDisplayedText(text);
1227
+ animatorRef.targetText = text;
1228
+ animatorRef.stop();
1229
+ return;
1230
+ }
1231
+ animatorRef.targetText = text;
1232
+ animatorRef.start();
1233
+ console.log("animating");
1234
+ }, [animatorRef, smooth, text]);
1235
+ useEffect8(() => {
1236
+ return () => {
1237
+ animatorRef.stop();
1238
+ };
1239
+ }, [animatorRef]);
1240
+ return smooth ? displayedText : text;
1241
+ };
1242
+
1243
+ // src/primitives/contentPart/ContentPartText.tsx
1166
1244
  import { jsx as jsx14 } from "react/jsx-runtime";
1167
- var ContentPartPrimitiveText = forwardRef7((props, forwardedRef) => {
1245
+ var ContentPartPrimitiveText = forwardRef7(({ smooth = true, ...rest }, forwardedRef) => {
1168
1246
  const {
1169
- part: { text },
1170
- status
1247
+ status,
1248
+ part: { text }
1171
1249
  } = useContentPartText();
1172
- return /* @__PURE__ */ jsx14(Primitive4.span, { "data-status": status, ...props, ref: forwardedRef, children: text });
1250
+ const smoothText = useSmooth(text, smooth);
1251
+ return /* @__PURE__ */ jsx14(Primitive4.span, { "data-status": status, ...rest, ref: forwardedRef, children: smoothText });
1173
1252
  });
1174
1253
  ContentPartPrimitiveText.displayName = "ContentPartPrimitive.Text";
1175
1254
 
@@ -1178,14 +1257,18 @@ import { Primitive as Primitive5 } from "@radix-ui/react-primitive";
1178
1257
  import { forwardRef as forwardRef8 } from "react";
1179
1258
  import { jsx as jsx15 } from "react/jsx-runtime";
1180
1259
  var ContentPartPrimitiveImage = forwardRef8((props, forwardedRef) => {
1181
- const image = useContentPartImage();
1260
+ const {
1261
+ part: { image }
1262
+ } = useContentPartImage();
1182
1263
  return /* @__PURE__ */ jsx15(Primitive5.img, { src: image, ...props, ref: forwardedRef });
1183
1264
  });
1184
1265
  ContentPartPrimitiveImage.displayName = "ContentPartPrimitive.Image";
1185
1266
 
1186
1267
  // src/primitives/contentPart/ContentPartDisplay.tsx
1187
1268
  var ContentPartPrimitiveDisplay = () => {
1188
- const display = useContentPartDisplay();
1269
+ const {
1270
+ part: { display }
1271
+ } = useContentPartDisplay();
1189
1272
  return display ?? null;
1190
1273
  };
1191
1274
  ContentPartPrimitiveDisplay.displayName = "ContentPartPrimitive.Display";
@@ -1331,7 +1414,7 @@ import { Slot } from "@radix-ui/react-slot";
1331
1414
  import {
1332
1415
  forwardRef as forwardRef11,
1333
1416
  useCallback as useCallback15,
1334
- useEffect as useEffect8,
1417
+ useEffect as useEffect9,
1335
1418
  useRef as useRef4
1336
1419
  } from "react";
1337
1420
  import TextareaAutosize from "react-textarea-autosize";
@@ -1375,7 +1458,7 @@ var ComposerPrimitiveInput = forwardRef11(
1375
1458
  textareaRef.current.value.length
1376
1459
  );
1377
1460
  }, [autoFocusEnabled]);
1378
- useEffect8(() => focus(), [focus]);
1461
+ useEffect9(() => focus(), [focus]);
1379
1462
  useOnComposerFocus(() => {
1380
1463
  if (type === "new") {
1381
1464
  focus();
@@ -1536,11 +1619,11 @@ var useOnResizeContent = (callback) => {
1536
1619
 
1537
1620
  // src/utils/hooks/useOnScrollToBottom.tsx
1538
1621
  import { useCallbackRef as useCallbackRef3 } from "@radix-ui/react-use-callback-ref";
1539
- import { useEffect as useEffect9 } from "react";
1622
+ import { useEffect as useEffect10 } from "react";
1540
1623
  var useOnScrollToBottom = (callback) => {
1541
1624
  const callbackRef = useCallbackRef3(callback);
1542
1625
  const { useViewport } = useThreadContext();
1543
- useEffect9(() => {
1626
+ useEffect10(() => {
1544
1627
  return useViewport.getState().onScrollToBottom(() => {
1545
1628
  callbackRef();
1546
1629
  });
@@ -1615,7 +1698,7 @@ ThreadPrimitiveViewport.displayName = "ThreadPrimitive.Viewport";
1615
1698
  import { memo as memo3 } from "react";
1616
1699
 
1617
1700
  // src/context/providers/MessageProvider.tsx
1618
- import { useEffect as useEffect10, useState as useState5 } from "react";
1701
+ import { useEffect as useEffect11, useState as useState6 } from "react";
1619
1702
  import { create as create12 } from "zustand";
1620
1703
 
1621
1704
  // src/context/stores/EditComposer.ts
@@ -1677,7 +1760,7 @@ var syncMessage = (messages, getBranches, useMessage, messageIndex) => {
1677
1760
  };
1678
1761
  var useMessageContext2 = (messageIndex) => {
1679
1762
  const { useThreadMessages, useThreadActions } = useThreadContext();
1680
- const [context] = useState5(() => {
1763
+ const [context] = useState6(() => {
1681
1764
  const useMessage = create12(() => ({}));
1682
1765
  const useMessageUtils = makeMessageUtilsStore();
1683
1766
  const useEditComposer = makeEditComposerStore({
@@ -1714,7 +1797,7 @@ var useMessageContext2 = (messageIndex) => {
1714
1797
  );
1715
1798
  return { useMessage, useMessageUtils, useEditComposer };
1716
1799
  });
1717
- useEffect10(() => {
1800
+ useEffect11(() => {
1718
1801
  return useThreadMessages.subscribe((thread) => {
1719
1802
  syncMessage(
1720
1803
  thread,
@@ -1797,7 +1880,7 @@ var ThreadPrimitiveSuggestion = createActionButton(
1797
1880
  );
1798
1881
 
1799
1882
  // src/runtime/local/useLocalRuntime.tsx
1800
- import { useInsertionEffect as useInsertionEffect3, useState as useState6 } from "react";
1883
+ import { useInsertionEffect as useInsertionEffect3, useState as useState7 } from "react";
1801
1884
 
1802
1885
  // src/runtime/utils/idUtils.tsx
1803
1886
  import { customAlphabet } from "nanoid/non-secure";
@@ -2139,7 +2222,7 @@ var LocalThreadRuntime = class {
2139
2222
 
2140
2223
  // src/runtime/local/useLocalRuntime.tsx
2141
2224
  var useLocalRuntime = (adapter) => {
2142
- const [runtime] = useState6(() => new LocalRuntime(adapter));
2225
+ const [runtime] = useState7(() => new LocalRuntime(adapter));
2143
2226
  useInsertionEffect3(() => {
2144
2227
  runtime.adapter = adapter;
2145
2228
  });
@@ -2151,7 +2234,8 @@ var internal_exports = {};
2151
2234
  __export(internal_exports, {
2152
2235
  BaseAssistantRuntime: () => BaseAssistantRuntime,
2153
2236
  MessageRepository: () => MessageRepository,
2154
- ProxyConfigProvider: () => ProxyConfigProvider
2237
+ ProxyConfigProvider: () => ProxyConfigProvider,
2238
+ useSmooth: () => useSmooth
2155
2239
  });
2156
2240
  export {
2157
2241
  actionBar_exports as ActionBarPrimitive,