@assistant-ui/react-native 0.1.44 → 0.1.45

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.
Files changed (58) hide show
  1. package/LICENSE +1 -1
  2. package/dist/primitives/actionBar/ActionBarCopy.js.map +1 -1
  3. package/dist/primitives/actionBar/ActionBarEdit.js.map +1 -1
  4. package/dist/primitives/actionBar/ActionBarFeedbackNegative.js.map +1 -1
  5. package/dist/primitives/actionBar/ActionBarFeedbackPositive.js.map +1 -1
  6. package/dist/primitives/actionBar/ActionBarReload.js.map +1 -1
  7. package/dist/primitives/actionBar/ActionBarSpeak.js.map +1 -1
  8. package/dist/primitives/actionBar/ActionBarStopSpeaking.js.map +1 -1
  9. package/dist/primitives/attachment/AttachmentName.js.map +1 -1
  10. package/dist/primitives/attachment/AttachmentRemove.js.map +1 -1
  11. package/dist/primitives/attachment/AttachmentRoot.js.map +1 -1
  12. package/dist/primitives/attachment/AttachmentThumb.js.map +1 -1
  13. package/dist/primitives/branchPicker/BranchPickerCount.js.map +1 -1
  14. package/dist/primitives/branchPicker/BranchPickerNext.js.map +1 -1
  15. package/dist/primitives/branchPicker/BranchPickerNumber.js.map +1 -1
  16. package/dist/primitives/branchPicker/BranchPickerPrevious.js.map +1 -1
  17. package/dist/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.js.map +1 -1
  18. package/dist/primitives/chainOfThought/ChainOfThoughtRoot.js.map +1 -1
  19. package/dist/primitives/composer/ComposerAddAttachment.js.map +1 -1
  20. package/dist/primitives/composer/ComposerCancel.js.map +1 -1
  21. package/dist/primitives/composer/ComposerInput.js.map +1 -1
  22. package/dist/primitives/composer/ComposerQuote.js.map +1 -1
  23. package/dist/primitives/composer/ComposerQuoteDismiss.js.map +1 -1
  24. package/dist/primitives/composer/ComposerQuoteText.js.map +1 -1
  25. package/dist/primitives/composer/ComposerRoot.js.map +1 -1
  26. package/dist/primitives/composer/ComposerSend.js.map +1 -1
  27. package/dist/primitives/error/ErrorMessage.js.map +1 -1
  28. package/dist/primitives/error/ErrorRoot.js.map +1 -1
  29. package/dist/primitives/message/MessageContent.d.ts.map +1 -1
  30. package/dist/primitives/message/MessageContent.js +43 -33
  31. package/dist/primitives/message/MessageContent.js.map +1 -1
  32. package/dist/primitives/message/MessageIf.js.map +1 -1
  33. package/dist/primitives/message/MessageParts.js.map +1 -1
  34. package/dist/primitives/message/MessageRoot.js.map +1 -1
  35. package/dist/primitives/messagePart/MessagePartImage.js.map +1 -1
  36. package/dist/primitives/messagePart/MessagePartText.js.map +1 -1
  37. package/dist/primitives/queueItem/QueueItemRemove.js.map +1 -1
  38. package/dist/primitives/queueItem/QueueItemSteer.js.map +1 -1
  39. package/dist/primitives/queueItem/QueueItemText.js.map +1 -1
  40. package/dist/primitives/suggestion/SuggestionDescription.js.map +1 -1
  41. package/dist/primitives/suggestion/SuggestionTitle.js.map +1 -1
  42. package/dist/primitives/suggestion/SuggestionTrigger.js.map +1 -1
  43. package/dist/primitives/thread/ThreadEmpty.js.map +1 -1
  44. package/dist/primitives/thread/ThreadIf.js.map +1 -1
  45. package/dist/primitives/thread/ThreadMessages.js.map +1 -1
  46. package/dist/primitives/thread/ThreadRoot.js.map +1 -1
  47. package/dist/primitives/thread/ThreadSuggestion.js.map +1 -1
  48. package/dist/primitives/threadList/ThreadListItems.js.map +1 -1
  49. package/dist/primitives/threadList/ThreadListNew.js.map +1 -1
  50. package/dist/primitives/threadList/ThreadListRoot.js.map +1 -1
  51. package/dist/primitives/threadListItem/ThreadListItemArchive.js.map +1 -1
  52. package/dist/primitives/threadListItem/ThreadListItemDelete.js.map +1 -1
  53. package/dist/primitives/threadListItem/ThreadListItemRoot.js.map +1 -1
  54. package/dist/primitives/threadListItem/ThreadListItemTrigger.js.map +1 -1
  55. package/dist/primitives/threadListItem/ThreadListItemUnarchive.js.map +1 -1
  56. package/package.json +12 -9
  57. package/src/primitives/message/MessageContent.test.tsx +46 -1
  58. package/src/primitives/message/MessageContent.tsx +3 -1
@@ -1,4 +1,4 @@
1
- import { act, type ReactElement } from "react";
1
+ import { act, useState, type ReactElement } from "react";
2
2
  import { createRoot, type Root } from "react-dom/client";
3
3
  import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
4
4
  import { MessageContent } from "./MessageContent";
@@ -79,6 +79,51 @@ describe("MessageContent", () => {
79
79
  });
80
80
  };
81
81
 
82
+ it("keeps a text seed while streaming and resets it for a replacement id", async () => {
83
+ const SeededText = ({ text }: { text: string }) => {
84
+ const [seed] = useState(text);
85
+ return <span>{`${seed}:${text}`}</span>;
86
+ };
87
+ const renderText: NonNullable<
88
+ Parameters<typeof MessageContent>[0]["renderText"]
89
+ > = ({ part }) => <SeededText text={part.text} />;
90
+
91
+ h.state.message.content = [{ type: "text", id: "p1", text: "old" }];
92
+ await mount({ renderText });
93
+ h.state.message.content = [
94
+ { type: "text", id: "p1", text: "old streamed" },
95
+ ];
96
+ await mount({ renderText });
97
+ expect(container.textContent).toBe("old:old streamed");
98
+
99
+ h.state.message.content = [{ type: "text", id: "p2", text: "new" }];
100
+ await mount({ renderText });
101
+ expect(container.textContent).toBe("new:new");
102
+ });
103
+
104
+ it("keeps each seed with its id when identified parts swap", async () => {
105
+ const SeededText = ({ text }: { text: string }) => {
106
+ const [seed] = useState(text);
107
+ return <span>{`${seed}:${text}`}</span>;
108
+ };
109
+ const renderText: NonNullable<
110
+ Parameters<typeof MessageContent>[0]["renderText"]
111
+ > = ({ part }) => <SeededText text={part.text} />;
112
+ h.state.message.content = [
113
+ { type: "text", id: "p1", text: "first" },
114
+ { type: "text", id: "p2", text: "second" },
115
+ ];
116
+ await mount({ renderText });
117
+ h.state.message.content = [
118
+ { type: "text", id: "p2", text: "second updated" },
119
+ { type: "text", id: "p1", text: "first updated" },
120
+ ];
121
+ await mount({ renderText });
122
+ expect(
123
+ Array.from(container.querySelectorAll("span"), (el) => el.textContent),
124
+ ).toEqual(["second:second updated", "first:first updated"]);
125
+ });
126
+
82
127
  it("renders a text part through the default text renderer", async () => {
83
128
  h.state.message.content = [{ type: "text", text: "hello world" }];
84
129
  await mount();
@@ -1,5 +1,6 @@
1
1
  import { type ReactElement, Fragment, useMemo } from "react";
2
2
  import { Text } from "react-native";
3
+ import { getMessagePartKeys } from "@assistant-ui/core/internal";
3
4
  import type {
4
5
  ThreadUserMessagePart,
5
6
  ThreadAssistantMessagePart,
@@ -124,11 +125,12 @@ export const MessageContent = ({
124
125
  renderData,
125
126
  }: MessageContentProps) => {
126
127
  const content = useAuiState((s) => s.message.parts);
128
+ const partKeys = getMessagePartKeys(content);
127
129
 
128
130
  return (
129
131
  <>
130
132
  {content.map((part, index) => {
131
- const key = `${part.type}-${index}`;
133
+ const key = partKeys[index];
132
134
  switch (part.type) {
133
135
  case "text":
134
136
  return (