@assistant-ui/react-native 0.1.31 → 0.1.33

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 (25) hide show
  1. package/dist/primitives/attachment/AttachmentRemove.js +4 -3
  2. package/dist/primitives/attachment/AttachmentRemove.js.map +1 -1
  3. package/dist/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.js +4 -3
  4. package/dist/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.js.map +1 -1
  5. package/dist/primitives/composer/ComposerInput.js +3 -3
  6. package/dist/primitives/composer/ComposerInput.js.map +1 -1
  7. package/dist/primitives/message/MessageContent.d.ts.map +1 -1
  8. package/dist/primitives/message/MessageContent.js +4 -8
  9. package/dist/primitives/message/MessageContent.js.map +1 -1
  10. package/dist/primitives/thread/ThreadMessages.d.ts.map +1 -1
  11. package/dist/primitives/thread/ThreadMessages.js +49 -38
  12. package/dist/primitives/thread/ThreadMessages.js.map +1 -1
  13. package/dist/primitives/threadList/ThreadListItems.js +1 -0
  14. package/dist/primitives/threadList/ThreadListItems.js.map +1 -1
  15. package/package.json +6 -6
  16. package/src/primitives/attachment/AttachmentRemove.test.tsx +2 -3
  17. package/src/primitives/attachment/AttachmentRemove.tsx +1 -1
  18. package/src/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.test.tsx +4 -3
  19. package/src/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.tsx +1 -1
  20. package/src/primitives/composer/ComposerInput.test.tsx +5 -6
  21. package/src/primitives/composer/ComposerInput.tsx +3 -3
  22. package/src/primitives/message/MessageContent.test.tsx +17 -17
  23. package/src/primitives/message/MessageContent.tsx +4 -9
  24. package/src/primitives/thread/ThreadMessages.test.tsx +222 -0
  25. package/src/primitives/thread/ThreadMessages.tsx +21 -3
@@ -2,6 +2,7 @@ import { useAui } from "@assistant-ui/store";
2
2
  import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
3
3
  import { Pressable } from "react-native";
4
4
  import { jsx } from "react/jsx-runtime";
5
+ import "@assistant-ui/tap/react-shim";
5
6
  //#region src/primitives/attachment/AttachmentRemove.tsx
6
7
  const AttachmentRemove = (t0) => {
7
8
  const $ = c(9);
@@ -18,11 +19,11 @@ const AttachmentRemove = (t0) => {
18
19
  }
19
20
  const aui = useAui();
20
21
  let t1;
21
- if ($[3] !== aui) {
22
+ if ($[3] !== aui.attachment) {
22
23
  t1 = () => {
23
- aui.attachment().remove();
24
+ aui.attachment.remove();
24
25
  };
25
- $[3] = aui;
26
+ $[3] = aui.attachment;
26
27
  $[4] = t1;
27
28
  } else t1 = $[4];
28
29
  const handleRemove = t1;
@@ -1 +1 @@
1
- {"version":3,"file":"AttachmentRemove.js","names":["ReactNode","useCallback","Pressable","PressableProps","useAui","AttachmentRemoveProps","Omit","children","AttachmentRemove","t0","$","_c","pressableProps","aui","t1","attachment","remove","handleRemove","t2"],"sources":["../../../src/primitives/attachment/AttachmentRemove.tsx"],"sourcesContent":["import { type ReactNode, useCallback } from \"react\";\nimport { Pressable, type PressableProps } from \"react-native\";\n\nimport { useAui } from \"@assistant-ui/store\";\n\nexport type AttachmentRemoveProps = Omit<PressableProps, \"onPress\"> & {\n children: ReactNode;\n};\n\nexport const AttachmentRemove = ({\n children,\n ...pressableProps\n}: AttachmentRemoveProps) => {\n const aui = useAui();\n\n const handleRemove = useCallback(() => {\n aui.attachment().remove();\n }, [aui]);\n\n return (\n <Pressable onPress={handleRemove} {...pressableProps}>\n {children}\n </Pressable>\n );\n};\n"],"mappings":";;;;;AASA,MAAaQ,oBAAmBC,OAAA;CAAA,MAAAC,IAAAC,EAAA,CAAA;CAAA,IAAAJ;CAAA,IAAAK;CAAA,IAAAF,EAAA,OAAAD,IAAA;EAAC,CAAA,CAAAF,aAAAK,kBAAAH;EAGTC,EAAA,KAAAD;EAAAC,EAAA,KAAAH;EAAAG,EAAA,KAAAE;CAAA,OAAA;EAAAL,WAAAG,EAAA;EAAAE,iBAAAF,EAAA;CAAA;CACtB,MAAAG,MAAYT,OAAO;CAAE,IAAAU;CAAA,IAAAJ,EAAA,OAAAG,KAAA;EAEYC,WAAA;GAC/BD,IAAGE,WAAY,CAAC,CAAAC,OAAQ;EAAC;EAC1BN,EAAA,KAAAG;EAAAH,EAAA,KAAAI;CAAA,OAAAA,KAAAJ,EAAA;CAFD,MAAAO,eAAqBH;CAEX,IAAAI;CAAA,IAAAR,EAAA,OAAAH,YAAAG,EAAA,OAAAO,gBAAAP,EAAA,OAAAE,gBAAA;EAGRM,KAAA,oBAAC,WAAD;GAAoBD,SAAAA;GAAY,GAAML;GACnCL;EADO,CAAA;EAEEG,EAAA,KAAAH;EAAAG,EAAA,KAAAO;EAAAP,EAAA,KAAAE;EAAAF,EAAA,KAAAQ;CAAA,OAAAA,KAAAR,EAAA;CAAA,OAFZQ;AAEY"}
1
+ {"version":3,"file":"AttachmentRemove.js","names":["ReactNode","useCallback","Pressable","PressableProps","useAui","AttachmentRemoveProps","Omit","children","AttachmentRemove","t0","$","_c","pressableProps","aui","t1","attachment","remove","handleRemove","t2"],"sources":["../../../src/primitives/attachment/AttachmentRemove.tsx"],"sourcesContent":["import { type ReactNode, useCallback } from \"react\";\nimport { Pressable, type PressableProps } from \"react-native\";\n\nimport { useAui } from \"@assistant-ui/store\";\n\nexport type AttachmentRemoveProps = Omit<PressableProps, \"onPress\"> & {\n children: ReactNode;\n};\n\nexport const AttachmentRemove = ({\n children,\n ...pressableProps\n}: AttachmentRemoveProps) => {\n const aui = useAui();\n\n const handleRemove = useCallback(() => {\n aui.attachment.remove();\n }, [aui]);\n\n return (\n <Pressable onPress={handleRemove} {...pressableProps}>\n {children}\n </Pressable>\n );\n};\n"],"mappings":";;;;;;AASA,MAAaQ,oBAAmBC,OAAA;CAAA,MAAAC,IAAAC,EAAA,CAAA;CAAA,IAAAJ;CAAA,IAAAK;CAAA,IAAAF,EAAA,OAAAD,IAAA;EAAC,CAAA,CAAAF,aAAAK,kBAAAH;EAGTC,EAAA,KAAAD;EAAAC,EAAA,KAAAH;EAAAG,EAAA,KAAAE;CAAA,OAAA;EAAAL,WAAAG,EAAA;EAAAE,iBAAAF,EAAA;CAAA;CACtB,MAAAG,MAAYT,OAAO;CAAE,IAAAU;CAAA,IAAAJ,EAAA,OAAAG,IAAAE,YAAA;EAEYD,WAAA;GAC/BD,IAAGE,WAAWC,OAAQ;EAAC;EACxBN,EAAA,KAAAG,IAAAE;EAAAL,EAAA,KAAAI;CAAA,OAAAA,KAAAJ,EAAA;CAFD,MAAAO,eAAqBH;CAEX,IAAAI;CAAA,IAAAR,EAAA,OAAAH,YAAAG,EAAA,OAAAO,gBAAAP,EAAA,OAAAE,gBAAA;EAGRM,KAAA,oBAAC,WAAD;GAAoBD,SAAAA;GAAY,GAAML;GACnCL;EADO,CAAA;EAEEG,EAAA,KAAAH;EAAAG,EAAA,KAAAO;EAAAP,EAAA,KAAAE;EAAAF,EAAA,KAAAQ;CAAA,OAAAA,KAAAR,EAAA;CAAA,OAFZQ;AAEY"}
@@ -2,6 +2,7 @@ import { useAui, useAuiState } from "@assistant-ui/store";
2
2
  import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
3
3
  import { Pressable } from "react-native";
4
4
  import { jsx } from "react/jsx-runtime";
5
+ import "@assistant-ui/tap/react-shim";
5
6
  //#region src/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.tsx
6
7
  const ChainOfThoughtAccordionTrigger = (t0) => {
7
8
  const $ = c(10);
@@ -19,11 +20,11 @@ const ChainOfThoughtAccordionTrigger = (t0) => {
19
20
  const aui = useAui();
20
21
  const collapsed = useAuiState(_temp);
21
22
  let t1;
22
- if ($[3] !== aui || $[4] !== collapsed) {
23
+ if ($[3] !== aui.chainOfThought || $[4] !== collapsed) {
23
24
  t1 = () => {
24
- aui.chainOfThought().setCollapsed(!collapsed);
25
+ aui.chainOfThought.setCollapsed(!collapsed);
25
26
  };
26
- $[3] = aui;
27
+ $[3] = aui.chainOfThought;
27
28
  $[4] = collapsed;
28
29
  $[5] = t1;
29
30
  } else t1 = $[5];
@@ -1 +1 @@
1
- {"version":3,"file":"ChainOfThoughtAccordionTrigger.js","names":["useCallback","ReactNode","Pressable","PressableProps","useAuiState","useAui","ChainOfThoughtAccordionTriggerProps","Omit","children","ChainOfThoughtAccordionTrigger","t0","$","_c","pressableProps","aui","collapsed","_temp","t1","chainOfThought","setCollapsed","onPress","t2","s"],"sources":["../../../src/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.tsx"],"sourcesContent":["import { useCallback, type ReactNode } from \"react\";\nimport { Pressable, type PressableProps } from \"react-native\";\nimport { useAuiState, useAui } from \"@assistant-ui/store\";\n\nexport type ChainOfThoughtAccordionTriggerProps = Omit<\n PressableProps,\n \"onPress\"\n> & {\n children: ReactNode;\n};\n\nexport const ChainOfThoughtAccordionTrigger = ({\n children,\n ...pressableProps\n}: ChainOfThoughtAccordionTriggerProps) => {\n const aui = useAui();\n const collapsed = useAuiState((s) => s.chainOfThought.collapsed);\n\n const onPress = useCallback(() => {\n aui.chainOfThought().setCollapsed(!collapsed);\n }, [aui, collapsed]);\n\n return (\n <Pressable onPress={onPress} {...pressableProps}>\n {children}\n </Pressable>\n );\n};\n"],"mappings":";;;;;AAWA,MAAaS,kCAAiCC,OAAA;CAAA,MAAAC,IAAAC,EAAA,EAAA;CAAA,IAAAJ;CAAA,IAAAK;CAAA,IAAAF,EAAA,OAAAD,IAAA;EAAC,CAAA,CAAAF,aAAAK,kBAAAH;EAGTC,EAAA,KAAAD;EAAAC,EAAA,KAAAH;EAAAG,EAAA,KAAAE;CAAA,OAAA;EAAAL,WAAAG,EAAA;EAAAE,iBAAAF,EAAA;CAAA;CACpC,MAAAG,MAAYT,OAAO;CACnB,MAAAU,YAAkBX,YAAYY,KAAiC;CAAE,IAAAC;CAAA,IAAAN,EAAA,OAAAG,OAAAH,EAAA,OAAAI,WAAA;EAErCE,WAAA;GAC1BH,IAAGI,eAAgB,CAAC,CAAAC,aAAc,CAACJ,SAAS;EAAC;EAC9CJ,EAAA,KAAAG;EAAAH,EAAA,KAAAI;EAAAJ,EAAA,KAAAM;CAAA,OAAAA,KAAAN,EAAA;CAFD,MAAAS,UAAgBH;CAEK,IAAAI;CAAA,IAAAV,EAAA,OAAAH,YAAAG,EAAA,OAAAS,WAAAT,EAAA,OAAAE,gBAAA;EAGnBQ,KAAA,oBAAC,WAAD;GAAoBD;GAAO,GAAMP;GAC9BL;EADO,CAAA;EAEEG,EAAA,KAAAH;EAAAG,EAAA,KAAAS;EAAAT,EAAA,KAAAE;EAAAF,EAAA,KAAAU;CAAA,OAAAA,KAAAV,EAAA;CAAA,OAFZU;AAEY;AAd8B,SAAAL,MAAAM,GAAA;CAAA,OAKPA,EAACJ,eAAeH;AAAU"}
1
+ {"version":3,"file":"ChainOfThoughtAccordionTrigger.js","names":["useCallback","ReactNode","Pressable","PressableProps","useAuiState","useAui","ChainOfThoughtAccordionTriggerProps","Omit","children","ChainOfThoughtAccordionTrigger","t0","$","_c","pressableProps","aui","collapsed","_temp","t1","chainOfThought","setCollapsed","onPress","t2","s"],"sources":["../../../src/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.tsx"],"sourcesContent":["import { useCallback, type ReactNode } from \"react\";\nimport { Pressable, type PressableProps } from \"react-native\";\nimport { useAuiState, useAui } from \"@assistant-ui/store\";\n\nexport type ChainOfThoughtAccordionTriggerProps = Omit<\n PressableProps,\n \"onPress\"\n> & {\n children: ReactNode;\n};\n\nexport const ChainOfThoughtAccordionTrigger = ({\n children,\n ...pressableProps\n}: ChainOfThoughtAccordionTriggerProps) => {\n const aui = useAui();\n const collapsed = useAuiState((s) => s.chainOfThought.collapsed);\n\n const onPress = useCallback(() => {\n aui.chainOfThought.setCollapsed(!collapsed);\n }, [aui, collapsed]);\n\n return (\n <Pressable onPress={onPress} {...pressableProps}>\n {children}\n </Pressable>\n );\n};\n"],"mappings":";;;;;;AAWA,MAAaS,kCAAiCC,OAAA;CAAA,MAAAC,IAAAC,EAAA,EAAA;CAAA,IAAAJ;CAAA,IAAAK;CAAA,IAAAF,EAAA,OAAAD,IAAA;EAAC,CAAA,CAAAF,aAAAK,kBAAAH;EAGTC,EAAA,KAAAD;EAAAC,EAAA,KAAAH;EAAAG,EAAA,KAAAE;CAAA,OAAA;EAAAL,WAAAG,EAAA;EAAAE,iBAAAF,EAAA;CAAA;CACpC,MAAAG,MAAYT,OAAO;CACnB,MAAAU,YAAkBX,YAAYY,KAAiC;CAAE,IAAAC;CAAA,IAAAN,EAAA,OAAAG,IAAAI,kBAAAP,EAAA,OAAAI,WAAA;EAErCE,WAAA;GAC1BH,IAAGI,eAAeC,aAAc,CAACJ,SAAS;EAAC;EAC5CJ,EAAA,KAAAG,IAAAI;EAAAP,EAAA,KAAAI;EAAAJ,EAAA,KAAAM;CAAA,OAAAA,KAAAN,EAAA;CAFD,MAAAS,UAAgBH;CAEK,IAAAI;CAAA,IAAAV,EAAA,OAAAH,YAAAG,EAAA,OAAAS,WAAAT,EAAA,OAAAE,gBAAA;EAGnBQ,KAAA,oBAAC,WAAD;GAAoBD;GAAO,GAAMP;GAC9BL;EADO,CAAA;EAEEG,EAAA,KAAAH;EAAAG,EAAA,KAAAS;EAAAT,EAAA,KAAAE;EAAAF,EAAA,KAAAU;CAAA,OAAAA,KAAAV,EAAA;CAAA,OAFZU;AAEY;AAd8B,SAAAL,MAAAM,GAAA;CAAA,OAKPA,EAACJ,eAAeH;AAAU"}
@@ -58,11 +58,11 @@ const ComposerInput = (t0) => {
58
58
  t2 = (value) => {
59
59
  if (Platform.OS === "web") {
60
60
  flushTapSync(() => {
61
- aui.composer().setText(value);
61
+ aui.composer.setText(value);
62
62
  });
63
63
  return;
64
64
  }
65
- aui.composer().setText(value);
65
+ aui.composer.setText(value);
66
66
  };
67
67
  $[6] = aui;
68
68
  $[7] = t2;
@@ -92,7 +92,7 @@ const ComposerInput = (t0) => {
92
92
  if (nativeEvent.isComposing || nativeEvent.keyCode === 229) return;
93
93
  if (nativeEvent.key === "Enter" && !nativeEvent.shiftKey) {
94
94
  e.preventDefault?.();
95
- aui.composer().send();
95
+ aui.composer.send();
96
96
  }
97
97
  };
98
98
  $[11] = aui;
@@ -1 +1 @@
1
- {"version":3,"file":"ComposerInput.js","names":["useCallback","useEffect","useRef","Platform","TextInput","NativeSyntheticEvent","TextInputKeyPressEventData","TextInputProps","useAui","useAuiState","flushTapSync","ComposerInputProps","Omit","submitMode","getWebTextareaMaxHeight","el","HTMLTextAreaElement","computedMaxHeight","globalThis","getComputedStyle","maxHeight","parsedComputedMaxHeight","Number","parseFloat","isFinite","inlineMaxHeight","style","adjustWebTextareaHeight","ref","React","RefObject","OS","current","rows","overflowX","overflowY","height","scrollHeight","needsScrollbar","nextHeight","Math","min","ComposerInput","t0","$","_c","numberOfLines","onKeyPressProp","props","t1","onKeyPress","undefined","aui","text","_temp","inputRef","t2","value","composer","setText","onChangeText","t3","Symbol","for","t4","t5","e","nativeEvent","shiftKey","isComposing","keyCode","key","Event","preventDefault","send","t6","t7","s"],"sources":["../../../src/primitives/composer/ComposerInput.tsx"],"sourcesContent":["import { useCallback, useEffect, useRef } from \"react\";\nimport {\n Platform,\n TextInput,\n type NativeSyntheticEvent,\n type TextInputKeyPressEventData,\n type TextInputProps,\n} from \"react-native\";\nimport { useAui, useAuiState } from \"@assistant-ui/store\";\nimport { flushTapSync } from \"@assistant-ui/tap\";\n\nexport type ComposerInputProps = Omit<\n TextInputProps,\n \"value\" | \"onChangeText\"\n> & {\n /**\n * Controls how the Enter key submits messages (web only).\n * - \"enter\": Plain Enter submits (Shift+Enter for newline)\n * - \"none\": Enter inserts newline (no keyboard submission)\n * @default \"enter\"\n */\n submitMode?: \"enter\" | \"none\";\n};\n\nconst getWebTextareaMaxHeight = (el: HTMLTextAreaElement) => {\n const computedMaxHeight = globalThis.getComputedStyle?.(el).maxHeight;\n const parsedComputedMaxHeight = Number.parseFloat(computedMaxHeight ?? \"\");\n if (Number.isFinite(parsedComputedMaxHeight)) return parsedComputedMaxHeight;\n\n const inlineMaxHeight = Number.parseFloat(el.style.maxHeight);\n return Number.isFinite(inlineMaxHeight) ? inlineMaxHeight : null;\n};\n\nconst adjustWebTextareaHeight = (ref: React.RefObject<TextInput | null>) => {\n if (Platform.OS !== \"web\") return;\n // On web, the TextInput ref IS the DOM element\n const el = ref.current as unknown as HTMLTextAreaElement | null;\n if (!el) return;\n // Ensure rows=1 so scrollHeight reflects actual content\n if (el.rows !== 1) el.rows = 1;\n\n el.style.overflowX = \"hidden\";\n el.style.overflowY = \"hidden\";\n el.style.height = \"auto\";\n\n const scrollHeight = el.scrollHeight;\n const maxHeight = getWebTextareaMaxHeight(el);\n const needsScrollbar = maxHeight !== null && scrollHeight > maxHeight;\n const nextHeight =\n maxHeight === null ? scrollHeight : Math.min(scrollHeight, maxHeight);\n\n el.style.overflowY = needsScrollbar ? \"auto\" : \"hidden\";\n el.style.height = `${nextHeight}px`;\n};\n\nexport const ComposerInput = ({\n submitMode = \"enter\",\n onKeyPress: onKeyPressProp,\n numberOfLines,\n style,\n ...props\n}: ComposerInputProps) => {\n const aui = useAui();\n const text = useAuiState((s) => s.composer.text);\n const inputRef = useRef<TextInput>(null);\n\n const onChangeText = useCallback(\n (value: string) => {\n if (Platform.OS === \"web\") {\n // Keep the controlled value in sync mid-IME so react-dom does not reset the textarea to a stale value\n flushTapSync(() => {\n aui.composer().setText(value);\n });\n return;\n }\n aui.composer().setText(value);\n },\n [aui],\n );\n\n // Auto-resize textarea on web when text changes\n useEffect(() => {\n void text; // trigger re-run when text changes\n adjustWebTextareaHeight(inputRef);\n }, [text]);\n\n const onKeyPress = useCallback(\n (e: NativeSyntheticEvent<TextInputKeyPressEventData>) => {\n onKeyPressProp?.(e);\n\n if (Platform.OS !== \"web\") return;\n if (submitMode !== \"enter\") return;\n\n const nativeEvent = e.nativeEvent as TextInputKeyPressEventData & {\n shiftKey?: boolean;\n isComposing?: boolean;\n keyCode?: number;\n };\n // react-native-web forwards the raw DOM keydown before its own composition guard, so re-check it here (mirrors isEventComposing)\n if (nativeEvent.isComposing || nativeEvent.keyCode === 229) return;\n if (nativeEvent.key === \"Enter\" && !nativeEvent.shiftKey) {\n (e as unknown as Event).preventDefault?.();\n aui.composer().send();\n }\n },\n [aui, submitMode, onKeyPressProp],\n );\n\n return (\n <TextInput\n ref={inputRef}\n value={text}\n onChangeText={onChangeText}\n onKeyPress={onKeyPress}\n numberOfLines={numberOfLines ?? (Platform.OS === \"web\" ? 1 : undefined)}\n style={style}\n {...props}\n />\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"ComposerInput.js","names":["useCallback","useEffect","useRef","Platform","TextInput","NativeSyntheticEvent","TextInputKeyPressEventData","TextInputProps","useAui","useAuiState","flushTapSync","ComposerInputProps","Omit","submitMode","getWebTextareaMaxHeight","el","HTMLTextAreaElement","computedMaxHeight","globalThis","getComputedStyle","maxHeight","parsedComputedMaxHeight","Number","parseFloat","isFinite","inlineMaxHeight","style","adjustWebTextareaHeight","ref","React","RefObject","OS","current","rows","overflowX","overflowY","height","scrollHeight","needsScrollbar","nextHeight","Math","min","ComposerInput","t0","$","_c","numberOfLines","onKeyPressProp","props","t1","onKeyPress","undefined","aui","text","_temp","inputRef","t2","value","composer","setText","onChangeText","t3","Symbol","for","t4","t5","e","nativeEvent","shiftKey","isComposing","keyCode","key","Event","preventDefault","send","t6","t7","s"],"sources":["../../../src/primitives/composer/ComposerInput.tsx"],"sourcesContent":["import { useCallback, useEffect, useRef } from \"react\";\nimport {\n Platform,\n TextInput,\n type NativeSyntheticEvent,\n type TextInputKeyPressEventData,\n type TextInputProps,\n} from \"react-native\";\nimport { useAui, useAuiState } from \"@assistant-ui/store\";\nimport { flushTapSync } from \"@assistant-ui/tap\";\n\nexport type ComposerInputProps = Omit<\n TextInputProps,\n \"value\" | \"onChangeText\"\n> & {\n /**\n * Controls how the Enter key submits messages (web only).\n * - \"enter\": Plain Enter submits (Shift+Enter for newline)\n * - \"none\": Enter inserts newline (no keyboard submission)\n * @default \"enter\"\n */\n submitMode?: \"enter\" | \"none\";\n};\n\nconst getWebTextareaMaxHeight = (el: HTMLTextAreaElement) => {\n const computedMaxHeight = globalThis.getComputedStyle?.(el).maxHeight;\n const parsedComputedMaxHeight = Number.parseFloat(computedMaxHeight ?? \"\");\n if (Number.isFinite(parsedComputedMaxHeight)) return parsedComputedMaxHeight;\n\n const inlineMaxHeight = Number.parseFloat(el.style.maxHeight);\n return Number.isFinite(inlineMaxHeight) ? inlineMaxHeight : null;\n};\n\nconst adjustWebTextareaHeight = (ref: React.RefObject<TextInput | null>) => {\n if (Platform.OS !== \"web\") return;\n // On web, the TextInput ref IS the DOM element\n const el = ref.current as unknown as HTMLTextAreaElement | null;\n if (!el) return;\n // Ensure rows=1 so scrollHeight reflects actual content\n if (el.rows !== 1) el.rows = 1;\n\n el.style.overflowX = \"hidden\";\n el.style.overflowY = \"hidden\";\n el.style.height = \"auto\";\n\n const scrollHeight = el.scrollHeight;\n const maxHeight = getWebTextareaMaxHeight(el);\n const needsScrollbar = maxHeight !== null && scrollHeight > maxHeight;\n const nextHeight =\n maxHeight === null ? scrollHeight : Math.min(scrollHeight, maxHeight);\n\n el.style.overflowY = needsScrollbar ? \"auto\" : \"hidden\";\n el.style.height = `${nextHeight}px`;\n};\n\nexport const ComposerInput = ({\n submitMode = \"enter\",\n onKeyPress: onKeyPressProp,\n numberOfLines,\n style,\n ...props\n}: ComposerInputProps) => {\n const aui = useAui();\n const text = useAuiState((s) => s.composer.text);\n const inputRef = useRef<TextInput>(null);\n\n const onChangeText = useCallback(\n (value: string) => {\n if (Platform.OS === \"web\") {\n // Keep the controlled value in sync mid-IME so react-dom does not reset the textarea to a stale value\n flushTapSync(() => {\n aui.composer.setText(value);\n });\n return;\n }\n aui.composer.setText(value);\n },\n [aui],\n );\n\n // Auto-resize textarea on web when text changes\n useEffect(() => {\n void text; // trigger re-run when text changes\n adjustWebTextareaHeight(inputRef);\n }, [text]);\n\n const onKeyPress = useCallback(\n (e: NativeSyntheticEvent<TextInputKeyPressEventData>) => {\n onKeyPressProp?.(e);\n\n if (Platform.OS !== \"web\") return;\n if (submitMode !== \"enter\") return;\n\n const nativeEvent = e.nativeEvent as TextInputKeyPressEventData & {\n shiftKey?: boolean;\n isComposing?: boolean;\n keyCode?: number;\n };\n // react-native-web forwards the raw DOM keydown before its own composition guard, so re-check it here (mirrors isEventComposing)\n if (nativeEvent.isComposing || nativeEvent.keyCode === 229) return;\n if (nativeEvent.key === \"Enter\" && !nativeEvent.shiftKey) {\n (e as unknown as Event).preventDefault?.();\n aui.composer.send();\n }\n },\n [aui, submitMode, onKeyPressProp],\n );\n\n return (\n <TextInput\n ref={inputRef}\n value={text}\n onChangeText={onChangeText}\n onKeyPress={onKeyPress}\n numberOfLines={numberOfLines ?? (Platform.OS === \"web\" ? 1 : undefined)}\n style={style}\n {...props}\n />\n );\n};\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"MessageContent.d.ts","names":[],"sources":["../../../src/primitives/message/MessageContent.tsx"],"mappings":";;;KAcK,qBAAqB,wBAAwB;KAEtC;EACV,cAAc;IACZ,MAAM,QAAQ;MAAsB;;IACpC;QACI;EACN,kBAAkB;IAChB,MAAM,QAAQ;MAAsB;;IACpC;QACI;EACN,eAAe;IACb,MAAM,QAAQ;MAAsB;;IACpC;QACI;EACN,mBAAmB;IACjB,MAAM,QAAQ;MAAsB;;IACpC;QACI;EACN,gBAAgB;IACd,MAAM,QAAQ;MAAsB;;IACpC;QACI;EACN,cAAc;IACZ,MAAM,QAAQ;MAAsB;;IACpC;QACI;EACN,cAAc;IACZ,MAAM,QAAQ;MAAsB;;IACpC;QACI;;cAqEK,mBAAkB,YAAA,gBAAA,aAAA,iBAAA,cAAA,YAAA,cAQ5B,wCAAmB,IAAA"}
1
+ {"version":3,"file":"MessageContent.d.ts","names":[],"sources":["../../../src/primitives/message/MessageContent.tsx"],"mappings":";;;KAcK,qBAAqB,wBAAwB;KAEtC;EACV,cAAc;IACZ,MAAM,QAAQ;MAAsB;;IACpC;QACI;EACN,kBAAkB;IAChB,MAAM,QAAQ;MAAsB;;IACpC;QACI;EACN,eAAe;IACb,MAAM,QAAQ;MAAsB;;IACpC;QACI;EACN,mBAAmB;IACjB,MAAM,QAAQ;MAAsB;;IACpC;QACI;EACN,gBAAgB;IACd,MAAM,QAAQ;MAAsB;;IACpC;QACI;EACN,cAAc;IACZ,MAAM,QAAQ;MAAsB;;IACpC;QACI;EACN,cAAc;IACZ,MAAM,QAAQ;MAAsB;;IACpC;QACI;;cAgEK,mBAAkB,YAAA,gBAAA,aAAA,iBAAA,cAAA,YAAA,cAQ5B,wCAAmB,IAAA"}
@@ -21,19 +21,15 @@ const ToolUIDisplay = (t0) => {
21
21
  const aui = useAui();
22
22
  let t1;
23
23
  if ($[0] !== part.toolName) {
24
- t1 = (s) => {
25
- const renders = s.tools.tools[part.toolName];
26
- if (Array.isArray(renders)) return renders[0];
27
- return renders;
28
- };
24
+ t1 = (s) => s.tools.toolUIs[part.toolName]?.[0]?.render;
29
25
  $[0] = part.toolName;
30
26
  $[1] = t1;
31
27
  } else t1 = $[1];
32
28
  const Render = useAuiState(t1);
33
29
  let t2;
34
- if ($[2] !== aui || $[3] !== index) {
35
- t2 = aui.message().part({ index });
36
- $[2] = aui;
30
+ if ($[2] !== aui.message || $[3] !== index) {
31
+ t2 = aui.message.part({ index });
32
+ $[2] = aui.message;
37
33
  $[3] = index;
38
34
  $[4] = t2;
39
35
  } else t2 = $[4];
@@ -1 +1 @@
1
- {"version":3,"file":"MessageContent.js","names":["ReactElement","Fragment","useMemo","Text","ThreadUserMessagePart","ThreadAssistantMessagePart","ToolCallMessagePart","DataMessagePart","useAui","useAuiState","ToolCallMessagePartProps","DataMessagePartProps","MessageContentPart","MessageContentProps","renderText","props","part","Extract","type","index","renderToolCall","renderImage","renderReasoning","renderSource","renderFile","renderData","DefaultTextRenderer","t0","$","_c","t1","text","ToolUIDisplay","Fallback","aui","toolName","s","renders","tools","Array","isArray","Render","t2","message","partMethods","t3","t4","addToolResult","respondToToolApproval","resumeToolCall","DataUIDisplay","name","dataRenderers","renderers","MessageContent","content","_temp","key","map"],"sources":["../../../src/primitives/message/MessageContent.tsx"],"sourcesContent":["import { type ReactElement, Fragment, useMemo } from \"react\";\nimport { Text } from \"react-native\";\nimport type {\n ThreadUserMessagePart,\n ThreadAssistantMessagePart,\n ToolCallMessagePart,\n DataMessagePart,\n} from \"@assistant-ui/core\";\nimport { useAui, useAuiState } from \"@assistant-ui/store\";\nimport type {\n ToolCallMessagePartProps,\n DataMessagePartProps,\n} from \"@assistant-ui/core/react\";\n\ntype MessageContentPart = ThreadUserMessagePart | ThreadAssistantMessagePart;\n\nexport type MessageContentProps = {\n renderText?: (props: {\n part: Extract<MessageContentPart, { type: \"text\" }>;\n index: number;\n }) => ReactElement;\n renderToolCall?: (props: {\n part: Extract<MessageContentPart, { type: \"tool-call\" }>;\n index: number;\n }) => ReactElement;\n renderImage?: (props: {\n part: Extract<MessageContentPart, { type: \"image\" }>;\n index: number;\n }) => ReactElement;\n renderReasoning?: (props: {\n part: Extract<MessageContentPart, { type: \"reasoning\" }>;\n index: number;\n }) => ReactElement;\n renderSource?: (props: {\n part: Extract<MessageContentPart, { type: \"source\" }>;\n index: number;\n }) => ReactElement;\n renderFile?: (props: {\n part: Extract<MessageContentPart, { type: \"file\" }>;\n index: number;\n }) => ReactElement;\n renderData?: (props: {\n part: Extract<MessageContentPart, { type: \"data\" }>;\n index: number;\n }) => ReactElement;\n};\n\nconst DefaultTextRenderer = ({\n part,\n}: {\n part: Extract<MessageContentPart, { type: \"text\" }>;\n}) => {\n return <Text>{part.text}</Text>;\n};\n\nconst ToolUIDisplay = ({\n Fallback,\n part,\n index,\n}: {\n Fallback:\n | ((props: { part: ToolCallMessagePart; index: number }) => ReactElement)\n | undefined;\n part: ToolCallMessagePart;\n index: number;\n}) => {\n const aui = useAui();\n const Render = useAuiState((s) => {\n const renders = s.tools.tools[part.toolName];\n if (Array.isArray(renders)) return renders[0];\n return renders;\n });\n\n const partMethods = useMemo(\n () => aui.message().part({ index }),\n [aui, index],\n );\n\n if (Render) {\n return (\n <Render\n {...(part as ToolCallMessagePartProps)}\n addResult={partMethods.addToolResult}\n resume={partMethods.resumeToolCall}\n respondToApproval={partMethods.respondToToolApproval}\n />\n );\n }\n if (Fallback) return <Fallback part={part} index={index} />;\n return null;\n};\n\nconst DataUIDisplay = ({\n Fallback,\n part,\n index,\n}: {\n Fallback:\n | ((props: { part: DataMessagePart; index: number }) => ReactElement)\n | undefined;\n part: DataMessagePart;\n index: number;\n}) => {\n const Render = useAuiState((s) => {\n const renders = s.dataRenderers.renderers[part.name];\n if (Array.isArray(renders)) return renders[0];\n return renders;\n });\n if (Render) return <Render {...(part as DataMessagePartProps)} />;\n if (Fallback) return <Fallback part={part} index={index} />;\n return null;\n};\n\nexport const MessageContent = ({\n renderText,\n renderToolCall,\n renderImage,\n renderReasoning,\n renderSource,\n renderFile,\n renderData,\n}: MessageContentProps) => {\n const content = useAuiState((s) => s.message.content);\n\n return (\n <>\n {content.map((part, index) => {\n const key = `${part.type}-${index}`;\n switch (part.type) {\n case \"text\":\n return (\n <Fragment key={key}>\n {renderText ? (\n renderText({ part, index })\n ) : (\n <DefaultTextRenderer part={part} />\n )}\n </Fragment>\n );\n case \"tool-call\":\n return (\n <Fragment key={key}>\n <ToolUIDisplay\n Fallback={renderToolCall}\n part={part}\n index={index}\n />\n </Fragment>\n );\n case \"image\":\n if (!renderImage) return null;\n return (\n <Fragment key={key}>{renderImage({ part, index })}</Fragment>\n );\n case \"reasoning\":\n if (!renderReasoning) return null;\n return (\n <Fragment key={key}>{renderReasoning({ part, index })}</Fragment>\n );\n case \"source\":\n if (!renderSource) return null;\n return (\n <Fragment key={key}>{renderSource({ part, index })}</Fragment>\n );\n case \"file\":\n if (!renderFile) return null;\n return <Fragment key={key}>{renderFile({ part, index })}</Fragment>;\n case \"data\":\n return (\n <Fragment key={key}>\n <DataUIDisplay\n Fallback={renderData}\n part={part}\n index={index}\n />\n </Fragment>\n );\n default:\n return null;\n }\n })}\n </>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"MessageContent.js","names":["ReactElement","Fragment","useMemo","Text","ThreadUserMessagePart","ThreadAssistantMessagePart","ToolCallMessagePart","DataMessagePart","useAui","useAuiState","ToolCallMessagePartProps","DataMessagePartProps","MessageContentPart","MessageContentProps","renderText","props","part","Extract","type","index","renderToolCall","renderImage","renderReasoning","renderSource","renderFile","renderData","DefaultTextRenderer","t0","$","_c","t1","text","ToolUIDisplay","Fallback","aui","toolName","s","tools","toolUIs","render","Render","t2","message","partMethods","t3","t4","addToolResult","respondToToolApproval","resumeToolCall","DataUIDisplay","name","renders","dataRenderers","renderers","Array","isArray","MessageContent","content","_temp","key","map"],"sources":["../../../src/primitives/message/MessageContent.tsx"],"sourcesContent":["import { type ReactElement, Fragment, useMemo } from \"react\";\nimport { Text } from \"react-native\";\nimport type {\n ThreadUserMessagePart,\n ThreadAssistantMessagePart,\n ToolCallMessagePart,\n DataMessagePart,\n} from \"@assistant-ui/core\";\nimport { useAui, useAuiState } from \"@assistant-ui/store\";\nimport type {\n ToolCallMessagePartProps,\n DataMessagePartProps,\n} from \"@assistant-ui/core/react\";\n\ntype MessageContentPart = ThreadUserMessagePart | ThreadAssistantMessagePart;\n\nexport type MessageContentProps = {\n renderText?: (props: {\n part: Extract<MessageContentPart, { type: \"text\" }>;\n index: number;\n }) => ReactElement;\n renderToolCall?: (props: {\n part: Extract<MessageContentPart, { type: \"tool-call\" }>;\n index: number;\n }) => ReactElement;\n renderImage?: (props: {\n part: Extract<MessageContentPart, { type: \"image\" }>;\n index: number;\n }) => ReactElement;\n renderReasoning?: (props: {\n part: Extract<MessageContentPart, { type: \"reasoning\" }>;\n index: number;\n }) => ReactElement;\n renderSource?: (props: {\n part: Extract<MessageContentPart, { type: \"source\" }>;\n index: number;\n }) => ReactElement;\n renderFile?: (props: {\n part: Extract<MessageContentPart, { type: \"file\" }>;\n index: number;\n }) => ReactElement;\n renderData?: (props: {\n part: Extract<MessageContentPart, { type: \"data\" }>;\n index: number;\n }) => ReactElement;\n};\n\nconst DefaultTextRenderer = ({\n part,\n}: {\n part: Extract<MessageContentPart, { type: \"text\" }>;\n}) => {\n return <Text>{part.text}</Text>;\n};\n\nconst ToolUIDisplay = ({\n Fallback,\n part,\n index,\n}: {\n Fallback:\n | ((props: { part: ToolCallMessagePart; index: number }) => ReactElement)\n | undefined;\n part: ToolCallMessagePart;\n index: number;\n}) => {\n const aui = useAui();\n const Render = useAuiState(\n (s) => s.tools.toolUIs[part.toolName]?.[0]?.render,\n );\n\n const partMethods = useMemo(() => aui.message.part({ index }), [aui, index]);\n\n if (Render) {\n return (\n <Render\n {...(part as ToolCallMessagePartProps)}\n addResult={partMethods.addToolResult}\n resume={partMethods.resumeToolCall}\n respondToApproval={partMethods.respondToToolApproval}\n />\n );\n }\n if (Fallback) return <Fallback part={part} index={index} />;\n return null;\n};\n\nconst DataUIDisplay = ({\n Fallback,\n part,\n index,\n}: {\n Fallback:\n | ((props: { part: DataMessagePart; index: number }) => ReactElement)\n | undefined;\n part: DataMessagePart;\n index: number;\n}) => {\n const Render = useAuiState((s) => {\n const renders = s.dataRenderers.renderers[part.name];\n if (Array.isArray(renders)) return renders[0];\n return renders;\n });\n if (Render) return <Render {...(part as DataMessagePartProps)} />;\n if (Fallback) return <Fallback part={part} index={index} />;\n return null;\n};\n\nexport const MessageContent = ({\n renderText,\n renderToolCall,\n renderImage,\n renderReasoning,\n renderSource,\n renderFile,\n renderData,\n}: MessageContentProps) => {\n const content = useAuiState((s) => s.message.content);\n\n return (\n <>\n {content.map((part, index) => {\n const key = `${part.type}-${index}`;\n switch (part.type) {\n case \"text\":\n return (\n <Fragment key={key}>\n {renderText ? (\n renderText({ part, index })\n ) : (\n <DefaultTextRenderer part={part} />\n )}\n </Fragment>\n );\n case \"tool-call\":\n return (\n <Fragment key={key}>\n <ToolUIDisplay\n Fallback={renderToolCall}\n part={part}\n index={index}\n />\n </Fragment>\n );\n case \"image\":\n if (!renderImage) return null;\n return (\n <Fragment key={key}>{renderImage({ part, index })}</Fragment>\n );\n case \"reasoning\":\n if (!renderReasoning) return null;\n return (\n <Fragment key={key}>{renderReasoning({ part, index })}</Fragment>\n );\n case \"source\":\n if (!renderSource) return null;\n return (\n <Fragment key={key}>{renderSource({ part, index })}</Fragment>\n );\n case \"file\":\n if (!renderFile) return null;\n return <Fragment key={key}>{renderFile({ part, index })}</Fragment>;\n case \"data\":\n return (\n <Fragment key={key}>\n <DataUIDisplay\n Fallback={renderData}\n part={part}\n index={index}\n />\n </Fragment>\n );\n default:\n return null;\n }\n })}\n </>\n );\n};\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ThreadMessages.d.ts","names":[],"sources":["../../../src/primitives/thread/ThreadMessages.tsx"],"mappings":";;;;KA2BK;EAEC,SAAS;EACT,eAAe;EACf,mBAAmB;EACnB,wBAAwB;EACxB,qBAAqB;EACrB,cAAc;EACd,mBAAmB;EACnB,gBAAgB;;EAGhB,UAAU;EACV,eAAe;EACf,mBAAmB;EACnB,wBAAwB;EACxB,qBAAqB;EACrB,aAAa;EACb,kBAAkB;EAClB,gBAAgB;;KAGjB;;EAGC,YAAY;EACZ;;EAGA,WAAW;IAAS,SAAS;QAAmB;EAChD;;KAGM,8BAA8B,KACxC,cAAc,sDAGd;EACE;EACA;EACA;EACA;;;KAIQ,sBAAsB;cAmRrB,wCAAsB,0BAAA,8CAAA,cAAA,SAAA;;cA4GtB,gCAAc,0BAAA,8CAAA,cAAA,SAAA"}
1
+ {"version":3,"file":"ThreadMessages.d.ts","names":[],"sources":["../../../src/primitives/thread/ThreadMessages.tsx"],"mappings":";;;;KA2BK;EAEC,SAAS;EACT,eAAe;EACf,mBAAmB;EACnB,wBAAwB;EACxB,qBAAqB;EACrB,cAAc;EACd,mBAAmB;EACnB,gBAAgB;;EAGhB,UAAU;EACV,eAAe;EACf,mBAAmB;EACnB,wBAAwB;EACxB,qBAAqB;EACrB,aAAa;EACb,kBAAkB;EAClB,gBAAgB;;KAGjB;;EAGC,YAAY;EACZ;;EAGA,WAAW;IAAS,SAAS;QAAmB;EAChD;;KAGM,8BAA8B,KACxC,cAAc,sDAGd;EACE;EACA;EACA;EACA;;;KAIQ,sBAAsB;cAqSrB,wCAAsB,0BAAA,8CAAA,cAAA,SAAA;;cA4GtB,gCAAc,0BAAA,8CAAA,cAAA,SAAA"}
@@ -66,7 +66,7 @@ const ThreadMessageByChildren = memo(({ index, children }) => {
66
66
  return /* @__PURE__ */ jsx(MessageByIndexProvider, {
67
67
  index,
68
68
  children: /* @__PURE__ */ jsx(RenderChildrenWithAccessor, {
69
- getItemState: (aui) => aui.thread().message({ index }).getState(),
69
+ getItemState: (aui) => aui.thread.message({ index }).getState(),
70
70
  children: (getItem) => children({ get message() {
71
71
  return getItem();
72
72
  } })
@@ -100,7 +100,7 @@ const useComposedFlatListRef = (forwardedRef) => {
100
100
  return t1;
101
101
  };
102
102
  const useThreadMessagesFlatListAutoScroll = (t0) => {
103
- const $ = c(22);
103
+ const $ = c(25);
104
104
  const { flatListRef, hasMessages, autoScroll: t1, scrollToBottomOnRunStart: t2, scrollToBottomOnInitialize: t3, scrollToBottomOnThreadSwitch: t4 } = t0;
105
105
  const autoScroll = t1 === void 0 ? true : t1;
106
106
  const scrollToBottomOnRunStart = t2 === void 0 ? true : t2;
@@ -142,16 +142,26 @@ const useThreadMessagesFlatListAutoScroll = (t0) => {
142
142
  } else t7 = $[3];
143
143
  const scrollToBottom = t7;
144
144
  let t8;
145
- if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
145
+ if ($[4] !== autoScroll || $[5] !== scrollToBottom) {
146
146
  t8 = (event) => {
147
- metricsRef.current.viewportHeight = event.nativeEvent.layout.height;
147
+ const wasAtBottom = isAtBottomRef.current;
148
+ const previousViewportHeight = metricsRef.current.viewportHeight;
149
+ const viewportHeight_1 = event.nativeEvent.layout.height;
150
+ metricsRef.current.viewportHeight = viewportHeight_1;
148
151
  updateIsAtBottom();
152
+ if (!wasAtBottom) return;
153
+ if (autoScroll && previousViewportHeight !== 0 && viewportHeight_1 !== previousViewportHeight) {
154
+ const pending = pendingScrollToBottomRef.current;
155
+ scrollToBottom(pending ? pending.animated : false);
156
+ } else isAtBottomRef.current = true;
149
157
  };
150
- $[4] = t8;
151
- } else t8 = $[4];
158
+ $[4] = autoScroll;
159
+ $[5] = scrollToBottom;
160
+ $[6] = t8;
161
+ } else t8 = $[6];
152
162
  const handleLayout = t8;
153
163
  let t9;
154
- if ($[5] === Symbol.for("react.memo_cache_sentinel")) {
164
+ if ($[7] === Symbol.for("react.memo_cache_sentinel")) {
155
165
  t9 = (event_0) => {
156
166
  const { contentOffset, contentSize, layoutMeasurement } = event_0.nativeEvent;
157
167
  const previousEventY = lastScrollEventYRef.current;
@@ -167,15 +177,15 @@ const useThreadMessagesFlatListAutoScroll = (t0) => {
167
177
  if (wasPinnedToBottom && !upwardMove) isAtBottomRef.current = true;
168
178
  if (!isAtBottomRef.current && upwardMove) pendingScrollToBottomRef.current = false;
169
179
  };
170
- $[5] = t9;
171
- } else t9 = $[5];
180
+ $[7] = t9;
181
+ } else t9 = $[7];
172
182
  const handleScroll = t9;
173
183
  let t10;
174
- if ($[6] !== autoScroll || $[7] !== scrollToBottom) {
184
+ if ($[8] !== autoScroll || $[9] !== scrollToBottom) {
175
185
  t10 = (_width, height) => {
176
186
  const metrics = metricsRef.current;
177
187
  const previousContentHeight = metrics.contentHeight;
178
- const wasAtBottom = isAtBottomRef.current;
188
+ const wasAtBottom_0 = isAtBottomRef.current;
179
189
  metrics.contentHeight = height;
180
190
  updateIsAtBottom();
181
191
  const pendingScroll = pendingScrollToBottomRef.current;
@@ -185,19 +195,19 @@ const useThreadMessagesFlatListAutoScroll = (t0) => {
185
195
  return;
186
196
  }
187
197
  if (!autoScroll) return;
188
- if (!wasAtBottom) return;
198
+ if (!wasAtBottom_0) return;
189
199
  if (previousContentHeight === 0) return;
190
200
  if (height <= previousContentHeight) return;
191
201
  scrollToBottom(false);
192
202
  };
193
- $[6] = autoScroll;
194
- $[7] = scrollToBottom;
195
- $[8] = t10;
196
- } else t10 = $[8];
203
+ $[8] = autoScroll;
204
+ $[9] = scrollToBottom;
205
+ $[10] = t10;
206
+ } else t10 = $[10];
197
207
  const handleContentSizeChange = t10;
198
208
  let t11;
199
209
  let t12;
200
- if ($[9] !== hasMessages || $[10] !== scrollToBottom || $[11] !== scrollToBottomOnInitialize) {
210
+ if ($[11] !== hasMessages || $[12] !== scrollToBottom || $[13] !== scrollToBottomOnInitialize) {
201
211
  t11 = () => {
202
212
  if (!scrollToBottomOnInitialize) return;
203
213
  if (!hasMessages) {
@@ -214,30 +224,30 @@ const useThreadMessagesFlatListAutoScroll = (t0) => {
214
224
  scrollToBottom,
215
225
  scrollToBottomOnInitialize
216
226
  ];
217
- $[9] = hasMessages;
218
- $[10] = scrollToBottom;
219
- $[11] = scrollToBottomOnInitialize;
220
- $[12] = t11;
221
- $[13] = t12;
227
+ $[11] = hasMessages;
228
+ $[12] = scrollToBottom;
229
+ $[13] = scrollToBottomOnInitialize;
230
+ $[14] = t11;
231
+ $[15] = t12;
222
232
  } else {
223
- t11 = $[12];
224
- t12 = $[13];
233
+ t11 = $[14];
234
+ t12 = $[15];
225
235
  }
226
236
  useEffect(t11, t12);
227
237
  let t13;
228
- if ($[14] !== scrollToBottom || $[15] !== scrollToBottomOnRunStart) {
238
+ if ($[16] !== scrollToBottom || $[17] !== scrollToBottomOnRunStart) {
229
239
  t13 = () => {
230
240
  if (!scrollToBottomOnRunStart) return;
231
241
  pendingScrollToBottomRef.current = { animated: true };
232
242
  scrollToBottom(true);
233
243
  };
234
- $[14] = scrollToBottom;
235
- $[15] = scrollToBottomOnRunStart;
236
- $[16] = t13;
237
- } else t13 = $[16];
244
+ $[16] = scrollToBottom;
245
+ $[17] = scrollToBottomOnRunStart;
246
+ $[18] = t13;
247
+ } else t13 = $[18];
238
248
  useAuiEvent("thread.runStart", t13);
239
249
  let t14;
240
- if ($[17] !== scrollToBottom || $[18] !== scrollToBottomOnThreadSwitch) {
250
+ if ($[19] !== scrollToBottom || $[20] !== scrollToBottomOnThreadSwitch) {
241
251
  t14 = () => {
242
252
  if (!scrollToBottomOnThreadSwitch) return;
243
253
  initializeScrollRequestedRef.current = false;
@@ -245,21 +255,22 @@ const useThreadMessagesFlatListAutoScroll = (t0) => {
245
255
  pendingScrollToBottomRef.current = { animated: false };
246
256
  scrollToBottom(false);
247
257
  };
248
- $[17] = scrollToBottom;
249
- $[18] = scrollToBottomOnThreadSwitch;
250
- $[19] = t14;
251
- } else t14 = $[19];
258
+ $[19] = scrollToBottom;
259
+ $[20] = scrollToBottomOnThreadSwitch;
260
+ $[21] = t14;
261
+ } else t14 = $[21];
252
262
  useAuiEvent("threadListItem.switchedTo", t14);
253
263
  let t15;
254
- if ($[20] !== handleContentSizeChange) {
264
+ if ($[22] !== handleContentSizeChange || $[23] !== handleLayout) {
255
265
  t15 = {
256
266
  handleLayout,
257
267
  handleScroll,
258
268
  handleContentSizeChange
259
269
  };
260
- $[20] = handleContentSizeChange;
261
- $[21] = t15;
262
- } else t15 = $[21];
270
+ $[22] = handleContentSizeChange;
271
+ $[23] = handleLayout;
272
+ $[24] = t15;
273
+ } else t15 = $[24];
263
274
  return t15;
264
275
  };
265
276
  const ThreadMessagesFlatList = forwardRef((t0, forwardedRef) => {
@@ -1 +1 @@
1
- {"version":3,"file":"ThreadMessages.js","names":["ComponentType","FC","ForwardedRef","ReactNode","RefObject","forwardRef","memo","useCallback","useEffect","useRef","FlatList","FlatListProps","LayoutChangeEvent","NativeScrollEvent","NativeSyntheticEvent","MessageState","ThreadMessage","RenderChildrenWithAccessor","useAuiEvent","useAuiState","MessageByIndexProvider","MessageComponents","Message","EditComposer","UserEditComposer","AssistantEditComposer","SystemEditComposer","UserMessage","AssistantMessage","SystemMessage","MessagesContent","components","children","value","message","ThreadMessagesFlatListProps","Omit","autoScroll","scrollToBottomOnRunStart","scrollToBottomOnInitialize","scrollToBottomOnThreadSwitch","ThreadMessagesProps","DEFAULT_SYSTEM_MESSAGE","AT_BOTTOM_THRESHOLD","getComponent","role","isEditing","_exhaustiveCheck","Error","ThreadMessageComponent","t0","$","_c","_temp","_temp2","t1","Component","t2","ThreadMessageByIndex","index","prev","next","displayName","ThreadMessageByChildren","aui","thread","getState","getItem","setForwardedRef","ref","T","current","useComposedFlatListRef","forwardedRef","flatListRef","node","setFlatListRef","const","useThreadMessagesFlatListAutoScroll","hasMessages","t3","t4","undefined","t5","Symbol","for","contentHeight","viewportHeight","scrollY","metricsRef","isAtBottomRef","lastScrollEventYRef","initializeScrollRequestedRef","pendingScrollToBottomRef","t6","updateIsAtBottom","t7","animated","contentHeight_0","viewportHeight_0","Math","max","scrollToEnd","scrollToBottom","t8","event","nativeEvent","layout","height","handleLayout","t9","event_0","contentOffset","contentSize","layoutMeasurement","previousEventY","wasPinnedToBottom","y","upwardMove","handleScroll","t10","_width","metrics","previousContentHeight","wasAtBottom","pendingScroll","handleContentSizeChange","t11","t12","t13","t14","t15","ThreadMessagesFlatList","flatListProps","onContentSizeChange","onLayout","onScroll","scrollEventThrottle","messages","_temp3","length","handleAutoScrollContentSizeChange","handleAutoScrollLayout","handleAutoScrollScroll","renderItem","keyExtractor","_temp4","scrollTracking","width","ThreadMessages","props","s","s_0","composer","item","id"],"sources":["../../../src/primitives/thread/ThreadMessages.tsx"],"sourcesContent":["import {\n type ComponentType,\n type FC,\n type ForwardedRef,\n type ReactNode,\n type RefObject,\n forwardRef,\n memo,\n useCallback,\n useEffect,\n useRef,\n} from \"react\";\nimport {\n FlatList,\n type FlatListProps,\n type LayoutChangeEvent,\n type NativeScrollEvent,\n type NativeSyntheticEvent,\n} from \"react-native\";\nimport type { MessageState, ThreadMessage } from \"@assistant-ui/core\";\nimport {\n RenderChildrenWithAccessor,\n useAuiEvent,\n useAuiState,\n} from \"@assistant-ui/store\";\nimport { MessageByIndexProvider } from \"@assistant-ui/core/react\";\n\ntype MessageComponents =\n | {\n Message: ComponentType;\n EditComposer?: ComponentType | undefined;\n UserEditComposer?: ComponentType | undefined;\n AssistantEditComposer?: ComponentType | undefined;\n SystemEditComposer?: ComponentType | undefined;\n UserMessage?: ComponentType | undefined;\n AssistantMessage?: ComponentType | undefined;\n SystemMessage?: ComponentType | undefined;\n }\n | {\n Message?: ComponentType | undefined;\n EditComposer?: ComponentType | undefined;\n UserEditComposer?: ComponentType | undefined;\n AssistantEditComposer?: ComponentType | undefined;\n SystemEditComposer?: ComponentType | undefined;\n UserMessage: ComponentType;\n AssistantMessage: ComponentType;\n SystemMessage?: ComponentType | undefined;\n };\n\ntype MessagesContent =\n | {\n /** @deprecated Use the children render function instead. */\n components: MessageComponents;\n children?: never;\n }\n | {\n children: (value: { message: MessageState }) => ReactNode;\n components?: never;\n };\n\nexport type ThreadMessagesFlatListProps = Omit<\n FlatListProps<ThreadMessage>,\n \"data\" | \"renderItem\" | \"children\"\n> &\n MessagesContent & {\n autoScroll?: boolean | undefined;\n scrollToBottomOnRunStart?: boolean | undefined;\n scrollToBottomOnInitialize?: boolean | undefined;\n scrollToBottomOnThreadSwitch?: boolean | undefined;\n };\n\n/** @deprecated Use ThreadMessagesFlatListProps instead. */\nexport type ThreadMessagesProps = ThreadMessagesFlatListProps;\n\nconst DEFAULT_SYSTEM_MESSAGE = () => null;\nconst AT_BOTTOM_THRESHOLD = 4;\n\nconst getComponent = (\n components: MessageComponents,\n role: ThreadMessage[\"role\"],\n isEditing: boolean,\n) => {\n switch (role) {\n case \"user\":\n if (isEditing) {\n return (\n components.UserEditComposer ??\n components.EditComposer ??\n components.UserMessage ??\n (components.Message as ComponentType)\n );\n } else {\n return components.UserMessage ?? (components.Message as ComponentType);\n }\n case \"assistant\":\n if (isEditing) {\n return (\n components.AssistantEditComposer ??\n components.EditComposer ??\n components.AssistantMessage ??\n (components.Message as ComponentType)\n );\n } else {\n return (\n components.AssistantMessage ?? (components.Message as ComponentType)\n );\n }\n case \"system\":\n if (isEditing) {\n return (\n components.SystemEditComposer ??\n components.EditComposer ??\n components.SystemMessage ??\n (components.Message as ComponentType)\n );\n } else {\n return (\n components.SystemMessage ??\n (components.Message as ComponentType) ??\n DEFAULT_SYSTEM_MESSAGE\n );\n }\n default: {\n const _exhaustiveCheck: never = role;\n throw new Error(`Unknown message role: ${_exhaustiveCheck}`);\n }\n }\n};\n\nconst ThreadMessageComponent: FC<{ components: MessageComponents }> = ({\n components,\n}) => {\n const role = useAuiState((s) => s.message.role);\n const isEditing = useAuiState((s) => s.message.composer.isEditing);\n const Component = getComponent(components, role, isEditing);\n\n return <Component />;\n};\n\nconst ThreadMessageByIndex = memo(\n ({ index, components }: { index: number; components: MessageComponents }) => {\n return (\n <MessageByIndexProvider index={index}>\n <ThreadMessageComponent components={components} />\n </MessageByIndexProvider>\n );\n },\n (prev, next) =>\n prev.index === next.index && prev.components === next.components,\n);\nThreadMessageByIndex.displayName = \"ThreadPrimitive.MessageByIndex\";\n\nconst ThreadMessageByChildren = memo(\n ({\n index,\n children,\n }: {\n index: number;\n children: (value: { message: MessageState }) => ReactNode;\n }) => {\n return (\n <MessageByIndexProvider index={index}>\n <RenderChildrenWithAccessor\n getItemState={(aui) => aui.thread().message({ index }).getState()}\n >\n {(getItem) =>\n children({\n get message() {\n return getItem();\n },\n })\n }\n </RenderChildrenWithAccessor>\n </MessageByIndexProvider>\n );\n },\n (prev, next) => prev.index === next.index && prev.children === next.children,\n);\nThreadMessageByChildren.displayName = \"ThreadPrimitive.MessageByChildren\";\n\nconst setForwardedRef = <T,>(ref: ForwardedRef<T>, value: T | null) => {\n if (typeof ref === \"function\") {\n ref(value);\n } else if (ref) {\n ref.current = value;\n }\n};\n\nconst useComposedFlatListRef = (\n forwardedRef: ForwardedRef<FlatList<ThreadMessage>>,\n) => {\n const flatListRef = useRef<FlatList<ThreadMessage> | null>(null);\n\n const setFlatListRef = useCallback(\n (node: FlatList<ThreadMessage> | null) => {\n flatListRef.current = node;\n setForwardedRef(forwardedRef, node);\n },\n [forwardedRef],\n );\n\n return [flatListRef, setFlatListRef] as const;\n};\n\nconst useThreadMessagesFlatListAutoScroll = ({\n flatListRef,\n hasMessages,\n autoScroll = true,\n scrollToBottomOnRunStart = true,\n scrollToBottomOnInitialize = true,\n scrollToBottomOnThreadSwitch = true,\n}: {\n flatListRef: RefObject<FlatList<ThreadMessage> | null>;\n hasMessages: boolean;\n autoScroll?: boolean | undefined;\n scrollToBottomOnRunStart?: boolean | undefined;\n scrollToBottomOnInitialize?: boolean | undefined;\n scrollToBottomOnThreadSwitch?: boolean | undefined;\n}) => {\n const metricsRef = useRef({\n contentHeight: 0,\n viewportHeight: 0,\n scrollY: 0,\n });\n const isAtBottomRef = useRef(true);\n const lastScrollEventYRef = useRef(0);\n const initializeScrollRequestedRef = useRef(false);\n const pendingScrollToBottomRef = useRef<false | { animated: boolean }>(false);\n\n const updateIsAtBottom = useCallback(() => {\n const { contentHeight, scrollY, viewportHeight } = metricsRef.current;\n isAtBottomRef.current =\n contentHeight <= viewportHeight ||\n contentHeight - scrollY - viewportHeight <= AT_BOTTOM_THRESHOLD;\n }, []);\n\n // Commanding a scroll records the intended position immediately; the\n // native scroll echo is bridged and throttled, so waiting for it lets a\n // fast stream observe stale metrics and drop out of following.\n const scrollToBottom = useCallback(\n (animated: boolean) => {\n const { contentHeight, viewportHeight } = metricsRef.current;\n metricsRef.current.scrollY = Math.max(0, contentHeight - viewportHeight);\n isAtBottomRef.current = true;\n flatListRef.current?.scrollToEnd({ animated });\n },\n [flatListRef],\n );\n\n const handleLayout = useCallback(\n (event: LayoutChangeEvent) => {\n metricsRef.current.viewportHeight = event.nativeEvent.layout.height;\n updateIsAtBottom();\n },\n [updateIsAtBottom],\n );\n\n const handleScroll = useCallback(\n (event: NativeSyntheticEvent<NativeScrollEvent>) => {\n const { contentOffset, contentSize, layoutMeasurement } =\n event.nativeEvent;\n const previousEventY = lastScrollEventYRef.current;\n const wasPinnedToBottom = isAtBottomRef.current;\n lastScrollEventYRef.current = contentOffset.y;\n metricsRef.current = {\n contentHeight: contentSize.height,\n viewportHeight: layoutMeasurement.height,\n scrollY: contentOffset.y,\n };\n updateIsAtBottom();\n const upwardMove = contentOffset.y < previousEventY;\n // Only a deliberate upward move unpins or cancels a pending scroll.\n // Gestures are detected echo-to-echo because a commanded scroll\n // optimistically moves the tracked position ahead of its ascending\n // animation echoes, and those echoes must not unpin mid-flight.\n if (wasPinnedToBottom && !upwardMove) {\n isAtBottomRef.current = true;\n }\n if (!isAtBottomRef.current && upwardMove) {\n pendingScrollToBottomRef.current = false;\n }\n },\n [updateIsAtBottom],\n );\n\n const handleContentSizeChange = useCallback(\n (_width: number, height: number) => {\n const metrics = metricsRef.current;\n const previousContentHeight = metrics.contentHeight;\n const wasAtBottom = isAtBottomRef.current;\n metrics.contentHeight = height;\n updateIsAtBottom();\n\n // FlatList.scrollToEnd is a no-op before the list has measured, so the\n // initialize and thread-switch scrolls land on the next content-size\n // event, once real metrics exist.\n const pendingScroll = pendingScrollToBottomRef.current;\n if (pendingScroll) {\n pendingScrollToBottomRef.current = false;\n scrollToBottom(pendingScroll.animated);\n return;\n }\n\n if (!autoScroll) return;\n if (!wasAtBottom) return;\n if (previousContentHeight === 0) return;\n if (height <= previousContentHeight) return;\n\n scrollToBottom(false);\n },\n [autoScroll, scrollToBottom, updateIsAtBottom],\n );\n\n useEffect(() => {\n if (!scrollToBottomOnInitialize) return;\n if (!hasMessages) {\n initializeScrollRequestedRef.current = false;\n return;\n }\n if (initializeScrollRequestedRef.current) return;\n\n initializeScrollRequestedRef.current = true;\n pendingScrollToBottomRef.current = { animated: false };\n scrollToBottom(false);\n }, [hasMessages, scrollToBottom, scrollToBottomOnInitialize]);\n\n useAuiEvent(\"thread.runStart\", () => {\n if (!scrollToBottomOnRunStart) return;\n pendingScrollToBottomRef.current = { animated: true };\n scrollToBottom(true);\n });\n\n useAuiEvent(\"threadListItem.switchedTo\", () => {\n if (!scrollToBottomOnThreadSwitch) return;\n initializeScrollRequestedRef.current = false;\n lastScrollEventYRef.current = 0;\n pendingScrollToBottomRef.current = { animated: false };\n scrollToBottom(false);\n });\n\n return {\n handleLayout,\n handleScroll,\n handleContentSizeChange,\n };\n};\n\nexport const ThreadMessagesFlatList = forwardRef<\n FlatList<ThreadMessage>,\n ThreadMessagesFlatListProps\n>(\n (\n {\n autoScroll,\n components,\n children,\n onContentSizeChange,\n onLayout,\n onScroll,\n scrollEventThrottle,\n scrollToBottomOnInitialize,\n scrollToBottomOnRunStart,\n scrollToBottomOnThreadSwitch,\n ...flatListProps\n },\n forwardedRef,\n ) => {\n const messages = useAuiState((s) => s.thread.messages);\n const [flatListRef, setFlatListRef] = useComposedFlatListRef(forwardedRef);\n const {\n handleContentSizeChange: handleAutoScrollContentSizeChange,\n handleLayout: handleAutoScrollLayout,\n handleScroll: handleAutoScrollScroll,\n } = useThreadMessagesFlatListAutoScroll({\n flatListRef,\n hasMessages: messages.length > 0,\n autoScroll,\n scrollToBottomOnInitialize,\n scrollToBottomOnRunStart,\n scrollToBottomOnThreadSwitch,\n });\n\n const renderItem = useCallback(\n ({ index }: { item: ThreadMessage; index: number }) => {\n if (children) {\n return (\n <ThreadMessageByChildren index={index}>\n {children}\n </ThreadMessageByChildren>\n );\n }\n return <ThreadMessageByIndex index={index} components={components!} />;\n },\n [components, children],\n );\n\n const keyExtractor = useCallback((item: ThreadMessage) => item.id, []);\n\n const scrollTracking =\n (autoScroll ?? true) ||\n (scrollToBottomOnInitialize ?? true) ||\n (scrollToBottomOnRunStart ?? true) ||\n (scrollToBottomOnThreadSwitch ?? true);\n\n const handleLayout = useCallback(\n (event: LayoutChangeEvent) => {\n handleAutoScrollLayout(event);\n onLayout?.(event);\n },\n [handleAutoScrollLayout, onLayout],\n );\n\n const handleScroll = useCallback(\n (event: NativeSyntheticEvent<NativeScrollEvent>) => {\n handleAutoScrollScroll(event);\n onScroll?.(event);\n },\n [handleAutoScrollScroll, onScroll],\n );\n\n const handleContentSizeChange = useCallback(\n (width: number, height: number) => {\n handleAutoScrollContentSizeChange(width, height);\n onContentSizeChange?.(width, height);\n },\n [handleAutoScrollContentSizeChange, onContentSizeChange],\n );\n\n return (\n <FlatList\n ref={setFlatListRef}\n data={messages as unknown as ThreadMessage[]}\n renderItem={renderItem}\n keyExtractor={keyExtractor}\n {...(scrollTracking\n ? {\n onContentSizeChange: handleContentSizeChange,\n onLayout: handleLayout,\n onScroll: handleScroll,\n scrollEventThrottle: scrollEventThrottle ?? 16,\n }\n : {\n ...(onContentSizeChange && { onContentSizeChange }),\n ...(onLayout && { onLayout }),\n ...(onScroll && { onScroll }),\n ...(scrollEventThrottle !== undefined && { scrollEventThrottle }),\n })}\n {...flatListProps}\n />\n );\n },\n);\nThreadMessagesFlatList.displayName = \"ThreadPrimitive.MessagesFlatList\";\n\n/** @deprecated Use ThreadPrimitive.MessagesFlatList instead. */\nexport const ThreadMessages = forwardRef<\n FlatList<ThreadMessage>,\n ThreadMessagesProps\n>(\n (\n {\n autoScroll = false,\n scrollToBottomOnInitialize = false,\n scrollToBottomOnRunStart = false,\n scrollToBottomOnThreadSwitch = false,\n ...props\n },\n ref,\n ) => (\n <ThreadMessagesFlatList\n ref={ref}\n autoScroll={autoScroll}\n scrollToBottomOnInitialize={scrollToBottomOnInitialize}\n scrollToBottomOnRunStart={scrollToBottomOnRunStart}\n scrollToBottomOnThreadSwitch={scrollToBottomOnThreadSwitch}\n {...props}\n />\n ),\n);\nThreadMessages.displayName = \"ThreadPrimitive.Messages\";\n"],"mappings":"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"}
1
+ {"version":3,"file":"ThreadMessages.js","names":["ComponentType","FC","ForwardedRef","ReactNode","RefObject","forwardRef","memo","useCallback","useEffect","useRef","FlatList","FlatListProps","LayoutChangeEvent","NativeScrollEvent","NativeSyntheticEvent","MessageState","ThreadMessage","RenderChildrenWithAccessor","useAuiEvent","useAuiState","MessageByIndexProvider","MessageComponents","Message","EditComposer","UserEditComposer","AssistantEditComposer","SystemEditComposer","UserMessage","AssistantMessage","SystemMessage","MessagesContent","components","children","value","message","ThreadMessagesFlatListProps","Omit","autoScroll","scrollToBottomOnRunStart","scrollToBottomOnInitialize","scrollToBottomOnThreadSwitch","ThreadMessagesProps","DEFAULT_SYSTEM_MESSAGE","AT_BOTTOM_THRESHOLD","getComponent","role","isEditing","_exhaustiveCheck","Error","ThreadMessageComponent","t0","$","_c","_temp","_temp2","t1","Component","t2","ThreadMessageByIndex","index","prev","next","displayName","ThreadMessageByChildren","aui","thread","getState","getItem","setForwardedRef","ref","T","current","useComposedFlatListRef","forwardedRef","flatListRef","node","setFlatListRef","const","useThreadMessagesFlatListAutoScroll","hasMessages","t3","t4","undefined","t5","Symbol","for","contentHeight","viewportHeight","scrollY","metricsRef","isAtBottomRef","lastScrollEventYRef","initializeScrollRequestedRef","pendingScrollToBottomRef","t6","updateIsAtBottom","t7","animated","contentHeight_0","viewportHeight_0","Math","max","scrollToEnd","scrollToBottom","t8","event","wasAtBottom","previousViewportHeight","viewportHeight_1","nativeEvent","layout","height","pending","handleLayout","t9","event_0","contentOffset","contentSize","layoutMeasurement","previousEventY","wasPinnedToBottom","y","upwardMove","handleScroll","t10","_width","metrics","previousContentHeight","wasAtBottom_0","pendingScroll","handleContentSizeChange","t11","t12","t13","t14","t15","ThreadMessagesFlatList","flatListProps","onContentSizeChange","onLayout","onScroll","scrollEventThrottle","messages","_temp3","length","handleAutoScrollContentSizeChange","handleAutoScrollLayout","handleAutoScrollScroll","renderItem","keyExtractor","_temp4","scrollTracking","width","ThreadMessages","props","s","s_0","composer","item","id"],"sources":["../../../src/primitives/thread/ThreadMessages.tsx"],"sourcesContent":["import {\n type ComponentType,\n type FC,\n type ForwardedRef,\n type ReactNode,\n type RefObject,\n forwardRef,\n memo,\n useCallback,\n useEffect,\n useRef,\n} from \"react\";\nimport {\n FlatList,\n type FlatListProps,\n type LayoutChangeEvent,\n type NativeScrollEvent,\n type NativeSyntheticEvent,\n} from \"react-native\";\nimport type { MessageState, ThreadMessage } from \"@assistant-ui/core\";\nimport {\n RenderChildrenWithAccessor,\n useAuiEvent,\n useAuiState,\n} from \"@assistant-ui/store\";\nimport { MessageByIndexProvider } from \"@assistant-ui/core/react\";\n\ntype MessageComponents =\n | {\n Message: ComponentType;\n EditComposer?: ComponentType | undefined;\n UserEditComposer?: ComponentType | undefined;\n AssistantEditComposer?: ComponentType | undefined;\n SystemEditComposer?: ComponentType | undefined;\n UserMessage?: ComponentType | undefined;\n AssistantMessage?: ComponentType | undefined;\n SystemMessage?: ComponentType | undefined;\n }\n | {\n Message?: ComponentType | undefined;\n EditComposer?: ComponentType | undefined;\n UserEditComposer?: ComponentType | undefined;\n AssistantEditComposer?: ComponentType | undefined;\n SystemEditComposer?: ComponentType | undefined;\n UserMessage: ComponentType;\n AssistantMessage: ComponentType;\n SystemMessage?: ComponentType | undefined;\n };\n\ntype MessagesContent =\n | {\n /** @deprecated Use the children render function instead. */\n components: MessageComponents;\n children?: never;\n }\n | {\n children: (value: { message: MessageState }) => ReactNode;\n components?: never;\n };\n\nexport type ThreadMessagesFlatListProps = Omit<\n FlatListProps<ThreadMessage>,\n \"data\" | \"renderItem\" | \"children\"\n> &\n MessagesContent & {\n autoScroll?: boolean | undefined;\n scrollToBottomOnRunStart?: boolean | undefined;\n scrollToBottomOnInitialize?: boolean | undefined;\n scrollToBottomOnThreadSwitch?: boolean | undefined;\n };\n\n/** @deprecated Use ThreadMessagesFlatListProps instead. */\nexport type ThreadMessagesProps = ThreadMessagesFlatListProps;\n\nconst DEFAULT_SYSTEM_MESSAGE = () => null;\nconst AT_BOTTOM_THRESHOLD = 4;\n\nconst getComponent = (\n components: MessageComponents,\n role: ThreadMessage[\"role\"],\n isEditing: boolean,\n) => {\n switch (role) {\n case \"user\":\n if (isEditing) {\n return (\n components.UserEditComposer ??\n components.EditComposer ??\n components.UserMessage ??\n (components.Message as ComponentType)\n );\n } else {\n return components.UserMessage ?? (components.Message as ComponentType);\n }\n case \"assistant\":\n if (isEditing) {\n return (\n components.AssistantEditComposer ??\n components.EditComposer ??\n components.AssistantMessage ??\n (components.Message as ComponentType)\n );\n } else {\n return (\n components.AssistantMessage ?? (components.Message as ComponentType)\n );\n }\n case \"system\":\n if (isEditing) {\n return (\n components.SystemEditComposer ??\n components.EditComposer ??\n components.SystemMessage ??\n (components.Message as ComponentType)\n );\n } else {\n return (\n components.SystemMessage ??\n (components.Message as ComponentType) ??\n DEFAULT_SYSTEM_MESSAGE\n );\n }\n default: {\n const _exhaustiveCheck: never = role;\n throw new Error(`Unknown message role: ${_exhaustiveCheck}`);\n }\n }\n};\n\nconst ThreadMessageComponent: FC<{ components: MessageComponents }> = ({\n components,\n}) => {\n const role = useAuiState((s) => s.message.role);\n const isEditing = useAuiState((s) => s.message.composer.isEditing);\n const Component = getComponent(components, role, isEditing);\n\n return <Component />;\n};\n\nconst ThreadMessageByIndex = memo(\n ({ index, components }: { index: number; components: MessageComponents }) => {\n return (\n <MessageByIndexProvider index={index}>\n <ThreadMessageComponent components={components} />\n </MessageByIndexProvider>\n );\n },\n (prev, next) =>\n prev.index === next.index && prev.components === next.components,\n);\nThreadMessageByIndex.displayName = \"ThreadPrimitive.MessageByIndex\";\n\nconst ThreadMessageByChildren = memo(\n ({\n index,\n children,\n }: {\n index: number;\n children: (value: { message: MessageState }) => ReactNode;\n }) => {\n return (\n <MessageByIndexProvider index={index}>\n <RenderChildrenWithAccessor\n getItemState={(aui) => aui.thread.message({ index }).getState()}\n >\n {(getItem) =>\n children({\n get message() {\n return getItem();\n },\n })\n }\n </RenderChildrenWithAccessor>\n </MessageByIndexProvider>\n );\n },\n (prev, next) => prev.index === next.index && prev.children === next.children,\n);\nThreadMessageByChildren.displayName = \"ThreadPrimitive.MessageByChildren\";\n\nconst setForwardedRef = <T,>(ref: ForwardedRef<T>, value: T | null) => {\n if (typeof ref === \"function\") {\n ref(value);\n } else if (ref) {\n ref.current = value;\n }\n};\n\nconst useComposedFlatListRef = (\n forwardedRef: ForwardedRef<FlatList<ThreadMessage>>,\n) => {\n const flatListRef = useRef<FlatList<ThreadMessage> | null>(null);\n\n const setFlatListRef = useCallback(\n (node: FlatList<ThreadMessage> | null) => {\n flatListRef.current = node;\n setForwardedRef(forwardedRef, node);\n },\n [forwardedRef],\n );\n\n return [flatListRef, setFlatListRef] as const;\n};\n\nconst useThreadMessagesFlatListAutoScroll = ({\n flatListRef,\n hasMessages,\n autoScroll = true,\n scrollToBottomOnRunStart = true,\n scrollToBottomOnInitialize = true,\n scrollToBottomOnThreadSwitch = true,\n}: {\n flatListRef: RefObject<FlatList<ThreadMessage> | null>;\n hasMessages: boolean;\n autoScroll?: boolean | undefined;\n scrollToBottomOnRunStart?: boolean | undefined;\n scrollToBottomOnInitialize?: boolean | undefined;\n scrollToBottomOnThreadSwitch?: boolean | undefined;\n}) => {\n const metricsRef = useRef({\n contentHeight: 0,\n viewportHeight: 0,\n scrollY: 0,\n });\n const isAtBottomRef = useRef(true);\n const lastScrollEventYRef = useRef(0);\n const initializeScrollRequestedRef = useRef(false);\n const pendingScrollToBottomRef = useRef<false | { animated: boolean }>(false);\n\n const updateIsAtBottom = useCallback(() => {\n const { contentHeight, scrollY, viewportHeight } = metricsRef.current;\n isAtBottomRef.current =\n contentHeight <= viewportHeight ||\n contentHeight - scrollY - viewportHeight <= AT_BOTTOM_THRESHOLD;\n }, []);\n\n // Commanding a scroll records the intended position immediately; the\n // native scroll echo is bridged and throttled, so waiting for it lets a\n // fast stream observe stale metrics and drop out of following.\n const scrollToBottom = useCallback(\n (animated: boolean) => {\n const { contentHeight, viewportHeight } = metricsRef.current;\n metricsRef.current.scrollY = Math.max(0, contentHeight - viewportHeight);\n isAtBottomRef.current = true;\n flatListRef.current?.scrollToEnd({ animated });\n },\n [flatListRef],\n );\n\n const handleLayout = useCallback(\n (event: LayoutChangeEvent) => {\n const wasAtBottom = isAtBottomRef.current;\n const previousViewportHeight = metricsRef.current.viewportHeight;\n const viewportHeight = event.nativeEvent.layout.height;\n metricsRef.current.viewportHeight = viewportHeight;\n updateIsAtBottom();\n if (!wasAtBottom) return;\n // Layout changes are never user gestures, so they must not unpin. Past\n // the first measurement, a viewport change while pinned re-commands the\n // bottom position, since no content-size event follows a bare keyboard\n // open or close.\n if (\n autoScroll &&\n previousViewportHeight !== 0 &&\n viewportHeight !== previousViewportHeight\n ) {\n const pending = pendingScrollToBottomRef.current;\n scrollToBottom(pending ? pending.animated : false);\n } else {\n isAtBottomRef.current = true;\n }\n },\n [autoScroll, scrollToBottom, updateIsAtBottom],\n );\n\n const handleScroll = useCallback(\n (event: NativeSyntheticEvent<NativeScrollEvent>) => {\n const { contentOffset, contentSize, layoutMeasurement } =\n event.nativeEvent;\n const previousEventY = lastScrollEventYRef.current;\n const wasPinnedToBottom = isAtBottomRef.current;\n lastScrollEventYRef.current = contentOffset.y;\n metricsRef.current = {\n contentHeight: contentSize.height,\n viewportHeight: layoutMeasurement.height,\n scrollY: contentOffset.y,\n };\n updateIsAtBottom();\n const upwardMove = contentOffset.y < previousEventY;\n // Only a deliberate upward move unpins or cancels a pending scroll.\n // Gestures are detected echo-to-echo because a commanded scroll\n // optimistically moves the tracked position ahead of its ascending\n // animation echoes, and those echoes must not unpin mid-flight.\n if (wasPinnedToBottom && !upwardMove) {\n isAtBottomRef.current = true;\n }\n if (!isAtBottomRef.current && upwardMove) {\n pendingScrollToBottomRef.current = false;\n }\n },\n [updateIsAtBottom],\n );\n\n const handleContentSizeChange = useCallback(\n (_width: number, height: number) => {\n const metrics = metricsRef.current;\n const previousContentHeight = metrics.contentHeight;\n const wasAtBottom = isAtBottomRef.current;\n metrics.contentHeight = height;\n updateIsAtBottom();\n\n // FlatList.scrollToEnd is a no-op before the list has measured, so the\n // initialize and thread-switch scrolls land on the next content-size\n // event, once real metrics exist.\n const pendingScroll = pendingScrollToBottomRef.current;\n if (pendingScroll) {\n pendingScrollToBottomRef.current = false;\n scrollToBottom(pendingScroll.animated);\n return;\n }\n\n if (!autoScroll) return;\n if (!wasAtBottom) return;\n if (previousContentHeight === 0) return;\n if (height <= previousContentHeight) return;\n\n scrollToBottom(false);\n },\n [autoScroll, scrollToBottom, updateIsAtBottom],\n );\n\n useEffect(() => {\n if (!scrollToBottomOnInitialize) return;\n if (!hasMessages) {\n initializeScrollRequestedRef.current = false;\n return;\n }\n if (initializeScrollRequestedRef.current) return;\n\n initializeScrollRequestedRef.current = true;\n pendingScrollToBottomRef.current = { animated: false };\n scrollToBottom(false);\n }, [hasMessages, scrollToBottom, scrollToBottomOnInitialize]);\n\n useAuiEvent(\"thread.runStart\", () => {\n if (!scrollToBottomOnRunStart) return;\n pendingScrollToBottomRef.current = { animated: true };\n scrollToBottom(true);\n });\n\n useAuiEvent(\"threadListItem.switchedTo\", () => {\n if (!scrollToBottomOnThreadSwitch) return;\n initializeScrollRequestedRef.current = false;\n lastScrollEventYRef.current = 0;\n pendingScrollToBottomRef.current = { animated: false };\n scrollToBottom(false);\n });\n\n return {\n handleLayout,\n handleScroll,\n handleContentSizeChange,\n };\n};\n\nexport const ThreadMessagesFlatList = forwardRef<\n FlatList<ThreadMessage>,\n ThreadMessagesFlatListProps\n>(\n (\n {\n autoScroll,\n components,\n children,\n onContentSizeChange,\n onLayout,\n onScroll,\n scrollEventThrottle,\n scrollToBottomOnInitialize,\n scrollToBottomOnRunStart,\n scrollToBottomOnThreadSwitch,\n ...flatListProps\n },\n forwardedRef,\n ) => {\n const messages = useAuiState((s) => s.thread.messages);\n const [flatListRef, setFlatListRef] = useComposedFlatListRef(forwardedRef);\n const {\n handleContentSizeChange: handleAutoScrollContentSizeChange,\n handleLayout: handleAutoScrollLayout,\n handleScroll: handleAutoScrollScroll,\n } = useThreadMessagesFlatListAutoScroll({\n flatListRef,\n hasMessages: messages.length > 0,\n autoScroll,\n scrollToBottomOnInitialize,\n scrollToBottomOnRunStart,\n scrollToBottomOnThreadSwitch,\n });\n\n const renderItem = useCallback(\n ({ index }: { item: ThreadMessage; index: number }) => {\n if (children) {\n return (\n <ThreadMessageByChildren index={index}>\n {children}\n </ThreadMessageByChildren>\n );\n }\n return <ThreadMessageByIndex index={index} components={components!} />;\n },\n [components, children],\n );\n\n const keyExtractor = useCallback((item: ThreadMessage) => item.id, []);\n\n const scrollTracking =\n (autoScroll ?? true) ||\n (scrollToBottomOnInitialize ?? true) ||\n (scrollToBottomOnRunStart ?? true) ||\n (scrollToBottomOnThreadSwitch ?? true);\n\n const handleLayout = useCallback(\n (event: LayoutChangeEvent) => {\n handleAutoScrollLayout(event);\n onLayout?.(event);\n },\n [handleAutoScrollLayout, onLayout],\n );\n\n const handleScroll = useCallback(\n (event: NativeSyntheticEvent<NativeScrollEvent>) => {\n handleAutoScrollScroll(event);\n onScroll?.(event);\n },\n [handleAutoScrollScroll, onScroll],\n );\n\n const handleContentSizeChange = useCallback(\n (width: number, height: number) => {\n handleAutoScrollContentSizeChange(width, height);\n onContentSizeChange?.(width, height);\n },\n [handleAutoScrollContentSizeChange, onContentSizeChange],\n );\n\n return (\n <FlatList\n ref={setFlatListRef}\n data={messages as unknown as ThreadMessage[]}\n renderItem={renderItem}\n keyExtractor={keyExtractor}\n {...(scrollTracking\n ? {\n onContentSizeChange: handleContentSizeChange,\n onLayout: handleLayout,\n onScroll: handleScroll,\n scrollEventThrottle: scrollEventThrottle ?? 16,\n }\n : {\n ...(onContentSizeChange && { onContentSizeChange }),\n ...(onLayout && { onLayout }),\n ...(onScroll && { onScroll }),\n ...(scrollEventThrottle !== undefined && { scrollEventThrottle }),\n })}\n {...flatListProps}\n />\n );\n },\n);\nThreadMessagesFlatList.displayName = \"ThreadPrimitive.MessagesFlatList\";\n\n/** @deprecated Use ThreadPrimitive.MessagesFlatList instead. */\nexport const ThreadMessages = forwardRef<\n FlatList<ThreadMessage>,\n ThreadMessagesProps\n>(\n (\n {\n autoScroll = false,\n scrollToBottomOnInitialize = false,\n scrollToBottomOnRunStart = false,\n scrollToBottomOnThreadSwitch = false,\n ...props\n },\n ref,\n ) => (\n <ThreadMessagesFlatList\n ref={ref}\n autoScroll={autoScroll}\n scrollToBottomOnInitialize={scrollToBottomOnInitialize}\n scrollToBottomOnRunStart={scrollToBottomOnRunStart}\n scrollToBottomOnThreadSwitch={scrollToBottomOnThreadSwitch}\n {...props}\n />\n ),\n);\nThreadMessages.displayName = \"ThreadPrimitive.Messages\";\n"],"mappings":"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"}
@@ -2,6 +2,7 @@ import { useAuiState } from "@assistant-ui/store";
2
2
  import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
3
3
  import { FlatList } from "react-native";
4
4
  import { jsx } from "react/jsx-runtime";
5
+ import "@assistant-ui/tap/react-shim";
5
6
  //#region src/primitives/threadList/ThreadListItems.tsx
6
7
  const ThreadListItems = (t0) => {
7
8
  const $ = c(9);
@@ -1 +1 @@
1
- {"version":3,"file":"ThreadListItems.js","names":["ReactElement","useCallback","FlatList","FlatListProps","useAuiState","ThreadListItemsProps","Omit","renderItem","props","threadId","index","ThreadListItems","t0","$","_c","flatListProps","threadIds","_temp","t1","t2","item","renderFlatListItem","keyExtractor","_temp2","t3","s","threads","item_0"],"sources":["../../../src/primitives/threadList/ThreadListItems.tsx"],"sourcesContent":["import { type ReactElement, useCallback } from \"react\";\nimport { FlatList, type FlatListProps } from \"react-native\";\nimport { useAuiState } from \"@assistant-ui/store\";\n\nexport type ThreadListItemsProps = Omit<\n FlatListProps<string>,\n \"data\" | \"renderItem\"\n> & {\n renderItem: (props: { threadId: string; index: number }) => ReactElement;\n};\n\nexport const ThreadListItems = ({\n renderItem,\n ...flatListProps\n}: ThreadListItemsProps) => {\n const threadIds = useAuiState((s) => s.threads.threadIds);\n\n const renderFlatListItem = useCallback(\n ({ item, index }: { item: string; index: number }) => {\n return renderItem({ threadId: item, index });\n },\n [renderItem],\n );\n\n const keyExtractor = useCallback((item: string) => item, []);\n\n return (\n <FlatList\n data={threadIds as string[]}\n renderItem={renderFlatListItem}\n keyExtractor={keyExtractor}\n {...flatListProps}\n />\n );\n};\n"],"mappings":";;;;;AAWA,MAAaW,mBAAkBC,OAAA;CAAA,MAAAC,IAAAC,EAAA,CAAA;CAAA,IAAAC;CAAA,IAAAR;CAAA,IAAAM,EAAA,OAAAD,IAAA;EAAC,CAAA,CAAAL,eAAAQ,iBAAAH;EAGTC,EAAA,KAAAD;EAAAC,EAAA,KAAAE;EAAAF,EAAA,KAAAN;CAAA,OAAA;EAAAQ,gBAAAF,EAAA;EAAAN,aAAAM,EAAA;CAAA;CACrB,MAAAG,YAAkBZ,YAAYa,KAA0B;CAAE,IAAAC;CAAA,IAAAL,EAAA,OAAAN,YAAA;EAGxDW,MAAAC,OAAA;GAAC,MAAA,EAAAC,MAAAV,UAAAS;GAAgD,OACxCZ,WAAW;IAAAE,UAAYW;IAAIV;GAAQ,CAAC;EAAC;EAC7CG,EAAA,KAAAN;EAAAM,EAAA,KAAAK;CAAA,OAAAA,KAAAL,EAAA;CAHH,MAAAQ,qBAA2BH;CAO3B,MAAAI,eAAqBC;CAIX,MAAAJ,KAAAH;CAAqB,IAAAQ;CAAA,IAAAX,EAAA,OAAAE,iBAAAF,EAAA,OAAAQ,sBAAAR,EAAA,OAAAM,IAAA;EAD7BK,KAAA,oBAAC,UAAD;GACQ,MAAAL;GACME,YAAAA;GACEC;GAAY,GACtBP;EAAa,CAAA;EACjBF,EAAA,KAAAE;EAAAF,EAAA,KAAAQ;EAAAR,EAAA,KAAAM;EAAAN,EAAA,KAAAW;CAAA,OAAAA,KAAAX,EAAA;CAAA,OALFW;AAKE;AArByB,SAAAP,MAAAQ,GAAA;CAAA,OAIQA,EAACC,QAAQV;AAAU;AAJ3B,SAAAO,OAAAI,QAAA;CAAA,OAasBP;AAAI"}
1
+ {"version":3,"file":"ThreadListItems.js","names":["ReactElement","useCallback","FlatList","FlatListProps","useAuiState","ThreadListItemsProps","Omit","renderItem","props","threadId","index","ThreadListItems","t0","$","_c","flatListProps","threadIds","_temp","t1","t2","item","renderFlatListItem","keyExtractor","_temp2","t3","s","threads","item_0"],"sources":["../../../src/primitives/threadList/ThreadListItems.tsx"],"sourcesContent":["import { type ReactElement, useCallback } from \"react\";\nimport { FlatList, type FlatListProps } from \"react-native\";\nimport { useAuiState } from \"@assistant-ui/store\";\n\nexport type ThreadListItemsProps = Omit<\n FlatListProps<string>,\n \"data\" | \"renderItem\"\n> & {\n renderItem: (props: { threadId: string; index: number }) => ReactElement;\n};\n\nexport const ThreadListItems = ({\n renderItem,\n ...flatListProps\n}: ThreadListItemsProps) => {\n const threadIds = useAuiState((s) => s.threads.threadIds);\n\n const renderFlatListItem = useCallback(\n ({ item, index }: { item: string; index: number }) => {\n return renderItem({ threadId: item, index });\n },\n [renderItem],\n );\n\n const keyExtractor = useCallback((item: string) => item, []);\n\n return (\n <FlatList\n data={threadIds as string[]}\n renderItem={renderFlatListItem}\n keyExtractor={keyExtractor}\n {...flatListProps}\n />\n );\n};\n"],"mappings":";;;;;;AAWA,MAAaW,mBAAkBC,OAAA;CAAA,MAAAC,IAAAC,EAAA,CAAA;CAAA,IAAAC;CAAA,IAAAR;CAAA,IAAAM,EAAA,OAAAD,IAAA;EAAC,CAAA,CAAAL,eAAAQ,iBAAAH;EAGTC,EAAA,KAAAD;EAAAC,EAAA,KAAAE;EAAAF,EAAA,KAAAN;CAAA,OAAA;EAAAQ,gBAAAF,EAAA;EAAAN,aAAAM,EAAA;CAAA;CACrB,MAAAG,YAAkBZ,YAAYa,KAA0B;CAAE,IAAAC;CAAA,IAAAL,EAAA,OAAAN,YAAA;EAGxDW,MAAAC,OAAA;GAAC,MAAA,EAAAC,MAAAV,UAAAS;GAAgD,OACxCZ,WAAW;IAAAE,UAAYW;IAAIV;GAAQ,CAAC;EAAC;EAC7CG,EAAA,KAAAN;EAAAM,EAAA,KAAAK;CAAA,OAAAA,KAAAL,EAAA;CAHH,MAAAQ,qBAA2BH;CAO3B,MAAAI,eAAqBC;CAIX,MAAAJ,KAAAH;CAAqB,IAAAQ;CAAA,IAAAX,EAAA,OAAAE,iBAAAF,EAAA,OAAAQ,sBAAAR,EAAA,OAAAM,IAAA;EAD7BK,KAAA,oBAAC,UAAD;GACQ,MAAAL;GACME,YAAAA;GACEC;GAAY,GACtBP;EAAa,CAAA;EACjBF,EAAA,KAAAE;EAAAF,EAAA,KAAAQ;EAAAR,EAAA,KAAAM;EAAAN,EAAA,KAAAW;CAAA,OAAAA,KAAAX,EAAA;CAAA,OALFW;AAKE;AArByB,SAAAP,MAAAQ,GAAA;CAAA,OAIQA,EAACC,QAAQV;AAAU;AAJ3B,SAAAO,OAAAI,QAAA;CAAA,OAasBP;AAAI"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@assistant-ui/react-native",
3
- "version": "0.1.31",
3
+ "version": "0.1.33",
4
4
  "description": "React Native bindings for assistant-ui",
5
5
  "keywords": [
6
6
  "assistant",
@@ -31,10 +31,10 @@
31
31
  ],
32
32
  "sideEffects": false,
33
33
  "dependencies": {
34
- "@assistant-ui/core": "^0.2.22",
35
- "@assistant-ui/store": "^0.2.21",
36
- "@assistant-ui/tap": "^0.9.5",
37
- "assistant-stream": "^0.3.27",
34
+ "@assistant-ui/core": "^0.3.0",
35
+ "@assistant-ui/store": "^0.3.0",
36
+ "@assistant-ui/tap": "^0.9.7",
37
+ "assistant-stream": "^0.3.29",
38
38
  "zustand": "^5.0.14"
39
39
  },
40
40
  "peerDependencies": {
@@ -56,7 +56,7 @@
56
56
  "react-native": "^0.86.0",
57
57
  "react-native-web": "^0.21.2",
58
58
  "vitest": "^4.1.10",
59
- "@assistant-ui/x-buildutils": "0.0.19"
59
+ "@assistant-ui/x-buildutils": "0.0.20"
60
60
  },
61
61
  "publishConfig": {
62
62
  "access": "public",
@@ -8,9 +8,8 @@ const h = vi.hoisted(() => ({
8
8
  }));
9
9
 
10
10
  vi.mock("@assistant-ui/store", () => {
11
- const aui = {
12
- attachment: () => ({ remove: h.remove }),
13
- };
11
+ const attachment = Object.assign(() => attachment, { remove: h.remove });
12
+ const aui = { attachment };
14
13
  return {
15
14
  useAui: () => aui,
16
15
  };
@@ -14,7 +14,7 @@ export const AttachmentRemove = ({
14
14
  const aui = useAui();
15
15
 
16
16
  const handleRemove = useCallback(() => {
17
- aui.attachment().remove();
17
+ aui.attachment.remove();
18
18
  }, [aui]);
19
19
 
20
20
  return (
@@ -10,9 +10,10 @@ const h = vi.hoisted(() => ({
10
10
  }));
11
11
 
12
12
  vi.mock("@assistant-ui/store", () => {
13
- const aui = {
14
- chainOfThought: () => ({ setCollapsed: h.setCollapsed }),
15
- };
13
+ const chainOfThought = Object.assign(() => chainOfThought, {
14
+ setCollapsed: h.setCollapsed,
15
+ });
16
+ const aui = { chainOfThought };
16
17
  return {
17
18
  useAui: () => aui,
18
19
  useAuiState: <T,>(selector: (s: typeof h.state) => T) => selector(h.state),
@@ -17,7 +17,7 @@ export const ChainOfThoughtAccordionTrigger = ({
17
17
  const collapsed = useAuiState((s) => s.chainOfThought.collapsed);
18
18
 
19
19
  const onPress = useCallback(() => {
20
- aui.chainOfThought().setCollapsed(!collapsed);
20
+ aui.chainOfThought.setCollapsed(!collapsed);
21
21
  }, [aui, collapsed]);
22
22
 
23
23
  return (
@@ -12,12 +12,11 @@ const h = vi.hoisted(() => ({
12
12
  }));
13
13
 
14
14
  vi.mock("@assistant-ui/store", () => {
15
- const aui = {
16
- composer: () => ({
17
- setText: h.setText,
18
- send: h.sendSpy,
19
- }),
20
- };
15
+ const composer = Object.assign(() => composer, {
16
+ setText: h.setText,
17
+ send: h.sendSpy,
18
+ });
19
+ const aui = { composer };
21
20
  return {
22
21
  useAui: () => aui,
23
22
  useAuiState: <T,>(
@@ -69,11 +69,11 @@ export const ComposerInput = ({
69
69
  if (Platform.OS === "web") {
70
70
  // Keep the controlled value in sync mid-IME so react-dom does not reset the textarea to a stale value
71
71
  flushTapSync(() => {
72
- aui.composer().setText(value);
72
+ aui.composer.setText(value);
73
73
  });
74
74
  return;
75
75
  }
76
- aui.composer().setText(value);
76
+ aui.composer.setText(value);
77
77
  },
78
78
  [aui],
79
79
  );
@@ -100,7 +100,7 @@ export const ComposerInput = ({
100
100
  if (nativeEvent.isComposing || nativeEvent.keyCode === 229) return;
101
101
  if (nativeEvent.key === "Enter" && !nativeEvent.shiftKey) {
102
102
  (e as unknown as Event).preventDefault?.();
103
- aui.composer().send();
103
+ aui.composer.send();
104
104
  }
105
105
  },
106
106
  [aui, submitMode, onKeyPressProp],
@@ -11,23 +11,21 @@ const h = vi.hoisted(() => ({
11
11
  respondToToolApproval: vi.fn(),
12
12
  state: {
13
13
  message: { content: [] as AnyPart[] },
14
- tools: { tools: {} as Record<string, unknown> },
14
+ tools: { toolUIs: {} as Record<string, unknown> },
15
15
  dataRenderers: { renderers: {} as Record<string, unknown> },
16
16
  },
17
17
  }));
18
18
 
19
19
  vi.mock("@assistant-ui/store", () => {
20
- const aui = {
21
- message: () => ({
22
- part: ({ index }: { index: number }) => ({
23
- addToolResult: (...args: unknown[]) => h.addToolResult(index, ...args),
24
- resumeToolCall: (...args: unknown[]) =>
25
- h.resumeToolCall(index, ...args),
26
- respondToToolApproval: (...args: unknown[]) =>
27
- h.respondToToolApproval(index, ...args),
28
- }),
20
+ const message = Object.assign(() => message, {
21
+ part: ({ index }: { index: number }) => ({
22
+ addToolResult: (...args: unknown[]) => h.addToolResult(index, ...args),
23
+ resumeToolCall: (...args: unknown[]) => h.resumeToolCall(index, ...args),
24
+ respondToToolApproval: (...args: unknown[]) =>
25
+ h.respondToToolApproval(index, ...args),
29
26
  }),
30
- };
27
+ });
28
+ const aui = { message };
31
29
  return {
32
30
  useAui: () => aui,
33
31
  useAuiState: <T,>(selector: (s: typeof h.state) => T) => selector(h.state),
@@ -45,7 +43,7 @@ describe("MessageContent", () => {
45
43
  h.resumeToolCall.mockReset();
46
44
  h.respondToToolApproval.mockReset();
47
45
  h.state.message.content = [];
48
- h.state.tools.tools = {};
46
+ h.state.tools.toolUIs = {};
49
47
  h.state.dataRenderers.renderers = {};
50
48
 
51
49
  container = document.createElement("div");
@@ -153,7 +151,7 @@ describe("MessageContent", () => {
153
151
  (props.respondToApproval as () => void)();
154
152
  return <span data-testid="tool">tool:{String(props.toolName)}</span>;
155
153
  });
156
- h.state.tools.tools = { search: ToolRender };
154
+ h.state.tools.toolUIs = { search: [{ render: ToolRender }] };
157
155
 
158
156
  await mount();
159
157
 
@@ -164,13 +162,15 @@ describe("MessageContent", () => {
164
162
  expect(h.respondToToolApproval).toHaveBeenCalledWith(0);
165
163
  });
166
164
 
167
- it("picks the first renderer when the registry holds an array", async () => {
165
+ it("picks the first registration when multiple are registered", async () => {
168
166
  h.state.message.content = [
169
167
  { type: "tool-call", toolName: "search", toolCallId: "c1" },
170
168
  ];
171
169
  const First = vi.fn(() => <span data-testid="first">first</span>);
172
170
  const Second = vi.fn(() => <span>second</span>);
173
- h.state.tools.tools = { search: [First, Second] };
171
+ h.state.tools.toolUIs = {
172
+ search: [{ render: First }, { render: Second }],
173
+ };
174
174
 
175
175
  await mount();
176
176
 
@@ -265,8 +265,8 @@ describe("MessageContent", () => {
265
265
  { type: "tool-call", toolName: "t", toolCallId: "c" },
266
266
  { type: "data", name: "d", data: {} },
267
267
  ];
268
- h.state.tools.tools = {
269
- t: () => <span>[tool]</span>,
268
+ h.state.tools.toolUIs = {
269
+ t: [{ render: () => <span>[tool]</span> }],
270
270
  };
271
271
  h.state.dataRenderers.renderers = {
272
272
  d: () => <span>[data]</span>,
@@ -65,17 +65,12 @@ const ToolUIDisplay = ({
65
65
  index: number;
66
66
  }) => {
67
67
  const aui = useAui();
68
- const Render = useAuiState((s) => {
69
- const renders = s.tools.tools[part.toolName];
70
- if (Array.isArray(renders)) return renders[0];
71
- return renders;
72
- });
73
-
74
- const partMethods = useMemo(
75
- () => aui.message().part({ index }),
76
- [aui, index],
68
+ const Render = useAuiState(
69
+ (s) => s.tools.toolUIs[part.toolName]?.[0]?.render,
77
70
  );
78
71
 
72
+ const partMethods = useMemo(() => aui.message.part({ index }), [aui, index]);
73
+
79
74
  if (Render) {
80
75
  return (
81
76
  <Render
@@ -623,4 +623,226 @@ describe("ThreadMessages", () => {
623
623
  expect(getFlatListProps().scrollEventThrottle).toBe(16);
624
624
  });
625
625
  });
626
+
627
+ describe("isAtBottom pin state", () => {
628
+ const mountPinned = async () => {
629
+ await mountFlatList({ components: messageComponents });
630
+ const props = getFlatListProps();
631
+ await act(async () => {
632
+ props.onLayout?.({
633
+ nativeEvent: { layout: { height: 100 } },
634
+ });
635
+ props.onScroll?.({
636
+ nativeEvent: {
637
+ contentOffset: { y: 200 },
638
+ contentSize: { height: 300, width: 0 },
639
+ layoutMeasurement: { height: 100, width: 0 },
640
+ },
641
+ });
642
+ props.onContentSizeChange?.(0, 300);
643
+ });
644
+ h.scrollToEnd.mockClear();
645
+ return props;
646
+ };
647
+
648
+ it("stays pinned when the viewport shrinks while at the bottom", async () => {
649
+ const props = await mountPinned();
650
+
651
+ await act(async () => {
652
+ props.onLayout?.({
653
+ nativeEvent: { layout: { height: 60 } },
654
+ });
655
+ });
656
+ h.scrollToEnd.mockClear();
657
+ await act(async () => {
658
+ props.onContentSizeChange?.(0, 340);
659
+ });
660
+
661
+ expect(h.scrollToEnd).toHaveBeenCalledWith({ animated: false });
662
+ });
663
+
664
+ it("commands a bottom scroll when the viewport shrinks while pinned", async () => {
665
+ const props = await mountPinned();
666
+
667
+ await act(async () => {
668
+ props.onLayout?.({
669
+ nativeEvent: { layout: { height: 60 } },
670
+ });
671
+ });
672
+
673
+ expect(h.scrollToEnd).toHaveBeenCalledWith({ animated: false });
674
+ });
675
+
676
+ it("preserves a pending animated scroll on a pinned viewport change", async () => {
677
+ const props = await mountPinned();
678
+
679
+ await emit("thread.runStart");
680
+ h.scrollToEnd.mockClear();
681
+ await act(async () => {
682
+ props.onLayout?.({
683
+ nativeEvent: { layout: { height: 60 } },
684
+ });
685
+ });
686
+
687
+ expect(h.scrollToEnd).toHaveBeenCalledTimes(1);
688
+ expect(h.scrollToEnd).toHaveBeenCalledWith({ animated: true });
689
+ });
690
+
691
+ it("ignores a layout event with an unchanged viewport height", async () => {
692
+ const props = await mountPinned();
693
+
694
+ await act(async () => {
695
+ props.onLayout?.({
696
+ nativeEvent: { layout: { height: 100 } },
697
+ });
698
+ });
699
+
700
+ expect(h.scrollToEnd).not.toHaveBeenCalled();
701
+ });
702
+
703
+ it("does not command a scroll on the first layout measurement", async () => {
704
+ await mountFlatList({ components: messageComponents });
705
+ getFlatListProps();
706
+ h.scrollToEnd.mockClear();
707
+
708
+ await act(async () => {
709
+ getFlatListProps().onLayout?.({
710
+ nativeEvent: { layout: { height: 100 } },
711
+ });
712
+ });
713
+
714
+ expect(h.scrollToEnd).not.toHaveBeenCalled();
715
+ });
716
+
717
+ it("does not command a scroll on viewport change when autoScroll is off", async () => {
718
+ await mountFlatList({ components: messageComponents, autoScroll: false });
719
+ const props = getFlatListProps();
720
+ await act(async () => {
721
+ props.onLayout?.({
722
+ nativeEvent: { layout: { height: 100 } },
723
+ });
724
+ props.onScroll?.({
725
+ nativeEvent: {
726
+ contentOffset: { y: 200 },
727
+ contentSize: { height: 300, width: 0 },
728
+ layoutMeasurement: { height: 100, width: 0 },
729
+ },
730
+ });
731
+ props.onContentSizeChange?.(0, 300);
732
+ });
733
+ h.scrollToEnd.mockClear();
734
+
735
+ await act(async () => {
736
+ props.onLayout?.({
737
+ nativeEvent: { layout: { height: 60 } },
738
+ });
739
+ });
740
+
741
+ expect(h.scrollToEnd).not.toHaveBeenCalled();
742
+ });
743
+
744
+ it("stays unpinned when the viewport shrinks after scrolling away", async () => {
745
+ const props = await mountPinned();
746
+
747
+ await act(async () => {
748
+ props.onScroll?.({
749
+ nativeEvent: {
750
+ contentOffset: { y: 50 },
751
+ contentSize: { height: 300, width: 0 },
752
+ layoutMeasurement: { height: 100, width: 0 },
753
+ },
754
+ });
755
+ });
756
+ await act(async () => {
757
+ props.onLayout?.({
758
+ nativeEvent: { layout: { height: 60 } },
759
+ });
760
+ });
761
+ await act(async () => {
762
+ props.onContentSizeChange?.(0, 340);
763
+ });
764
+
765
+ expect(h.scrollToEnd).not.toHaveBeenCalled();
766
+ });
767
+
768
+ it("keeps the pin through a downward scroll echo after a commanded scroll", async () => {
769
+ const props = await mountPinned();
770
+
771
+ await act(async () => {
772
+ props.onScroll?.({
773
+ nativeEvent: {
774
+ contentOffset: { y: 50 },
775
+ contentSize: { height: 300, width: 0 },
776
+ layoutMeasurement: { height: 100, width: 0 },
777
+ },
778
+ });
779
+ });
780
+ await emit("thread.runStart");
781
+ await act(async () => {
782
+ props.onContentSizeChange?.(0, 320);
783
+ });
784
+ h.scrollToEnd.mockClear();
785
+ await act(async () => {
786
+ props.onScroll?.({
787
+ nativeEvent: {
788
+ contentOffset: { y: 150 },
789
+ contentSize: { height: 320, width: 0 },
790
+ layoutMeasurement: { height: 100, width: 0 },
791
+ },
792
+ });
793
+ });
794
+ await act(async () => {
795
+ props.onContentSizeChange?.(0, 360);
796
+ });
797
+
798
+ expect(h.scrollToEnd).toHaveBeenCalledWith({ animated: false });
799
+ });
800
+
801
+ it("unpins and cancels a pending scroll on an upward gesture echo", async () => {
802
+ const props = await mountPinned();
803
+
804
+ await emit("thread.runStart");
805
+ h.scrollToEnd.mockClear();
806
+ await act(async () => {
807
+ props.onScroll?.({
808
+ nativeEvent: {
809
+ contentOffset: { y: 50 },
810
+ contentSize: { height: 300, width: 0 },
811
+ layoutMeasurement: { height: 100, width: 0 },
812
+ },
813
+ });
814
+ });
815
+ await act(async () => {
816
+ props.onContentSizeChange?.(0, 360);
817
+ });
818
+
819
+ expect(h.scrollToEnd).not.toHaveBeenCalled();
820
+ });
821
+
822
+ it("scrolls on content growth while pinned and stays put while unpinned", async () => {
823
+ const props = await mountPinned();
824
+ h.scrollToEnd.mockClear();
825
+
826
+ await act(async () => {
827
+ props.onContentSizeChange?.(0, 340);
828
+ });
829
+ expect(h.scrollToEnd).toHaveBeenCalledWith({ animated: false });
830
+
831
+ await act(async () => {
832
+ props.onScroll?.({
833
+ nativeEvent: {
834
+ contentOffset: { y: 50 },
835
+ contentSize: { height: 340, width: 0 },
836
+ layoutMeasurement: { height: 100, width: 0 },
837
+ },
838
+ });
839
+ });
840
+ h.scrollToEnd.mockClear();
841
+ await act(async () => {
842
+ props.onContentSizeChange?.(0, 380);
843
+ });
844
+
845
+ expect(h.scrollToEnd).not.toHaveBeenCalled();
846
+ });
847
+ });
626
848
  });
@@ -161,7 +161,7 @@ const ThreadMessageByChildren = memo(
161
161
  return (
162
162
  <MessageByIndexProvider index={index}>
163
163
  <RenderChildrenWithAccessor
164
- getItemState={(aui) => aui.thread().message({ index }).getState()}
164
+ getItemState={(aui) => aui.thread.message({ index }).getState()}
165
165
  >
166
166
  {(getItem) =>
167
167
  children({
@@ -249,10 +249,28 @@ const useThreadMessagesFlatListAutoScroll = ({
249
249
 
250
250
  const handleLayout = useCallback(
251
251
  (event: LayoutChangeEvent) => {
252
- metricsRef.current.viewportHeight = event.nativeEvent.layout.height;
252
+ const wasAtBottom = isAtBottomRef.current;
253
+ const previousViewportHeight = metricsRef.current.viewportHeight;
254
+ const viewportHeight = event.nativeEvent.layout.height;
255
+ metricsRef.current.viewportHeight = viewportHeight;
253
256
  updateIsAtBottom();
257
+ if (!wasAtBottom) return;
258
+ // Layout changes are never user gestures, so they must not unpin. Past
259
+ // the first measurement, a viewport change while pinned re-commands the
260
+ // bottom position, since no content-size event follows a bare keyboard
261
+ // open or close.
262
+ if (
263
+ autoScroll &&
264
+ previousViewportHeight !== 0 &&
265
+ viewportHeight !== previousViewportHeight
266
+ ) {
267
+ const pending = pendingScrollToBottomRef.current;
268
+ scrollToBottom(pending ? pending.animated : false);
269
+ } else {
270
+ isAtBottomRef.current = true;
271
+ }
254
272
  },
255
- [updateIsAtBottom],
273
+ [autoScroll, scrollToBottom, updateIsAtBottom],
256
274
  );
257
275
 
258
276
  const handleScroll = useCallback(