@mitodl/smoot-design 0.0.0-0a23f44

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 (325) hide show
  1. package/LICENSE +28 -0
  2. package/README.md +35 -0
  3. package/dist/bundles/aiDrawerManager.es.js +38832 -0
  4. package/dist/bundles/aiDrawerManager.es.js.map +1 -0
  5. package/dist/bundles/aiDrawerManager.umd.js +245 -0
  6. package/dist/bundles/aiDrawerManager.umd.js.map +1 -0
  7. package/dist/bundles/remoteTutorDrawer.es.js +38832 -0
  8. package/dist/bundles/remoteTutorDrawer.es.js.map +1 -0
  9. package/dist/bundles/remoteTutorDrawer.umd.js +245 -0
  10. package/dist/bundles/remoteTutorDrawer.umd.js.map +1 -0
  11. package/dist/cjs/VERSION.d.ts +12 -0
  12. package/dist/cjs/VERSION.js +15 -0
  13. package/dist/cjs/ai.d.ts +3 -0
  14. package/dist/cjs/ai.js +9 -0
  15. package/dist/cjs/bundles/AiDrawer/AiDrawer.d.ts +55 -0
  16. package/dist/cjs/bundles/AiDrawer/AiDrawer.js +262 -0
  17. package/dist/cjs/bundles/AiDrawer/AiDrawer.stories.d.ts +17 -0
  18. package/dist/cjs/bundles/AiDrawer/AiDrawer.stories.js +264 -0
  19. package/dist/cjs/bundles/AiDrawer/AiDrawerManager.d.ts +12 -0
  20. package/dist/cjs/bundles/AiDrawer/AiDrawerManager.js +51 -0
  21. package/dist/cjs/bundles/AiDrawer/AiDrawerManager.stories.d.ts +6 -0
  22. package/dist/cjs/bundles/AiDrawer/AiDrawerManager.stories.js +267 -0
  23. package/dist/cjs/bundles/AiDrawer/AiDrawerManager.test.d.ts +1 -0
  24. package/dist/cjs/bundles/AiDrawer/AiDrawerManager.test.js +245 -0
  25. package/dist/cjs/bundles/AiDrawer/FlashcardsScreen.d.ts +9 -0
  26. package/dist/cjs/bundles/AiDrawer/FlashcardsScreen.js +87 -0
  27. package/dist/cjs/bundles/aiDrawerManager.d.ts +6 -0
  28. package/dist/cjs/bundles/aiDrawerManager.js +44 -0
  29. package/dist/cjs/components/AiChat/AiChat.d.ts +5 -0
  30. package/dist/cjs/components/AiChat/AiChat.js +267 -0
  31. package/dist/cjs/components/AiChat/AiChat.stories.d.ts +17 -0
  32. package/dist/cjs/components/AiChat/AiChat.stories.js +194 -0
  33. package/dist/cjs/components/AiChat/AiChat.test.d.ts +1 -0
  34. package/dist/cjs/components/AiChat/AiChat.test.js +211 -0
  35. package/dist/cjs/components/AiChat/AiChatContext.d.ts +26 -0
  36. package/dist/cjs/components/AiChat/AiChatContext.js +106 -0
  37. package/dist/cjs/components/AiChat/AiChatContext.stories.d.ts +14 -0
  38. package/dist/cjs/components/AiChat/AiChatContext.stories.js +75 -0
  39. package/dist/cjs/components/AiChat/AiChatMarkdown.stories.d.ts +15 -0
  40. package/dist/cjs/components/AiChat/AiChatMarkdown.stories.js +282 -0
  41. package/dist/cjs/components/AiChat/ChatTitle.d.ts +8 -0
  42. package/dist/cjs/components/AiChat/ChatTitle.js +43 -0
  43. package/dist/cjs/components/AiChat/EllipsisIcon.d.ts +6 -0
  44. package/dist/cjs/components/AiChat/EllipsisIcon.js +17 -0
  45. package/dist/cjs/components/AiChat/EntryScreen.d.ts +11 -0
  46. package/dist/cjs/components/AiChat/EntryScreen.js +123 -0
  47. package/dist/cjs/components/AiChat/Markdown.d.ts +7 -0
  48. package/dist/cjs/components/AiChat/Markdown.js +14 -0
  49. package/dist/cjs/components/AiChat/TimLogo.d.ts +5 -0
  50. package/dist/cjs/components/AiChat/TimLogo.js +15 -0
  51. package/dist/cjs/components/AiChat/test-utils/api.d.ts +2 -0
  52. package/dist/cjs/components/AiChat/test-utils/api.js +164 -0
  53. package/dist/cjs/components/AiChat/types.d.ts +96 -0
  54. package/dist/cjs/components/AiChat/types.js +3 -0
  55. package/dist/cjs/components/AiChat/utils.d.ts +9 -0
  56. package/dist/cjs/components/AiChat/utils.js +41 -0
  57. package/dist/cjs/components/Alert/Alert.d.ts +15 -0
  58. package/dist/cjs/components/Alert/Alert.js +62 -0
  59. package/dist/cjs/components/Alert/Alert.stories.d.ts +8 -0
  60. package/dist/cjs/components/Alert/Alert.stories.js +53 -0
  61. package/dist/cjs/components/Button/ActionButton.d.ts +30 -0
  62. package/dist/cjs/components/Button/ActionButton.js +73 -0
  63. package/dist/cjs/components/Button/ActionButton.stories.d.ts +15 -0
  64. package/dist/cjs/components/Button/ActionButton.stories.js +113 -0
  65. package/dist/cjs/components/Button/Button.d.ts +58 -0
  66. package/dist/cjs/components/Button/Button.js +261 -0
  67. package/dist/cjs/components/Button/Button.stories.d.ts +18 -0
  68. package/dist/cjs/components/Button/Button.stories.js +148 -0
  69. package/dist/cjs/components/Button/Button.test.d.ts +1 -0
  70. package/dist/cjs/components/Button/Button.test.js +46 -0
  71. package/dist/cjs/components/Checkbox/Checkbox.d.ts +20 -0
  72. package/dist/cjs/components/Checkbox/Checkbox.js +85 -0
  73. package/dist/cjs/components/Checkbox/Checkbox.stories.d.ts +8 -0
  74. package/dist/cjs/components/Checkbox/Checkbox.stories.js +33 -0
  75. package/dist/cjs/components/CheckboxChoiceField/CheckboxChoiceField.d.ts +21 -0
  76. package/dist/cjs/components/CheckboxChoiceField/CheckboxChoiceField.js +43 -0
  77. package/dist/cjs/components/CheckboxChoiceField/CheckboxChoiceField.stories.d.ts +8 -0
  78. package/dist/cjs/components/CheckboxChoiceField/CheckboxChoiceField.stories.js +50 -0
  79. package/dist/cjs/components/CheckboxChoiceField/CheckboxChoiceField.test.d.ts +1 -0
  80. package/dist/cjs/components/CheckboxChoiceField/CheckboxChoiceField.test.js +52 -0
  81. package/dist/cjs/components/ImageAdapter/ImageAdapter.d.ts +23 -0
  82. package/dist/cjs/components/ImageAdapter/ImageAdapter.js +30 -0
  83. package/dist/cjs/components/Input/Input.d.ts +116 -0
  84. package/dist/cjs/components/Input/Input.js +237 -0
  85. package/dist/cjs/components/Input/Input.stories.d.ts +19 -0
  86. package/dist/cjs/components/Input/Input.stories.js +135 -0
  87. package/dist/cjs/components/Input/Input.test.d.ts +1 -0
  88. package/dist/cjs/components/Input/Input.test.js +32 -0
  89. package/dist/cjs/components/LinkAdapter/LinkAdapter.d.ts +23 -0
  90. package/dist/cjs/components/LinkAdapter/LinkAdapter.js +34 -0
  91. package/dist/cjs/components/RadioChoiceField/BooleanRadioChoiceField.stories.d.ts +6 -0
  92. package/dist/cjs/components/RadioChoiceField/BooleanRadioChoiceField.stories.js +47 -0
  93. package/dist/cjs/components/RadioChoiceField/RadioChoiceField.d.ts +45 -0
  94. package/dist/cjs/components/RadioChoiceField/RadioChoiceField.js +69 -0
  95. package/dist/cjs/components/RadioChoiceField/RadioChoiceField.stories.d.ts +6 -0
  96. package/dist/cjs/components/RadioChoiceField/RadioChoiceField.stories.js +55 -0
  97. package/dist/cjs/components/RadioChoiceField/RadioChoiceField.test.d.ts +1 -0
  98. package/dist/cjs/components/RadioChoiceField/RadioChoiceField.test.js +53 -0
  99. package/dist/cjs/components/ScrollSnap/ScrollSnap.d.ts +19 -0
  100. package/dist/cjs/components/ScrollSnap/ScrollSnap.js +59 -0
  101. package/dist/cjs/components/ScrollSnap/ScrollSnap.stories.d.ts +6 -0
  102. package/dist/cjs/components/ScrollSnap/ScrollSnap.stories.js +43 -0
  103. package/dist/cjs/components/ScrollSnap/useScrollSnap.d.ts +6 -0
  104. package/dist/cjs/components/ScrollSnap/useScrollSnap.js +36 -0
  105. package/dist/cjs/components/SrAnnouncer/SrAnnouncer.d.ts +25 -0
  106. package/dist/cjs/components/SrAnnouncer/SrAnnouncer.js +43 -0
  107. package/dist/cjs/components/SrAnnouncer/SrAnnouncer.stories.d.ts +6 -0
  108. package/dist/cjs/components/SrAnnouncer/SrAnnouncer.stories.js +44 -0
  109. package/dist/cjs/components/SrAnnouncer/SrAnnouncer.test.d.ts +1 -0
  110. package/dist/cjs/components/SrAnnouncer/SrAnnouncer.test.js +62 -0
  111. package/dist/cjs/components/TabButtons/TabButtonList.d.ts +25 -0
  112. package/dist/cjs/components/TabButtons/TabButtonList.js +97 -0
  113. package/dist/cjs/components/TabButtons/TabButtonList.stories.d.ts +24 -0
  114. package/dist/cjs/components/TabButtons/TabButtonList.stories.js +139 -0
  115. package/dist/cjs/components/TextField/TextField.d.ts +29 -0
  116. package/dist/cjs/components/TextField/TextField.js +33 -0
  117. package/dist/cjs/components/TextField/TextField.stories.d.ts +10 -0
  118. package/dist/cjs/components/TextField/TextField.stories.js +136 -0
  119. package/dist/cjs/components/TextField/TextField.test.d.ts +1 -0
  120. package/dist/cjs/components/TextField/TextField.test.js +77 -0
  121. package/dist/cjs/components/ThemeProvider/ThemeProvider.d.ts +21 -0
  122. package/dist/cjs/components/ThemeProvider/ThemeProvider.js +86 -0
  123. package/dist/cjs/components/ThemeProvider/ThemeProvider.stories.d.ts +63 -0
  124. package/dist/cjs/components/ThemeProvider/ThemeProvider.stories.js +102 -0
  125. package/dist/cjs/components/ThemeProvider/Typography.stories.d.ts +39 -0
  126. package/dist/cjs/components/ThemeProvider/Typography.stories.js +65 -0
  127. package/dist/cjs/components/ThemeProvider/breakpoints.d.ts +4 -0
  128. package/dist/cjs/components/ThemeProvider/breakpoints.js +19 -0
  129. package/dist/cjs/components/ThemeProvider/buttons.d.ts +7 -0
  130. package/dist/cjs/components/ThemeProvider/buttons.js +20 -0
  131. package/dist/cjs/components/ThemeProvider/chips.d.ts +3 -0
  132. package/dist/cjs/components/ThemeProvider/chips.js +154 -0
  133. package/dist/cjs/components/ThemeProvider/colors.d.ts +32 -0
  134. package/dist/cjs/components/ThemeProvider/colors.js +35 -0
  135. package/dist/cjs/components/ThemeProvider/typography.d.ts +18 -0
  136. package/dist/cjs/components/ThemeProvider/typography.js +173 -0
  137. package/dist/cjs/components/VisuallyHidden/VisuallyHidden.d.ts +24 -0
  138. package/dist/cjs/components/VisuallyHidden/VisuallyHidden.js +33 -0
  139. package/dist/cjs/components/VisuallyHidden/VisuallyHidden.stories.d.ts +6 -0
  140. package/dist/cjs/components/VisuallyHidden/VisuallyHidden.stories.js +13 -0
  141. package/dist/cjs/components/internal/FormHelpers/FormHelpers.d.ts +39 -0
  142. package/dist/cjs/components/internal/FormHelpers/FormHelpers.js +78 -0
  143. package/dist/cjs/components/internal/FormHelpers/FormHelpers.test.d.ts +1 -0
  144. package/dist/cjs/components/internal/FormHelpers/FormHelpers.test.js +93 -0
  145. package/dist/cjs/index.d.ts +25 -0
  146. package/dist/cjs/index.js +44 -0
  147. package/dist/cjs/jest-setup.d.ts +1 -0
  148. package/dist/cjs/jest-setup.js +18 -0
  149. package/dist/cjs/jsdom-extended.d.ts +6 -0
  150. package/dist/cjs/jsdom-extended.js +14 -0
  151. package/dist/cjs/story-utils/index.d.ts +6 -0
  152. package/dist/cjs/story-utils/index.js +17 -0
  153. package/dist/cjs/utils/composeRefs.d.ts +7 -0
  154. package/dist/cjs/utils/composeRefs.js +20 -0
  155. package/dist/cjs/utils/composeRefs.test.d.ts +1 -0
  156. package/dist/cjs/utils/composeRefs.test.js +19 -0
  157. package/dist/cjs/utils/retryingFetch.d.ts +19 -0
  158. package/dist/cjs/utils/retryingFetch.js +98 -0
  159. package/dist/cjs/utils/retryingFetch.test.d.ts +1 -0
  160. package/dist/cjs/utils/retryingFetch.test.js +48 -0
  161. package/dist/cjs/utils/useDevCheckStable.d.ts +8 -0
  162. package/dist/cjs/utils/useDevCheckStable.js +29 -0
  163. package/dist/cjs/utils/useInterval.d.ts +7 -0
  164. package/dist/cjs/utils/useInterval.js +25 -0
  165. package/dist/esm/VERSION.d.ts +12 -0
  166. package/dist/esm/VERSION.js +12 -0
  167. package/dist/esm/ai.d.ts +3 -0
  168. package/dist/esm/ai.js +2 -0
  169. package/dist/esm/bundles/AiDrawer/AiDrawer.d.ts +55 -0
  170. package/dist/esm/bundles/AiDrawer/AiDrawer.js +259 -0
  171. package/dist/esm/bundles/AiDrawer/AiDrawer.stories.d.ts +17 -0
  172. package/dist/esm/bundles/AiDrawer/AiDrawer.stories.js +261 -0
  173. package/dist/esm/bundles/AiDrawer/AiDrawerManager.d.ts +12 -0
  174. package/dist/esm/bundles/AiDrawer/AiDrawerManager.js +48 -0
  175. package/dist/esm/bundles/AiDrawer/AiDrawerManager.stories.d.ts +6 -0
  176. package/dist/esm/bundles/AiDrawer/AiDrawerManager.stories.js +264 -0
  177. package/dist/esm/bundles/AiDrawer/AiDrawerManager.test.d.ts +1 -0
  178. package/dist/esm/bundles/AiDrawer/AiDrawerManager.test.js +243 -0
  179. package/dist/esm/bundles/AiDrawer/FlashcardsScreen.d.ts +9 -0
  180. package/dist/esm/bundles/AiDrawer/FlashcardsScreen.js +83 -0
  181. package/dist/esm/bundles/aiDrawerManager.d.ts +6 -0
  182. package/dist/esm/bundles/aiDrawerManager.js +41 -0
  183. package/dist/esm/components/AiChat/AiChat.d.ts +5 -0
  184. package/dist/esm/components/AiChat/AiChat.js +263 -0
  185. package/dist/esm/components/AiChat/AiChat.stories.d.ts +17 -0
  186. package/dist/esm/components/AiChat/AiChat.stories.js +191 -0
  187. package/dist/esm/components/AiChat/AiChat.test.d.ts +1 -0
  188. package/dist/esm/components/AiChat/AiChat.test.js +209 -0
  189. package/dist/esm/components/AiChat/AiChatContext.d.ts +26 -0
  190. package/dist/esm/components/AiChat/AiChatContext.js +102 -0
  191. package/dist/esm/components/AiChat/AiChatContext.stories.d.ts +14 -0
  192. package/dist/esm/components/AiChat/AiChatContext.stories.js +72 -0
  193. package/dist/esm/components/AiChat/AiChatMarkdown.stories.d.ts +15 -0
  194. package/dist/esm/components/AiChat/AiChatMarkdown.stories.js +279 -0
  195. package/dist/esm/components/AiChat/ChatTitle.d.ts +8 -0
  196. package/dist/esm/components/AiChat/ChatTitle.js +40 -0
  197. package/dist/esm/components/AiChat/EllipsisIcon.d.ts +6 -0
  198. package/dist/esm/components/AiChat/EllipsisIcon.js +15 -0
  199. package/dist/esm/components/AiChat/EntryScreen.d.ts +11 -0
  200. package/dist/esm/components/AiChat/EntryScreen.js +120 -0
  201. package/dist/esm/components/AiChat/Markdown.d.ts +7 -0
  202. package/dist/esm/components/AiChat/Markdown.js +12 -0
  203. package/dist/esm/components/AiChat/TimLogo.d.ts +5 -0
  204. package/dist/esm/components/AiChat/TimLogo.js +13 -0
  205. package/dist/esm/components/AiChat/test-utils/api.d.ts +2 -0
  206. package/dist/esm/components/AiChat/test-utils/api.js +161 -0
  207. package/dist/esm/components/AiChat/types.d.ts +96 -0
  208. package/dist/esm/components/AiChat/types.js +2 -0
  209. package/dist/esm/components/AiChat/utils.d.ts +9 -0
  210. package/dist/esm/components/AiChat/utils.js +38 -0
  211. package/dist/esm/components/Alert/Alert.d.ts +15 -0
  212. package/dist/esm/components/Alert/Alert.js +59 -0
  213. package/dist/esm/components/Alert/Alert.stories.d.ts +8 -0
  214. package/dist/esm/components/Alert/Alert.stories.js +50 -0
  215. package/dist/esm/components/Button/ActionButton.d.ts +30 -0
  216. package/dist/esm/components/Button/ActionButton.js +68 -0
  217. package/dist/esm/components/Button/ActionButton.stories.d.ts +15 -0
  218. package/dist/esm/components/Button/ActionButton.stories.js +110 -0
  219. package/dist/esm/components/Button/Button.d.ts +58 -0
  220. package/dist/esm/components/Button/Button.js +252 -0
  221. package/dist/esm/components/Button/Button.stories.d.ts +18 -0
  222. package/dist/esm/components/Button/Button.stories.js +145 -0
  223. package/dist/esm/components/Button/Button.test.d.ts +1 -0
  224. package/dist/esm/components/Button/Button.test.js +44 -0
  225. package/dist/esm/components/Checkbox/Checkbox.d.ts +20 -0
  226. package/dist/esm/components/Checkbox/Checkbox.js +81 -0
  227. package/dist/esm/components/Checkbox/Checkbox.stories.d.ts +8 -0
  228. package/dist/esm/components/Checkbox/Checkbox.stories.js +30 -0
  229. package/dist/esm/components/CheckboxChoiceField/CheckboxChoiceField.d.ts +21 -0
  230. package/dist/esm/components/CheckboxChoiceField/CheckboxChoiceField.js +40 -0
  231. package/dist/esm/components/CheckboxChoiceField/CheckboxChoiceField.stories.d.ts +8 -0
  232. package/dist/esm/components/CheckboxChoiceField/CheckboxChoiceField.stories.js +47 -0
  233. package/dist/esm/components/CheckboxChoiceField/CheckboxChoiceField.test.d.ts +1 -0
  234. package/dist/esm/components/CheckboxChoiceField/CheckboxChoiceField.test.js +50 -0
  235. package/dist/esm/components/ImageAdapter/ImageAdapter.d.ts +23 -0
  236. package/dist/esm/components/ImageAdapter/ImageAdapter.js +27 -0
  237. package/dist/esm/components/Input/Input.d.ts +116 -0
  238. package/dist/esm/components/Input/Input.js +232 -0
  239. package/dist/esm/components/Input/Input.stories.d.ts +19 -0
  240. package/dist/esm/components/Input/Input.stories.js +132 -0
  241. package/dist/esm/components/Input/Input.test.d.ts +1 -0
  242. package/dist/esm/components/Input/Input.test.js +30 -0
  243. package/dist/esm/components/LinkAdapter/LinkAdapter.d.ts +23 -0
  244. package/dist/esm/components/LinkAdapter/LinkAdapter.js +31 -0
  245. package/dist/esm/components/RadioChoiceField/BooleanRadioChoiceField.stories.d.ts +6 -0
  246. package/dist/esm/components/RadioChoiceField/BooleanRadioChoiceField.stories.js +44 -0
  247. package/dist/esm/components/RadioChoiceField/RadioChoiceField.d.ts +45 -0
  248. package/dist/esm/components/RadioChoiceField/RadioChoiceField.js +65 -0
  249. package/dist/esm/components/RadioChoiceField/RadioChoiceField.stories.d.ts +6 -0
  250. package/dist/esm/components/RadioChoiceField/RadioChoiceField.stories.js +52 -0
  251. package/dist/esm/components/RadioChoiceField/RadioChoiceField.test.d.ts +1 -0
  252. package/dist/esm/components/RadioChoiceField/RadioChoiceField.test.js +51 -0
  253. package/dist/esm/components/ScrollSnap/ScrollSnap.d.ts +19 -0
  254. package/dist/esm/components/ScrollSnap/ScrollSnap.js +56 -0
  255. package/dist/esm/components/ScrollSnap/ScrollSnap.stories.d.ts +6 -0
  256. package/dist/esm/components/ScrollSnap/ScrollSnap.stories.js +40 -0
  257. package/dist/esm/components/ScrollSnap/useScrollSnap.d.ts +6 -0
  258. package/dist/esm/components/ScrollSnap/useScrollSnap.js +33 -0
  259. package/dist/esm/components/SrAnnouncer/SrAnnouncer.d.ts +25 -0
  260. package/dist/esm/components/SrAnnouncer/SrAnnouncer.js +40 -0
  261. package/dist/esm/components/SrAnnouncer/SrAnnouncer.stories.d.ts +6 -0
  262. package/dist/esm/components/SrAnnouncer/SrAnnouncer.stories.js +41 -0
  263. package/dist/esm/components/SrAnnouncer/SrAnnouncer.test.d.ts +1 -0
  264. package/dist/esm/components/SrAnnouncer/SrAnnouncer.test.js +60 -0
  265. package/dist/esm/components/TabButtons/TabButtonList.d.ts +25 -0
  266. package/dist/esm/components/TabButtons/TabButtonList.js +92 -0
  267. package/dist/esm/components/TabButtons/TabButtonList.stories.d.ts +24 -0
  268. package/dist/esm/components/TabButtons/TabButtonList.stories.js +136 -0
  269. package/dist/esm/components/TextField/TextField.d.ts +29 -0
  270. package/dist/esm/components/TextField/TextField.js +30 -0
  271. package/dist/esm/components/TextField/TextField.stories.d.ts +10 -0
  272. package/dist/esm/components/TextField/TextField.stories.js +133 -0
  273. package/dist/esm/components/TextField/TextField.test.d.ts +1 -0
  274. package/dist/esm/components/TextField/TextField.test.js +75 -0
  275. package/dist/esm/components/ThemeProvider/ThemeProvider.d.ts +21 -0
  276. package/dist/esm/components/ThemeProvider/ThemeProvider.js +82 -0
  277. package/dist/esm/components/ThemeProvider/ThemeProvider.stories.d.ts +63 -0
  278. package/dist/esm/components/ThemeProvider/ThemeProvider.stories.js +99 -0
  279. package/dist/esm/components/ThemeProvider/Typography.stories.d.ts +39 -0
  280. package/dist/esm/components/ThemeProvider/Typography.stories.js +62 -0
  281. package/dist/esm/components/ThemeProvider/breakpoints.d.ts +4 -0
  282. package/dist/esm/components/ThemeProvider/breakpoints.js +15 -0
  283. package/dist/esm/components/ThemeProvider/buttons.d.ts +7 -0
  284. package/dist/esm/components/ThemeProvider/buttons.js +17 -0
  285. package/dist/esm/components/ThemeProvider/chips.d.ts +3 -0
  286. package/dist/esm/components/ThemeProvider/chips.js +151 -0
  287. package/dist/esm/components/ThemeProvider/colors.d.ts +32 -0
  288. package/dist/esm/components/ThemeProvider/colors.js +32 -0
  289. package/dist/esm/components/ThemeProvider/typography.d.ts +18 -0
  290. package/dist/esm/components/ThemeProvider/typography.js +167 -0
  291. package/dist/esm/components/VisuallyHidden/VisuallyHidden.d.ts +24 -0
  292. package/dist/esm/components/VisuallyHidden/VisuallyHidden.js +30 -0
  293. package/dist/esm/components/VisuallyHidden/VisuallyHidden.stories.d.ts +6 -0
  294. package/dist/esm/components/VisuallyHidden/VisuallyHidden.stories.js +10 -0
  295. package/dist/esm/components/internal/FormHelpers/FormHelpers.d.ts +39 -0
  296. package/dist/esm/components/internal/FormHelpers/FormHelpers.js +73 -0
  297. package/dist/esm/components/internal/FormHelpers/FormHelpers.test.d.ts +1 -0
  298. package/dist/esm/components/internal/FormHelpers/FormHelpers.test.js +91 -0
  299. package/dist/esm/index.d.ts +25 -0
  300. package/dist/esm/index.js +16 -0
  301. package/dist/esm/jest-setup.d.ts +1 -0
  302. package/dist/esm/jest-setup.js +16 -0
  303. package/dist/esm/jsdom-extended.d.ts +6 -0
  304. package/dist/esm/jsdom-extended.js +12 -0
  305. package/dist/esm/story-utils/index.d.ts +6 -0
  306. package/dist/esm/story-utils/index.js +13 -0
  307. package/dist/esm/utils/composeRefs.d.ts +7 -0
  308. package/dist/esm/utils/composeRefs.js +17 -0
  309. package/dist/esm/utils/composeRefs.test.d.ts +1 -0
  310. package/dist/esm/utils/composeRefs.test.js +17 -0
  311. package/dist/esm/utils/retryingFetch.d.ts +19 -0
  312. package/dist/esm/utils/retryingFetch.js +96 -0
  313. package/dist/esm/utils/retryingFetch.test.d.ts +1 -0
  314. package/dist/esm/utils/retryingFetch.test.js +46 -0
  315. package/dist/esm/utils/useDevCheckStable.d.ts +8 -0
  316. package/dist/esm/utils/useDevCheckStable.js +26 -0
  317. package/dist/esm/utils/useInterval.d.ts +7 -0
  318. package/dist/esm/utils/useInterval.js +22 -0
  319. package/dist/tsconfig.tsbuildinfo +1 -0
  320. package/dist/type-augmentation/TypescriptDocs.mdx +17 -0
  321. package/dist/type-augmentation/imports.d.ts +3 -0
  322. package/dist/type-augmentation/index.d.ts +3 -0
  323. package/dist/type-augmentation/theme.d.ts +105 -0
  324. package/dist/type-augmentation/typography.d.ts +54 -0
  325. package/package.json +159 -0
@@ -0,0 +1,243 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { act, render, screen } from "@testing-library/react";
11
+ import user from "@testing-library/user-event";
12
+ import { AiDrawerManager } from "./AiDrawerManager";
13
+ import { ThemeProvider } from "../../components/ThemeProvider/ThemeProvider";
14
+ import * as React from "react";
15
+ import { http, HttpResponse } from "msw";
16
+ import { setupServer } from "msw/node";
17
+ jest.mock("../../components/AiChat/Markdown", () => {
18
+ return {
19
+ __esModule: true,
20
+ default: ({ children }) => React.createElement("div", null, children),
21
+ };
22
+ });
23
+ jest.mock("better-react-mathjax", () => ({
24
+ MathJaxContext: ({ children }) => (React.createElement(React.Fragment, null, children)),
25
+ }));
26
+ const TEST_API_STREAMING = "http://localhost:4567/test";
27
+ const CONTENT_FILE_URL = "http://localhost:4567/api/v1/contentfiles/1";
28
+ const CONTENT_RESPONSE = {
29
+ count: 1,
30
+ next: null,
31
+ previous: null,
32
+ results: [
33
+ {
34
+ id: 1,
35
+ summary: "This is a test summary",
36
+ flashcards: [
37
+ {
38
+ question: "Test question 1?",
39
+ answer: "Test answer 1",
40
+ },
41
+ {
42
+ question: "Test question 2?",
43
+ answer: "Test answer 2",
44
+ },
45
+ {
46
+ question: "Test question 3?",
47
+ answer: "Test answer 3",
48
+ },
49
+ ],
50
+ },
51
+ ],
52
+ };
53
+ class MockResizeObserver {
54
+ constructor() {
55
+ this.observe = jest.fn();
56
+ this.unobserve = jest.fn();
57
+ this.disconnect = jest.fn();
58
+ }
59
+ }
60
+ global.ResizeObserver = MockResizeObserver;
61
+ describe("AiDrawerManager", () => {
62
+ const server = setupServer(http.post(TEST_API_STREAMING, () => __awaiter(void 0, void 0, void 0, function* () {
63
+ return HttpResponse.text("AI Response");
64
+ })), http.get(CONTENT_FILE_URL, () => {
65
+ return HttpResponse.json(CONTENT_RESPONSE);
66
+ }));
67
+ beforeEach(() => {
68
+ jest.resetAllMocks();
69
+ });
70
+ afterEach(() => {
71
+ server.resetHandlers();
72
+ });
73
+ afterAll(() => server.close());
74
+ const setup = (message) => __awaiter(void 0, void 0, void 0, function* () {
75
+ server.listen();
76
+ render(React.createElement(AiDrawerManager, { messageOrigin: "http://localhost:6006" }), {
77
+ wrapper: ThemeProvider,
78
+ });
79
+ yield screen.findByTestId("ai-drawer-manager-waiting");
80
+ const event = new MessageEvent("message", {
81
+ data: message,
82
+ origin: "http://localhost:6006",
83
+ });
84
+ yield act(() => __awaiter(void 0, void 0, void 0, function* () {
85
+ window.dispatchEvent(event);
86
+ yield new Promise((resolve) => setTimeout(resolve, 100));
87
+ }));
88
+ });
89
+ test("Problem drawer opens showing title", () => __awaiter(void 0, void 0, void 0, function* () {
90
+ yield setup({
91
+ type: "smoot-design::ai-drawer-open",
92
+ payload: {
93
+ blockType: "problem",
94
+ title: "Drawer Title",
95
+ chat: {
96
+ apiUrl: TEST_API_STREAMING,
97
+ },
98
+ },
99
+ });
100
+ screen.getByRole("heading", { name: "Drawer Title" });
101
+ }));
102
+ test("Video drawer opens showing chat entry screen and tabs", () => __awaiter(void 0, void 0, void 0, function* () {
103
+ yield setup({
104
+ type: "smoot-design::ai-drawer-open",
105
+ payload: {
106
+ blockType: "video",
107
+ chat: {
108
+ entryScreenTitle: "Entry screen title",
109
+ apiUrl: TEST_API_STREAMING,
110
+ conversationStarters: [
111
+ { content: "Prompt 1" },
112
+ { content: "Prompt 2" },
113
+ { content: "Prompt 3" },
114
+ ],
115
+ },
116
+ summary: {
117
+ apiUrl: CONTENT_FILE_URL,
118
+ },
119
+ },
120
+ });
121
+ screen.getByText("Entry screen title");
122
+ screen.getByRole("tab", { name: "Chat" });
123
+ screen.getByRole("tab", { name: "Flashcards" });
124
+ screen.getByRole("tab", { name: "Summary" });
125
+ screen.getByRole("button", { name: "Prompt 1" });
126
+ screen.getByRole("button", { name: "Prompt 2" });
127
+ screen.getByRole("button", { name: "Prompt 3" });
128
+ }));
129
+ test("Video drawer chat entry screen selects starters from flashcards", () => __awaiter(void 0, void 0, void 0, function* () {
130
+ yield setup({
131
+ type: "smoot-design::ai-drawer-open",
132
+ payload: {
133
+ blockType: "video",
134
+ chat: {
135
+ entryScreenTitle: "Entry screen title",
136
+ apiUrl: TEST_API_STREAMING,
137
+ },
138
+ summary: {
139
+ apiUrl: CONTENT_FILE_URL,
140
+ },
141
+ },
142
+ });
143
+ screen.getByRole("button", { name: "Test question 1?" });
144
+ screen.getByRole("button", { name: "Test question 2?" });
145
+ screen.getByRole("button", { name: "Test question 3?" });
146
+ }));
147
+ test("Video drawer chat entry screen shows default starters where no flashcards are available", server.boundary(() => __awaiter(void 0, void 0, void 0, function* () {
148
+ const contentResponse = JSON.parse(JSON.stringify(CONTENT_RESPONSE));
149
+ contentResponse.results[0].flashcards = null;
150
+ server.use(http.get(CONTENT_FILE_URL, () => {
151
+ return HttpResponse.json(contentResponse);
152
+ }));
153
+ yield setup({
154
+ type: "smoot-design::ai-drawer-open",
155
+ payload: {
156
+ blockType: "video",
157
+ chat: {
158
+ entryScreenTitle: "Entry screen title",
159
+ apiUrl: TEST_API_STREAMING,
160
+ },
161
+ summary: {
162
+ apiUrl: CONTENT_FILE_URL,
163
+ },
164
+ },
165
+ });
166
+ screen.getByRole("button", {
167
+ name: "What are the most important concepts introduced in the video?",
168
+ });
169
+ screen.getByRole("button", {
170
+ name: "What examples are used to illustrate concepts covered in the video?",
171
+ });
172
+ screen.getByRole("button", {
173
+ name: "What are the key terms introduced in this video?",
174
+ });
175
+ })));
176
+ test("Video drawer chat entry screen displays default title", () => __awaiter(void 0, void 0, void 0, function* () {
177
+ yield setup({
178
+ type: "smoot-design::ai-drawer-open",
179
+ payload: {
180
+ blockType: "video",
181
+ chat: {
182
+ apiUrl: TEST_API_STREAMING,
183
+ },
184
+ summary: {
185
+ apiUrl: CONTENT_FILE_URL,
186
+ },
187
+ },
188
+ });
189
+ screen.getByText("What do you want to know about this video?");
190
+ }));
191
+ test("Flashcard shows content and can be click navigated", server.boundary(() => __awaiter(void 0, void 0, void 0, function* () {
192
+ yield setup({
193
+ type: "smoot-design::ai-drawer-open",
194
+ payload: {
195
+ blockType: "video",
196
+ chat: {
197
+ apiUrl: TEST_API_STREAMING,
198
+ },
199
+ summary: {
200
+ apiUrl: CONTENT_FILE_URL,
201
+ },
202
+ },
203
+ });
204
+ yield user.click(screen.getByRole("tab", { name: "Flashcards" }));
205
+ yield user.click(screen.getByText("Q: Test question 1?"));
206
+ screen.getByText("Answer: Test answer 1");
207
+ yield user.click(screen.getByRole("button", { name: "Next card" }));
208
+ yield user.click(screen.getByText("Q: Test question 2?"));
209
+ screen.getByText("Answer: Test answer 2");
210
+ yield user.click(screen.getByRole("button", { name: "Previous card" }));
211
+ screen.getByText("Q: Test question 1?");
212
+ })));
213
+ test("Flashcard shows content and can be keyboard navigated and cycles", server.boundary(() => __awaiter(void 0, void 0, void 0, function* () {
214
+ yield setup({
215
+ type: "smoot-design::ai-drawer-open",
216
+ payload: {
217
+ blockType: "video",
218
+ chat: {
219
+ apiUrl: TEST_API_STREAMING,
220
+ },
221
+ summary: {
222
+ apiUrl: CONTENT_FILE_URL,
223
+ },
224
+ },
225
+ });
226
+ yield user.click(screen.getByRole("tab", { name: "Flashcards" }));
227
+ screen.getByText("Q: Test question 1?");
228
+ yield user.keyboard("{enter}");
229
+ screen.getByText("Answer: Test answer 1");
230
+ yield user.keyboard("{arrowright}");
231
+ screen.getByText("Q: Test question 2?");
232
+ yield user.keyboard("{enter}");
233
+ screen.getByText("Answer: Test answer 2");
234
+ yield user.keyboard("{arrowleft}");
235
+ screen.getByText("Q: Test question 1?");
236
+ yield user.keyboard("{arrowleft}");
237
+ screen.getByText("Q: Test question 3?");
238
+ yield user.keyboard("{arrowright}");
239
+ yield user.keyboard("{arrowright}");
240
+ yield user.keyboard("{arrowright}");
241
+ screen.getByText("Q: Test question 3?");
242
+ })));
243
+ });
@@ -0,0 +1,9 @@
1
+ import * as React from "react";
2
+ export type Flashcard = {
3
+ question: string;
4
+ answer: string;
5
+ };
6
+ export declare const FlashcardsScreen: ({ flashcards, wasKeyboardFocus, }: {
7
+ flashcards?: Flashcard[];
8
+ wasKeyboardFocus: boolean;
9
+ }) => React.JSX.Element | null;
@@ -0,0 +1,83 @@
1
+ import { ActionButton } from "../../components/Button/ActionButton";
2
+ import Typography from "@mui/material/Typography";
3
+ import * as React from "react";
4
+ import { useState, useCallback, useEffect, useRef } from "react";
5
+ import styled from "@emotion/styled";
6
+ import { RiArrowRightLine, RiArrowLeftLine } from "@remixicon/react";
7
+ const Container = styled.div ``;
8
+ const FlashcardContainer = styled.div(({ theme }) => ({
9
+ display: "flex",
10
+ height: 300,
11
+ padding: 40,
12
+ flexDirection: "column",
13
+ justifyContent: "center",
14
+ alignItems: "center",
15
+ alignSelf: "stretch",
16
+ borderRadius: 8,
17
+ border: `1px solid ${theme.custom.colors.lightGray2}`,
18
+ marginTop: "8px",
19
+ cursor: "pointer",
20
+ textAlign: "center",
21
+ }));
22
+ const Navigation = styled.div({
23
+ display: "flex",
24
+ justifyContent: "space-between",
25
+ alignItems: "center",
26
+ width: "100%",
27
+ marginTop: "24px",
28
+ });
29
+ const Page = styled.div(({ theme }) => (Object.assign({ color: theme.custom.colors.silverGrayDark }, theme.typography.body2)));
30
+ const Flashcard = React.forwardRef(({ content, "aria-label": ariaLabel }, ref) => {
31
+ const [screen, setScreen] = useState(0);
32
+ useEffect(() => setScreen(0), [content]);
33
+ const handleKeyDown = (e) => {
34
+ if (e.key === "Enter" || e.key === " ") {
35
+ setScreen(screen === 0 ? 1 : 0);
36
+ }
37
+ };
38
+ return (React.createElement(FlashcardContainer, { ref: ref, onClick: () => setScreen(screen === 0 ? 1 : 0), onKeyDown: handleKeyDown, tabIndex: 0, "aria-label": ariaLabel, role: "button" },
39
+ React.createElement(Typography, { variant: "h5" }, screen === 0 ? `Q: ${content.question}` : `Answer: ${content.answer}`)));
40
+ });
41
+ Flashcard.displayName = "Flashcard";
42
+ export const FlashcardsScreen = ({ flashcards, wasKeyboardFocus, }) => {
43
+ const [cardIndex, setCardIndex] = useState(0);
44
+ const containerRef = useRef(null);
45
+ const flashcardRef = useRef(null);
46
+ const handleKeyDown = useCallback((e) => {
47
+ var _a;
48
+ if (!flashcards)
49
+ return;
50
+ if (!((_a = containerRef.current) === null || _a === void 0 ? void 0 : _a.contains(document.activeElement)) &&
51
+ wasKeyboardFocus) {
52
+ return;
53
+ }
54
+ if (e.key === "ArrowRight") {
55
+ setCardIndex((prevIndex) => (prevIndex + 1) % flashcards.length);
56
+ }
57
+ else if (e.key === "ArrowLeft") {
58
+ setCardIndex((prevIndex) => (prevIndex - 1 + flashcards.length) % flashcards.length);
59
+ }
60
+ }, [flashcards, wasKeyboardFocus]);
61
+ useEffect(() => {
62
+ var _a;
63
+ (_a = flashcardRef.current) === null || _a === void 0 ? void 0 : _a.focus();
64
+ }, [cardIndex]);
65
+ useEffect(() => {
66
+ window.addEventListener("keydown", handleKeyDown);
67
+ return () => window.removeEventListener("keydown", handleKeyDown);
68
+ }, [handleKeyDown]);
69
+ if (!(flashcards === null || flashcards === void 0 ? void 0 : flashcards.length)) {
70
+ return null;
71
+ }
72
+ return (React.createElement(Container, { ref: containerRef },
73
+ React.createElement(Flashcard, { ref: flashcardRef, content: flashcards[cardIndex], "aria-label": `Flashcard ${cardIndex + 1} of ${flashcards.length}` }),
74
+ React.createElement(Navigation, null,
75
+ React.createElement(ActionButton, { onClick: () => setCardIndex(cardIndex - 1), disabled: cardIndex === 0, variant: "secondary", color: "secondary", size: "small", "aria-label": "Previous card" },
76
+ React.createElement(RiArrowLeftLine, { "aria-hidden": true })),
77
+ React.createElement(Page, null,
78
+ cardIndex + 1,
79
+ " / ",
80
+ flashcards.length),
81
+ React.createElement(ActionButton, { onClick: () => setCardIndex(cardIndex + 1), disabled: cardIndex === flashcards.length - 1, variant: "secondary", color: "secondary", size: "small", "aria-label": "Next card" },
82
+ React.createElement(RiArrowRightLine, { "aria-hidden": true })))));
83
+ };
@@ -0,0 +1,6 @@
1
+ import type { AiDrawerManagerProps } from "./AiDrawer/AiDrawerManager";
2
+ /**
3
+ * Renders the AiDrawerManager to the page.
4
+ */
5
+ declare const init: (opts: AiDrawerManagerProps) => void;
6
+ export { init };
@@ -0,0 +1,41 @@
1
+ import * as React from "react";
2
+ import { createRoot } from "react-dom/client";
3
+ import { AiDrawerManager } from "./AiDrawer/AiDrawerManager";
4
+ import { ThemeProvider, createTheme, } from "../components/ThemeProvider/ThemeProvider";
5
+ import { CacheProvider } from "@emotion/react";
6
+ import createCache from "@emotion/cache";
7
+ import { MathJaxContext } from "better-react-mathjax";
8
+ /**
9
+ * Renders the AiDrawerManager to the page.
10
+ */
11
+ const init = (opts) => {
12
+ const container = document.createElement("div");
13
+ document.body.appendChild(container);
14
+ container.id = "smoot-chat-drawer-root";
15
+ const cache = createCache({
16
+ key: "css",
17
+ prepend: true,
18
+ container: container,
19
+ });
20
+ const theme = createTheme({
21
+ components: {
22
+ MuiPopover: { defaultProps: { container: container } },
23
+ MuiPopper: { defaultProps: { container: container } },
24
+ MuiModal: { defaultProps: { container: container } },
25
+ },
26
+ });
27
+ createRoot(container).render(React.createElement(CacheProvider, { value: cache },
28
+ React.createElement(ThemeProvider, { theme: theme },
29
+ React.createElement(MathJaxContext, null,
30
+ React.createElement(AiDrawerManager, Object.assign({}, opts))))));
31
+ // Ensure mathjax context menu is rendered above the drawer
32
+ // Mathjax context menu is appended to end of body.
33
+ const style = document.createElement("style");
34
+ style.textContent = `
35
+ .CtxtMenu_MenuFrame {
36
+ z-index: ${theme.zIndex.drawer + 100} !important;
37
+ }
38
+ `;
39
+ document.head.appendChild(style);
40
+ };
41
+ export { init };
@@ -0,0 +1,5 @@
1
+ import type { FC } from "react";
2
+ import type { AiChatDisplayProps, AiChatProps } from "./types";
3
+ declare const AiChatDisplay: FC<AiChatDisplayProps>;
4
+ declare const AiChat: FC<AiChatProps>;
5
+ export { AiChatDisplay, AiChat };
@@ -0,0 +1,263 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
12
+ import * as React from "react";
13
+ import { useEffect, useRef, useState } from "react";
14
+ import styled from "@emotion/styled";
15
+ import Typography from "@mui/material/Typography";
16
+ import classNames from "classnames";
17
+ import { RiSendPlaneFill, RiStopFill } from "@remixicon/react";
18
+ import { Input, AdornmentButton } from "../Input/Input";
19
+ import { EntryScreen } from "./EntryScreen";
20
+ import { ScrollSnap } from "../ScrollSnap/ScrollSnap";
21
+ import { SrAnnouncer } from "../SrAnnouncer/SrAnnouncer";
22
+ import { VisuallyHidden } from "../VisuallyHidden/VisuallyHidden";
23
+ import { Alert } from "../Alert/Alert";
24
+ import { ChatTitle } from "./ChatTitle";
25
+ import { AiChatProvider, useAiChat } from "./AiChatContext";
26
+ import { useScrollSnap } from "../ScrollSnap/useScrollSnap";
27
+ import Markdown from "./Markdown";
28
+ import EllipsisIcon from "./EllipsisIcon";
29
+ const classes = {
30
+ root: "MitAiChat--root",
31
+ title: "MitAiChat--title",
32
+ entryScreenContainer: "MitAiChat--entryScreenContainer",
33
+ conversationStarter: "MitAiChat--conversationStarter",
34
+ chatScreenContainer: "MitAiChat--chatScreenContainer",
35
+ messagesContainer: "MitAiChat--messagesContainer",
36
+ messageRow: "MitAiChat--messageRow",
37
+ messageRowUser: "MitAiChat--messageRowUser",
38
+ messageRowAssistant: "MitAiChat--messageRowAssistant",
39
+ message: "MitAiChat--message",
40
+ input: "MitAiChat--input",
41
+ bottomSection: "MitAiChat--bottomSection",
42
+ };
43
+ const Container = styled.div();
44
+ const ChatScreen = styled.div(({ externalScroll, theme }) => (Object.assign({ padding: "16px 32px 0", [theme.breakpoints.down("md")]: {
45
+ padding: "16px 16px 0",
46
+ }, boxSizing: "border-box", background: "white", position: "absolute", bottom: 0, top: 0, left: 0, right: 0, zIndex: 1 }, (externalScroll && {
47
+ padding: "0 32px",
48
+ [theme.breakpoints.down("md")]: {
49
+ padding: "0 16px",
50
+ },
51
+ }))));
52
+ const ChatContainer = styled.div(({ externalScroll }) => ({
53
+ width: "100%",
54
+ height: externalScroll ? "auto" : "100%",
55
+ minHeight: externalScroll ? "100%" : "auto",
56
+ display: "flex",
57
+ flexDirection: "column",
58
+ }));
59
+ const MessagesContainer = styled(ScrollSnap)(({ externalScroll }) => ({
60
+ display: "flex",
61
+ flexDirection: "column",
62
+ flex: 1,
63
+ padding: "14px 0",
64
+ overflow: externalScroll ? "visible" : "auto",
65
+ gap: "16px",
66
+ [`> .${classes.messageRowAssistant}:first-child`]: {
67
+ marginTop: "16px",
68
+ },
69
+ }));
70
+ const MessageRow = styled.div({
71
+ display: "flex",
72
+ width: "100%",
73
+ gap: "10px",
74
+ [`&.${classes.messageRowUser}`]: {
75
+ flexDirection: "row-reverse",
76
+ },
77
+ "> *": {
78
+ minWidth: 0,
79
+ },
80
+ position: "relative",
81
+ });
82
+ const Message = styled.div(({ theme }) => (Object.assign(Object.assign({ color: theme.custom.colors.darkGray2, backgroundColor: theme.custom.colors.white }, theme.typography.body2), { "p:first-of-type": {
83
+ marginTop: 0,
84
+ }, "p:last-of-type": {
85
+ marginBottom: 0,
86
+ }, "ol,ul": {
87
+ paddingInlineStart: "16px",
88
+ margin: "12px 0 12px 4px",
89
+ }, "ol > li, ul > li": {
90
+ margin: "12px 0",
91
+ "ol,ul": {
92
+ margin: "12px 0 12px 4px",
93
+ },
94
+ li: {
95
+ margin: "6px 0",
96
+ },
97
+ }, ul: {
98
+ paddingInlineStart: 0,
99
+ "> li": {
100
+ listStyleType: "none",
101
+ position: "relative",
102
+ "&::before": {
103
+ content: '"–"',
104
+ position: "absolute",
105
+ left: 0,
106
+ color: "#888",
107
+ marginRight: "8px",
108
+ },
109
+ paddingLeft: "16px",
110
+ },
111
+ }, "ol + ul": {
112
+ marginLeft: "24px",
113
+ li: {
114
+ margin: "6px 0",
115
+ },
116
+ }, a: {
117
+ color: theme.custom.colors.red,
118
+ fontWeight: "normal",
119
+ }, borderRadius: "12px", [`.${classes.messageRowUser} &`]: {
120
+ padding: "12px 16px",
121
+ borderRadius: "8px 0px 8px 8px",
122
+ backgroundColor: theme.custom.colors.lightGray1,
123
+ } })));
124
+ const StarterContainer = styled.div({
125
+ alignSelf: "flex-end",
126
+ alignItems: "end",
127
+ display: "flex",
128
+ flexDirection: "column",
129
+ gap: "12px",
130
+ });
131
+ const Starter = styled.button(({ theme }) => (Object.assign(Object.assign({ border: `1px solid ${theme.custom.colors.lightGray2}`, backgroundColor: theme.custom.colors.white, padding: "8px 16px" }, theme.typography.body3), { cursor: "pointer", boxSizing: "border-box", "&:hover": {
132
+ color: theme.custom.colors.white,
133
+ backgroundColor: theme.custom.colors.silverGrayDark,
134
+ borderColor: "transparent",
135
+ }, borderRadius: "8px" })));
136
+ const StyledSendButton = styled(RiSendPlaneFill)(({ theme }) => ({
137
+ fill: theme.custom.colors.red,
138
+ }));
139
+ const StyledStopButton = styled(RiStopFill)(({ theme }) => ({
140
+ fill: theme.custom.colors.red,
141
+ }));
142
+ const BottomSection = styled.div(({ externalScroll, theme }) => (Object.assign(Object.assign({ padding: "12px 0 16px" }, (externalScroll && {
143
+ position: "sticky",
144
+ bottom: 0,
145
+ background: theme.custom.colors.white,
146
+ })), { "button:focus-visible": {
147
+ outlineOffset: "-1px",
148
+ borderRadius: "7px",
149
+ } })));
150
+ const Disclaimer = styled(Typography)(({ theme }) => ({
151
+ color: theme.custom.colors.silverGrayDark,
152
+ marginTop: "16px",
153
+ textAlign: "center",
154
+ }));
155
+ const StyledEllipsisIcon = styled(EllipsisIcon)(({ theme }) => ({
156
+ ellipse: {
157
+ fill: theme.custom.colors.darkGray2,
158
+ },
159
+ width: "24px",
160
+ height: "24px",
161
+ }));
162
+ const AiChatDisplay = (_a) => {
163
+ var _b, _c;
164
+ var { conversationStarters, askTimTitle, entryScreenEnabled = true, entryScreenTitle, srLoadingMessages, placeholder = "", className, scrollElement, ref, useMathJax = false } = _a, others = __rest(_a, ["conversationStarters", "askTimTitle", "entryScreenEnabled", "entryScreenTitle", "srLoadingMessages", "placeholder", "className", "scrollElement", "ref", "useMathJax"]) // Could contain data attributes
165
+ ;
166
+ const containerRef = useRef(null);
167
+ const messagesContainerRef = useRef(null);
168
+ const chatScreenRef = useRef(null);
169
+ const promptInputRef = useRef(null);
170
+ const { messages, input, handleInputChange, handleSubmit, append, isLoading, stop, error, initialMessages, status, } = useAiChat();
171
+ useScrollSnap({
172
+ scrollElement: scrollElement || messagesContainerRef.current,
173
+ contentElement: scrollElement ? messagesContainerRef.current : null,
174
+ threshold: 200,
175
+ });
176
+ const [showEntryScreen, setShowEntryScreen] = useState(entryScreenEnabled);
177
+ useEffect(() => {
178
+ var _a, _b;
179
+ if (!showEntryScreen) {
180
+ (_b = (_a = promptInputRef.current) === null || _a === void 0 ? void 0 : _a.querySelector("input")) === null || _b === void 0 ? void 0 : _b.focus();
181
+ }
182
+ }, [showEntryScreen]);
183
+ useEffect(() => {
184
+ if (messages.some((m) => m.role === "user" || ["submitted", "streaming"].includes(status))) {
185
+ setShowEntryScreen(false);
186
+ }
187
+ }, [messages, status]);
188
+ const showStarters = messages.length === ((initialMessages === null || initialMessages === void 0 ? void 0 : initialMessages.length) || 0);
189
+ const waiting = !showStarters && !error && ((_b = messages[messages.length - 1]) === null || _b === void 0 ? void 0 : _b.role) === "user";
190
+ const stoppable = isLoading && ((_c = messages[messages.length - 1]) === null || _c === void 0 ? void 0 : _c.role) !== "user";
191
+ const scrollToBottom = () => {
192
+ const element = scrollElement || messagesContainerRef.current;
193
+ element === null || element === void 0 ? void 0 : element.scrollBy({
194
+ behavior: "instant",
195
+ top: element === null || element === void 0 ? void 0 : element.scrollHeight,
196
+ });
197
+ };
198
+ const lastMsg = messages[messages.length - 1];
199
+ const externalScroll = !!scrollElement;
200
+ return (React.createElement(Container, { className: className, ref: containerRef }, showEntryScreen ? (React.createElement(EntryScreen, { className: classes.entryScreenContainer, title: entryScreenTitle, conversationStarters: conversationStarters, onPromptSubmit: (prompt) => {
201
+ if (prompt.trim() === "") {
202
+ return;
203
+ }
204
+ setShowEntryScreen(false);
205
+ append({ role: "user", content: prompt });
206
+ } })) : (React.createElement(ChatScreen, { className: classes.chatScreenContainer, "data-testid": "ai-chat-screen", externalScroll: externalScroll, ref: chatScreenRef },
207
+ React.createElement(ChatContainer, Object.assign({ className: classNames(className, classes.root), externalScroll: externalScroll }, others),
208
+ React.createElement(ChatTitle, { askTimTitle: askTimTitle, externalScroll: externalScroll, className: classNames(className, classes.title) }),
209
+ React.createElement(MessagesContainer, { className: classes.messagesContainer, externalScroll: externalScroll, ref: messagesContainerRef },
210
+ messages.map((m, i) => {
211
+ // Our Markdown+Mathjax has issues when rendering streaming display math
212
+ // Force a re-render of the last (streaming) message when it's done loading.
213
+ const key = i === messages.length - 1 && isLoading
214
+ ? `isLoading-${m.id}`
215
+ : m.id;
216
+ return (React.createElement(MessageRow, { key: key, "data-chat-role": m.role, className: classNames(classes.messageRow, {
217
+ [classes.messageRowUser]: m.role === "user",
218
+ [classes.messageRowAssistant]: m.role === "assistant",
219
+ }) },
220
+ React.createElement(Message, { className: classes.message },
221
+ React.createElement(VisuallyHidden, { as: m.role === "user" ? "h5" : "h6" }, m.role === "user" ? "You said: " : "Assistant said: "),
222
+ React.createElement(Markdown, { enableMathjax: useMathJax }, m.content))));
223
+ }),
224
+ showStarters ? (React.createElement(StarterContainer, null, conversationStarters === null || conversationStarters === void 0 ? void 0 : conversationStarters.map((m) => (React.createElement(Starter, { className: classes.conversationStarter, key: m.content, onClick: () => {
225
+ scrollToBottom();
226
+ append({ role: "user", content: m.content });
227
+ } }, m.content))))) : null,
228
+ waiting ? (React.createElement(MessageRow, { className: classNames(classes.messageRow, classes.messageRowAssistant), key: "loading" },
229
+ React.createElement(Message, null,
230
+ React.createElement(StyledEllipsisIcon, null)))) : null,
231
+ error ? (React.createElement(Alert, { severity: "error", closable: true }, "An unexpected error has occurred.")) : null),
232
+ React.createElement(BottomSection, { externalScroll: externalScroll, className: classes.bottomSection },
233
+ React.createElement("form", { onSubmit: (e) => {
234
+ e.preventDefault();
235
+ if (isLoading && stoppable) {
236
+ stop();
237
+ }
238
+ else {
239
+ scrollToBottom();
240
+ handleSubmit(e);
241
+ }
242
+ } },
243
+ React.createElement(Input, { ref: promptInputRef, fullWidth: true, size: "chat", className: classes.input, placeholder: placeholder, name: "message", sx: { flex: 1 }, value: input, onChange: handleInputChange, inputProps: {
244
+ "aria-label": "Ask a question",
245
+ }, endAdornment: isLoading ? (React.createElement(AdornmentButton, { "aria-label": "Stop", onClick: stop, disabled: !stoppable },
246
+ React.createElement(StyledStopButton, null))) : (React.createElement(AdornmentButton, { "aria-label": "Send", type: "submit", onClick: (e) => {
247
+ if (input.trim() === "") {
248
+ e.preventDefault();
249
+ return;
250
+ }
251
+ scrollToBottom();
252
+ handleSubmit(e);
253
+ } },
254
+ React.createElement(StyledSendButton, null))) })),
255
+ React.createElement(Disclaimer, { variant: "body3" }, "AI-generated content may be incorrect.")),
256
+ React.createElement(SrAnnouncer, { isLoading: isLoading, loadingMessages: srLoadingMessages, message: (lastMsg === null || lastMsg === void 0 ? void 0 : lastMsg.role) === "assistant" ? lastMsg === null || lastMsg === void 0 ? void 0 : lastMsg.content : "" }))))));
257
+ };
258
+ const AiChat = (_a) => {
259
+ var { requestOpts, initialMessages, chatId, parseContent } = _a, displayProps = __rest(_a, ["requestOpts", "initialMessages", "chatId", "parseContent"]);
260
+ return (React.createElement(AiChatProvider, { requestOpts: requestOpts, chatId: chatId, initialMessages: initialMessages, parseContent: parseContent },
261
+ React.createElement(AiChatDisplay, Object.assign({}, displayProps))));
262
+ };
263
+ export { AiChatDisplay, AiChat };
@@ -0,0 +1,17 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { AiChat } from "./AiChat";
3
+ declare const meta: Meta<typeof AiChat>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof AiChat>;
6
+ export declare const StreamingResponses: Story;
7
+ /**
8
+ * Here `AiChat` is used with a non-streaming JSON API. The JSON is converted
9
+ * to text via `parseContent`.
10
+ */
11
+ export declare const JsonResponses: Story;
12
+ /**
13
+ * Where a scrollable container exists in the including component, it can be passed in
14
+ * for the AiChat component to use in place of its own height constrained message container
15
+ * overflow scroll. This is useful for cases such as use inside a modal or drawer.
16
+ */
17
+ export declare const ScrollContainer: Story;