@assistant-ui/react-native 0.1.42 → 0.1.44
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/context/AssistantContext.d.ts +2 -2
- package/dist/context/AssistantContext.d.ts.map +1 -0
- package/dist/context/providers/AttachmentByIndexProvider.d.ts +2 -2
- package/dist/context/providers/AttachmentByIndexProvider.d.ts.map +1 -0
- package/dist/context/providers/RuntimeAdapterProvider.d.ts +2 -2
- package/dist/context/providers/RuntimeAdapterProvider.d.ts.map +1 -0
- package/dist/context/providers/ThreadListItemRuntimeProvider.d.ts +2 -2
- package/dist/context/providers/ThreadListItemRuntimeProvider.d.ts.map +1 -0
- package/dist/index.d.ts +54 -22
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -4
- package/dist/internal.d.ts +4 -3
- package/dist/internal.d.ts.map +1 -0
- package/dist/primitives/actionBar/ActionBarCopy.d.ts +9 -11
- package/dist/primitives/actionBar/ActionBarCopy.d.ts.map +1 -1
- package/dist/primitives/actionBar/ActionBarCopy.js +23 -19
- package/dist/primitives/actionBar/ActionBarCopy.js.map +1 -1
- package/dist/primitives/actionBar/ActionBarEdit.d.ts +7 -7
- package/dist/primitives/actionBar/ActionBarEdit.d.ts.map +1 -1
- package/dist/primitives/actionBar/ActionBarEdit.js +21 -11
- package/dist/primitives/actionBar/ActionBarEdit.js.map +1 -1
- package/dist/primitives/actionBar/ActionBarFeedbackNegative.d.ts +8 -10
- package/dist/primitives/actionBar/ActionBarFeedbackNegative.d.ts.map +1 -1
- package/dist/primitives/actionBar/ActionBarFeedbackNegative.js +35 -17
- package/dist/primitives/actionBar/ActionBarFeedbackNegative.js.map +1 -1
- package/dist/primitives/actionBar/ActionBarFeedbackPositive.d.ts +8 -10
- package/dist/primitives/actionBar/ActionBarFeedbackPositive.d.ts.map +1 -1
- package/dist/primitives/actionBar/ActionBarFeedbackPositive.js +35 -17
- package/dist/primitives/actionBar/ActionBarFeedbackPositive.js.map +1 -1
- package/dist/primitives/actionBar/ActionBarReload.d.ts +7 -7
- package/dist/primitives/actionBar/ActionBarReload.d.ts.map +1 -1
- package/dist/primitives/actionBar/ActionBarReload.js +21 -11
- package/dist/primitives/actionBar/ActionBarReload.js.map +1 -1
- package/dist/primitives/actionBar/ActionBarSpeak.d.ts +12 -0
- package/dist/primitives/actionBar/ActionBarSpeak.d.ts.map +1 -0
- package/dist/primitives/actionBar/ActionBarSpeak.js +61 -0
- package/dist/primitives/actionBar/ActionBarSpeak.js.map +1 -0
- package/dist/primitives/actionBar/ActionBarStopSpeaking.d.ts +12 -0
- package/dist/primitives/actionBar/ActionBarStopSpeaking.d.ts.map +1 -0
- package/dist/primitives/actionBar/ActionBarStopSpeaking.js +61 -0
- package/dist/primitives/actionBar/ActionBarStopSpeaking.js.map +1 -0
- package/dist/primitives/actionBar.d.ts +7 -10
- package/dist/primitives/actionBar.d.ts.map +1 -1
- package/dist/primitives/actionBar.js +6 -2
- package/dist/primitives/actionBar.js.map +1 -1
- package/dist/primitives/attachment/AttachmentName.d.ts +4 -7
- package/dist/primitives/attachment/AttachmentName.d.ts.map +1 -1
- package/dist/primitives/attachment/AttachmentRemove.d.ts +4 -7
- package/dist/primitives/attachment/AttachmentRemove.d.ts.map +1 -1
- package/dist/primitives/attachment/AttachmentRoot.d.ts +5 -8
- package/dist/primitives/attachment/AttachmentRoot.d.ts.map +1 -1
- package/dist/primitives/attachment/AttachmentThumb.d.ts +4 -7
- package/dist/primitives/attachment/AttachmentThumb.d.ts.map +1 -1
- package/dist/primitives/attachment.d.ts +4 -9
- package/dist/primitives/attachment.d.ts.map +1 -1
- package/dist/primitives/branchPicker/BranchPickerCount.d.ts +3 -6
- package/dist/primitives/branchPicker/BranchPickerCount.d.ts.map +1 -1
- package/dist/primitives/branchPicker/BranchPickerNext.d.ts +7 -7
- package/dist/primitives/branchPicker/BranchPickerNext.d.ts.map +1 -1
- package/dist/primitives/branchPicker/BranchPickerNext.js +21 -11
- package/dist/primitives/branchPicker/BranchPickerNext.js.map +1 -1
- package/dist/primitives/branchPicker/BranchPickerNumber.d.ts +3 -6
- package/dist/primitives/branchPicker/BranchPickerNumber.d.ts.map +1 -1
- package/dist/primitives/branchPicker/BranchPickerPrevious.d.ts +7 -7
- package/dist/primitives/branchPicker/BranchPickerPrevious.d.ts.map +1 -1
- package/dist/primitives/branchPicker/BranchPickerPrevious.js +21 -11
- package/dist/primitives/branchPicker/BranchPickerPrevious.js.map +1 -1
- package/dist/primitives/branchPicker.d.ts +4 -9
- package/dist/primitives/branchPicker.d.ts.map +1 -1
- package/dist/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.d.ts +4 -7
- package/dist/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.d.ts.map +1 -1
- package/dist/primitives/chainOfThought/ChainOfThoughtRoot.d.ts +5 -8
- package/dist/primitives/chainOfThought/ChainOfThoughtRoot.d.ts.map +1 -1
- package/dist/primitives/chainOfThought.d.ts +3 -8
- package/dist/primitives/chainOfThought.d.ts.map +1 -1
- package/dist/primitives/composer/ComposerAddAttachment.d.ts +4 -7
- package/dist/primitives/composer/ComposerAddAttachment.d.ts.map +1 -1
- package/dist/primitives/composer/ComposerAttachments.d.ts +5 -8
- package/dist/primitives/composer/ComposerAttachments.d.ts.map +1 -1
- package/dist/primitives/composer/ComposerCancel.d.ts +4 -7
- package/dist/primitives/composer/ComposerCancel.d.ts.map +1 -1
- package/dist/primitives/composer/ComposerIf.d.ts +2 -2
- package/dist/primitives/composer/ComposerIf.d.ts.map +1 -0
- package/dist/primitives/composer/ComposerInput.d.ts +10 -13
- package/dist/primitives/composer/ComposerInput.d.ts.map +1 -1
- package/dist/primitives/composer/ComposerInput.js +1 -1
- package/dist/primitives/composer/ComposerInput.js.map +1 -1
- package/dist/primitives/composer/ComposerQueue.d.ts +2 -2
- package/dist/primitives/composer/ComposerQueue.d.ts.map +1 -0
- package/dist/primitives/composer/ComposerQuote.d.ts +5 -8
- package/dist/primitives/composer/ComposerQuote.d.ts.map +1 -1
- package/dist/primitives/composer/ComposerQuoteDismiss.d.ts +4 -7
- package/dist/primitives/composer/ComposerQuoteDismiss.d.ts.map +1 -1
- package/dist/primitives/composer/ComposerQuoteText.d.ts +5 -8
- package/dist/primitives/composer/ComposerQuoteText.d.ts.map +1 -1
- package/dist/primitives/composer/ComposerRoot.d.ts +5 -8
- package/dist/primitives/composer/ComposerRoot.d.ts.map +1 -1
- package/dist/primitives/composer/ComposerSend.d.ts +4 -7
- package/dist/primitives/composer/ComposerSend.d.ts.map +1 -1
- package/dist/primitives/composer.d.ts +11 -16
- package/dist/primitives/composer.d.ts.map +1 -1
- package/dist/primitives/error/ErrorMessage.d.ts +7 -10
- package/dist/primitives/error/ErrorMessage.d.ts.map +1 -1
- package/dist/primitives/error/ErrorRoot.d.ts +7 -10
- package/dist/primitives/error/ErrorRoot.d.ts.map +1 -1
- package/dist/primitives/error/index.d.ts +2 -7
- package/dist/primitives/error/index.d.ts.map +1 -1
- package/dist/primitives/message/MessageAttachments.d.ts +5 -8
- package/dist/primitives/message/MessageAttachments.d.ts.map +1 -1
- package/dist/primitives/message/MessageContent.d.ts +47 -49
- package/dist/primitives/message/MessageContent.d.ts.map +1 -1
- package/dist/primitives/message/MessageContent.js +27 -21
- package/dist/primitives/message/MessageContent.js.map +1 -1
- package/dist/primitives/message/MessageIf.d.ts +8 -11
- package/dist/primitives/message/MessageIf.d.ts.map +1 -1
- package/dist/primitives/message/MessageParts.d.ts +6 -8
- package/dist/primitives/message/MessageParts.d.ts.map +1 -1
- package/dist/primitives/message/MessageRoot.d.ts +5 -8
- package/dist/primitives/message/MessageRoot.d.ts.map +1 -1
- package/dist/primitives/message.d.ts +6 -11
- package/dist/primitives/message.d.ts.map +1 -1
- package/dist/primitives/messagePart/MessagePartImage.d.ts +9 -0
- package/dist/primitives/messagePart/MessagePartImage.d.ts.map +1 -0
- package/dist/primitives/messagePart/MessagePartImage.js +39 -0
- package/dist/primitives/messagePart/MessagePartImage.js.map +1 -0
- package/dist/primitives/messagePart/MessagePartInProgress.d.ts +2 -0
- package/dist/primitives/messagePart/MessagePartInProgress.d.ts.map +1 -0
- package/dist/primitives/messagePart/MessagePartInProgress.js +2 -0
- package/dist/primitives/messagePart/MessagePartText.d.ts +9 -0
- package/dist/primitives/messagePart/MessagePartText.d.ts.map +1 -0
- package/dist/primitives/messagePart/MessagePartText.js +32 -0
- package/dist/primitives/messagePart/MessagePartText.js.map +1 -0
- package/dist/primitives/messagePart.d.ts +5 -0
- package/dist/primitives/messagePart.d.ts.map +1 -0
- package/dist/primitives/messagePart.js +16 -0
- package/dist/primitives/messagePart.js.map +1 -0
- package/dist/primitives/queueItem/QueueItemRemove.d.ts +4 -7
- package/dist/primitives/queueItem/QueueItemRemove.d.ts.map +1 -1
- package/dist/primitives/queueItem/QueueItemSteer.d.ts +4 -7
- package/dist/primitives/queueItem/QueueItemSteer.d.ts.map +1 -1
- package/dist/primitives/queueItem/QueueItemText.d.ts +5 -8
- package/dist/primitives/queueItem/QueueItemText.d.ts.map +1 -1
- package/dist/primitives/queueItem.d.ts +3 -8
- package/dist/primitives/queueItem.d.ts.map +1 -1
- package/dist/primitives/suggestion/SuggestionDescription.d.ts +5 -8
- package/dist/primitives/suggestion/SuggestionDescription.d.ts.map +1 -1
- package/dist/primitives/suggestion/SuggestionTitle.d.ts +5 -8
- package/dist/primitives/suggestion/SuggestionTitle.d.ts.map +1 -1
- package/dist/primitives/suggestion/SuggestionTrigger.d.ts +15 -18
- package/dist/primitives/suggestion/SuggestionTrigger.d.ts.map +1 -1
- package/dist/primitives/suggestion/SuggestionTrigger.js +1 -1
- package/dist/primitives/suggestion.d.ts +3 -8
- package/dist/primitives/suggestion.d.ts.map +1 -1
- package/dist/primitives/thread/ThreadEmpty.d.ts +4 -7
- package/dist/primitives/thread/ThreadEmpty.d.ts.map +1 -1
- package/dist/primitives/thread/ThreadIf.d.ts +6 -9
- package/dist/primitives/thread/ThreadIf.d.ts.map +1 -1
- package/dist/primitives/thread/ThreadMessages.d.ts +41 -37
- package/dist/primitives/thread/ThreadMessages.d.ts.map +1 -1
- package/dist/primitives/thread/ThreadMessages.js +123 -72
- package/dist/primitives/thread/ThreadMessages.js.map +1 -1
- package/dist/primitives/thread/ThreadRoot.d.ts +5 -8
- package/dist/primitives/thread/ThreadRoot.d.ts.map +1 -1
- package/dist/primitives/thread/ThreadSuggestion.d.ts +17 -20
- package/dist/primitives/thread/ThreadSuggestion.d.ts.map +1 -1
- package/dist/primitives/thread.d.ts +8 -11
- package/dist/primitives/thread.d.ts.map +1 -1
- package/dist/primitives/threadList/ThreadListItems.d.ts +8 -11
- package/dist/primitives/threadList/ThreadListItems.d.ts.map +1 -1
- package/dist/primitives/threadList/ThreadListItems.js +1 -1
- package/dist/primitives/threadList/ThreadListNew.d.ts +7 -10
- package/dist/primitives/threadList/ThreadListNew.d.ts.map +1 -1
- package/dist/primitives/threadList/ThreadListNew.js +21 -17
- package/dist/primitives/threadList/ThreadListNew.js.map +1 -1
- package/dist/primitives/threadList/ThreadListRoot.d.ts +5 -8
- package/dist/primitives/threadList/ThreadListRoot.d.ts.map +1 -1
- package/dist/primitives/threadList.d.ts +3 -8
- package/dist/primitives/threadList.d.ts.map +1 -1
- package/dist/primitives/threadListItem/ThreadListItemArchive.d.ts +4 -7
- package/dist/primitives/threadListItem/ThreadListItemArchive.d.ts.map +1 -1
- package/dist/primitives/threadListItem/ThreadListItemDelete.d.ts +4 -7
- package/dist/primitives/threadListItem/ThreadListItemDelete.d.ts.map +1 -1
- package/dist/primitives/threadListItem/ThreadListItemRoot.d.ts +5 -8
- package/dist/primitives/threadListItem/ThreadListItemRoot.d.ts.map +1 -1
- package/dist/primitives/threadListItem/ThreadListItemTrigger.d.ts +7 -10
- package/dist/primitives/threadListItem/ThreadListItemTrigger.d.ts.map +1 -1
- package/dist/primitives/threadListItem/ThreadListItemTrigger.js +21 -17
- package/dist/primitives/threadListItem/ThreadListItemTrigger.js.map +1 -1
- package/dist/primitives/threadListItem/ThreadListItemUnarchive.d.ts +4 -7
- package/dist/primitives/threadListItem/ThreadListItemUnarchive.d.ts.map +1 -1
- package/dist/primitives/threadListItem.d.ts +6 -11
- package/dist/primitives/threadListItem.d.ts.map +1 -1
- package/dist/runtimes/useLocalRuntime.d.ts +2 -2
- package/dist/runtimes/useLocalRuntime.d.ts.map +1 -0
- package/dist/runtimes/useRemoteThreadListRuntime.d.ts +2 -2
- package/dist/runtimes/useRemoteThreadListRuntime.d.ts.map +1 -0
- package/package.json +13 -12
- package/src/index.ts +91 -1
- package/src/primitives/accessibilityRole.test.tsx +20 -0
- package/src/primitives/actionBar/ActionBar.test.tsx +375 -0
- package/src/primitives/actionBar/ActionBarCopy.tsx +8 -3
- package/src/primitives/actionBar/ActionBarEdit.tsx +16 -4
- package/src/primitives/actionBar/ActionBarFeedbackNegative.tsx +18 -4
- package/src/primitives/actionBar/ActionBarFeedbackPositive.tsx +18 -4
- package/src/primitives/actionBar/ActionBarReload.tsx +16 -4
- package/src/primitives/actionBar/ActionBarSpeak.tsx +42 -0
- package/src/primitives/actionBar/ActionBarStopSpeaking.tsx +42 -0
- package/src/primitives/actionBar.ts +8 -0
- package/src/primitives/branchPicker/BranchPickerNext.test.tsx +52 -3
- package/src/primitives/branchPicker/BranchPickerNext.tsx +16 -4
- package/src/primitives/branchPicker/BranchPickerPrevious.test.tsx +52 -6
- package/src/primitives/branchPicker/BranchPickerPrevious.tsx +16 -4
- package/src/primitives/composer/ComposerInput.test.tsx +17 -1
- package/src/primitives/composer/ComposerInput.tsx +6 -1
- package/src/primitives/message/MessageContent.test.tsx +64 -3
- package/src/primitives/message/MessageContent.tsx +5 -3
- package/src/primitives/messagePart/MessagePartImage.test.tsx +91 -0
- package/src/primitives/messagePart/MessagePartImage.tsx +33 -0
- package/src/primitives/messagePart/MessagePartInProgress.ts +1 -0
- package/src/primitives/messagePart/MessagePartText.test.tsx +80 -0
- package/src/primitives/messagePart/MessagePartText.tsx +36 -0
- package/src/primitives/messagePart.ts +10 -0
- package/src/primitives/thread/ThreadMessages.test.tsx +190 -6
- package/src/primitives/thread/ThreadMessages.tsx +68 -1
- package/src/primitives/threadList/ThreadListNew.test.tsx +35 -8
- package/src/primitives/threadList/ThreadListNew.tsx +4 -1
- package/src/primitives/threadListItem/ThreadListItemTrigger.test.tsx +32 -6
- package/src/primitives/threadListItem/ThreadListItemTrigger.tsx +4 -1
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import {
|
|
3
|
+
Pressable,
|
|
4
|
+
type PressableProps,
|
|
5
|
+
type PressableStateCallbackType,
|
|
6
|
+
} from "react-native";
|
|
7
|
+
import { useActionBarStopSpeaking } from "@assistant-ui/core/react";
|
|
8
|
+
|
|
9
|
+
export type ActionBarStopSpeakingProps = Omit<
|
|
10
|
+
PressableProps,
|
|
11
|
+
"children" | "onPress"
|
|
12
|
+
> & {
|
|
13
|
+
children:
|
|
14
|
+
| ReactNode
|
|
15
|
+
| ((
|
|
16
|
+
state: PressableStateCallbackType & { disabled: boolean },
|
|
17
|
+
) => ReactNode);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const ActionBarStopSpeaking = ({
|
|
21
|
+
children,
|
|
22
|
+
disabled: disabledProp,
|
|
23
|
+
...pressableProps
|
|
24
|
+
}: ActionBarStopSpeakingProps) => {
|
|
25
|
+
const { stopSpeaking, disabled } = useActionBarStopSpeaking();
|
|
26
|
+
const isDisabled = disabledProp ?? disabled;
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<Pressable
|
|
30
|
+
onPress={() => stopSpeaking()}
|
|
31
|
+
disabled={isDisabled}
|
|
32
|
+
accessibilityRole="button"
|
|
33
|
+
{...pressableProps}
|
|
34
|
+
>
|
|
35
|
+
{typeof children === "function"
|
|
36
|
+
? (state) => children({ ...state, disabled: isDisabled })
|
|
37
|
+
: children}
|
|
38
|
+
</Pressable>
|
|
39
|
+
);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
ActionBarStopSpeaking.displayName = "ActionBarPrimitive.StopSpeaking";
|
|
@@ -10,6 +10,14 @@ export {
|
|
|
10
10
|
ActionBarReload as Reload,
|
|
11
11
|
type ActionBarReloadProps as ReloadProps,
|
|
12
12
|
} from "./actionBar/ActionBarReload";
|
|
13
|
+
export {
|
|
14
|
+
ActionBarSpeak as Speak,
|
|
15
|
+
type ActionBarSpeakProps as SpeakProps,
|
|
16
|
+
} from "./actionBar/ActionBarSpeak";
|
|
17
|
+
export {
|
|
18
|
+
ActionBarStopSpeaking as StopSpeaking,
|
|
19
|
+
type ActionBarStopSpeakingProps as StopSpeakingProps,
|
|
20
|
+
} from "./actionBar/ActionBarStopSpeaking";
|
|
13
21
|
export {
|
|
14
22
|
ActionBarFeedbackPositive as FeedbackPositive,
|
|
15
23
|
type ActionBarFeedbackPositiveProps as FeedbackPositiveProps,
|
|
@@ -8,9 +8,17 @@ const h = vi.hoisted(() => ({
|
|
|
8
8
|
state: { disabled: false },
|
|
9
9
|
}));
|
|
10
10
|
|
|
11
|
-
vi.mock("@assistant-ui/core/react", () =>
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
vi.mock("@assistant-ui/core/react", async (importOriginal) => {
|
|
12
|
+
const actual =
|
|
13
|
+
await importOriginal<typeof import("@assistant-ui/core/react")>();
|
|
14
|
+
return {
|
|
15
|
+
...actual,
|
|
16
|
+
useBranchPickerNext: () => ({
|
|
17
|
+
next: h.next,
|
|
18
|
+
disabled: h.state.disabled,
|
|
19
|
+
}),
|
|
20
|
+
};
|
|
21
|
+
});
|
|
14
22
|
|
|
15
23
|
(globalThis as Record<string, unknown>).IS_REACT_ACT_ENVIRONMENT = true;
|
|
16
24
|
|
|
@@ -94,4 +102,45 @@ describe("BranchPickerNext", () => {
|
|
|
94
102
|
|
|
95
103
|
expect(h.next).toHaveBeenCalledTimes(1);
|
|
96
104
|
});
|
|
105
|
+
|
|
106
|
+
it("passes the hook disabled state and an explicit override to render children", async () => {
|
|
107
|
+
h.state.disabled = true;
|
|
108
|
+
let hookState: unknown = null;
|
|
109
|
+
|
|
110
|
+
await act(async () => {
|
|
111
|
+
root.render(
|
|
112
|
+
<BranchPickerNext testID="t">
|
|
113
|
+
{(state) => {
|
|
114
|
+
hookState = state;
|
|
115
|
+
return state.disabled ? "disabled" : "enabled";
|
|
116
|
+
}}
|
|
117
|
+
</BranchPickerNext>,
|
|
118
|
+
);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
expect(hookState).toMatchObject({ pressed: false, disabled: true });
|
|
122
|
+
expect(container.textContent).toBe("disabled");
|
|
123
|
+
|
|
124
|
+
let overrideState: unknown = null;
|
|
125
|
+
|
|
126
|
+
await act(async () => {
|
|
127
|
+
root.render(
|
|
128
|
+
<BranchPickerNext testID="t" disabled={false}>
|
|
129
|
+
{(state) => {
|
|
130
|
+
overrideState = state;
|
|
131
|
+
return state.disabled ? "disabled" : "enabled";
|
|
132
|
+
}}
|
|
133
|
+
</BranchPickerNext>,
|
|
134
|
+
);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
expect(overrideState).toMatchObject({ pressed: false, disabled: false });
|
|
138
|
+
expect(container.textContent).toBe("enabled");
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
it("renders plain children", async () => {
|
|
142
|
+
const el = await mount();
|
|
143
|
+
|
|
144
|
+
expect(el.textContent).toBe("next");
|
|
145
|
+
});
|
|
97
146
|
});
|
|
@@ -1,11 +1,20 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import {
|
|
3
|
+
Pressable,
|
|
4
|
+
type PressableProps,
|
|
5
|
+
type PressableStateCallbackType,
|
|
6
|
+
} from "react-native";
|
|
2
7
|
import { useBranchPickerNext } from "@assistant-ui/core/react";
|
|
3
8
|
|
|
4
9
|
export type BranchPickerNextProps = Omit<
|
|
5
10
|
PressableProps,
|
|
6
11
|
"onPress" | "children"
|
|
7
12
|
> & {
|
|
8
|
-
children:
|
|
13
|
+
children:
|
|
14
|
+
| ReactNode
|
|
15
|
+
| ((
|
|
16
|
+
state: PressableStateCallbackType & { disabled: boolean },
|
|
17
|
+
) => ReactNode);
|
|
9
18
|
};
|
|
10
19
|
|
|
11
20
|
export const BranchPickerNext = ({
|
|
@@ -14,15 +23,18 @@ export const BranchPickerNext = ({
|
|
|
14
23
|
...pressableProps
|
|
15
24
|
}: BranchPickerNextProps) => {
|
|
16
25
|
const { next, disabled } = useBranchPickerNext();
|
|
26
|
+
const isDisabled = disabledProp ?? disabled;
|
|
17
27
|
|
|
18
28
|
return (
|
|
19
29
|
<Pressable
|
|
20
30
|
onPress={next}
|
|
21
|
-
disabled={
|
|
31
|
+
disabled={isDisabled}
|
|
22
32
|
accessibilityRole="button"
|
|
23
33
|
{...pressableProps}
|
|
24
34
|
>
|
|
25
|
-
{children
|
|
35
|
+
{typeof children === "function"
|
|
36
|
+
? (state) => children({ ...state, disabled: isDisabled })
|
|
37
|
+
: children}
|
|
26
38
|
</Pressable>
|
|
27
39
|
);
|
|
28
40
|
};
|
|
@@ -8,12 +8,17 @@ const h = vi.hoisted(() => ({
|
|
|
8
8
|
state: { disabled: false },
|
|
9
9
|
}));
|
|
10
10
|
|
|
11
|
-
vi.mock("@assistant-ui/core/react", () =>
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
vi.mock("@assistant-ui/core/react", async (importOriginal) => {
|
|
12
|
+
const actual =
|
|
13
|
+
await importOriginal<typeof import("@assistant-ui/core/react")>();
|
|
14
|
+
return {
|
|
15
|
+
...actual,
|
|
16
|
+
useBranchPickerPrevious: () => ({
|
|
17
|
+
previous: h.previous,
|
|
18
|
+
disabled: h.state.disabled,
|
|
19
|
+
}),
|
|
20
|
+
};
|
|
21
|
+
});
|
|
17
22
|
|
|
18
23
|
(globalThis as Record<string, unknown>).IS_REACT_ACT_ENVIRONMENT = true;
|
|
19
24
|
|
|
@@ -97,4 +102,45 @@ describe("BranchPickerPrevious", () => {
|
|
|
97
102
|
|
|
98
103
|
expect(h.previous).toHaveBeenCalledTimes(1);
|
|
99
104
|
});
|
|
105
|
+
|
|
106
|
+
it("passes the hook disabled state and an explicit override to render children", async () => {
|
|
107
|
+
h.state.disabled = true;
|
|
108
|
+
let hookState: unknown = null;
|
|
109
|
+
|
|
110
|
+
await act(async () => {
|
|
111
|
+
root.render(
|
|
112
|
+
<BranchPickerPrevious testID="t">
|
|
113
|
+
{(state) => {
|
|
114
|
+
hookState = state;
|
|
115
|
+
return state.disabled ? "disabled" : "enabled";
|
|
116
|
+
}}
|
|
117
|
+
</BranchPickerPrevious>,
|
|
118
|
+
);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
expect(hookState).toMatchObject({ pressed: false, disabled: true });
|
|
122
|
+
expect(container.textContent).toBe("disabled");
|
|
123
|
+
|
|
124
|
+
let overrideState: unknown = null;
|
|
125
|
+
|
|
126
|
+
await act(async () => {
|
|
127
|
+
root.render(
|
|
128
|
+
<BranchPickerPrevious testID="t" disabled={false}>
|
|
129
|
+
{(state) => {
|
|
130
|
+
overrideState = state;
|
|
131
|
+
return state.disabled ? "disabled" : "enabled";
|
|
132
|
+
}}
|
|
133
|
+
</BranchPickerPrevious>,
|
|
134
|
+
);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
expect(overrideState).toMatchObject({ pressed: false, disabled: false });
|
|
138
|
+
expect(container.textContent).toBe("enabled");
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
it("renders plain children", async () => {
|
|
142
|
+
const el = await mount();
|
|
143
|
+
|
|
144
|
+
expect(el.textContent).toBe("prev");
|
|
145
|
+
});
|
|
100
146
|
});
|
|
@@ -1,11 +1,20 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import {
|
|
3
|
+
Pressable,
|
|
4
|
+
type PressableProps,
|
|
5
|
+
type PressableStateCallbackType,
|
|
6
|
+
} from "react-native";
|
|
2
7
|
import { useBranchPickerPrevious } from "@assistant-ui/core/react";
|
|
3
8
|
|
|
4
9
|
export type BranchPickerPreviousProps = Omit<
|
|
5
10
|
PressableProps,
|
|
6
11
|
"onPress" | "children"
|
|
7
12
|
> & {
|
|
8
|
-
children:
|
|
13
|
+
children:
|
|
14
|
+
| ReactNode
|
|
15
|
+
| ((
|
|
16
|
+
state: PressableStateCallbackType & { disabled: boolean },
|
|
17
|
+
) => ReactNode);
|
|
9
18
|
};
|
|
10
19
|
|
|
11
20
|
export const BranchPickerPrevious = ({
|
|
@@ -14,15 +23,18 @@ export const BranchPickerPrevious = ({
|
|
|
14
23
|
...pressableProps
|
|
15
24
|
}: BranchPickerPreviousProps) => {
|
|
16
25
|
const { previous, disabled } = useBranchPickerPrevious();
|
|
26
|
+
const isDisabled = disabledProp ?? disabled;
|
|
17
27
|
|
|
18
28
|
return (
|
|
19
29
|
<Pressable
|
|
20
30
|
onPress={previous}
|
|
21
|
-
disabled={
|
|
31
|
+
disabled={isDisabled}
|
|
22
32
|
accessibilityRole="button"
|
|
23
33
|
{...pressableProps}
|
|
24
34
|
>
|
|
25
|
-
{children
|
|
35
|
+
{typeof children === "function"
|
|
36
|
+
? (state) => children({ ...state, disabled: isDisabled })
|
|
37
|
+
: children}
|
|
26
38
|
</Pressable>
|
|
27
39
|
);
|
|
28
40
|
};
|
|
@@ -8,7 +8,7 @@ const h = vi.hoisted(() => ({
|
|
|
8
8
|
sendSpy: vi.fn<() => void>(),
|
|
9
9
|
flushTapSyncSpy: vi.fn(<T,>(fn: () => T) => fn()),
|
|
10
10
|
composerState: { text: "" },
|
|
11
|
-
threadState: { isRunning: false, queue: false },
|
|
11
|
+
threadState: { isRunning: false, queue: false, voice: false },
|
|
12
12
|
platform: { os: "web" as "web" | "ios" | "android" },
|
|
13
13
|
}));
|
|
14
14
|
|
|
@@ -21,6 +21,7 @@ vi.mock("@assistant-ui/store", () => {
|
|
|
21
21
|
getState: () => ({
|
|
22
22
|
isRunning: h.threadState.isRunning,
|
|
23
23
|
capabilities: { queue: h.threadState.queue },
|
|
24
|
+
voice: h.threadState.voice ? { status: { type: "running" } } : undefined,
|
|
24
25
|
}),
|
|
25
26
|
};
|
|
26
27
|
const aui = { composer, thread };
|
|
@@ -109,6 +110,7 @@ describe("ComposerInput", () => {
|
|
|
109
110
|
h.composerState.text = "";
|
|
110
111
|
h.threadState.isRunning = false;
|
|
111
112
|
h.threadState.queue = false;
|
|
113
|
+
h.threadState.voice = false;
|
|
112
114
|
h.platform.os = "web";
|
|
113
115
|
|
|
114
116
|
container = document.createElement("div");
|
|
@@ -203,6 +205,20 @@ describe("ComposerInput", () => {
|
|
|
203
205
|
expect(h.sendSpy).toHaveBeenCalledTimes(1);
|
|
204
206
|
});
|
|
205
207
|
|
|
208
|
+
it("submits while a spoken reply runs during a voice session", async () => {
|
|
209
|
+
h.threadState.isRunning = true;
|
|
210
|
+
h.threadState.voice = true;
|
|
211
|
+
const input = await mount();
|
|
212
|
+
|
|
213
|
+
let event!: KeyboardEvent;
|
|
214
|
+
await act(async () => {
|
|
215
|
+
event = fireKeyDown(input, { key: "Enter" });
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
expect(h.sendSpy).toHaveBeenCalledTimes(1);
|
|
219
|
+
expect(event.defaultPrevented).toBe(true);
|
|
220
|
+
});
|
|
221
|
+
|
|
206
222
|
it("blocks submission when the thread starts running after mount", async () => {
|
|
207
223
|
const input = await mount();
|
|
208
224
|
|
|
@@ -103,7 +103,12 @@ export const ComposerInput = ({
|
|
|
103
103
|
if (nativeEvent.isComposing || nativeEvent.keyCode === 229) return;
|
|
104
104
|
if (nativeEvent.key === "Enter" && !nativeEvent.shiftKey) {
|
|
105
105
|
const threadState = aui.thread.getState();
|
|
106
|
-
if (
|
|
106
|
+
if (
|
|
107
|
+
threadState.isRunning &&
|
|
108
|
+
!threadState.capabilities.queue &&
|
|
109
|
+
threadState.voice === undefined
|
|
110
|
+
)
|
|
111
|
+
return;
|
|
107
112
|
(e as unknown as Event).preventDefault?.();
|
|
108
113
|
aui.composer.send();
|
|
109
114
|
}
|
|
@@ -9,6 +9,7 @@ const h = vi.hoisted(() => ({
|
|
|
9
9
|
addToolResult: vi.fn(),
|
|
10
10
|
resumeToolCall: vi.fn(),
|
|
11
11
|
respondToToolApproval: vi.fn(),
|
|
12
|
+
unstable_recordInteraction: vi.fn(),
|
|
12
13
|
state: {
|
|
13
14
|
message: {
|
|
14
15
|
content: [] as AnyPart[],
|
|
@@ -17,7 +18,10 @@ const h = vi.hoisted(() => ({
|
|
|
17
18
|
},
|
|
18
19
|
},
|
|
19
20
|
tools: { toolUIs: {} as Record<string, unknown> },
|
|
20
|
-
dataRenderers: {
|
|
21
|
+
dataRenderers: {
|
|
22
|
+
renderers: {} as Record<string, unknown>,
|
|
23
|
+
fallbacks: [] as unknown[],
|
|
24
|
+
},
|
|
21
25
|
},
|
|
22
26
|
}));
|
|
23
27
|
|
|
@@ -28,6 +32,8 @@ vi.mock("@assistant-ui/store", () => {
|
|
|
28
32
|
resumeToolCall: (...args: unknown[]) => h.resumeToolCall(index, ...args),
|
|
29
33
|
respondToToolApproval: (...args: unknown[]) =>
|
|
30
34
|
h.respondToToolApproval(index, ...args),
|
|
35
|
+
unstable_recordInteraction: (...args: unknown[]) =>
|
|
36
|
+
h.unstable_recordInteraction(index, ...args),
|
|
31
37
|
}),
|
|
32
38
|
});
|
|
33
39
|
const aui = { message };
|
|
@@ -47,9 +53,11 @@ describe("MessageContent", () => {
|
|
|
47
53
|
h.addToolResult.mockReset();
|
|
48
54
|
h.resumeToolCall.mockReset();
|
|
49
55
|
h.respondToToolApproval.mockReset();
|
|
56
|
+
h.unstable_recordInteraction.mockReset();
|
|
50
57
|
h.state.message.content = [];
|
|
51
58
|
h.state.tools.toolUIs = {};
|
|
52
59
|
h.state.dataRenderers.renderers = {};
|
|
60
|
+
h.state.dataRenderers.fallbacks = [];
|
|
53
61
|
|
|
54
62
|
container = document.createElement("div");
|
|
55
63
|
document.body.appendChild(container);
|
|
@@ -152,6 +160,10 @@ describe("MessageContent", () => {
|
|
|
152
160
|
(props.addResult as () => void)();
|
|
153
161
|
(props.resume as () => void)();
|
|
154
162
|
(props.respondToApproval as () => void)();
|
|
163
|
+
(props.unstable_recordInteraction as (input: unknown) => void)({
|
|
164
|
+
type: "action",
|
|
165
|
+
payload: { choice: "retry" },
|
|
166
|
+
});
|
|
155
167
|
return <span data-testid="tool">tool:{String(props.toolName)}</span>;
|
|
156
168
|
});
|
|
157
169
|
h.state.tools.toolUIs = { search: [{ render: ToolRender }] };
|
|
@@ -163,6 +175,10 @@ describe("MessageContent", () => {
|
|
|
163
175
|
expect(h.addToolResult).toHaveBeenCalledWith(0);
|
|
164
176
|
expect(h.resumeToolCall).toHaveBeenCalledWith(0);
|
|
165
177
|
expect(h.respondToToolApproval).toHaveBeenCalledWith(0);
|
|
178
|
+
expect(h.unstable_recordInteraction).toHaveBeenCalledWith(0, {
|
|
179
|
+
type: "action",
|
|
180
|
+
payload: { choice: "retry" },
|
|
181
|
+
});
|
|
166
182
|
});
|
|
167
183
|
|
|
168
184
|
it("picks the first registration when multiple are registered", async () => {
|
|
@@ -218,7 +234,7 @@ describe("MessageContent", () => {
|
|
|
218
234
|
const DataRender = vi.fn((props: Record<string, unknown>) => (
|
|
219
235
|
<span data-testid="data">data:{String(props.name)}</span>
|
|
220
236
|
));
|
|
221
|
-
h.state.dataRenderers.renderers = { chart: DataRender };
|
|
237
|
+
h.state.dataRenderers.renderers = { chart: [DataRender] };
|
|
222
238
|
|
|
223
239
|
await mount();
|
|
224
240
|
|
|
@@ -251,6 +267,51 @@ describe("MessageContent", () => {
|
|
|
251
267
|
expect(el?.textContent).toBe("fallback:chart:0");
|
|
252
268
|
});
|
|
253
269
|
|
|
270
|
+
it("uses dataRenderers.fallbacks[0] before renderData when no named renderer matches", async () => {
|
|
271
|
+
h.state.message.content = [{ type: "data", name: "chart", data: {} }];
|
|
272
|
+
const DataFallback = vi.fn((props: Record<string, unknown>) => (
|
|
273
|
+
<span data-testid="gfallback">global:{String(props.name)}</span>
|
|
274
|
+
));
|
|
275
|
+
h.state.dataRenderers.fallbacks = [DataFallback];
|
|
276
|
+
const renderData = vi.fn(({ part, index }): ReactElement => (
|
|
277
|
+
<span data-testid="dfallback">
|
|
278
|
+
fallback:{String(part.name)}:{index}
|
|
279
|
+
</span>
|
|
280
|
+
));
|
|
281
|
+
await mount({ renderData });
|
|
282
|
+
|
|
283
|
+
expect(
|
|
284
|
+
container.querySelector('[data-testid="gfallback"]')?.textContent,
|
|
285
|
+
).toBe("global:chart");
|
|
286
|
+
expect(DataFallback.mock.calls[0]?.[0]).toEqual({
|
|
287
|
+
type: "data",
|
|
288
|
+
name: "chart",
|
|
289
|
+
data: {},
|
|
290
|
+
});
|
|
291
|
+
expect(renderData).not.toHaveBeenCalled();
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
it("prefers a named data renderer over dataRenderers.fallbacks", async () => {
|
|
295
|
+
h.state.message.content = [{ type: "data", name: "chart", data: {} }];
|
|
296
|
+
const DataRender = vi.fn((props: Record<string, unknown>) => (
|
|
297
|
+
<span data-testid="data">data:{String(props.name)}</span>
|
|
298
|
+
));
|
|
299
|
+
const DataFallback = vi.fn(() => (
|
|
300
|
+
<span data-testid="gfallback">global-fallback</span>
|
|
301
|
+
));
|
|
302
|
+
h.state.dataRenderers.renderers = { chart: [DataRender] };
|
|
303
|
+
h.state.dataRenderers.fallbacks = [DataFallback];
|
|
304
|
+
await mount({
|
|
305
|
+
renderData: () => <span data-testid="dfallback">render prop</span>,
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
expect(container.querySelector('[data-testid="data"]')?.textContent).toBe(
|
|
309
|
+
"data:chart",
|
|
310
|
+
);
|
|
311
|
+
expect(DataFallback).not.toHaveBeenCalled();
|
|
312
|
+
expect(container.querySelector('[data-testid="dfallback"]')).toBeNull();
|
|
313
|
+
});
|
|
314
|
+
|
|
254
315
|
it("renders null when no data renderer is registered and no fallback is given", async () => {
|
|
255
316
|
h.state.message.content = [{ type: "data", name: "chart", data: {} }];
|
|
256
317
|
await mount();
|
|
@@ -268,7 +329,7 @@ describe("MessageContent", () => {
|
|
|
268
329
|
t: [{ render: () => <span>[tool]</span> }],
|
|
269
330
|
};
|
|
270
331
|
h.state.dataRenderers.renderers = {
|
|
271
|
-
d: () => <span>[data]</span
|
|
332
|
+
d: [() => <span>[data]</span>],
|
|
272
333
|
};
|
|
273
334
|
await mount();
|
|
274
335
|
|
|
@@ -81,6 +81,9 @@ const ToolUIDisplay = ({
|
|
|
81
81
|
addResult={partMethods.addToolResult}
|
|
82
82
|
resume={partMethods.resumeToolCall}
|
|
83
83
|
respondToApproval={partMethods.respondToToolApproval}
|
|
84
|
+
{...(partMethods.unstable_recordInteraction && {
|
|
85
|
+
unstable_recordInteraction: partMethods.unstable_recordInteraction,
|
|
86
|
+
})}
|
|
84
87
|
/>
|
|
85
88
|
);
|
|
86
89
|
}
|
|
@@ -103,9 +106,8 @@ const DataUIDisplay = ({
|
|
|
103
106
|
index: number;
|
|
104
107
|
}) => {
|
|
105
108
|
const Render = useAuiState((s) => {
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
return renders;
|
|
109
|
+
const named = s.dataRenderers.renderers[part.name]?.[0];
|
|
110
|
+
return named ?? s.dataRenderers.fallbacks[0];
|
|
109
111
|
});
|
|
110
112
|
if (Render) return <Render {...(part as DataMessagePartProps)} />;
|
|
111
113
|
if (Fallback) return <Fallback part={part} index={index} />;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { act } from "react";
|
|
2
|
+
import { createRoot, type Root } from "react-dom/client";
|
|
3
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
4
|
+
import type { ThreadMessageLike } from "@assistant-ui/core";
|
|
5
|
+
import {
|
|
6
|
+
AssistantRuntimeProvider,
|
|
7
|
+
MessageByIndexProvider,
|
|
8
|
+
PartByIndexProvider,
|
|
9
|
+
useExternalStoreRuntime,
|
|
10
|
+
} from "@assistant-ui/core/react";
|
|
11
|
+
import { MessagePartPrimitiveImage } from "./MessagePartImage";
|
|
12
|
+
|
|
13
|
+
vi.mock("react-native", async (importOriginal) => {
|
|
14
|
+
const actual = await importOriginal<typeof import("react-native")>();
|
|
15
|
+
const React = await import("react");
|
|
16
|
+
|
|
17
|
+
const ImageMock = React.forwardRef(function ImageMock(
|
|
18
|
+
props: { source?: { uri?: string }; testID?: string },
|
|
19
|
+
ref: React.Ref<HTMLImageElement>,
|
|
20
|
+
) {
|
|
21
|
+
return React.createElement("img", {
|
|
22
|
+
ref,
|
|
23
|
+
src: props.source?.uri,
|
|
24
|
+
"data-testid": props.testID,
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
return { ...actual, Image: ImageMock };
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
(globalThis as Record<string, unknown>).IS_REACT_ACT_ENVIRONMENT = true;
|
|
32
|
+
|
|
33
|
+
const messages: ThreadMessageLike[] = [
|
|
34
|
+
{
|
|
35
|
+
role: "assistant",
|
|
36
|
+
content: [
|
|
37
|
+
{ type: "text", text: "Answer" },
|
|
38
|
+
{ type: "image", image: "https://example.com/image.png" },
|
|
39
|
+
],
|
|
40
|
+
},
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
const App = ({ partIndex }: { partIndex: number }) => {
|
|
44
|
+
const runtime = useExternalStoreRuntime({
|
|
45
|
+
messages,
|
|
46
|
+
convertMessage: (message) => message,
|
|
47
|
+
onNew: async () => {
|
|
48
|
+
throw new Error("This thread is read-only");
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<AssistantRuntimeProvider runtime={runtime}>
|
|
54
|
+
<MessageByIndexProvider index={0}>
|
|
55
|
+
<PartByIndexProvider index={partIndex}>
|
|
56
|
+
<MessagePartPrimitiveImage testID="image" />
|
|
57
|
+
</PartByIndexProvider>
|
|
58
|
+
</MessageByIndexProvider>
|
|
59
|
+
</AssistantRuntimeProvider>
|
|
60
|
+
);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
describe("MessagePartPrimitiveImage", () => {
|
|
64
|
+
let container: HTMLDivElement;
|
|
65
|
+
let root: Root;
|
|
66
|
+
|
|
67
|
+
beforeEach(() => {
|
|
68
|
+
container = document.createElement("div");
|
|
69
|
+
document.body.appendChild(container);
|
|
70
|
+
root = createRoot(container);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
afterEach(async () => {
|
|
74
|
+
await act(async () => root.unmount());
|
|
75
|
+
container.remove();
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
const mount = async (partIndex: number) => {
|
|
79
|
+
await act(async () => root.render(<App partIndex={partIndex} />));
|
|
80
|
+
return container.querySelector<HTMLImageElement>('[data-testid="image"]');
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
it("renders the current image part URI", async () => {
|
|
84
|
+
const image = await mount(1);
|
|
85
|
+
expect(image?.getAttribute("src")).toBe("https://example.com/image.png");
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it("renders nothing for a non-image part", async () => {
|
|
89
|
+
expect(await mount(0)).toBeNull();
|
|
90
|
+
});
|
|
91
|
+
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type ComponentRef,
|
|
3
|
+
type ForwardRefExoticComponent,
|
|
4
|
+
forwardRef,
|
|
5
|
+
type RefAttributes,
|
|
6
|
+
} from "react";
|
|
7
|
+
import { Image, type ImageProps } from "react-native";
|
|
8
|
+
import { useAuiState } from "@assistant-ui/store";
|
|
9
|
+
|
|
10
|
+
export namespace MessagePartPrimitiveImage {
|
|
11
|
+
export type Element = ComponentRef<typeof Image>;
|
|
12
|
+
export type Props = Omit<ImageProps, "source">;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const MessagePartPrimitiveImage: ForwardRefExoticComponent<
|
|
16
|
+
MessagePartPrimitiveImage.Props &
|
|
17
|
+
RefAttributes<MessagePartPrimitiveImage.Element>
|
|
18
|
+
> = forwardRef<
|
|
19
|
+
MessagePartPrimitiveImage.Element,
|
|
20
|
+
MessagePartPrimitiveImage.Props
|
|
21
|
+
>((props, forwardedRef) => {
|
|
22
|
+
const uri = useAuiState((s) => {
|
|
23
|
+
const part = s.part;
|
|
24
|
+
return part.type === "image" ? part.image : undefined;
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
if (uri === undefined) return null;
|
|
28
|
+
return <Image source={{ uri }} {...props} ref={forwardedRef} />;
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
MessagePartPrimitiveImage.displayName = "MessagePartPrimitive.Image";
|
|
32
|
+
|
|
33
|
+
export type MessagePartImageProps = MessagePartPrimitiveImage.Props;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { MessagePartPrimitiveInProgress } from "@assistant-ui/core/react";
|