@assistant-ui/react-native 0.1.46 → 0.1.47

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 (51) hide show
  1. package/dist/index.d.ts +9 -1
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/primitives/actionBar/ActionBarCopy.d.ts +2 -2
  4. package/dist/primitives/actionBar/ActionBarCopy.d.ts.map +1 -1
  5. package/dist/primitives/actionBar/ActionBarCopy.js +2 -1
  6. package/dist/primitives/actionBar/ActionBarCopy.js.map +1 -1
  7. package/dist/primitives/actionBar/ActionBarFeedbackNegative.d.ts +2 -2
  8. package/dist/primitives/actionBar/ActionBarFeedbackNegative.d.ts.map +1 -1
  9. package/dist/primitives/actionBar/ActionBarFeedbackNegative.js +2 -1
  10. package/dist/primitives/actionBar/ActionBarFeedbackNegative.js.map +1 -1
  11. package/dist/primitives/actionBar/ActionBarFeedbackPositive.d.ts +2 -2
  12. package/dist/primitives/actionBar/ActionBarFeedbackPositive.d.ts.map +1 -1
  13. package/dist/primitives/actionBar/ActionBarFeedbackPositive.js +2 -1
  14. package/dist/primitives/actionBar/ActionBarFeedbackPositive.js.map +1 -1
  15. package/dist/primitives/composer/ComposerInput.d.ts +1 -1
  16. package/dist/primitives/composer/ComposerInput.d.ts.map +1 -1
  17. package/dist/primitives/composer/ComposerInput.js +55 -38
  18. package/dist/primitives/composer/ComposerInput.js.map +1 -1
  19. package/dist/primitives/message/MessageContent.d.ts.map +1 -1
  20. package/dist/primitives/message/MessageContent.js +13 -10
  21. package/dist/primitives/message/MessageContent.js.map +1 -1
  22. package/dist/primitives/message/MessageParts.d.ts +1 -0
  23. package/dist/primitives/message/MessageParts.d.ts.map +1 -1
  24. package/dist/primitives/message/MessageParts.js +22 -3
  25. package/dist/primitives/message/MessageParts.js.map +1 -1
  26. package/dist/primitives/message.js +1 -1
  27. package/dist/primitives/messagePart.js +1 -1
  28. package/dist/primitives/threadListItem/ThreadListItemTitle.d.ts +10 -0
  29. package/dist/primitives/threadListItem/ThreadListItemTitle.d.ts.map +1 -0
  30. package/dist/primitives/threadListItem/ThreadListItemTitle.js +47 -0
  31. package/dist/primitives/threadListItem/ThreadListItemTitle.js.map +1 -0
  32. package/dist/primitives/threadListItem.d.ts +1 -1
  33. package/dist/primitives/threadListItem.d.ts.map +1 -1
  34. package/dist/primitives/threadListItem.js +3 -3
  35. package/dist/primitives/threadListItem.js.map +1 -1
  36. package/package.json +7 -7
  37. package/src/index.ts +4 -0
  38. package/src/primitives/actionBar/ActionBar.test.tsx +45 -0
  39. package/src/primitives/actionBar/ActionBarCopy.tsx +12 -3
  40. package/src/primitives/actionBar/ActionBarFeedbackNegative.tsx +13 -3
  41. package/src/primitives/actionBar/ActionBarFeedbackPositive.tsx +13 -3
  42. package/src/primitives/composer/ComposerInput.test.tsx +64 -4
  43. package/src/primitives/composer/ComposerInput.tsx +13 -2
  44. package/src/primitives/message/MessageContent.runtime.test.tsx +35 -0
  45. package/src/primitives/message/MessageContent.test.tsx +68 -4
  46. package/src/primitives/message/MessageContent.tsx +19 -9
  47. package/src/primitives/message/MessageParts.test.tsx +68 -1
  48. package/src/primitives/message/MessageParts.tsx +17 -1
  49. package/src/primitives/threadListItem/ThreadListItemTitle.test.tsx +164 -0
  50. package/src/primitives/threadListItem/ThreadListItemTitle.tsx +23 -0
  51. package/src/primitives/threadListItem.ts +4 -1
@@ -1 +1 @@
1
- {"version":3,"file":"MessageParts.js","names":["FC","Text","MessagePrimitiveParts","MessagePrimitivePartsBase","MessagePartComponent","MessagePartComponentBase","MessagePrimitivePartByIndex","MessagePrimitivePartByIndexBase","messagePartsDefaultComponents","rnDefaultComponents","text","Props","props","$","_c","t0","children","components","rest","merged","t1","t2","displayName","_c","MessagePrimitivePartsBase","merged"],"sources":["../../../src/primitives/message/MessageParts.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { Text } from \"react-native\";\nimport {\n MessagePrimitiveParts as MessagePrimitivePartsBase,\n MessagePartComponent as MessagePartComponentBase,\n MessagePrimitivePartByIndex as MessagePrimitivePartByIndexBase,\n messagePartsDefaultComponents,\n} from \"@assistant-ui/core/react\";\n\nconst rnDefaultComponents = {\n ...messagePartsDefaultComponents,\n Text: ({ text }: { text: string }) => <Text>{text}</Text>,\n} satisfies MessagePrimitiveParts.Props[\"components\"];\n\nexport namespace MessagePrimitiveParts {\n export type Props = MessagePrimitivePartsBase.Props;\n}\n\n/**\n * Renders the parts of a message with React Native-specific default components.\n */\nexport const MessagePrimitiveParts: FC<MessagePrimitiveParts.Props> = (\n props,\n) => {\n if (\"children\" in props) {\n return (\n <MessagePrimitivePartsBase>{props.children}</MessagePrimitivePartsBase>\n );\n }\n\n const { components, ...rest } = props;\n const merged = components\n ? { ...components, Text: components.Text ?? rnDefaultComponents.Text }\n : rnDefaultComponents;\n\n return <MessagePrimitivePartsBase components={merged as any} {...rest} />;\n};\n\nMessagePrimitiveParts.displayName = \"MessagePrimitive.Parts\";\n\nexport {\n MessagePartComponentBase as MessagePartComponent,\n MessagePrimitivePartByIndexBase as MessagePrimitivePartByIndex,\n};\n"],"mappings":";;;;;AASA,MAAMS,sBAAsB;CAC1B,GAAGD;CACHP,OAAO,EAAES,WAA6B,oBAAC,MAAD,EAAA,UAAOA,KAAW,CAAA;AAC1D;;;;AASA,MAAaR,yBAAyDU,UAAA;CAAA,MAAAC,IAAAC,EAAA,EAAA;CAGpE,IAAI,cAAcF,OAAK;EAAA,IAAAG;EAAA,IAAAF,EAAA,OAAAD,MAAAI,UAAA;GAEnBD,KAAA,oBAACS,yBAAD,EAAA,UAA4BZ,MAAKI,SAAP,CAAA;GAA6CH,EAAA,KAAAD,MAAAI;GAAAH,EAAA,KAAAE;EAAA,OAAAA,KAAAF,EAAA;EAAA,OAAvEE;CAAuE;CAE1E,IAAAE;CAAA,IAAAC;CAAA,IAAAL,EAAA,OAAAD,OAAA;EAED,CAAA,CAAAK,YAAA,GAAAC,QAAgCN;EAAMC,EAAA,KAAAD;EAAAC,EAAA,KAAAI;EAAAJ,EAAA,KAAAK;CAAA,OAAA;EAAAD,aAAAJ,EAAA;EAAAK,OAAAL,EAAA;CAAA;CAAA,IAAAE;CAAA,IAAAF,EAAA,OAAAI,YAAA;EACvBF,KAAAE,aAAA;GAAA,GACNA;GAAUhB,MAAQgB,WAAUhB,QAASQ,oBAAmBR;EAC3C,IAFPQ;EAEQI,EAAA,KAAAI;EAAAJ,EAAA,KAAAE;CAAA,OAAAA,KAAAF,EAAA;CAEuB,MAAAO,KAAAD;CAAa,IAAAE;CAAA,IAAAR,EAAA,OAAAK,QAAAL,EAAA,OAAAO,IAAA;EAApDC,KAAA,oBAACG,yBAAD;GAAuC,YAAAJ;GAAa,GAAMF;EAAI,CAAA;EAAIL,EAAA,KAAAK;EAAAL,EAAA,KAAAO;EAAAP,EAAA,KAAAQ;CAAA,OAAAA,KAAAR,EAAA;CAAA,OAAlEQ;AAAkE;AAG3EnB,sBAAsBoB,cAAc"}
1
+ {"version":3,"file":"MessageParts.js","names":["FC","Text","MessagePrimitiveParts","MessagePrimitivePartsBase","MessagePartComponent","MessagePartComponentBase","MessagePrimitivePartByIndex","MessagePrimitivePartByIndexBase","messagePartsDefaultComponents","MessagePartPrimitiveImage","DEFAULT_IMAGE_STYLE","width","aspectRatio","const","DefaultMessageImage","$","_c","t0","Symbol","for","rnDefaultComponents","text","Image","Props","props","children","components","rest","merged","t1","t2","displayName","_c","MessagePrimitivePartsBase","merged"],"sources":["../../../src/primitives/message/MessageParts.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { Text } from \"react-native\";\nimport {\n MessagePrimitiveParts as MessagePrimitivePartsBase,\n MessagePartComponent as MessagePartComponentBase,\n MessagePrimitivePartByIndex as MessagePrimitivePartByIndexBase,\n messagePartsDefaultComponents,\n} from \"@assistant-ui/core/react\";\nimport { MessagePartPrimitiveImage } from \"../messagePart/MessagePartImage\";\n\n// React Native derives no intrinsic size from a remote or data URI, so an\n// Image with no dimensions lays out at zero. The default fills the available\n// width and keeps the picture whole inside a square box; a consumer that knows\n// its own aspect ratio overrides `components.Image`.\nconst DEFAULT_IMAGE_STYLE = { width: \"100%\", aspectRatio: 1 } as const;\n\nexport const DefaultMessageImage = () => (\n <MessagePartPrimitiveImage style={DEFAULT_IMAGE_STYLE} resizeMode=\"contain\" />\n);\n\nconst rnDefaultComponents = {\n ...messagePartsDefaultComponents,\n Text: ({ text }: { text: string }) => <Text>{text}</Text>,\n Image: DefaultMessageImage,\n} satisfies MessagePrimitiveParts.Props[\"components\"];\n\nexport namespace MessagePrimitiveParts {\n export type Props = MessagePrimitivePartsBase.Props;\n}\n\n/**\n * Renders the parts of a message with React Native-specific default components.\n */\nexport const MessagePrimitiveParts: FC<MessagePrimitiveParts.Props> = (\n props,\n) => {\n if (\"children\" in props) {\n return (\n <MessagePrimitivePartsBase>{props.children}</MessagePrimitivePartsBase>\n );\n }\n\n const { components, ...rest } = props;\n const merged = components\n ? {\n ...components,\n Text: components.Text ?? rnDefaultComponents.Text,\n Image: components.Image ?? rnDefaultComponents.Image,\n }\n : rnDefaultComponents;\n\n return <MessagePrimitivePartsBase components={merged as any} {...rest} />;\n};\n\nMessagePrimitiveParts.displayName = \"MessagePrimitive.Parts\";\n\nexport {\n MessagePartComponentBase as MessagePartComponent,\n MessagePrimitivePartByIndexBase as MessagePrimitivePartByIndex,\n};\n"],"mappings":";;;;;;AAcA,MAAMU,sBAAsB;CAAEC,OAAO;CAAQC,aAAa;AAAE;AAE5D,MAAaE,4BAAsB;CAAA,MAAAC,IAAAC,EAAA,CAAA;CAAA,IAAAC;CAAA,IAAAF,EAAA,OAAAG,OAAAC,IAAA,2BAAA,GAAA;EACjCF,KAAA,oBAAC,2BAAD;GAAkCP,OAAAA;GAAgC,YAAA;EAAS,CAAA;EAAGK,EAAA,KAAAE;CAAA,OAAAA,KAAAF,EAAA;CAAA,OAA9EE;AAA8E;AAGhF,MAAMG,sBAAsB;CAC1B,GAAGZ;CACHP,OAAO,EAAEoB,WAA6B,oBAAC,MAAD,EAAA,UAAOA,KAAW,CAAA;CACxDC,OAAOR;AACT;;;;AASA,MAAaZ,yBAAyDsB,UAAA;CAAA,MAAAT,IAAAC,EAAA,EAAA;CAGpE,IAAI,cAAcQ,OAAK;EAAA,IAAAP;EAAA,IAAAF,EAAA,OAAAS,MAAAC,UAAA;GAEnBR,KAAA,oBAACgB,yBAAD,EAAA,UAA4BT,MAAKC,SAAP,CAAA;GAA6CV,EAAA,KAAAS,MAAAC;GAAAV,EAAA,KAAAE;EAAA,OAAAA,KAAAF,EAAA;EAAA,OAAvEE;CAAuE;CAE1E,IAAAS;CAAA,IAAAC;CAAA,IAAAZ,EAAA,OAAAS,OAAA;EAED,CAAA,CAAAE,YAAA,GAAAC,QAAgCH;EAAMT,EAAA,KAAAS;EAAAT,EAAA,KAAAW;EAAAX,EAAA,KAAAY;CAAA,OAAA;EAAAD,aAAAX,EAAA;EAAAY,OAAAZ,EAAA;CAAA;CAAA,IAAAE;CAAA,IAAAF,EAAA,OAAAW,YAAA;EACvBT,KAAAS,aAAA;GAAA,GAENA;GAAUzB,MACPyB,WAAUzB,QAASmB,oBAAmBnB;GAAKqB,OAC1CI,WAAUJ,SAAUF,oBAAmBE;EAE9B,IANPF;EAMQL,EAAA,KAAAW;EAAAX,EAAA,KAAAE;CAAA,OAAAA,KAAAF,EAAA;CAEuB,MAAAc,KAAAD;CAAa,IAAAE;CAAA,IAAAf,EAAA,OAAAY,QAAAZ,EAAA,OAAAc,IAAA;EAApDC,KAAA,oBAACG,yBAAD;GAAuC,YAAAJ;GAAa,GAAMF;EAAI,CAAA;EAAIZ,EAAA,KAAAY;EAAAZ,EAAA,KAAAc;EAAAd,EAAA,KAAAe;CAAA,OAAAA,KAAAf,EAAA;CAAA,OAAlEe;AAAkE;AAG3E5B,sBAAsB6B,cAAc"}
@@ -1,7 +1,7 @@
1
1
  import { __exportAll } from "../_virtual/_rolldown/runtime.js";
2
2
  import { MessageRoot } from "./message/MessageRoot.js";
3
- import { MessageContent } from "./message/MessageContent.js";
4
3
  import { MessagePrimitivePartByIndex as MessagePrimitivePartByIndexBase, MessagePrimitiveParts } from "./message/MessageParts.js";
4
+ import { MessageContent } from "./message/MessageContent.js";
5
5
  import { MessageIf } from "./message/MessageIf.js";
6
6
  import { MessageAttachmentByIndex, MessageAttachments } from "./message/MessageAttachments.js";
7
7
  import { MessagePrimitiveGroupedParts as GroupedParts, MessagePrimitiveQuote as Quote } from "@assistant-ui/core/react";
@@ -1,6 +1,6 @@
1
1
  import { __exportAll } from "../_virtual/_rolldown/runtime.js";
2
- import { MessagePartPrimitiveText } from "./messagePart/MessagePartText.js";
3
2
  import { MessagePartPrimitiveImage } from "./messagePart/MessagePartImage.js";
3
+ import { MessagePartPrimitiveText } from "./messagePart/MessagePartText.js";
4
4
  import { MessagePartPrimitiveInProgress } from "./messagePart/MessagePartInProgress.js";
5
5
  import { PartPrimitiveMessages as Messages } from "@assistant-ui/core/react";
6
6
  //#region src/primitives/messagePart.ts
@@ -0,0 +1,10 @@
1
+ import type { ReactNode } from "react";
2
+ import { type TextProps } from "react-native";
3
+ export type ThreadListItemTitleProps = Omit<TextProps, "children"> & {
4
+ fallback?: ReactNode;
5
+ };
6
+ export declare function ThreadListItemTitle({ fallback, ...props }: ThreadListItemTitleProps): import("react").JSX.Element;
7
+ export declare namespace ThreadListItemTitle {
8
+ type Props = ThreadListItemTitleProps;
9
+ }
10
+ //# sourceMappingURL=ThreadListItemTitle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ThreadListItemTitle.d.ts","sourceRoot":"","sources":["../../../src/primitives/threadListItem/ThreadListItemTitle.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,EAAQ,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAGpD,MAAM,MAAM,wBAAwB,GAAG,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,GAAG;IACnE,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB,CAAC;AAEF,wBAAgB,mBAAmB,CAAC,EAClC,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,wBAAwB,+BAO1B;AAED,yBAAiB,mBAAmB,CAAC;IACnC,KAAY,KAAK,GAAG,wBAAwB,CAAC;CAC9C"}
@@ -0,0 +1,47 @@
1
+ import { useAuiState } from "@assistant-ui/store";
2
+ import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
3
+ import { Text } from "react-native";
4
+ import { Fragment, jsx } from "react/jsx-runtime";
5
+ //#region src/primitives/threadListItem/ThreadListItemTitle.tsx
6
+ function ThreadListItemTitle(t0) {
7
+ const $ = c(8);
8
+ let fallback;
9
+ let props;
10
+ if ($[0] !== t0) {
11
+ ({fallback, ...props} = t0);
12
+ $[0] = t0;
13
+ $[1] = fallback;
14
+ $[2] = props;
15
+ } else {
16
+ fallback = $[1];
17
+ props = $[2];
18
+ }
19
+ const content = useAuiState(_temp) || fallback;
20
+ if (typeof content === "string" || typeof content === "number") {
21
+ let t1;
22
+ if ($[3] !== content || $[4] !== props) {
23
+ t1 = /* @__PURE__ */ jsx(Text, {
24
+ ...props,
25
+ children: content
26
+ });
27
+ $[3] = content;
28
+ $[4] = props;
29
+ $[5] = t1;
30
+ } else t1 = $[5];
31
+ return t1;
32
+ }
33
+ let t1;
34
+ if ($[6] !== content) {
35
+ t1 = /* @__PURE__ */ jsx(Fragment, { children: content });
36
+ $[6] = content;
37
+ $[7] = t1;
38
+ } else t1 = $[7];
39
+ return t1;
40
+ }
41
+ function _temp(s) {
42
+ return s.threadListItem.title;
43
+ }
44
+ //#endregion
45
+ export { ThreadListItemTitle };
46
+
47
+ //# sourceMappingURL=ThreadListItemTitle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ThreadListItemTitle.js","names":["ReactNode","Text","TextProps","useAuiState","ThreadListItemTitleProps","Omit","fallback","ThreadListItemTitle","t0","$","_c","props","title","_temp","content","t1","s","threadListItem","Props","_c"],"sources":["../../../src/primitives/threadListItem/ThreadListItemTitle.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { Text, type TextProps } from \"react-native\";\nimport { useAuiState } from \"@assistant-ui/store\";\n\nexport type ThreadListItemTitleProps = Omit<TextProps, \"children\"> & {\n fallback?: ReactNode;\n};\n\nexport function ThreadListItemTitle({\n fallback,\n ...props\n}: ThreadListItemTitleProps) {\n const title = useAuiState((s) => s.threadListItem.title);\n const content = title || fallback;\n if (typeof content === \"string\" || typeof content === \"number\") {\n return <Text {...props}>{content}</Text>;\n }\n return <>{content}</>;\n}\n\nexport namespace ThreadListItemTitle {\n export type Props = ThreadListItemTitleProps;\n}\n"],"mappings":";;;;;AAQA,SAAOO,oBAAAC,IAAA;CAAA,MAAAC,IAAAC,EAAA,CAAA;CAAA,IAAAJ;CAAA,IAAAK;CAAA,IAAAF,EAAA,OAAAD,IAAA;EAA6B,CAAA,CAAAF,UAAA,GAAAK,SAAAH;EAGTC,EAAA,KAAAD;EAAAC,EAAA,KAAAH;EAAAG,EAAA,KAAAE;CAAA,OAAA;EAAAL,WAAAG,EAAA;EAAAE,QAAAF,EAAA;CAAA;CAEzB,MAAAK,UADcX,YAAYU,KACVD,KAAAN;CAChB,IAAI,OAAOQ,YAAY,YAAY,OAAOA,YAAY,UAAQ;EAAA,IAAAC;EAAA,IAAAN,EAAA,OAAAK,WAAAL,EAAA,OAAAE,OAAA;GACrDI,KAAA,oBAAC,MAAD;IAAK,GAAKJ;IAAQG,UAAAA;GAAb,CAAA;GAA4BL,EAAA,KAAAK;GAAAL,EAAA,KAAAE;GAAAF,EAAA,KAAAM;EAAA,OAAAA,KAAAN,EAAA;EAAA,OAAjCM;CAAiC;CACzC,IAAAA;CAAA,IAAAN,EAAA,OAAAK,SAAA;EACMC,KAAA,oBAAA,UAAA,EAAA,UAAGD,QAAO,CAAA;EAAIL,EAAA,KAAAK;EAAAL,EAAA,KAAAM;CAAA,OAAAA,KAAAN,EAAA;CAAA,OAAdM;AAAc;AAThB,SAAAF,MAAAG,GAAA;CAAA,OAI4BA,EAACC,eAAeL;AAAM"}
@@ -1,5 +1,5 @@
1
1
  export { ThreadListItemRoot as Root, type ThreadListItemRootProps as RootProps, } from "./threadListItem/ThreadListItemRoot.js";
2
- export { ThreadListItemPrimitiveTitle as Title } from "@assistant-ui/core/react";
2
+ export { ThreadListItemTitle as Title, type ThreadListItemTitleProps as TitleProps, } from "./threadListItem/ThreadListItemTitle.js";
3
3
  export { ThreadListItemTrigger as Trigger, type ThreadListItemTriggerProps as TriggerProps, } from "./threadListItem/ThreadListItemTrigger.js";
4
4
  export { ThreadListItemDelete as Delete, type ThreadListItemDeleteProps as DeleteProps, } from "./threadListItem/ThreadListItemDelete.js";
5
5
  export { ThreadListItemArchive as Archive, type ThreadListItemArchiveProps as ArchiveProps, } from "./threadListItem/ThreadListItemArchive.js";
@@ -1 +1 @@
1
- {"version":3,"file":"threadListItem.d.ts","sourceRoot":"","sources":["../../src/primitives/threadListItem.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,IAAI,IAAI,EAC1B,KAAK,uBAAuB,IAAI,SAAS,GAC1C,+CAA4C;AAC7C,OAAO,EAAE,4BAA4B,IAAI,KAAK,EAAE,MAAM,0BAA0B,CAAC;AACjF,OAAO,EACL,qBAAqB,IAAI,OAAO,EAChC,KAAK,0BAA0B,IAAI,YAAY,GAChD,kDAA+C;AAChD,OAAO,EACL,oBAAoB,IAAI,MAAM,EAC9B,KAAK,yBAAyB,IAAI,WAAW,GAC9C,iDAA8C;AAC/C,OAAO,EACL,qBAAqB,IAAI,OAAO,EAChC,KAAK,0BAA0B,IAAI,YAAY,GAChD,kDAA+C;AAChD,OAAO,EACL,uBAAuB,IAAI,SAAS,EACpC,KAAK,4BAA4B,IAAI,cAAc,GACpD,oDAAiD"}
1
+ {"version":3,"file":"threadListItem.d.ts","sourceRoot":"","sources":["../../src/primitives/threadListItem.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,IAAI,IAAI,EAC1B,KAAK,uBAAuB,IAAI,SAAS,GAC1C,+CAA4C;AAC7C,OAAO,EACL,mBAAmB,IAAI,KAAK,EAC5B,KAAK,wBAAwB,IAAI,UAAU,GAC5C,gDAA6C;AAC9C,OAAO,EACL,qBAAqB,IAAI,OAAO,EAChC,KAAK,0BAA0B,IAAI,YAAY,GAChD,kDAA+C;AAChD,OAAO,EACL,oBAAoB,IAAI,MAAM,EAC9B,KAAK,yBAAyB,IAAI,WAAW,GAC9C,iDAA8C;AAC/C,OAAO,EACL,qBAAqB,IAAI,OAAO,EAChC,KAAK,0BAA0B,IAAI,YAAY,GAChD,kDAA+C;AAChD,OAAO,EACL,uBAAuB,IAAI,SAAS,EACpC,KAAK,4BAA4B,IAAI,cAAc,GACpD,oDAAiD"}
@@ -1,20 +1,20 @@
1
1
  import { __exportAll } from "../_virtual/_rolldown/runtime.js";
2
2
  import { ThreadListItemRoot } from "./threadListItem/ThreadListItemRoot.js";
3
+ import { ThreadListItemTitle } from "./threadListItem/ThreadListItemTitle.js";
3
4
  import { ThreadListItemTrigger } from "./threadListItem/ThreadListItemTrigger.js";
4
5
  import { ThreadListItemDelete } from "./threadListItem/ThreadListItemDelete.js";
5
6
  import { ThreadListItemArchive } from "./threadListItem/ThreadListItemArchive.js";
6
7
  import { ThreadListItemUnarchive } from "./threadListItem/ThreadListItemUnarchive.js";
7
- import { ThreadListItemPrimitiveTitle as Title } from "@assistant-ui/core/react";
8
8
  //#region src/primitives/threadListItem.ts
9
9
  var threadListItem_exports = /* @__PURE__ */ __exportAll({
10
10
  Archive: () => ThreadListItemArchive,
11
11
  Delete: () => ThreadListItemDelete,
12
12
  Root: () => ThreadListItemRoot,
13
- Title: () => Title,
13
+ Title: () => ThreadListItemTitle,
14
14
  Trigger: () => ThreadListItemTrigger,
15
15
  Unarchive: () => ThreadListItemUnarchive
16
16
  });
17
17
  //#endregion
18
- export { ThreadListItemArchive as Archive, ThreadListItemDelete as Delete, ThreadListItemRoot as Root, Title, ThreadListItemTrigger as Trigger, ThreadListItemUnarchive as Unarchive, threadListItem_exports };
18
+ export { ThreadListItemArchive as Archive, ThreadListItemDelete as Delete, ThreadListItemRoot as Root, ThreadListItemTitle as Title, ThreadListItemTrigger as Trigger, ThreadListItemUnarchive as Unarchive, threadListItem_exports };
19
19
 
20
20
  //# sourceMappingURL=threadListItem.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"threadListItem.js","names":["ThreadListItemRoot","Root","ThreadListItemRootProps","RootProps","ThreadListItemPrimitiveTitle","Title","ThreadListItemTrigger","Trigger","ThreadListItemTriggerProps","TriggerProps","ThreadListItemDelete","Delete","ThreadListItemDeleteProps","DeleteProps","ThreadListItemArchive","Archive","ThreadListItemArchiveProps","ArchiveProps","ThreadListItemUnarchive","Unarchive","ThreadListItemUnarchiveProps","UnarchiveProps"],"sources":["../../src/primitives/threadListItem.ts"],"sourcesContent":["export {\n ThreadListItemRoot as Root,\n type ThreadListItemRootProps as RootProps,\n} from \"./threadListItem/ThreadListItemRoot\";\nexport { ThreadListItemPrimitiveTitle as Title } from \"@assistant-ui/core/react\";\nexport {\n ThreadListItemTrigger as Trigger,\n type ThreadListItemTriggerProps as TriggerProps,\n} from \"./threadListItem/ThreadListItemTrigger\";\nexport {\n ThreadListItemDelete as Delete,\n type ThreadListItemDeleteProps as DeleteProps,\n} from \"./threadListItem/ThreadListItemDelete\";\nexport {\n ThreadListItemArchive as Archive,\n type ThreadListItemArchiveProps as ArchiveProps,\n} from \"./threadListItem/ThreadListItemArchive\";\nexport {\n ThreadListItemUnarchive as Unarchive,\n type ThreadListItemUnarchiveProps as UnarchiveProps,\n} from \"./threadListItem/ThreadListItemUnarchive\";\n"],"mappings":""}
1
+ {"version":3,"file":"threadListItem.js","names":["ThreadListItemRoot","Root","ThreadListItemRootProps","RootProps","ThreadListItemTitle","Title","ThreadListItemTitleProps","TitleProps","ThreadListItemTrigger","Trigger","ThreadListItemTriggerProps","TriggerProps","ThreadListItemDelete","Delete","ThreadListItemDeleteProps","DeleteProps","ThreadListItemArchive","Archive","ThreadListItemArchiveProps","ArchiveProps","ThreadListItemUnarchive","Unarchive","ThreadListItemUnarchiveProps","UnarchiveProps"],"sources":["../../src/primitives/threadListItem.ts"],"sourcesContent":["export {\n ThreadListItemRoot as Root,\n type ThreadListItemRootProps as RootProps,\n} from \"./threadListItem/ThreadListItemRoot\";\nexport {\n ThreadListItemTitle as Title,\n type ThreadListItemTitleProps as TitleProps,\n} from \"./threadListItem/ThreadListItemTitle\";\nexport {\n ThreadListItemTrigger as Trigger,\n type ThreadListItemTriggerProps as TriggerProps,\n} from \"./threadListItem/ThreadListItemTrigger\";\nexport {\n ThreadListItemDelete as Delete,\n type ThreadListItemDeleteProps as DeleteProps,\n} from \"./threadListItem/ThreadListItemDelete\";\nexport {\n ThreadListItemArchive as Archive,\n type ThreadListItemArchiveProps as ArchiveProps,\n} from \"./threadListItem/ThreadListItemArchive\";\nexport {\n ThreadListItemUnarchive as Unarchive,\n type ThreadListItemUnarchiveProps as UnarchiveProps,\n} from \"./threadListItem/ThreadListItemUnarchive\";\n"],"mappings":""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@assistant-ui/react-native",
3
- "version": "0.1.46",
3
+ "version": "0.1.47",
4
4
  "description": "React Native bindings for assistant-ui",
5
5
  "keywords": [
6
6
  "assistant",
@@ -31,11 +31,11 @@
31
31
  ],
32
32
  "sideEffects": false,
33
33
  "dependencies": {
34
- "@assistant-ui/core": "^0.3.24",
35
- "@assistant-ui/store": "^0.3.17",
36
- "@assistant-ui/tap": "^0.9.21",
37
- "assistant-cloud": "^0.2.5",
38
- "assistant-stream": "^0.3.48"
34
+ "@assistant-ui/core": "^0.3.25",
35
+ "@assistant-ui/store": "^0.3.18",
36
+ "@assistant-ui/tap": "^0.9.22",
37
+ "assistant-cloud": "^0.2.6",
38
+ "assistant-stream": "^0.3.49"
39
39
  },
40
40
  "peerDependencies": {
41
41
  "@types/react": "*",
@@ -53,7 +53,7 @@
53
53
  "@babel/core": "^7.29.7",
54
54
  "@types/react": "^19.3.0",
55
55
  "@types/react-dom": "^19.3.0",
56
- "jsdom": "^30.0.1",
56
+ "jsdom": "^30.1.2",
57
57
  "react": "^19.3.0",
58
58
  "react-dom": "^19.3.0",
59
59
  "react-native": "^0.87.1",
package/src/index.ts CHANGED
@@ -160,9 +160,13 @@ export {
160
160
  useExternalStoreRuntime,
161
161
  useExternalStoreSharedOptions,
162
162
  useExternalMessageConverter,
163
+ /** @deprecated Experimental since 2025-01-26. Not scheduled for removal; the API may change in any release. */
163
164
  convertExternalMessages as unstable_convertExternalMessages,
165
+ /** @deprecated Experimental since 2026-09-15. Not scheduled for removal; the API may change in any release. */
164
166
  createExternalMessageConversionCache as unstable_createExternalMessageConversionCache,
167
+ /** @deprecated Experimental since 2025-02-02. Not scheduled for removal; the API may change in any release. */
165
168
  createMessageConverter as unstable_createMessageConverter,
169
+ /** @deprecated Experimental since 2026-09-15. Not scheduled for removal; the API may change in any release. */
166
170
  type ExternalMessageConversionCache as Unstable_ExternalMessageConversionCache,
167
171
  type JoinStrategy,
168
172
  } from "@assistant-ui/core/react";
@@ -1,5 +1,6 @@
1
1
  import { act, type ReactNode } from "react";
2
2
  import { createRoot, type Root } from "react-dom/client";
3
+ import { Text } from "react-native";
3
4
  import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
4
5
  import { ActionBarCopy } from "./ActionBarCopy";
5
6
  import { ActionBarEdit } from "./ActionBarEdit";
@@ -222,6 +223,50 @@ describe("ActionBar", () => {
222
223
  return container.querySelector('[data-testid="t"]') as HTMLElement;
223
224
  };
224
225
 
226
+ const assertRenderState = async <TState extends object>(
227
+ render: (children: (state: TState) => ReactNode) => ReactNode,
228
+ expectedState: TState,
229
+ ) => {
230
+ let renderState: unknown;
231
+ await mount(
232
+ render((state) => {
233
+ renderState = state;
234
+ return <Text>label</Text>;
235
+ }),
236
+ );
237
+
238
+ expect(renderState).toMatchObject(expectedState);
239
+ };
240
+
241
+ it("ActionBarCopy passes Pressable state alongside isCopied", async () => {
242
+ await assertRenderState(
243
+ (children) => <ActionBarCopy testID="t">{children}</ActionBarCopy>,
244
+ { pressed: false, disabled: false, isCopied: false },
245
+ );
246
+ });
247
+
248
+ it("ActionBarFeedbackPositive passes Pressable state alongside isSubmitted", async () => {
249
+ await assertRenderState(
250
+ (children) => (
251
+ <ActionBarFeedbackPositive testID="t">
252
+ {children}
253
+ </ActionBarFeedbackPositive>
254
+ ),
255
+ { pressed: false, disabled: false, isSubmitted: false },
256
+ );
257
+ });
258
+
259
+ it("ActionBarFeedbackNegative passes Pressable state alongside isSubmitted", async () => {
260
+ await assertRenderState(
261
+ (children) => (
262
+ <ActionBarFeedbackNegative testID="t">
263
+ {children}
264
+ </ActionBarFeedbackNegative>
265
+ ),
266
+ { pressed: false, disabled: false, isSubmitted: false },
267
+ );
268
+ });
269
+
225
270
  for (const actionBar of actionBars) {
226
271
  describe(actionBar.name, () => {
227
272
  it("passes the effective disabled state to render children", async () => {
@@ -1,5 +1,9 @@
1
1
  import type { ReactNode } from "react";
2
- import { Pressable, type PressableProps } from "react-native";
2
+ import {
3
+ Pressable,
4
+ type PressableProps,
5
+ type PressableStateCallbackType,
6
+ } from "react-native";
3
7
  import {
4
8
  useActionBarCopy,
5
9
  type UseActionBarCopyOptions,
@@ -9,7 +13,12 @@ export type ActionBarCopyProps = Omit<PressableProps, "onPress" | "children"> &
9
13
  UseActionBarCopyOptions & {
10
14
  children:
11
15
  | ReactNode
12
- | ((props: { isCopied: boolean; disabled: boolean }) => ReactNode);
16
+ | ((
17
+ props: PressableStateCallbackType & {
18
+ isCopied: boolean;
19
+ disabled: boolean;
20
+ },
21
+ ) => ReactNode);
13
22
  };
14
23
 
15
24
  export const ActionBarCopy = ({
@@ -33,7 +42,7 @@ export const ActionBarCopy = ({
33
42
  {...pressableProps}
34
43
  >
35
44
  {typeof children === "function"
36
- ? children({ isCopied, disabled: isDisabled })
45
+ ? (state) => children({ ...state, isCopied, disabled: isDisabled })
37
46
  : children}
38
47
  </Pressable>
39
48
  );
@@ -1,5 +1,10 @@
1
1
  import type { ReactNode } from "react";
2
- import { Platform, Pressable, type PressableProps } from "react-native";
2
+ import {
3
+ Platform,
4
+ Pressable,
5
+ type PressableProps,
6
+ type PressableStateCallbackType,
7
+ } from "react-native";
3
8
  import { useActionBarFeedbackNegative } from "@assistant-ui/core/react";
4
9
 
5
10
  export type ActionBarFeedbackNegativeProps = Omit<
@@ -8,7 +13,12 @@ export type ActionBarFeedbackNegativeProps = Omit<
8
13
  > & {
9
14
  children:
10
15
  | ReactNode
11
- | ((props: { isSubmitted: boolean; disabled: boolean }) => ReactNode);
16
+ | ((
17
+ props: PressableStateCallbackType & {
18
+ isSubmitted: boolean;
19
+ disabled: boolean;
20
+ },
21
+ ) => ReactNode);
12
22
  };
13
23
 
14
24
  export const ActionBarFeedbackNegative = ({
@@ -30,7 +40,7 @@ export const ActionBarFeedbackNegative = ({
30
40
  {...pressableProps}
31
41
  >
32
42
  {typeof children === "function"
33
- ? children({ isSubmitted, disabled })
43
+ ? (state) => children({ ...state, isSubmitted, disabled })
34
44
  : children}
35
45
  </Pressable>
36
46
  );
@@ -1,5 +1,10 @@
1
1
  import type { ReactNode } from "react";
2
- import { Platform, Pressable, type PressableProps } from "react-native";
2
+ import {
3
+ Platform,
4
+ Pressable,
5
+ type PressableProps,
6
+ type PressableStateCallbackType,
7
+ } from "react-native";
3
8
  import { useActionBarFeedbackPositive } from "@assistant-ui/core/react";
4
9
 
5
10
  export type ActionBarFeedbackPositiveProps = Omit<
@@ -8,7 +13,12 @@ export type ActionBarFeedbackPositiveProps = Omit<
8
13
  > & {
9
14
  children:
10
15
  | ReactNode
11
- | ((props: { isSubmitted: boolean; disabled: boolean }) => ReactNode);
16
+ | ((
17
+ props: PressableStateCallbackType & {
18
+ isSubmitted: boolean;
19
+ disabled: boolean;
20
+ },
21
+ ) => ReactNode);
12
22
  };
13
23
 
14
24
  export const ActionBarFeedbackPositive = ({
@@ -30,7 +40,7 @@ export const ActionBarFeedbackPositive = ({
30
40
  {...pressableProps}
31
41
  >
32
42
  {typeof children === "function"
33
- ? children({ isSubmitted, disabled })
43
+ ? (state) => children({ ...state, isSubmitted, disabled })
34
44
  : children}
35
45
  </Pressable>
36
46
  );
@@ -8,7 +8,12 @@ const h = vi.hoisted(() => ({
8
8
  sendSpy: vi.fn<() => void>(),
9
9
  flushTapSyncSpy: vi.fn(<T,>(fn: () => T) => fn()),
10
10
  composerState: { text: "" },
11
- threadState: { isRunning: false, queue: false, voice: false },
11
+ threadState: {
12
+ isRunning: false,
13
+ queue: false,
14
+ voice: false,
15
+ isDisabled: false,
16
+ },
12
17
  platform: { os: "web" as "web" | "ios" | "android" },
13
18
  }));
14
19
 
@@ -28,12 +33,20 @@ vi.mock("@assistant-ui/store", () => {
28
33
  return {
29
34
  useAui: () => aui,
30
35
  useAuiState: <T,>(
31
- selector: (s: { composer: typeof h.composerState }) => T,
32
- ) => selector({ composer: h.composerState }),
36
+ selector: (s: {
37
+ composer: typeof h.composerState;
38
+ thread: { isDisabled: boolean };
39
+ }) => T,
40
+ ) =>
41
+ selector({
42
+ composer: h.composerState,
43
+ thread: { isDisabled: h.threadState.isDisabled },
44
+ }),
33
45
  };
34
46
  });
35
47
 
36
- vi.mock("@assistant-ui/tap", () => ({
48
+ vi.mock("@assistant-ui/tap", async (importOriginal) => ({
49
+ ...(await importOriginal<typeof import("@assistant-ui/tap")>()),
37
50
  flushTapSync: h.flushTapSyncSpy,
38
51
  }));
39
52
 
@@ -111,6 +124,7 @@ describe("ComposerInput", () => {
111
124
  h.threadState.isRunning = false;
112
125
  h.threadState.queue = false;
113
126
  h.threadState.voice = false;
127
+ h.threadState.isDisabled = false;
114
128
  h.platform.os = "web";
115
129
 
116
130
  container = document.createElement("div");
@@ -421,4 +435,50 @@ describe("ComposerInput", () => {
421
435
  expect(onKeyPress).toHaveBeenCalledTimes(1);
422
436
  });
423
437
  });
438
+
439
+ describe("disabled thread", () => {
440
+ beforeEach(() => {
441
+ h.threadState.isDisabled = true;
442
+ });
443
+
444
+ it("makes the input non-editable", async () => {
445
+ const input = await mount();
446
+ expect(input.disabled || input.readOnly).toBe(true);
447
+ });
448
+
449
+ it("does not let editable props override the disabled thread", async () => {
450
+ const input = await mount({ editable: true, readOnly: false });
451
+ expect(input.readOnly).toBe(true);
452
+ });
453
+
454
+ it("ignores text changes", async () => {
455
+ const input = await mount();
456
+ await act(async () => fireInput(input, "hello"));
457
+ expect(h.setText).not.toHaveBeenCalled();
458
+ });
459
+
460
+ it("does not submit on Enter", async () => {
461
+ const input = await mount();
462
+ await act(async () => fireKeyDown(input, { key: "Enter" }));
463
+ expect(h.sendSpy).not.toHaveBeenCalled();
464
+ });
465
+
466
+ it("forwards caller key handlers while blocking submission", async () => {
467
+ const onKeyPress = vi.fn();
468
+ const input = await mount({ onKeyPress });
469
+
470
+ await act(async () => {
471
+ fireKeyDown(input, { key: "Escape" });
472
+ fireKeyDown(input, { key: "Enter" });
473
+ });
474
+
475
+ expect(onKeyPress).toHaveBeenCalledTimes(2);
476
+ expect(h.sendSpy).not.toHaveBeenCalled();
477
+ });
478
+ });
479
+
480
+ it("preserves a caller-provided non-editable setting", async () => {
481
+ const input = await mount({ editable: false });
482
+ expect(input.readOnly).toBe(true);
483
+ });
424
484
  });
@@ -1,5 +1,6 @@
1
1
  import { useCallback, useEffect, useRef } from "react";
2
2
  import { Platform, TextInput, type TextInputProps } from "react-native";
3
+ import { composerInputDisabled } from "@assistant-ui/core/store/internal";
3
4
  import { useAui, useAuiState } from "@assistant-ui/store";
4
5
  import { flushTapSync } from "@assistant-ui/tap";
5
6
 
@@ -59,14 +60,19 @@ export const ComposerInput = ({
59
60
  onKeyPress: onKeyPressProp,
60
61
  numberOfLines,
61
62
  style,
63
+ editable,
64
+ readOnly,
62
65
  ...props
63
66
  }: ComposerInputProps) => {
64
67
  const aui = useAui();
65
68
  const text = useAuiState((s) => s.composer.text);
69
+ const isInputDisabled = useAuiState(composerInputDisabled);
66
70
  const inputRef = useRef<TextInputInstance>(null);
67
71
 
68
72
  const onChangeText = useCallback(
69
73
  (value: string) => {
74
+ if (isInputDisabled) return;
75
+
70
76
  if (Platform.OS === "web") {
71
77
  // Keep the controlled value in sync mid-IME so react-dom does not reset the textarea to a stale value
72
78
  flushTapSync(() => {
@@ -76,7 +82,7 @@ export const ComposerInput = ({
76
82
  }
77
83
  aui.composer.setText(value);
78
84
  },
79
- [aui],
85
+ [aui, isInputDisabled],
80
86
  );
81
87
 
82
88
  // Auto-resize textarea on web when text changes
@@ -89,6 +95,7 @@ export const ComposerInput = ({
89
95
  (e: TextInputKeyPressEvent) => {
90
96
  onKeyPressProp?.(e);
91
97
  if (e.isDefaultPrevented()) return;
98
+ if (isInputDisabled) return;
92
99
 
93
100
  if (Platform.OS !== "web") return;
94
101
  if (submitMode !== "enter") return;
@@ -113,9 +120,11 @@ export const ComposerInput = ({
113
120
  aui.composer.send();
114
121
  }
115
122
  },
116
- [aui, submitMode, onKeyPressProp],
123
+ [aui, isInputDisabled, submitMode, onKeyPressProp],
117
124
  );
118
125
 
126
+ const isReadOnly = isInputDisabled || editable === false || readOnly === true;
127
+
119
128
  return (
120
129
  <TextInput
121
130
  ref={inputRef}
@@ -123,6 +132,8 @@ export const ComposerInput = ({
123
132
  onChangeText={onChangeText}
124
133
  onKeyPress={onKeyPress}
125
134
  numberOfLines={numberOfLines ?? (Platform.OS === "web" ? 1 : undefined)}
135
+ editable={editable}
136
+ readOnly={isReadOnly}
126
137
  style={style}
127
138
  {...props}
128
139
  />
@@ -14,6 +14,41 @@ import { MessageContent } from "./MessageContent";
14
14
  (globalThis as Record<string, unknown>).IS_REACT_ACT_ENVIRONMENT = true;
15
15
 
16
16
  describe("MessageContent with a runtime", () => {
17
+ it("renders a default image after a text part", async () => {
18
+ const image = "data:image/png;base64,iVBORw0KGgo=";
19
+ const App = () => {
20
+ const runtime = useExternalStoreRuntime({
21
+ messages: [
22
+ {
23
+ role: "assistant",
24
+ content: [
25
+ { type: "text", text: "lead" },
26
+ { type: "image", image },
27
+ ],
28
+ },
29
+ ] satisfies ThreadMessageLike[],
30
+ convertMessage: (value) => value,
31
+ onNew: async () => {},
32
+ });
33
+ return (
34
+ <AssistantRuntimeProvider runtime={runtime}>
35
+ <MessageByIndexProvider index={0}>
36
+ <MessageContent />
37
+ </MessageByIndexProvider>
38
+ </AssistantRuntimeProvider>
39
+ );
40
+ };
41
+ const container = document.createElement("div");
42
+ const root = createRoot(container);
43
+ try {
44
+ await act(async () => root.render(<App />));
45
+ expect(container.textContent).toContain("lead");
46
+ expect(container.querySelector("img")?.getAttribute("src")).toBe(image);
47
+ } finally {
48
+ await act(async () => root.unmount());
49
+ }
50
+ });
51
+
17
52
  it.each(["tool-call", "data"] as const)(
18
53
  "renders derived status for registered %s UIs",
19
54
  async (type) => {