@assistant-ui/vue 0.0.0 → 0.0.2

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 (231) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +90 -2
  3. package/dist/AuiIf.d.ts +27 -0
  4. package/dist/AuiIf.d.ts.map +1 -0
  5. package/dist/AuiIf.js +30 -0
  6. package/dist/AuiIf.js.map +1 -0
  7. package/dist/AuiProvider.d.ts +41 -0
  8. package/dist/AuiProvider.d.ts.map +1 -0
  9. package/dist/AuiProvider.js +61 -0
  10. package/dist/AuiProvider.js.map +1 -0
  11. package/dist/context.d.ts +10 -0
  12. package/dist/context.d.ts.map +1 -0
  13. package/dist/context.js +17 -0
  14. package/dist/context.js.map +1 -0
  15. package/dist/index.d.ts +34 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +35 -0
  18. package/dist/primitives/AttachmentByIndexProvider.d.ts +30 -0
  19. package/dist/primitives/AttachmentByIndexProvider.d.ts.map +1 -0
  20. package/dist/primitives/AttachmentByIndexProvider.js +63 -0
  21. package/dist/primitives/AttachmentByIndexProvider.js.map +1 -0
  22. package/dist/primitives/ChainOfThoughtPrimitiveAccordionTrigger.d.ts +11 -0
  23. package/dist/primitives/ChainOfThoughtPrimitiveAccordionTrigger.d.ts.map +1 -0
  24. package/dist/primitives/ChainOfThoughtPrimitiveAccordionTrigger.js +31 -0
  25. package/dist/primitives/ChainOfThoughtPrimitiveAccordionTrigger.js.map +1 -0
  26. package/dist/primitives/ChainOfThoughtPrimitiveParts.d.ts +19 -0
  27. package/dist/primitives/ChainOfThoughtPrimitiveParts.d.ts.map +1 -0
  28. package/dist/primitives/ChainOfThoughtPrimitiveParts.js +85 -0
  29. package/dist/primitives/ChainOfThoughtPrimitiveParts.js.map +1 -0
  30. package/dist/primitives/ComposerPrimitiveCancel.d.ts +12 -0
  31. package/dist/primitives/ComposerPrimitiveCancel.d.ts.map +1 -0
  32. package/dist/primitives/ComposerPrimitiveCancel.js +33 -0
  33. package/dist/primitives/ComposerPrimitiveCancel.js.map +1 -0
  34. package/dist/primitives/ComposerPrimitiveInput.d.ts +26 -0
  35. package/dist/primitives/ComposerPrimitiveInput.d.ts.map +1 -0
  36. package/dist/primitives/ComposerPrimitiveInput.js +57 -0
  37. package/dist/primitives/ComposerPrimitiveInput.js.map +1 -0
  38. package/dist/primitives/ComposerPrimitiveSend.d.ts +13 -0
  39. package/dist/primitives/ComposerPrimitiveSend.d.ts.map +1 -0
  40. package/dist/primitives/ComposerPrimitiveSend.js +31 -0
  41. package/dist/primitives/ComposerPrimitiveSend.js.map +1 -0
  42. package/dist/primitives/MessageByIdProvider.d.ts +23 -0
  43. package/dist/primitives/MessageByIdProvider.d.ts.map +1 -0
  44. package/dist/primitives/MessageByIdProvider.js +70 -0
  45. package/dist/primitives/MessageByIdProvider.js.map +1 -0
  46. package/dist/primitives/MessagePrimitiveParts.d.ts +51 -0
  47. package/dist/primitives/MessagePrimitiveParts.d.ts.map +1 -0
  48. package/dist/primitives/MessagePrimitiveParts.js +93 -0
  49. package/dist/primitives/MessagePrimitiveParts.js.map +1 -0
  50. package/dist/primitives/PartByIndexProvider.d.ts +21 -0
  51. package/dist/primitives/PartByIndexProvider.d.ts.map +1 -0
  52. package/dist/primitives/PartByIndexProvider.js +50 -0
  53. package/dist/primitives/PartByIndexProvider.js.map +1 -0
  54. package/dist/primitives/ThreadListItemPrimitiveRoot.d.ts +7 -0
  55. package/dist/primitives/ThreadListItemPrimitiveRoot.d.ts.map +1 -0
  56. package/dist/primitives/ThreadListItemPrimitiveRoot.js +36 -0
  57. package/dist/primitives/ThreadListItemPrimitiveRoot.js.map +1 -0
  58. package/dist/primitives/ThreadListItemPrimitiveTrigger.d.ts +14 -0
  59. package/dist/primitives/ThreadListItemPrimitiveTrigger.d.ts.map +1 -0
  60. package/dist/primitives/ThreadListItemPrimitiveTrigger.js +58 -0
  61. package/dist/primitives/ThreadListItemPrimitiveTrigger.js.map +1 -0
  62. package/dist/primitives/ThreadListPrimitiveRoot.d.ts +7 -0
  63. package/dist/primitives/ThreadListPrimitiveRoot.d.ts.map +1 -0
  64. package/dist/primitives/ThreadListPrimitiveRoot.js +16 -0
  65. package/dist/primitives/ThreadListPrimitiveRoot.js.map +1 -0
  66. package/dist/primitives/ThreadPrimitiveMessages.d.ts +21 -0
  67. package/dist/primitives/ThreadPrimitiveMessages.d.ts.map +1 -0
  68. package/dist/primitives/ThreadPrimitiveMessages.js +35 -0
  69. package/dist/primitives/ThreadPrimitiveMessages.js.map +1 -0
  70. package/dist/primitives/ThreadPrimitiveScrollToBottom.d.ts +25 -0
  71. package/dist/primitives/ThreadPrimitiveScrollToBottom.d.ts.map +1 -0
  72. package/dist/primitives/ThreadPrimitiveScrollToBottom.js +43 -0
  73. package/dist/primitives/ThreadPrimitiveScrollToBottom.js.map +1 -0
  74. package/dist/primitives/ThreadPrimitiveViewport.d.ts +57 -0
  75. package/dist/primitives/ThreadPrimitiveViewport.d.ts.map +1 -0
  76. package/dist/primitives/ThreadPrimitiveViewport.js +99 -0
  77. package/dist/primitives/ThreadPrimitiveViewport.js.map +1 -0
  78. package/dist/primitives/ThreadPrimitiveViewportFooter.d.ts +13 -0
  79. package/dist/primitives/ThreadPrimitiveViewportFooter.d.ts.map +1 -0
  80. package/dist/primitives/ThreadPrimitiveViewportFooter.js +46 -0
  81. package/dist/primitives/ThreadPrimitiveViewportFooter.js.map +1 -0
  82. package/dist/primitives/actionBar.d.ts +41 -0
  83. package/dist/primitives/actionBar.d.ts.map +1 -0
  84. package/dist/primitives/actionBar.js +110 -0
  85. package/dist/primitives/actionBar.js.map +1 -0
  86. package/dist/primitives/attachment.d.ts +27 -0
  87. package/dist/primitives/attachment.d.ts.map +1 -0
  88. package/dist/primitives/attachment.js +63 -0
  89. package/dist/primitives/attachment.js.map +1 -0
  90. package/dist/primitives/attrDisabled.d.ts +2 -0
  91. package/dist/primitives/attrDisabled.d.ts.map +1 -0
  92. package/dist/primitives/attrDisabled.js +6 -0
  93. package/dist/primitives/attrDisabled.js.map +1 -0
  94. package/dist/primitives/branchPicker.d.ts +18 -0
  95. package/dist/primitives/branchPicker.d.ts.map +1 -0
  96. package/dist/primitives/branchPicker.js +48 -0
  97. package/dist/primitives/branchPicker.js.map +1 -0
  98. package/dist/primitives/composerAttachments.d.ts +57 -0
  99. package/dist/primitives/composerAttachments.d.ts.map +1 -0
  100. package/dist/primitives/composerAttachments.js +132 -0
  101. package/dist/primitives/composerAttachments.js.map +1 -0
  102. package/dist/primitives/error.d.ts +15 -0
  103. package/dist/primitives/error.d.ts.map +1 -0
  104. package/dist/primitives/error.js +29 -0
  105. package/dist/primitives/error.js.map +1 -0
  106. package/dist/primitives/lastValidCache.d.ts +6 -0
  107. package/dist/primitives/lastValidCache.d.ts.map +1 -0
  108. package/dist/primitives/lastValidCache.js +9 -0
  109. package/dist/primitives/lastValidCache.js.map +1 -0
  110. package/dist/primitives/message.d.ts +12 -0
  111. package/dist/primitives/message.d.ts.map +1 -0
  112. package/dist/primitives/message.js +44 -0
  113. package/dist/primitives/message.js.map +1 -0
  114. package/dist/primitives/messageAttachments.d.ts +12 -0
  115. package/dist/primitives/messageAttachments.d.ts.map +1 -0
  116. package/dist/primitives/messageAttachments.js +27 -0
  117. package/dist/primitives/messageAttachments.js.map +1 -0
  118. package/dist/primitives/stableKeys.d.ts +5 -0
  119. package/dist/primitives/stableKeys.d.ts.map +1 -0
  120. package/dist/primitives/stableKeys.js +14 -0
  121. package/dist/primitives/stableKeys.js.map +1 -0
  122. package/dist/primitives/suggestions.d.ts +66 -0
  123. package/dist/primitives/suggestions.d.ts.map +1 -0
  124. package/dist/primitives/suggestions.js +137 -0
  125. package/dist/primitives/suggestions.js.map +1 -0
  126. package/dist/primitives/thread.d.ts +11 -0
  127. package/dist/primitives/thread.d.ts.map +1 -0
  128. package/dist/primitives/thread.js +37 -0
  129. package/dist/primitives/thread.js.map +1 -0
  130. package/dist/primitives/threadList.d.ts +82 -0
  131. package/dist/primitives/threadList.d.ts.map +1 -0
  132. package/dist/primitives/threadList.js +128 -0
  133. package/dist/primitives/threadList.js.map +1 -0
  134. package/dist/primitives/threadListFocusGroup.d.ts +14 -0
  135. package/dist/primitives/threadListFocusGroup.d.ts.map +1 -0
  136. package/dist/primitives/threadListFocusGroup.js +32 -0
  137. package/dist/primitives/threadListFocusGroup.js.map +1 -0
  138. package/dist/primitives/threadListStructural.d.ts +29 -0
  139. package/dist/primitives/threadListStructural.d.ts.map +1 -0
  140. package/dist/primitives/threadListStructural.js +55 -0
  141. package/dist/primitives/threadListStructural.js.map +1 -0
  142. package/dist/primitives/useComposerSendState.d.ts +6 -0
  143. package/dist/primitives/useComposerSendState.d.ts.map +1 -0
  144. package/dist/primitives/useComposerSendState.js +15 -0
  145. package/dist/primitives/useComposerSendState.js.map +1 -0
  146. package/dist/primitives/viewportContext.d.ts +12 -0
  147. package/dist/primitives/viewportContext.d.ts.map +1 -0
  148. package/dist/primitives/viewportContext.js +6 -0
  149. package/dist/primitives/viewportContext.js.map +1 -0
  150. package/dist/useAui.d.ts +15 -0
  151. package/dist/useAui.d.ts.map +1 -0
  152. package/dist/useAui.js +21 -0
  153. package/dist/useAui.js.map +1 -0
  154. package/dist/useAuiEvent.d.ts +17 -0
  155. package/dist/useAuiEvent.d.ts.map +1 -0
  156. package/dist/useAuiEvent.js +52 -0
  157. package/dist/useAuiEvent.js.map +1 -0
  158. package/dist/useAuiState.d.ts +23 -0
  159. package/dist/useAuiState.d.ts.map +1 -0
  160. package/dist/useAuiState.js +42 -0
  161. package/dist/useAuiState.js.map +1 -0
  162. package/dist/useScrollLock.d.ts +3 -0
  163. package/dist/useScrollLock.d.ts.map +1 -0
  164. package/dist/useScrollLock.js +53 -0
  165. package/dist/useScrollLock.js.map +1 -0
  166. package/package.json +57 -6
  167. package/src/AuiIf.ts +34 -0
  168. package/src/AuiProvider.ts +90 -0
  169. package/src/__tests__/AuiIf.test.ts +54 -0
  170. package/src/__tests__/AuiProvider.test.ts +266 -0
  171. package/src/__tests__/byindex-shrink-race.test.ts +411 -0
  172. package/src/__tests__/dist-graph.test.ts +49 -0
  173. package/src/__tests__/fixtures.ts +51 -0
  174. package/src/__tests__/primitives-actionbar.test.ts +469 -0
  175. package/src/__tests__/primitives-attachment.test.ts +493 -0
  176. package/src/__tests__/primitives-content.test.ts +829 -0
  177. package/src/__tests__/primitives-keyed-items.test.ts +270 -0
  178. package/src/__tests__/primitives-keyed-messages.test.ts +264 -0
  179. package/src/__tests__/primitives-structural.test.ts +573 -0
  180. package/src/__tests__/primitives-suggestions.test.ts +374 -0
  181. package/src/__tests__/primitives-threadlist.test.ts +443 -0
  182. package/src/__tests__/primitives-tool-ui.test.ts +579 -0
  183. package/src/__tests__/primitives.test.ts +408 -0
  184. package/src/__tests__/useAuiEvent.test.ts +159 -0
  185. package/src/__tests__/useAuiState.test.ts +124 -0
  186. package/src/context.ts +31 -0
  187. package/src/index.ts +87 -0
  188. package/src/primitives/AttachmentByIndexProvider.ts +88 -0
  189. package/src/primitives/ChainOfThoughtPrimitiveAccordionTrigger.test.ts +105 -0
  190. package/src/primitives/ChainOfThoughtPrimitiveAccordionTrigger.ts +38 -0
  191. package/src/primitives/ChainOfThoughtPrimitiveParts.test.ts +254 -0
  192. package/src/primitives/ChainOfThoughtPrimitiveParts.ts +112 -0
  193. package/src/primitives/ComposerPrimitiveCancel.ts +41 -0
  194. package/src/primitives/ComposerPrimitiveInput.ts +70 -0
  195. package/src/primitives/ComposerPrimitiveSend.ts +39 -0
  196. package/src/primitives/MessageByIdProvider.ts +89 -0
  197. package/src/primitives/MessagePrimitiveParts.tool-interaction.test.ts +88 -0
  198. package/src/primitives/MessagePrimitiveParts.ts +167 -0
  199. package/src/primitives/PartByIndexProvider.ts +62 -0
  200. package/src/primitives/ThreadListItemPrimitiveRoot.ts +57 -0
  201. package/src/primitives/ThreadListItemPrimitiveTrigger.ts +74 -0
  202. package/src/primitives/ThreadListKeyboardNav.test.ts +298 -0
  203. package/src/primitives/ThreadListPrimitiveRoot.ts +18 -0
  204. package/src/primitives/ThreadPrimitiveMessages.ts +38 -0
  205. package/src/primitives/ThreadPrimitiveScrollToBottom.ts +65 -0
  206. package/src/primitives/ThreadPrimitiveViewport.ts +120 -0
  207. package/src/primitives/ThreadPrimitiveViewportFooter.test.ts +400 -0
  208. package/src/primitives/ThreadPrimitiveViewportFooter.ts +60 -0
  209. package/src/primitives/actionBar.ts +159 -0
  210. package/src/primitives/attachment.ts +76 -0
  211. package/src/primitives/attrDisabled.ts +6 -0
  212. package/src/primitives/branchPicker.ts +77 -0
  213. package/src/primitives/composerAttachments.ts +181 -0
  214. package/src/primitives/error.ts +36 -0
  215. package/src/primitives/lastValidCache.ts +12 -0
  216. package/src/primitives/message.ts +54 -0
  217. package/src/primitives/messageAttachments.ts +32 -0
  218. package/src/primitives/stableKeys.test.ts +19 -0
  219. package/src/primitives/stableKeys.ts +21 -0
  220. package/src/primitives/suggestions.ts +179 -0
  221. package/src/primitives/thread.ts +46 -0
  222. package/src/primitives/threadList.ts +163 -0
  223. package/src/primitives/threadListFocusGroup.ts +56 -0
  224. package/src/primitives/threadListStructural.ts +86 -0
  225. package/src/primitives/useComposerSendState.ts +13 -0
  226. package/src/primitives/viewportContext.ts +16 -0
  227. package/src/useAui.ts +18 -0
  228. package/src/useAuiEvent.ts +64 -0
  229. package/src/useAuiState.ts +55 -0
  230. package/src/useScrollLock.test.ts +207 -0
  231. package/src/useScrollLock.ts +79 -0
@@ -0,0 +1,53 @@
1
+ import { onScopeDispose } from "vue";
2
+ //#region src/useScrollLock.ts
3
+ const findScrollableAncestor = (element) => {
4
+ let current = element;
5
+ while (current) {
6
+ const { overflowY } = getComputedStyle(current);
7
+ if (overflowY === "scroll" || overflowY === "auto") return current;
8
+ current = current.parentElement;
9
+ }
10
+ return null;
11
+ };
12
+ const useScrollLock = (target, animationDuration) => {
13
+ let cleanup = null;
14
+ onScopeDispose(() => cleanup?.());
15
+ return () => {
16
+ cleanup?.();
17
+ const scrollContainer = findScrollableAncestor(target.value);
18
+ if (!scrollContainer) {
19
+ cleanup = null;
20
+ return;
21
+ }
22
+ const scrollPosition = scrollContainer.scrollTop;
23
+ const scrollbarWidth = scrollContainer.style.scrollbarWidth;
24
+ const computed = getComputedStyle(scrollContainer);
25
+ const paddingSide = computed.direction === "rtl" ? "paddingLeft" : "paddingRight";
26
+ const previousPadding = scrollContainer.style[paddingSide];
27
+ const elementScrollbarSize = scrollContainer.offsetWidth - scrollContainer.clientWidth - parseFloat(computed.borderLeftWidth) - parseFloat(computed.borderRightWidth);
28
+ const ownerDocument = scrollContainer.ownerDocument;
29
+ const scrollbarSize = (scrollContainer === ownerDocument.documentElement || scrollContainer === ownerDocument.body) && elementScrollbarSize <= 0 ? (ownerDocument.defaultView?.innerWidth ?? 0) - ownerDocument.documentElement.clientWidth : elementScrollbarSize;
30
+ scrollContainer.style.scrollbarWidth = "none";
31
+ if (scrollbarSize > 0) scrollContainer.style[paddingSide] = `${parseFloat(computed[paddingSide]) + scrollbarSize}px`;
32
+ const restoreStyles = () => {
33
+ scrollContainer.style.scrollbarWidth = scrollbarWidth;
34
+ scrollContainer.style[paddingSide] = previousPadding;
35
+ };
36
+ const resetPosition = () => scrollContainer.scrollTop = scrollPosition;
37
+ scrollContainer.addEventListener("scroll", resetPosition);
38
+ const timeoutId = setTimeout(() => {
39
+ scrollContainer.removeEventListener("scroll", resetPosition);
40
+ restoreStyles();
41
+ cleanup = null;
42
+ }, animationDuration);
43
+ cleanup = () => {
44
+ clearTimeout(timeoutId);
45
+ scrollContainer.removeEventListener("scroll", resetPosition);
46
+ restoreStyles();
47
+ };
48
+ };
49
+ };
50
+ //#endregion
51
+ export { useScrollLock };
52
+
53
+ //# sourceMappingURL=useScrollLock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useScrollLock.js","names":[],"sources":["../src/useScrollLock.ts"],"sourcesContent":["import { onScopeDispose, type Ref } from \"vue\";\n\nconst findScrollableAncestor = (element: HTMLElement | null | undefined) => {\n let current = element;\n while (current) {\n const { overflowY } = getComputedStyle(current);\n if (overflowY === \"scroll\" || overflowY === \"auto\") return current;\n current = current.parentElement;\n }\n return null;\n};\n\nexport const useScrollLock = (\n target: Ref<HTMLElement | null | undefined>,\n animationDuration: number,\n) => {\n let cleanup: (() => void) | null = null;\n\n onScopeDispose(() => cleanup?.());\n\n return () => {\n cleanup?.();\n\n const scrollContainer = findScrollableAncestor(target.value);\n if (!scrollContainer) {\n cleanup = null;\n return;\n }\n\n const scrollPosition = scrollContainer.scrollTop;\n const scrollbarWidth = scrollContainer.style.scrollbarWidth;\n const computed = getComputedStyle(scrollContainer);\n const paddingSide =\n computed.direction === \"rtl\" ? \"paddingLeft\" : \"paddingRight\";\n const previousPadding = scrollContainer.style[paddingSide];\n const elementScrollbarSize =\n scrollContainer.offsetWidth -\n scrollContainer.clientWidth -\n parseFloat(computed.borderLeftWidth) -\n parseFloat(computed.borderRightWidth);\n // Root offsetWidth excludes the viewport scrollbar, so use the viewport\n // width only when the element's own gutter is absent.\n const ownerDocument = scrollContainer.ownerDocument;\n const isRootScroller =\n scrollContainer === ownerDocument.documentElement ||\n scrollContainer === ownerDocument.body;\n const scrollbarSize =\n isRootScroller && elementScrollbarSize <= 0\n ? (ownerDocument.defaultView?.innerWidth ?? 0) -\n ownerDocument.documentElement.clientWidth\n : elementScrollbarSize;\n\n scrollContainer.style.scrollbarWidth = \"none\";\n if (scrollbarSize > 0) {\n scrollContainer.style[paddingSide] = `${\n parseFloat(computed[paddingSide]) + scrollbarSize\n }px`;\n }\n\n const restoreStyles = () => {\n scrollContainer.style.scrollbarWidth = scrollbarWidth;\n scrollContainer.style[paddingSide] = previousPadding;\n };\n const resetPosition = () => (scrollContainer.scrollTop = scrollPosition);\n scrollContainer.addEventListener(\"scroll\", resetPosition);\n\n const timeoutId = setTimeout(() => {\n scrollContainer.removeEventListener(\"scroll\", resetPosition);\n restoreStyles();\n cleanup = null;\n }, animationDuration);\n\n cleanup = () => {\n clearTimeout(timeoutId);\n scrollContainer.removeEventListener(\"scroll\", resetPosition);\n restoreStyles();\n };\n };\n};\n"],"mappings":";;AAEA,MAAM,0BAA0B,YAA4C;CAC1E,IAAI,UAAU;CACd,OAAO,SAAS;EACd,MAAM,EAAE,cAAc,iBAAiB,OAAO;EAC9C,IAAI,cAAc,YAAY,cAAc,QAAQ,OAAO;EAC3D,UAAU,QAAQ;CACpB;CACA,OAAO;AACT;AAEA,MAAa,iBACX,QACA,sBACG;CACH,IAAI,UAA+B;CAEnC,qBAAqB,UAAU,CAAC;CAEhC,aAAa;EACX,UAAU;EAEV,MAAM,kBAAkB,uBAAuB,OAAO,KAAK;EAC3D,IAAI,CAAC,iBAAiB;GACpB,UAAU;GACV;EACF;EAEA,MAAM,iBAAiB,gBAAgB;EACvC,MAAM,iBAAiB,gBAAgB,MAAM;EAC7C,MAAM,WAAW,iBAAiB,eAAe;EACjD,MAAM,cACJ,SAAS,cAAc,QAAQ,gBAAgB;EACjD,MAAM,kBAAkB,gBAAgB,MAAM;EAC9C,MAAM,uBACJ,gBAAgB,cAChB,gBAAgB,cAChB,WAAW,SAAS,eAAe,IACnC,WAAW,SAAS,gBAAgB;EAGtC,MAAM,gBAAgB,gBAAgB;EAItC,MAAM,iBAFJ,oBAAoB,cAAc,mBAClC,oBAAoB,cAAc,SAEhB,wBAAwB,KACrC,cAAc,aAAa,cAAc,KAC1C,cAAc,gBAAgB,cAC9B;EAEN,gBAAgB,MAAM,iBAAiB;EACvC,IAAI,gBAAgB,GAClB,gBAAgB,MAAM,eAAe,GACnC,WAAW,SAAS,YAAY,IAAI,cACrC;EAGH,MAAM,sBAAsB;GAC1B,gBAAgB,MAAM,iBAAiB;GACvC,gBAAgB,MAAM,eAAe;EACvC;EACA,MAAM,sBAAuB,gBAAgB,YAAY;EACzD,gBAAgB,iBAAiB,UAAU,aAAa;EAExD,MAAM,YAAY,iBAAiB;GACjC,gBAAgB,oBAAoB,UAAU,aAAa;GAC3D,cAAc;GACd,UAAU;EACZ,GAAG,iBAAiB;EAEpB,gBAAgB;GACd,aAAa,SAAS;GACtB,gBAAgB,oBAAoB,UAAU,aAAa;GAC3D,cAAc;EAChB;CACF;AACF"}
package/package.json CHANGED
@@ -1,16 +1,67 @@
1
1
  {
2
2
  "name": "@assistant-ui/vue",
3
- "version": "0.0.0",
4
- "description": "Vue bindings for assistant-ui. This version only reserves the name; the first release is 0.0.1.",
3
+ "version": "0.0.2",
4
+ "description": "Vue bindings for assistant-ui",
5
+ "keywords": [
6
+ "assistant",
7
+ "ai",
8
+ "chat",
9
+ "vue",
10
+ "nuxt"
11
+ ],
5
12
  "author": "AgentbaseAI Inc.",
6
13
  "license": "MIT",
14
+ "type": "module",
15
+ "exports": {
16
+ ".": {
17
+ "types": "./dist/index.d.ts",
18
+ "default": "./dist/index.js"
19
+ }
20
+ },
21
+ "main": "./dist/index.js",
22
+ "types": "./dist/index.d.ts",
23
+ "files": [
24
+ "dist",
25
+ "src",
26
+ "README.md"
27
+ ],
28
+ "sideEffects": false,
29
+ "dependencies": {
30
+ "@assistant-ui/core": "^0.3.25",
31
+ "@assistant-ui/store": "^0.3.18",
32
+ "@assistant-ui/tap": "^0.9.22"
33
+ },
34
+ "peerDependencies": {
35
+ "@types/react": "*",
36
+ "vue": "^3.5.0"
37
+ },
38
+ "devDependencies": {
39
+ "@assistant-ui/x-buildutils": "0.0.30",
40
+ "@types/node": "^26.6.4",
41
+ "@types/react": "^19.3.0",
42
+ "assistant-cloud": "0.2.6",
43
+ "jsdom": "^30.1.2",
44
+ "vitest": "^5.0.3",
45
+ "vue": "^3.5.43"
46
+ },
47
+ "publishConfig": {
48
+ "access": "public",
49
+ "provenance": true
50
+ },
7
51
  "homepage": "https://www.assistant-ui.com/",
8
52
  "repository": {
9
53
  "type": "git",
10
54
  "url": "git+https://github.com/assistant-ui/assistant-ui.git",
11
55
  "directory": "packages/vue"
12
56
  },
13
- "files": [
14
- "README.md"
15
- ]
16
- }
57
+ "bugs": {
58
+ "url": "https://github.com/assistant-ui/assistant-ui/issues"
59
+ },
60
+ "scripts": {
61
+ "build": "aui-build",
62
+ "test": "vitest run",
63
+ "test:coverage": "vitest run --coverage --coverage.reporter=text --coverage.reporter=html --coverage.reporter=json-summary",
64
+ "typecheck": "tsc --noEmit",
65
+ "test:watch": "vitest"
66
+ }
67
+ }
package/src/AuiIf.ts ADDED
@@ -0,0 +1,34 @@
1
+ import {
2
+ defineComponent,
3
+ type PropType,
4
+ type SlotsType,
5
+ type VNodeChild,
6
+ } from "vue";
7
+ import type { AssistantState } from "@assistant-ui/store/client";
8
+ import { useAuiState } from "./useAuiState";
9
+
10
+ /**
11
+ * Renders the default slot while `condition` selects `true` from the
12
+ * assistant state.
13
+ *
14
+ * @example
15
+ * ```html
16
+ * <AuiIf :condition="(s) => s.thread.isRunning">
17
+ * <StopButton />
18
+ * </AuiIf>
19
+ * ```
20
+ */
21
+ export const AuiIf = defineComponent({
22
+ name: "AuiIf",
23
+ props: {
24
+ condition: {
25
+ type: Function as PropType<(state: AssistantState) => boolean>,
26
+ required: true,
27
+ },
28
+ },
29
+ slots: Object as SlotsType<{ default?: () => VNodeChild[] }>,
30
+ setup(props, { slots }) {
31
+ const active = useAuiState((state) => props.condition(state));
32
+ return () => (active.value ? slots.default?.() : null);
33
+ },
34
+ });
@@ -0,0 +1,90 @@
1
+ import {
2
+ defineComponent,
3
+ inject,
4
+ onScopeDispose,
5
+ provide,
6
+ watch,
7
+ type PropType,
8
+ type SlotsType,
9
+ type VNodeChild,
10
+ } from "vue";
11
+ import {
12
+ createAssistantClient,
13
+ type AssistantClient,
14
+ type AuiConfig,
15
+ } from "@assistant-ui/store/client";
16
+ import { auiInjectionKey, createClientFacade } from "./context";
17
+ import { isDevelopment } from "@assistant-ui/core/store/internal";
18
+
19
+ /**
20
+ * Creates an `AssistantClient` from the given config and provides it to the
21
+ * subtree.
22
+ *
23
+ * At the top level, `config` alone creates this subtree's own client. Under a
24
+ * parent provider, `extends` is mandatory: pass `:extends="aui"` to extend the
25
+ * parent client or `:extends="null"` to isolate from it (enforced with a dev
26
+ * error).
27
+ *
28
+ * The `config` prop is live: passing a new config object updates element args
29
+ * in place (scopes keep their state) and mounts or unmounts added and removed
30
+ * scopes. Pass a computed config to derive it from reactive inputs. `extends`
31
+ * is captured when the provider mounts; remount (for example with a `key`) to
32
+ * change the parent.
33
+ */
34
+ export const AuiProvider = defineComponent({
35
+ name: "AuiProvider",
36
+ props: {
37
+ config: {
38
+ type: Object as PropType<AuiConfig>,
39
+ required: true,
40
+ },
41
+ extends: {
42
+ type: Object as PropType<AssistantClient | null>,
43
+ default: undefined,
44
+ },
45
+ },
46
+ slots: Object as SlotsType<{ default?: () => VNodeChild[] }>,
47
+ setup(props, { slots }) {
48
+ const injected = inject(auiInjectionKey, null);
49
+ const hasExtends = props.extends !== undefined;
50
+
51
+ if (isDevelopment) {
52
+ if (injected && !hasExtends) {
53
+ throw new Error(
54
+ 'A parent AuiProvider exists. Pass :extends="aui" to inherit it or :extends="null" to isolate.',
55
+ );
56
+ }
57
+ }
58
+
59
+ const parent = !hasExtends
60
+ ? injected?.source
61
+ : props.extends === null
62
+ ? undefined
63
+ : injected && props.extends === injected.aui
64
+ ? injected.source
65
+ : props.extends;
66
+
67
+ const handle = createAssistantClient(
68
+ {
69
+ getConfig: () => props.config,
70
+ subscribe: (listener) => watch(() => props.config, listener),
71
+ },
72
+ parent ? { parent } : undefined,
73
+ );
74
+ // The provider holds the lifetime subscription that keeps the client
75
+ // mounted while descendants come and go
76
+ const release = handle.subscribe(() => {});
77
+ onScopeDispose(release);
78
+
79
+ const source = {
80
+ getClient: handle.getClient,
81
+ subscribe: handle.subscribe,
82
+ };
83
+ provide(auiInjectionKey, {
84
+ source,
85
+ aui: createClientFacade(source),
86
+ });
87
+
88
+ return () => slots.default?.();
89
+ },
90
+ });
@@ -0,0 +1,54 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { createApp, defineComponent, h, nextTick, type Component } from "vue";
3
+ import { flushTapSync } from "@assistant-ui/tap";
4
+ import { AuiConfig } from "@assistant-ui/store/client";
5
+ import { AuiProvider } from "../AuiProvider";
6
+ import { AuiIf } from "../AuiIf";
7
+ import { useAui } from "../useAui";
8
+ import { ThreadClient, type AnyClient } from "./fixtures";
9
+
10
+ const mountApp = (root: Component) => {
11
+ const app = createApp(root);
12
+ const el = document.createElement("div");
13
+ app.mount(el);
14
+ return { el, unmount: () => app.unmount() };
15
+ };
16
+
17
+ describe("AuiIf", () => {
18
+ it("renders the slot only while the condition selects true", async () => {
19
+ let aui!: AnyClient;
20
+ const Probe = defineComponent({
21
+ setup() {
22
+ aui = useAui() as AnyClient;
23
+ return () =>
24
+ h(
25
+ AuiIf,
26
+ { condition: (s) => (s as AnyClient).thread.selected === 1 },
27
+ { default: () => h("span", { id: "flag" }, "visible") },
28
+ );
29
+ },
30
+ });
31
+ const { el, unmount } = mountApp(
32
+ defineComponent({
33
+ setup: () => () =>
34
+ h(
35
+ AuiProvider,
36
+ { config: AuiConfig({ thread: ThreadClient() } as never) },
37
+ { default: () => h(Probe) },
38
+ ),
39
+ }),
40
+ );
41
+
42
+ expect(el.querySelector("#flag")).toBeNull();
43
+
44
+ flushTapSync(() => aui.thread.setSelected(1));
45
+ await nextTick();
46
+ expect(el.querySelector("#flag")?.textContent).toBe("visible");
47
+
48
+ flushTapSync(() => aui.thread.setSelected(0));
49
+ await nextTick();
50
+ expect(el.querySelector("#flag")).toBeNull();
51
+
52
+ unmount();
53
+ });
54
+ });
@@ -0,0 +1,266 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+ import {
3
+ createApp,
4
+ defineComponent,
5
+ h,
6
+ nextTick,
7
+ shallowRef,
8
+ type Component,
9
+ } from "vue";
10
+ import { flushTapSync } from "@assistant-ui/tap";
11
+ import { AuiConfig, type AssistantClient } from "@assistant-ui/store/client";
12
+ import { AuiProvider } from "../AuiProvider";
13
+ import { useAui } from "../useAui";
14
+ import {
15
+ MessageClient,
16
+ ThreadClient,
17
+ messageDerived,
18
+ trackers,
19
+ type AnyClient,
20
+ } from "./fixtures";
21
+
22
+ const mountApp = (root: Component) => {
23
+ const app = createApp(root);
24
+ const el = document.createElement("div");
25
+ app.mount(el);
26
+ return { app, unmount: () => app.unmount() };
27
+ };
28
+
29
+ const captureAui = () => {
30
+ let aui!: AnyClient;
31
+ const Probe = defineComponent({
32
+ setup() {
33
+ aui = useAui() as AnyClient;
34
+ return () => null;
35
+ },
36
+ });
37
+ return { Probe, getAui: () => aui };
38
+ };
39
+
40
+ describe("AuiProvider", () => {
41
+ it("provides a client built from the config", () => {
42
+ const { Probe, getAui } = captureAui();
43
+ const { unmount } = mountApp(
44
+ defineComponent({
45
+ setup: () => () =>
46
+ h(
47
+ AuiProvider,
48
+ { config: AuiConfig({ thread: ThreadClient() } as never) },
49
+ { default: () => h(Probe) },
50
+ ),
51
+ }),
52
+ );
53
+
54
+ expect(getAui().thread.getState()).toEqual({ selected: 0 });
55
+
56
+ flushTapSync(() => getAui().thread.setSelected(1));
57
+ expect(getAui().thread.getState()).toEqual({ selected: 1 });
58
+
59
+ unmount();
60
+ });
61
+
62
+ it("keeps the facade stable across structural changes", () => {
63
+ const { Probe, getAui } = captureAui();
64
+ const { unmount } = mountApp(
65
+ defineComponent({
66
+ setup: () => () =>
67
+ h(
68
+ AuiProvider,
69
+ {
70
+ config: AuiConfig({
71
+ thread: ThreadClient(),
72
+ message: messageDerived(),
73
+ } as never),
74
+ },
75
+ { default: () => h(Probe) },
76
+ ),
77
+ }),
78
+ );
79
+
80
+ const aui = getAui();
81
+ expect(aui.message.getState().id).toBe("m0");
82
+
83
+ flushTapSync(() => aui.thread.setSelected(1));
84
+
85
+ expect(getAui()).toBe(aui);
86
+ expect(aui.message.getState().id).toBe("m1");
87
+
88
+ unmount();
89
+ });
90
+
91
+ it("extends the parent provider's client with an explicit extends", () => {
92
+ const { Probe, getAui } = captureAui();
93
+ const Nested = defineComponent({
94
+ setup(_, { slots }) {
95
+ const aui = useAui();
96
+ return () =>
97
+ h(
98
+ AuiProvider,
99
+ {
100
+ config: AuiConfig({ message: messageDerived() } as never),
101
+ extends: aui,
102
+ },
103
+ { default: () => slots.default?.() },
104
+ );
105
+ },
106
+ });
107
+ const { unmount } = mountApp(
108
+ defineComponent({
109
+ setup: () => () =>
110
+ h(
111
+ AuiProvider,
112
+ { config: AuiConfig({ thread: ThreadClient() } as never) },
113
+ { default: () => h(Nested, null, { default: () => h(Probe) }) },
114
+ ),
115
+ }),
116
+ );
117
+
118
+ const aui = getAui();
119
+ expect(aui.message.getState().id).toBe("m0");
120
+ expect(aui.thread.getState()).toEqual({ selected: 0 });
121
+
122
+ flushTapSync(() => aui.thread.setSelected(1));
123
+ expect(aui.message.getState().id).toBe("m1");
124
+
125
+ unmount();
126
+ });
127
+
128
+ it("throws in dev when nested without an explicit extends", () => {
129
+ const Nested = defineComponent({
130
+ setup: () => () =>
131
+ h(
132
+ AuiProvider,
133
+ { config: AuiConfig({ message: messageDerived() } as never) },
134
+ { default: () => null },
135
+ ),
136
+ });
137
+ expect(() =>
138
+ mountApp(
139
+ defineComponent({
140
+ setup: () => () =>
141
+ h(
142
+ AuiProvider,
143
+ { config: AuiConfig({ thread: ThreadClient() } as never) },
144
+ { default: () => h(Nested) },
145
+ ),
146
+ }),
147
+ ),
148
+ ).toThrow("A parent AuiProvider exists.");
149
+ });
150
+
151
+ it("isolates from the parent with extends null", () => {
152
+ const { Probe, getAui } = captureAui();
153
+ const Isolated = defineComponent({
154
+ setup: () => () =>
155
+ h(
156
+ AuiProvider,
157
+ {
158
+ config: AuiConfig({
159
+ message: MessageClient({ id: "iso" }),
160
+ } as never),
161
+ extends: null,
162
+ },
163
+ { default: () => h(Probe) },
164
+ ),
165
+ });
166
+ const { unmount } = mountApp(
167
+ defineComponent({
168
+ setup: () => () =>
169
+ h(
170
+ AuiProvider,
171
+ { config: AuiConfig({ thread: ThreadClient() } as never) },
172
+ { default: () => h(Isolated) },
173
+ ),
174
+ }),
175
+ );
176
+
177
+ expect(getAui().message.getState()).toEqual({ id: "iso", text: "" });
178
+ expect(() => getAui().thread.getState()).toThrow(
179
+ 'The current scope does not have a "thread" property.',
180
+ );
181
+
182
+ unmount();
183
+ });
184
+
185
+ it("applies config changes in place, keeping scope state", async () => {
186
+ const { Probe, getAui } = captureAui();
187
+ const config = shallowRef(
188
+ AuiConfig({ message: MessageClient({ id: "m0" }) } as never),
189
+ );
190
+ const { unmount } = mountApp(
191
+ defineComponent({
192
+ setup: () => () =>
193
+ h(AuiProvider, { config: config.value }, { default: () => h(Probe) }),
194
+ }),
195
+ );
196
+
197
+ flushTapSync(() => getAui().message.setText("draft"));
198
+ expect(getAui().message.getState()).toEqual({ id: "m0", text: "draft" });
199
+
200
+ config.value = AuiConfig({ message: MessageClient({ id: "m1" }) } as never);
201
+ await nextTick();
202
+ await vi.waitFor(() => {
203
+ expect(getAui().message.getState()).toEqual({ id: "m1", text: "draft" });
204
+ });
205
+
206
+ config.value = AuiConfig({
207
+ message: MessageClient({ id: "m1" }),
208
+ thread: ThreadClient(),
209
+ } as never);
210
+ await nextTick();
211
+ await vi.waitFor(() => {
212
+ expect(getAui().thread.getState()).toEqual({ selected: 0 });
213
+ });
214
+ expect(getAui().message.getState()).toEqual({ id: "m1", text: "draft" });
215
+
216
+ config.value = AuiConfig({ message: MessageClient({ id: "m1" }) } as never);
217
+ await nextTick();
218
+ await vi.waitFor(() => {
219
+ expect(() => getAui().thread.getState()).toThrow(
220
+ 'The current scope does not have a "thread" property.',
221
+ );
222
+ });
223
+
224
+ unmount();
225
+ });
226
+
227
+ it("releases the client on unmount, soft unmounting its scopes", async () => {
228
+ const before = trackers.threadCleanups;
229
+ const { Probe } = captureAui();
230
+ const { unmount } = mountApp(
231
+ defineComponent({
232
+ setup: () => () =>
233
+ h(
234
+ AuiProvider,
235
+ { config: AuiConfig({ thread: ThreadClient() } as never) },
236
+ { default: () => h(Probe) },
237
+ ),
238
+ }),
239
+ );
240
+
241
+ const afterMount = trackers.threadCleanups;
242
+ unmount();
243
+ await vi.waitFor(() =>
244
+ expect(trackers.threadCleanups).toBe(afterMount + 1),
245
+ );
246
+ expect(afterMount).toBeGreaterThanOrEqual(before);
247
+ });
248
+
249
+ it("returns the throwing default client outside a provider", () => {
250
+ let aui!: AssistantClient;
251
+ const { unmount } = mountApp(
252
+ defineComponent({
253
+ setup() {
254
+ aui = useAui();
255
+ return () => null;
256
+ },
257
+ }),
258
+ );
259
+
260
+ expect(() => (aui as AnyClient).thread.getState()).toThrow(
261
+ "Wrap your component in an <AuiProvider> component.",
262
+ );
263
+
264
+ unmount();
265
+ });
266
+ });