@mitodl/smoot-design 0.0.0-7bc0c0f

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 (243) hide show
  1. package/LICENSE +28 -0
  2. package/README.md +31 -0
  3. package/dist/bundles/remoteTutorDrawer.es.js +38347 -0
  4. package/dist/bundles/remoteTutorDrawer.umd.js +207 -0
  5. package/dist/cjs/ai.d.ts +3 -0
  6. package/dist/cjs/ai.js +5 -0
  7. package/dist/cjs/bundles/RemoteTutorDrawer/FlashcardsScreen.d.ts +9 -0
  8. package/dist/cjs/bundles/RemoteTutorDrawer/FlashcardsScreen.js +87 -0
  9. package/dist/cjs/bundles/RemoteTutorDrawer/RemoteTutorDrawer.d.ts +57 -0
  10. package/dist/cjs/bundles/RemoteTutorDrawer/RemoteTutorDrawer.js +276 -0
  11. package/dist/cjs/bundles/RemoteTutorDrawer/RemoteTutorDrawer.stories.d.ts +16 -0
  12. package/dist/cjs/bundles/RemoteTutorDrawer/RemoteTutorDrawer.stories.js +283 -0
  13. package/dist/cjs/bundles/RemoteTutorDrawer/RemoteTutorDrawer.test.d.ts +1 -0
  14. package/dist/cjs/bundles/RemoteTutorDrawer/RemoteTutorDrawer.test.js +241 -0
  15. package/dist/cjs/bundles/remoteTutorDrawer.d.ts +7 -0
  16. package/dist/cjs/bundles/remoteTutorDrawer.js +40 -0
  17. package/dist/cjs/components/AiChat/AiChat.d.ts +5 -0
  18. package/dist/cjs/components/AiChat/AiChat.js +247 -0
  19. package/dist/cjs/components/AiChat/AiChat.stories.d.ts +21 -0
  20. package/dist/cjs/components/AiChat/AiChat.stories.js +243 -0
  21. package/dist/cjs/components/AiChat/AiChat.test.d.ts +1 -0
  22. package/dist/cjs/components/AiChat/AiChat.test.js +211 -0
  23. package/dist/cjs/components/AiChat/ChatTitle.d.ts +8 -0
  24. package/dist/cjs/components/AiChat/ChatTitle.js +43 -0
  25. package/dist/cjs/components/AiChat/EntryScreen.d.ts +11 -0
  26. package/dist/cjs/components/AiChat/EntryScreen.js +123 -0
  27. package/dist/cjs/components/AiChat/TimLogo.d.ts +5 -0
  28. package/dist/cjs/components/AiChat/TimLogo.js +15 -0
  29. package/dist/cjs/components/AiChat/test-utils/api.d.ts +2 -0
  30. package/dist/cjs/components/AiChat/test-utils/api.js +125 -0
  31. package/dist/cjs/components/AiChat/types.d.ts +82 -0
  32. package/dist/cjs/components/AiChat/types.js +3 -0
  33. package/dist/cjs/components/AiChat/utils.d.ts +9 -0
  34. package/dist/cjs/components/AiChat/utils.js +41 -0
  35. package/dist/cjs/components/Alert/Alert.d.ts +15 -0
  36. package/dist/cjs/components/Alert/Alert.js +62 -0
  37. package/dist/cjs/components/Alert/Alert.stories.d.ts +8 -0
  38. package/dist/cjs/components/Alert/Alert.stories.js +53 -0
  39. package/dist/cjs/components/Button/ActionButton.d.ts +30 -0
  40. package/dist/cjs/components/Button/ActionButton.js +73 -0
  41. package/dist/cjs/components/Button/ActionButton.stories.d.ts +15 -0
  42. package/dist/cjs/components/Button/ActionButton.stories.js +113 -0
  43. package/dist/cjs/components/Button/Button.d.ts +54 -0
  44. package/dist/cjs/components/Button/Button.js +240 -0
  45. package/dist/cjs/components/Button/Button.stories.d.ts +17 -0
  46. package/dist/cjs/components/Button/Button.stories.js +135 -0
  47. package/dist/cjs/components/Button/Button.test.d.ts +1 -0
  48. package/dist/cjs/components/Button/Button.test.js +46 -0
  49. package/dist/cjs/components/ImageAdapter/ImageAdapter.d.ts +23 -0
  50. package/dist/cjs/components/ImageAdapter/ImageAdapter.js +30 -0
  51. package/dist/cjs/components/Input/Input.d.ts +116 -0
  52. package/dist/cjs/components/Input/Input.js +237 -0
  53. package/dist/cjs/components/Input/Input.stories.d.ts +19 -0
  54. package/dist/cjs/components/Input/Input.stories.js +135 -0
  55. package/dist/cjs/components/Input/Input.test.d.ts +1 -0
  56. package/dist/cjs/components/Input/Input.test.js +32 -0
  57. package/dist/cjs/components/LinkAdapter/LinkAdapter.d.ts +23 -0
  58. package/dist/cjs/components/LinkAdapter/LinkAdapter.js +34 -0
  59. package/dist/cjs/components/ScrollSnap/ScrollSnap.d.ts +19 -0
  60. package/dist/cjs/components/ScrollSnap/ScrollSnap.js +59 -0
  61. package/dist/cjs/components/ScrollSnap/ScrollSnap.stories.d.ts +6 -0
  62. package/dist/cjs/components/ScrollSnap/ScrollSnap.stories.js +43 -0
  63. package/dist/cjs/components/ScrollSnap/useScrollSnap.d.ts +6 -0
  64. package/dist/cjs/components/ScrollSnap/useScrollSnap.js +36 -0
  65. package/dist/cjs/components/SrAnnouncer/SrAnnouncer.d.ts +25 -0
  66. package/dist/cjs/components/SrAnnouncer/SrAnnouncer.js +43 -0
  67. package/dist/cjs/components/SrAnnouncer/SrAnnouncer.stories.d.ts +6 -0
  68. package/dist/cjs/components/SrAnnouncer/SrAnnouncer.stories.js +44 -0
  69. package/dist/cjs/components/SrAnnouncer/SrAnnouncer.test.d.ts +1 -0
  70. package/dist/cjs/components/SrAnnouncer/SrAnnouncer.test.js +62 -0
  71. package/dist/cjs/components/TabButtons/TabButtonList.d.ts +25 -0
  72. package/dist/cjs/components/TabButtons/TabButtonList.js +97 -0
  73. package/dist/cjs/components/TabButtons/TabButtonList.stories.d.ts +24 -0
  74. package/dist/cjs/components/TabButtons/TabButtonList.stories.js +139 -0
  75. package/dist/cjs/components/TextField/TextField.d.ts +29 -0
  76. package/dist/cjs/components/TextField/TextField.js +33 -0
  77. package/dist/cjs/components/TextField/TextField.stories.d.ts +10 -0
  78. package/dist/cjs/components/TextField/TextField.stories.js +136 -0
  79. package/dist/cjs/components/TextField/TextField.test.d.ts +1 -0
  80. package/dist/cjs/components/TextField/TextField.test.js +77 -0
  81. package/dist/cjs/components/ThemeProvider/ThemeProvider.d.ts +21 -0
  82. package/dist/cjs/components/ThemeProvider/ThemeProvider.js +86 -0
  83. package/dist/cjs/components/ThemeProvider/ThemeProvider.stories.d.ts +63 -0
  84. package/dist/cjs/components/ThemeProvider/ThemeProvider.stories.js +102 -0
  85. package/dist/cjs/components/ThemeProvider/Typography.stories.d.ts +39 -0
  86. package/dist/cjs/components/ThemeProvider/Typography.stories.js +65 -0
  87. package/dist/cjs/components/ThemeProvider/breakpoints.d.ts +4 -0
  88. package/dist/cjs/components/ThemeProvider/breakpoints.js +19 -0
  89. package/dist/cjs/components/ThemeProvider/buttons.d.ts +7 -0
  90. package/dist/cjs/components/ThemeProvider/buttons.js +20 -0
  91. package/dist/cjs/components/ThemeProvider/chips.d.ts +3 -0
  92. package/dist/cjs/components/ThemeProvider/chips.js +154 -0
  93. package/dist/cjs/components/ThemeProvider/colors.d.ts +32 -0
  94. package/dist/cjs/components/ThemeProvider/colors.js +35 -0
  95. package/dist/cjs/components/ThemeProvider/typography.d.ts +18 -0
  96. package/dist/cjs/components/ThemeProvider/typography.js +173 -0
  97. package/dist/cjs/components/VisuallyHidden/VisuallyHidden.d.ts +24 -0
  98. package/dist/cjs/components/VisuallyHidden/VisuallyHidden.js +33 -0
  99. package/dist/cjs/components/VisuallyHidden/VisuallyHidden.stories.d.ts +6 -0
  100. package/dist/cjs/components/VisuallyHidden/VisuallyHidden.stories.js +13 -0
  101. package/dist/cjs/components/internal/FormHelpers/FormHelpers.d.ts +39 -0
  102. package/dist/cjs/components/internal/FormHelpers/FormHelpers.js +78 -0
  103. package/dist/cjs/components/internal/FormHelpers/FormHelpers.test.d.ts +1 -0
  104. package/dist/cjs/components/internal/FormHelpers/FormHelpers.test.js +93 -0
  105. package/dist/cjs/index.d.ts +16 -0
  106. package/dist/cjs/index.js +30 -0
  107. package/dist/cjs/jest-setup.d.ts +1 -0
  108. package/dist/cjs/jest-setup.js +18 -0
  109. package/dist/cjs/jsdom-extended.d.ts +6 -0
  110. package/dist/cjs/jsdom-extended.js +14 -0
  111. package/dist/cjs/story-utils/index.d.ts +6 -0
  112. package/dist/cjs/story-utils/index.js +17 -0
  113. package/dist/cjs/utils/composeRefs.d.ts +7 -0
  114. package/dist/cjs/utils/composeRefs.js +20 -0
  115. package/dist/cjs/utils/composeRefs.test.d.ts +1 -0
  116. package/dist/cjs/utils/composeRefs.test.js +19 -0
  117. package/dist/cjs/utils/useDevCheckStable.d.ts +8 -0
  118. package/dist/cjs/utils/useDevCheckStable.js +29 -0
  119. package/dist/cjs/utils/useInterval.d.ts +7 -0
  120. package/dist/cjs/utils/useInterval.js +25 -0
  121. package/dist/esm/ai.d.ts +3 -0
  122. package/dist/esm/ai.js +1 -0
  123. package/dist/esm/bundles/RemoteTutorDrawer/FlashcardsScreen.d.ts +9 -0
  124. package/dist/esm/bundles/RemoteTutorDrawer/FlashcardsScreen.js +83 -0
  125. package/dist/esm/bundles/RemoteTutorDrawer/RemoteTutorDrawer.d.ts +57 -0
  126. package/dist/esm/bundles/RemoteTutorDrawer/RemoteTutorDrawer.js +273 -0
  127. package/dist/esm/bundles/RemoteTutorDrawer/RemoteTutorDrawer.stories.d.ts +16 -0
  128. package/dist/esm/bundles/RemoteTutorDrawer/RemoteTutorDrawer.stories.js +280 -0
  129. package/dist/esm/bundles/RemoteTutorDrawer/RemoteTutorDrawer.test.d.ts +1 -0
  130. package/dist/esm/bundles/RemoteTutorDrawer/RemoteTutorDrawer.test.js +239 -0
  131. package/dist/esm/bundles/remoteTutorDrawer.d.ts +7 -0
  132. package/dist/esm/bundles/remoteTutorDrawer.js +37 -0
  133. package/dist/esm/components/AiChat/AiChat.d.ts +5 -0
  134. package/dist/esm/components/AiChat/AiChat.js +244 -0
  135. package/dist/esm/components/AiChat/AiChat.stories.d.ts +21 -0
  136. package/dist/esm/components/AiChat/AiChat.stories.js +240 -0
  137. package/dist/esm/components/AiChat/AiChat.test.d.ts +1 -0
  138. package/dist/esm/components/AiChat/AiChat.test.js +209 -0
  139. package/dist/esm/components/AiChat/ChatTitle.d.ts +8 -0
  140. package/dist/esm/components/AiChat/ChatTitle.js +40 -0
  141. package/dist/esm/components/AiChat/EntryScreen.d.ts +11 -0
  142. package/dist/esm/components/AiChat/EntryScreen.js +120 -0
  143. package/dist/esm/components/AiChat/TimLogo.d.ts +5 -0
  144. package/dist/esm/components/AiChat/TimLogo.js +13 -0
  145. package/dist/esm/components/AiChat/test-utils/api.d.ts +2 -0
  146. package/dist/esm/components/AiChat/test-utils/api.js +122 -0
  147. package/dist/esm/components/AiChat/types.d.ts +82 -0
  148. package/dist/esm/components/AiChat/types.js +2 -0
  149. package/dist/esm/components/AiChat/utils.d.ts +9 -0
  150. package/dist/esm/components/AiChat/utils.js +38 -0
  151. package/dist/esm/components/Alert/Alert.d.ts +15 -0
  152. package/dist/esm/components/Alert/Alert.js +59 -0
  153. package/dist/esm/components/Alert/Alert.stories.d.ts +8 -0
  154. package/dist/esm/components/Alert/Alert.stories.js +50 -0
  155. package/dist/esm/components/Button/ActionButton.d.ts +30 -0
  156. package/dist/esm/components/Button/ActionButton.js +68 -0
  157. package/dist/esm/components/Button/ActionButton.stories.d.ts +15 -0
  158. package/dist/esm/components/Button/ActionButton.stories.js +110 -0
  159. package/dist/esm/components/Button/Button.d.ts +54 -0
  160. package/dist/esm/components/Button/Button.js +232 -0
  161. package/dist/esm/components/Button/Button.stories.d.ts +17 -0
  162. package/dist/esm/components/Button/Button.stories.js +132 -0
  163. package/dist/esm/components/Button/Button.test.d.ts +1 -0
  164. package/dist/esm/components/Button/Button.test.js +44 -0
  165. package/dist/esm/components/ImageAdapter/ImageAdapter.d.ts +23 -0
  166. package/dist/esm/components/ImageAdapter/ImageAdapter.js +27 -0
  167. package/dist/esm/components/Input/Input.d.ts +116 -0
  168. package/dist/esm/components/Input/Input.js +232 -0
  169. package/dist/esm/components/Input/Input.stories.d.ts +19 -0
  170. package/dist/esm/components/Input/Input.stories.js +132 -0
  171. package/dist/esm/components/Input/Input.test.d.ts +1 -0
  172. package/dist/esm/components/Input/Input.test.js +30 -0
  173. package/dist/esm/components/LinkAdapter/LinkAdapter.d.ts +23 -0
  174. package/dist/esm/components/LinkAdapter/LinkAdapter.js +31 -0
  175. package/dist/esm/components/ScrollSnap/ScrollSnap.d.ts +19 -0
  176. package/dist/esm/components/ScrollSnap/ScrollSnap.js +56 -0
  177. package/dist/esm/components/ScrollSnap/ScrollSnap.stories.d.ts +6 -0
  178. package/dist/esm/components/ScrollSnap/ScrollSnap.stories.js +40 -0
  179. package/dist/esm/components/ScrollSnap/useScrollSnap.d.ts +6 -0
  180. package/dist/esm/components/ScrollSnap/useScrollSnap.js +33 -0
  181. package/dist/esm/components/SrAnnouncer/SrAnnouncer.d.ts +25 -0
  182. package/dist/esm/components/SrAnnouncer/SrAnnouncer.js +40 -0
  183. package/dist/esm/components/SrAnnouncer/SrAnnouncer.stories.d.ts +6 -0
  184. package/dist/esm/components/SrAnnouncer/SrAnnouncer.stories.js +41 -0
  185. package/dist/esm/components/SrAnnouncer/SrAnnouncer.test.d.ts +1 -0
  186. package/dist/esm/components/SrAnnouncer/SrAnnouncer.test.js +60 -0
  187. package/dist/esm/components/TabButtons/TabButtonList.d.ts +25 -0
  188. package/dist/esm/components/TabButtons/TabButtonList.js +92 -0
  189. package/dist/esm/components/TabButtons/TabButtonList.stories.d.ts +24 -0
  190. package/dist/esm/components/TabButtons/TabButtonList.stories.js +136 -0
  191. package/dist/esm/components/TextField/TextField.d.ts +29 -0
  192. package/dist/esm/components/TextField/TextField.js +30 -0
  193. package/dist/esm/components/TextField/TextField.stories.d.ts +10 -0
  194. package/dist/esm/components/TextField/TextField.stories.js +133 -0
  195. package/dist/esm/components/TextField/TextField.test.d.ts +1 -0
  196. package/dist/esm/components/TextField/TextField.test.js +75 -0
  197. package/dist/esm/components/ThemeProvider/ThemeProvider.d.ts +21 -0
  198. package/dist/esm/components/ThemeProvider/ThemeProvider.js +82 -0
  199. package/dist/esm/components/ThemeProvider/ThemeProvider.stories.d.ts +63 -0
  200. package/dist/esm/components/ThemeProvider/ThemeProvider.stories.js +99 -0
  201. package/dist/esm/components/ThemeProvider/Typography.stories.d.ts +39 -0
  202. package/dist/esm/components/ThemeProvider/Typography.stories.js +62 -0
  203. package/dist/esm/components/ThemeProvider/breakpoints.d.ts +4 -0
  204. package/dist/esm/components/ThemeProvider/breakpoints.js +15 -0
  205. package/dist/esm/components/ThemeProvider/buttons.d.ts +7 -0
  206. package/dist/esm/components/ThemeProvider/buttons.js +17 -0
  207. package/dist/esm/components/ThemeProvider/chips.d.ts +3 -0
  208. package/dist/esm/components/ThemeProvider/chips.js +151 -0
  209. package/dist/esm/components/ThemeProvider/colors.d.ts +32 -0
  210. package/dist/esm/components/ThemeProvider/colors.js +32 -0
  211. package/dist/esm/components/ThemeProvider/typography.d.ts +18 -0
  212. package/dist/esm/components/ThemeProvider/typography.js +167 -0
  213. package/dist/esm/components/VisuallyHidden/VisuallyHidden.d.ts +24 -0
  214. package/dist/esm/components/VisuallyHidden/VisuallyHidden.js +30 -0
  215. package/dist/esm/components/VisuallyHidden/VisuallyHidden.stories.d.ts +6 -0
  216. package/dist/esm/components/VisuallyHidden/VisuallyHidden.stories.js +10 -0
  217. package/dist/esm/components/internal/FormHelpers/FormHelpers.d.ts +39 -0
  218. package/dist/esm/components/internal/FormHelpers/FormHelpers.js +73 -0
  219. package/dist/esm/components/internal/FormHelpers/FormHelpers.test.d.ts +1 -0
  220. package/dist/esm/components/internal/FormHelpers/FormHelpers.test.js +91 -0
  221. package/dist/esm/index.d.ts +16 -0
  222. package/dist/esm/index.js +11 -0
  223. package/dist/esm/jest-setup.d.ts +1 -0
  224. package/dist/esm/jest-setup.js +16 -0
  225. package/dist/esm/jsdom-extended.d.ts +6 -0
  226. package/dist/esm/jsdom-extended.js +12 -0
  227. package/dist/esm/story-utils/index.d.ts +6 -0
  228. package/dist/esm/story-utils/index.js +13 -0
  229. package/dist/esm/utils/composeRefs.d.ts +7 -0
  230. package/dist/esm/utils/composeRefs.js +17 -0
  231. package/dist/esm/utils/composeRefs.test.d.ts +1 -0
  232. package/dist/esm/utils/composeRefs.test.js +17 -0
  233. package/dist/esm/utils/useDevCheckStable.d.ts +8 -0
  234. package/dist/esm/utils/useDevCheckStable.js +26 -0
  235. package/dist/esm/utils/useInterval.d.ts +7 -0
  236. package/dist/esm/utils/useInterval.js +22 -0
  237. package/dist/tsconfig.tsbuildinfo +1 -0
  238. package/dist/type-augmentation/TypescriptDocs.mdx +17 -0
  239. package/dist/type-augmentation/imports.d.ts +3 -0
  240. package/dist/type-augmentation/index.d.ts +3 -0
  241. package/dist/type-augmentation/theme.d.ts +105 -0
  242. package/dist/type-augmentation/typography.d.ts +54 -0
  243. package/package.json +155 -0
@@ -0,0 +1,211 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ // This was giving false positives
13
+ /* eslint-disable testing-library/await-async-utils */
14
+ const react_1 = require("@testing-library/react");
15
+ const user_event_1 = require("@testing-library/user-event");
16
+ const AiChat_1 = require("./AiChat");
17
+ const ThemeProvider_1 = require("../ThemeProvider/ThemeProvider");
18
+ const React = require("react");
19
+ const en_1 = require("@faker-js/faker/locale/en");
20
+ const msw_1 = require("msw");
21
+ const node_1 = require("msw/node");
22
+ const counter = jest.fn(); // use jest.fn as counter because it resets on each test
23
+ const API_URL = "http://localhost:4567/test";
24
+ const server = (0, node_1.setupServer)(msw_1.http.post(API_URL, () => __awaiter(void 0, void 0, void 0, function* () {
25
+ const count = counter.mock.calls.length;
26
+ counter();
27
+ return msw_1.HttpResponse.text(`AI Response ${count}`);
28
+ })));
29
+ beforeAll(() => server.listen());
30
+ afterEach(() => server.resetHandlers());
31
+ afterAll(() => server.close());
32
+ jest.mock("react-markdown", () => {
33
+ return {
34
+ __esModule: true,
35
+ default: ({ children }) => React.createElement("div", null, children),
36
+ };
37
+ });
38
+ const msg = {
39
+ ai: (text) => `Assistant said: ${text}`,
40
+ you: (text) => `You said: ${text}`,
41
+ };
42
+ const getMessages = () => {
43
+ return Array.from(document.querySelectorAll(".MitAiChat--message"));
44
+ };
45
+ const getConversationStarters = () => {
46
+ return Array.from(document.querySelectorAll("button.MitAiChat--conversationStarter"));
47
+ };
48
+ const whenCount = (cb, count) => __awaiter(void 0, void 0, void 0, function* () {
49
+ return yield (0, react_1.waitFor)(() => {
50
+ const result = cb();
51
+ expect(result).toHaveLength(count);
52
+ return result;
53
+ });
54
+ });
55
+ describe("AiChat", () => {
56
+ beforeEach(() => {
57
+ const MockObserverInstance = {
58
+ observe: jest.fn(),
59
+ unobserve: jest.fn(),
60
+ disconnect: jest.fn(),
61
+ };
62
+ global.ResizeObserver = jest
63
+ .fn()
64
+ .mockImplementation(() => MockObserverInstance);
65
+ });
66
+ const setup = (props = {}) => {
67
+ const initialMessages = [
68
+ { role: "assistant", content: en_1.faker.lorem.sentence() },
69
+ ];
70
+ const conversationStarters = [
71
+ { content: en_1.faker.lorem.sentence() },
72
+ { content: en_1.faker.lorem.sentence() },
73
+ ];
74
+ const view = (0, react_1.render)(React.createElement(AiChat_1.AiChat, Object.assign({ "data-testid": "ai-chat", initialMessages: initialMessages, conversationStarters: conversationStarters, requestOpts: { apiUrl: API_URL }, placeholder: "Type a message...", entryScreenEnabled: false }, props)), { wrapper: ThemeProvider_1.ThemeProvider });
75
+ const rerender = (newProps) => {
76
+ view.rerender(React.createElement(AiChat_1.AiChat, Object.assign({ "data-testid": "ai-chat", initialMessages: initialMessages, conversationStarters: conversationStarters, requestOpts: { apiUrl: API_URL }, entryScreenEnabled: false }, newProps)));
77
+ };
78
+ return { initialMessages, conversationStarters, rerender };
79
+ };
80
+ test("Clicking conversation starters and sending chats", () => __awaiter(void 0, void 0, void 0, function* () {
81
+ const { initialMessages, conversationStarters } = setup();
82
+ const scrollBy = jest.spyOn(HTMLElement.prototype, "scrollBy");
83
+ const initialMessageEls = getMessages();
84
+ expect(initialMessageEls.length).toBe(1);
85
+ expect(initialMessageEls[0]).toHaveTextContent(initialMessages[0].content);
86
+ const starterEls = getConversationStarters();
87
+ expect(starterEls.length).toBe(2);
88
+ expect(starterEls[0]).toHaveTextContent(conversationStarters[0].content);
89
+ expect(starterEls[1]).toHaveTextContent(conversationStarters[1].content);
90
+ const chosen = en_1.faker.helpers.arrayElement([0, 1]);
91
+ yield user_event_1.default.click(starterEls[chosen]);
92
+ expect(scrollBy).toHaveBeenCalled();
93
+ scrollBy.mockReset();
94
+ const messageEls = yield whenCount(getMessages, 3);
95
+ expect(messageEls[0]).toHaveTextContent(initialMessages[0].content);
96
+ expect(messageEls[1]).toHaveTextContent(conversationStarters[chosen].content);
97
+ expect(messageEls[2]).toHaveTextContent("AI Response 0");
98
+ yield user_event_1.default.click(react_1.screen.getByPlaceholderText("Type a message..."));
99
+ yield user_event_1.default.paste("User message");
100
+ yield user_event_1.default.click(react_1.screen.getByRole("button", { name: "Send" }));
101
+ expect(scrollBy).toHaveBeenCalled();
102
+ const afterSending = yield whenCount(getMessages, 5);
103
+ expect(afterSending[3]).toHaveTextContent("User message");
104
+ expect(afterSending[4]).toHaveTextContent("AI Response 1");
105
+ }));
106
+ test("Messages persist if chat has same chatId", () => __awaiter(void 0, void 0, void 0, function* () {
107
+ const { rerender } = setup({ chatId: "test-123" });
108
+ const starterEls = getConversationStarters();
109
+ const chosen = en_1.faker.helpers.arrayElement([0, 1]);
110
+ yield user_event_1.default.click(starterEls[chosen]);
111
+ yield whenCount(getMessages, 3);
112
+ // New chat ... starters should be shown
113
+ rerender({ chatId: "test-345" });
114
+ expect(getConversationStarters().length).toBeGreaterThan(0);
115
+ yield whenCount(getMessages, 1);
116
+ // existing chat ... starters should not be shown, messages should be restored
117
+ rerender({ chatId: "test-123" });
118
+ expect(getConversationStarters().length).toBe(0);
119
+ yield whenCount(getMessages, 3);
120
+ }));
121
+ test("transformBody is called before sending requests", () => __awaiter(void 0, void 0, void 0, function* () {
122
+ const mockFetch = jest.spyOn(window, "fetch");
123
+ const fakeBody = { message: en_1.faker.lorem.sentence() };
124
+ const transformBody = jest.fn(() => fakeBody);
125
+ const { initialMessages } = setup({
126
+ requestOpts: { apiUrl: API_URL, transformBody },
127
+ });
128
+ yield user_event_1.default.click(react_1.screen.getByPlaceholderText("Type a message..."));
129
+ yield user_event_1.default.paste("User message");
130
+ yield user_event_1.default.click(react_1.screen.getByRole("button", { name: "Send" }));
131
+ expect(transformBody).toHaveBeenCalledWith([
132
+ expect.objectContaining(initialMessages[0]),
133
+ expect.objectContaining({ content: "User message", role: "user" }),
134
+ ]);
135
+ expect(mockFetch).toHaveBeenCalledTimes(1);
136
+ expect(mockFetch).toHaveBeenCalledWith(API_URL, expect.objectContaining({
137
+ body: JSON.stringify(fakeBody),
138
+ }));
139
+ }));
140
+ test("parseContent is called on the API-received message content", () => __awaiter(void 0, void 0, void 0, function* () {
141
+ const fakeBody = { message: en_1.faker.lorem.sentence() };
142
+ const transformBody = jest.fn(() => fakeBody);
143
+ const { initialMessages, conversationStarters } = setup({
144
+ requestOpts: { apiUrl: API_URL, transformBody },
145
+ parseContent: jest.fn((content) => `Parsed: ${content}`),
146
+ });
147
+ yield user_event_1.default.click(getConversationStarters()[0]);
148
+ yield whenCount(getMessages, initialMessages.length + 2);
149
+ yield user_event_1.default.click(react_1.screen.getByPlaceholderText("Type a message..."));
150
+ yield user_event_1.default.paste("User message");
151
+ yield user_event_1.default.click(react_1.screen.getByRole("button", { name: "Send" }));
152
+ yield whenCount(getMessages, initialMessages.length + 4);
153
+ const messagesTexts = getMessages().map((el) => el.textContent);
154
+ expect(messagesTexts).toEqual([
155
+ msg.ai(initialMessages[0].content),
156
+ msg.you(conversationStarters[0].content),
157
+ msg.ai("Parsed: AI Response 0"),
158
+ msg.you("User message"),
159
+ msg.ai("Parsed: AI Response 1"),
160
+ ]);
161
+ }));
162
+ test("Passes extra attributes to root", () => {
163
+ const fakeBody = { message: en_1.faker.lorem.sentence() };
164
+ const transformBody = jest.fn(() => fakeBody);
165
+ setup({
166
+ requestOpts: { apiUrl: API_URL, transformBody },
167
+ parseContent: jest.fn((content) => `Parsed: ${content}`),
168
+ });
169
+ expect(react_1.screen.getByTestId("ai-chat")).toBeInTheDocument();
170
+ });
171
+ test("If the API returns an error, an alert is shown", () => __awaiter(void 0, void 0, void 0, function* () {
172
+ setup();
173
+ server.use(msw_1.http.post(API_URL, () => __awaiter(void 0, void 0, void 0, function* () {
174
+ return new msw_1.HttpResponse(null, { status: 500 });
175
+ })));
176
+ yield user_event_1.default.click(getConversationStarters()[0]);
177
+ const alert = yield react_1.screen.findByRole("alert");
178
+ expect(alert).toHaveTextContent("An unexpected error has occurred");
179
+ }));
180
+ test("Shows the entry screen if entryScreenEnabled is true", () => __awaiter(void 0, void 0, void 0, function* () {
181
+ setup({
182
+ entryScreenEnabled: true,
183
+ entryScreenTitle: "Entry Screen Title",
184
+ });
185
+ yield expect(react_1.screen.getByText("Entry Screen Title")).toBeInTheDocument();
186
+ }));
187
+ test("User can submit a prompt from the entry screen", () => __awaiter(void 0, void 0, void 0, function* () {
188
+ setup({
189
+ entryScreenEnabled: true,
190
+ entryScreenTitle: "Entry Screen Title",
191
+ initialMessages: [],
192
+ conversationStarters: [],
193
+ });
194
+ yield user_event_1.default.click(react_1.screen.getByRole("textbox"));
195
+ yield user_event_1.default.paste("User message");
196
+ yield user_event_1.default.click(react_1.screen.getByRole("button", { name: "Send" }));
197
+ const messages = getMessages();
198
+ expect(messages[0]).toHaveTextContent("User message");
199
+ }));
200
+ test("User can click starter on the entry screen to submit a prompt", () => __awaiter(void 0, void 0, void 0, function* () {
201
+ setup({
202
+ entryScreenEnabled: true,
203
+ entryScreenTitle: "Entry Screen Title",
204
+ initialMessages: [],
205
+ conversationStarters: [{ content: "Starter 1" }],
206
+ });
207
+ yield user_event_1.default.click(react_1.screen.getByRole("button", { name: "Starter 1" }));
208
+ const messages = getMessages();
209
+ expect(messages[0]).toHaveTextContent("Starter 1");
210
+ }));
211
+ });
@@ -0,0 +1,8 @@
1
+ import * as React from "react";
2
+ type ChatTitleProps = {
3
+ askTimTitle?: string;
4
+ externalScroll?: boolean;
5
+ className?: string;
6
+ };
7
+ declare const ChatTitle: ({ askTimTitle, externalScroll, className, }: ChatTitleProps) => React.JSX.Element | null;
8
+ export { ChatTitle };
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ChatTitle = void 0;
4
+ const React = require("react");
5
+ const styled_1 = require("@emotion/styled");
6
+ const Typography_1 = require("@mui/material/Typography");
7
+ const react_1 = require("@remixicon/react");
8
+ const Container = styled_1.default.div(({ externalScroll, theme }) => (Object.assign({ display: "flex", alignItems: "center", justifyContent: "space-between", padding: "12px 0", gap: "16px", color: theme.custom.colors.white, borderRadius: "8px 8px 0 0" }, (externalScroll && {
9
+ position: "sticky",
10
+ top: 0,
11
+ padding: "32px 0 26px",
12
+ zIndex: 2,
13
+ backgroundColor: theme.custom.colors.white,
14
+ borderRadius: 0,
15
+ }))));
16
+ const AskTimTitle = styled_1.default.div(({ theme }) => ({
17
+ display: "flex",
18
+ alignItems: "center",
19
+ gap: "8px",
20
+ color: theme.custom.colors.darkGray2,
21
+ img: {
22
+ width: "24px",
23
+ height: "24px",
24
+ },
25
+ svg: {
26
+ fill: theme.custom.colors.red,
27
+ width: "24px",
28
+ height: "24px",
29
+ },
30
+ }));
31
+ const ChatTitle = ({ askTimTitle, externalScroll, className, }) => {
32
+ if (!askTimTitle)
33
+ return null;
34
+ return (React.createElement(Container, { externalScroll: externalScroll, className: className },
35
+ React.createElement(AskTimTitle, null,
36
+ React.createElement(react_1.RiSparkling2Line, null),
37
+ React.createElement(Typography_1.default, { variant: "body1" },
38
+ "Ask",
39
+ React.createElement("strong", null, "TIM"),
40
+ "\u00A0",
41
+ askTimTitle))));
42
+ };
43
+ exports.ChatTitle = ChatTitle;
@@ -0,0 +1,11 @@
1
+ import * as React from "react";
2
+ type EntryScreenProps = {
3
+ title?: string;
4
+ conversationStarters?: {
5
+ content: string;
6
+ }[];
7
+ onPromptSubmit: (prompt: string) => void;
8
+ className?: string;
9
+ };
10
+ declare const EntryScreen: ({ title, conversationStarters, className, onPromptSubmit, }: EntryScreenProps) => React.JSX.Element;
11
+ export { EntryScreen };
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EntryScreen = void 0;
4
+ const React = require("react");
5
+ const react_1 = require("@remixicon/react");
6
+ const styled_1 = require("@emotion/styled");
7
+ const Typography_1 = require("@mui/material/Typography");
8
+ const Input_1 = require("../Input/Input");
9
+ const TimLogo_1 = require("./TimLogo");
10
+ const react_2 = require("react");
11
+ const Container = styled_1.default.div(({ theme }) => ({
12
+ display: "flex",
13
+ flexDirection: "column",
14
+ alignItems: "center",
15
+ gap: "16px",
16
+ padding: "114px 32px 24px",
17
+ [theme.breakpoints.down("md")]: {
18
+ padding: "114px 16px 24px",
19
+ width: "100%",
20
+ },
21
+ boxSizing: "border-box",
22
+ position: "absolute",
23
+ zIndex: 1,
24
+ background: "white",
25
+ bottom: 0,
26
+ top: 0,
27
+ left: 0,
28
+ right: 0,
29
+ }));
30
+ const TimLogoBox = styled_1.default.div(({ theme }) => ({
31
+ position: "relative",
32
+ padding: "16px",
33
+ border: `1px solid ${theme.custom.colors.lightGray2}`,
34
+ borderRadius: "8px",
35
+ "svg:first-child": {
36
+ fill: theme.custom.colors.red,
37
+ position: "absolute",
38
+ top: "-10px",
39
+ left: "-10px",
40
+ },
41
+ }));
42
+ const StyledTimLogo = (0, styled_1.default)(TimLogo_1.default)({
43
+ width: "40px",
44
+ height: "40px",
45
+ display: "block",
46
+ });
47
+ const Title = (0, styled_1.default)(Typography_1.default)({
48
+ textAlign: "center",
49
+ padding: "0 40px",
50
+ });
51
+ const StyledInput = (0, styled_1.default)(Input_1.Input)({
52
+ borderRadius: "8px",
53
+ margin: "8px 0 24px 0",
54
+ flexShrink: 0,
55
+ "button:focus-visible": {
56
+ outlineOffset: "-1px",
57
+ borderRadius: "7px",
58
+ },
59
+ });
60
+ const SendIcon = (0, styled_1.default)(react_1.RiSendPlaneFill)(({ theme }) => ({
61
+ fill: theme.custom.colors.red,
62
+ "button:disabled &": {
63
+ fill: theme.custom.colors.silverGray,
64
+ },
65
+ }));
66
+ const Starters = styled_1.default.div(({ theme }) => ({
67
+ display: "flex",
68
+ gap: "16px",
69
+ width: "100%",
70
+ [theme.breakpoints.down("sm")]: {
71
+ flexDirection: "column",
72
+ },
73
+ }));
74
+ const Starter = styled_1.default.button(({ theme }) => ({
75
+ flex: 1,
76
+ display: "flex",
77
+ alignItems: "center",
78
+ borderRadius: "8px",
79
+ border: `1px solid ${theme.custom.colors.lightGray2}`,
80
+ padding: "12px 16px",
81
+ color: theme.custom.colors.darkGray2,
82
+ backgroundColor: "transparent",
83
+ textAlign: "left",
84
+ [theme.breakpoints.down("sm")]: {
85
+ padding: "12px 36px",
86
+ },
87
+ ":hover": {
88
+ cursor: "pointer",
89
+ borderColor: "transparent",
90
+ color: theme.custom.colors.white,
91
+ backgroundColor: theme.custom.colors.darkGray1,
92
+ },
93
+ }));
94
+ const EntryScreen = ({ title, conversationStarters, className, onPromptSubmit, }) => {
95
+ const [prompt, setPrompt] = (0, react_2.useState)("");
96
+ const onPromptChange = (e) => {
97
+ setPrompt(e.target.value);
98
+ };
99
+ const onPromptKeyDown = (e) => {
100
+ if (e.key === "Enter" && prompt) {
101
+ onPromptSubmit(prompt);
102
+ }
103
+ else {
104
+ setPrompt(prompt);
105
+ }
106
+ };
107
+ return (React.createElement(Container, { className: className, "data-testid": "ai-chat-entry-screen" },
108
+ React.createElement(TimLogoBox, null,
109
+ React.createElement(react_1.RiSparkling2Line, null),
110
+ React.createElement(StyledTimLogo, null)),
111
+ title ? React.createElement(Title, { variant: "h4" }, title) : null,
112
+ React.createElement(StyledInput, { fullWidth: true, size: "chat", onChange: onPromptChange, onKeyDown: onPromptKeyDown, inputProps: {
113
+ "aria-label": "Ask a question",
114
+ }, endAdornment: React.createElement(Input_1.AdornmentButton, { "aria-label": "Send", onClick: () => onPromptSubmit(prompt) },
115
+ React.createElement(SendIcon, null)), responsive: true }),
116
+ React.createElement(Starters, null, conversationStarters === null || conversationStarters === void 0 ? void 0 : conversationStarters.map(({ content }, index) => (React.createElement(Starter, { key: index, onClick: () => onPromptSubmit(content), tabIndex: 0, onKeyDown: (e) => {
117
+ if (e.key === "Enter") {
118
+ onPromptSubmit(content);
119
+ }
120
+ } },
121
+ React.createElement(Typography_1.default, { variant: "body2" }, content)))))));
122
+ };
123
+ exports.EntryScreen = EntryScreen;
@@ -0,0 +1,5 @@
1
+ import * as React from "react";
2
+ declare const TimLogo: ({ className }: {
3
+ className?: string;
4
+ }) => React.JSX.Element;
5
+ export default TimLogo;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const React = require("react");
4
+ const TimLogo = ({ className }) => (React.createElement("svg", { className: className, width: "40", height: "40", viewBox: "0 0 40 40", fill: "none", xmlns: "http://www.w3.org/2000/svg" },
5
+ React.createElement("g", { clipPath: "url(#clip0_16894_46778)" },
6
+ React.createElement("path", { d: "M32.5546 5.17074C33.7099 6.67302 32.4042 7.80224 32.2498 7.94865L32.9819 8.97157C33.7621 8.23748 34.8612 6.35612 33.4291 4.49682C32.7933 3.67046 31.8246 3.32347 30.6251 3.49396C29.7868 3.6143 29.1209 3.95327 29.0928 3.96731L29.6102 4.74753C29.9974 4.57504 31.6059 3.93321 32.5546 5.16873V5.17074Z", fill: "#40464C" }),
7
+ React.createElement("path", { d: "M8.63481 5.04446L9.0881 4.22412C9.06002 4.21209 8.36805 3.92728 7.52163 3.87513C6.31219 3.80292 5.37351 4.22412 4.80589 5.10062C3.52825 7.07023 4.7738 8.85532 5.61219 9.52523L6.25803 8.44616C6.09356 8.31177 4.69959 7.29086 5.73053 5.70033C6.57895 4.3926 8.23166 4.90406 8.63079 5.04446H8.63481Z", fill: "#40464C" }),
8
+ React.createElement("path", { d: "M25.1577 7.25851C25.1778 7.25851 25.1978 7.25851 25.2179 7.25851C27.4382 7.29862 28.6296 8.96136 28.6296 8.96136L29.129 8.81896C29.109 8.75076 28.9144 8.12297 28.3468 7.48315C27.8133 6.88344 26.8425 6.16138 25.2399 6.1333C25.2119 6.1333 25.1858 6.1333 25.1577 6.1333C22.7168 6.1333 21.6056 8.07483 21.3589 9.11179L22.4721 9.37053C22.4941 9.28428 23.0216 7.2565 25.1577 7.2565V7.25851Z", fill: "#40464C" }),
9
+ React.createElement("path", { d: "M9.90619 9.34454C9.92625 9.2583 10.4357 7.23252 12.5898 7.23252C12.6099 7.23252 12.63 7.23252 12.65 7.23252C14.8703 7.27063 15.9213 8.97549 15.9213 8.97549L16.5612 8.79498C16.5411 8.72478 16.3465 8.09899 15.7789 7.46118C15.2454 6.86147 14.2746 6.13941 12.6721 6.11133C12.646 6.11133 12.6179 6.11133 12.5898 6.11133C10.1489 6.11133 9.03772 8.05286 8.79102 9.08982L9.90619 9.34655V9.34454Z", fill: "#40464C" }),
10
+ React.createElement("path", { d: "M19.6383 26.256L19.1973 26.269L19.363 31.8525L19.804 31.8394L19.6383 26.256Z", fill: "#40464C" }),
11
+ React.createElement("path", { d: "M14.1281 38.5777C14.786 38.9107 16.2321 39.4201 16.2321 39.4201L16.8318 39.5906L17.4616 39.725L17.8748 39.7912C17.8748 39.7912 19.0702 39.9336 19.704 39.9336C19.7562 39.9336 19.8103 39.9336 19.8625 39.9336C20.9255 39.9236 22.7748 39.6508 22.7748 39.6508L23.2782 39.5525L24.3031 39.2837L24.6461 39.1614L26.3068 38.5015L26.5977 38.3451L27.1994 37.984L27.4842 37.7754C27.4842 37.7754 28.6114 36.9411 29.0326 36.5359C29.4137 36.1689 29.6905 35.7797 29.8931 35.3987C30.3323 35.2482 31.6862 34.7689 33.1443 34.0187C33.732 33.7821 34.7429 33.0981 34.8091 33.054C38.0985 30.8718 39.7712 28.3907 39.9718 25.6429C40.3729 20.1592 36.6684 16.9922 35.6836 16.218C35.6415 14.8 35.469 13.0871 35.0137 11.318C35.6054 10.7163 36.173 9.95213 36.4518 9.02148C36.9472 7.36275 36.881 5.67595 36.2612 4.27195C35.5733 2.70949 34.2715 1.60234 32.4945 1.06681C30.6272 0.503205 28.6515 1.0989 27.2616 1.76079C25.1215 0.767959 22.6424 0.166244 19.9989 0.0238384C16.7235 -0.152665 13.8012 0.661656 11.3843 2.11179C9.95424 1.46394 7.56945 0.781999 5.46144 1.60635C3.73251 2.28428 2.52507 3.49373 1.96347 5.10432C1.46004 6.55245 1.52823 8.23925 2.15602 9.85385C2.56519 10.9028 3.50988 11.9338 4.33022 12.6378C4.0093 14.2404 3.89297 15.7366 3.8669 16.922C2.79584 17.8306 -1.06115 21.5793 0.276664 27.3718C0.936544 30.2279 2.92421 32.6528 6.02705 34.3858C6.36201 34.5723 6.709 34.7508 7.06 34.9173L8.38778 35.503C9.49494 35.9562 10.4898 36.2852 11.0012 36.4456C11.5528 36.931 12.1645 37.4004 12.8284 37.8316L14.1281 38.5797V38.5777ZM3.45572 9.54899C1.84714 6.20345 3.8328 3.63012 6.13536 2.72955C8.15111 1.9413 10.9029 3.49974 12.0201 4.09143L11.982 3.05648C14.2104 1.73271 16.9141 0.946468 19.9427 1.10893C22.151 1.22727 24.243 1.68457 26.0922 2.43672L26.2687 3.57195C27.3338 2.89201 29.8449 1.61437 31.9168 2.24016C34.2856 2.95419 36.199 5.26678 35.136 8.82292C34.765 10.0665 33.4472 11.2378 32.8696 11.6931L33.9827 12.1544C34.5945 15.2994 34.2796 18.1856 34.1372 19.1684C33.2426 18.8495 32.0612 18.5607 30.5209 18.3962C30.4547 16.6773 30.1117 12.9106 28.3126 11.2278C27.6106 10.5719 26.7621 10.2289 25.7894 10.2129C24.8186 10.1988 23.9862 10.5137 23.3304 11.1536C22.3716 12.0902 21.5332 13.5885 21.3948 15.8369C21.3447 16.6432 21.3587 17.3813 21.3868 17.9289C20.6186 17.7945 19.7943 17.7223 18.984 17.7203L18.5929 17.7143C17.951 17.7323 17.3714 17.7845 16.8479 17.8607C16.7717 16.1979 16.3926 12.9727 14.6516 11.3662C13.9577 10.7263 13.1213 10.3954 12.1605 10.3794C11.1978 10.3653 10.3815 10.6722 9.73362 11.294C7.87432 13.0831 7.72188 17.1005 7.73592 18.4684C6.76516 18.5767 5.99095 18.7432 5.3772 18.9297C5.27691 18.0191 5.08637 15.5501 5.56975 12.7561L6.26573 12.012C5.65399 11.6028 4.09755 10.8687 3.45974 9.54297L3.45572 9.54899ZM26.4673 13.0008C24.1888 13.1432 24.3011 17.0123 24.3914 18.2197C23.8017 18.2398 23.2842 18.2678 22.8691 18.2939C22.7708 16.4948 22.8951 13.1773 24.2189 11.8856C24.6261 11.4885 25.1155 11.296 25.7152 11.296C25.7312 11.296 25.7473 11.296 25.7613 11.296C26.4091 11.306 26.9567 11.5286 27.4341 11.9759C27.9636 12.4713 28.3968 13.2415 28.7177 14.2424C28.2464 13.4702 27.5364 12.9346 26.4653 13.0008H26.4673ZM27.7931 18.2718L26.9427 18.2257C26.4553 18.2057 25.9779 18.1956 25.5146 18.1896C25.4524 17.614 25.3601 15.9893 26.3309 15.9613C27.6607 15.9232 27.8051 17.4916 27.7931 18.2718ZM14.2364 18.2718L13.386 18.2257C12.8986 18.2057 12.4213 18.1956 11.958 18.1896C11.8958 17.614 11.8035 15.9893 12.7743 15.9613C14.1041 15.9232 14.2485 17.4916 14.2364 18.2718ZM19.2628 25.34C19.7903 25.4463 21.6436 25.9257 23.3143 26.7019C23.2662 27.2675 23.1579 28.1701 22.9112 29.0807C22.5722 30.3342 21.6596 32.2256 21.3347 32.8775C21.0318 32.8915 20.5224 32.9116 20.1252 32.9176C19.5355 32.9256 18.8777 32.9397 18.5347 32.9457C18.1596 32.4242 17.0886 30.8878 16.3946 29.4296C15.9192 28.4328 15.6204 27.5302 15.4599 26.9767C16.8439 26.1082 18.9358 25.4403 19.2628 25.338V25.34ZM10.7325 18.342C10.5881 18.342 10.4416 18.342 10.2892 18.342C9.94221 18.342 9.61528 18.3481 9.30038 18.3601C9.17001 16.7094 9.21614 13.3458 10.6081 12.006C11.0193 11.6109 11.5187 11.4203 12.1325 11.4324C12.7723 11.4424 13.3118 11.659 13.7832 12.0942C14.3528 12.6197 14.8101 13.4641 15.135 14.5713C14.6757 13.6868 13.9396 13.0389 12.7683 13.1111C10.4075 13.2556 10.6462 17.3913 10.7325 18.342ZM38.8686 25.4343C38.644 30.7454 31.6521 33.1182 30.3905 33.5093C30.4065 33.07 30.3524 32.7872 30.3524 32.7872C30.3303 32.8474 28.1561 38.7622 19.8525 38.8445C19.8023 38.8445 19.7562 38.8445 19.706 38.8445C13.3118 38.8445 7.3769 32.0411 7.3769 32.0411C7.68979 32.6027 8.24939 33.4712 9.04967 34.4319C7.42905 33.9686 2.62536 32.1855 1.45201 27.097C0.475229 22.8609 2.56719 19.9125 3.88495 18.5406C3.90902 19.0942 3.94311 19.4412 3.94712 19.5114L3.95114 19.5455C3.25716 19.9446 3.1308 20.2455 3.1308 20.2455C3.16088 20.2334 6.46229 19.387 10.2792 19.4251C11.5067 19.4372 12.4614 19.4833 13.1935 19.5415C13.0089 19.8102 12.9187 20.083 12.9167 20.3417C12.9127 21.4649 15.2393 21.8902 16.5089 22.3354C17.4015 22.6483 18.1536 22.9712 18.5848 23.1678C18.5909 23.6492 18.5989 24.287 18.6009 24.7944C17.7364 25.0251 15.7488 25.6288 14.4972 26.5795L14.439 26.6317C14.445 26.6618 14.5233 27.0108 14.6958 27.5603C13.8754 27.7308 12.9067 27.8471 11.7935 27.8451C7.76801 27.8411 5.18465 26.1844 5.18465 26.1844C5.26287 26.2967 7.17633 28.9282 11.7935 28.9322C12.1786 28.9322 12.5456 28.9182 12.8986 28.8941C13.1915 29.4918 13.713 30.7133 14.4811 31.7984C15.5362 33.2866 16.9562 34.6365 19.8585 34.6365C23.7857 34.6365 25.9779 32.4202 27.1292 29.1649C27.2977 29.1649 27.4641 29.1609 27.6326 29.1549C27.9174 29.1448 28.2022 29.1268 28.4891 29.1007C32.8595 28.6996 34.5925 26.9004 34.6647 26.8222C34.6647 26.8222 30.4406 27.8291 28.3908 28.0176C26.8945 28.156 25.4203 28.0417 24.0845 27.8191C24.2209 26.9145 24.243 26.2285 24.245 26.1423L24.251 26.1343C22.6444 25.3179 20.7209 24.9048 19.8043 24.7403C19.8003 24.1386 19.7903 23.3704 19.7843 22.893C20.1513 22.7005 20.6206 22.4738 21.1461 22.2612C23.0496 21.489 24.8427 21.2624 24.8748 20.0349C24.8828 19.746 24.7645 19.4813 24.5478 19.2406C26.1785 19.2226 28.2745 19.2567 30.2441 19.4592C34.1973 19.8644 36.7025 20.767 36.7185 20.775C36.7185 20.775 36.4598 20.3297 35.5211 19.7962V19.7822C35.5351 19.6859 35.6415 18.9297 35.6776 17.7704C36.9873 18.9979 39.0291 21.5492 38.8646 25.4302L38.8686 25.4343Z", fill: "#40464C" })),
12
+ React.createElement("defs", null,
13
+ React.createElement("clipPath", { id: "clip0_16894_46778" },
14
+ React.createElement("rect", { width: "40", height: "39.9338", fill: "white" })))));
15
+ exports.default = TimLogo;
@@ -0,0 +1,2 @@
1
+ declare const handlers: import("msw").HttpHandler[];
2
+ export { handlers };
@@ -0,0 +1,125 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.handlers = void 0;
13
+ const msw_1 = require("msw");
14
+ const SAMPLE_RESPONSES = [
15
+ `For exploring AI applications in business, I recommend the following course from MIT:
16
+
17
+ 1. **[Machine Learning, Modeling, and Simulation Principles](https://xpro.mit.edu/courses/course-v1:xPRO+MLx1/)**: Offered by MIT xPRO, this course is part of the program "Machine Learning, Modeling, and Simulation: Engineering Problem-Solving in the Age of AI." It focuses on the principles of machine learning and how they can be applied to solve engineering problems, which is highly relevant for business applications of AI.
18
+
19
+ This course is not free, but it provides a certification upon completion, which can be valuable for professionals looking to apply AI in business contexts. It covers essential concepts that can help you understand how AI can be leveraged to improve business processes and decision-making.
20
+ <!-- Comment! -->
21
+ `,
22
+ `
23
+ To understand global warming, I recommend the following resources from MIT:
24
+
25
+ 1. **[Global Warming Science](https://www.edx.org/learn/global-warming/massachusetts-institute-of-technology-global-warming-science)**: This course offered by MITx covers the physics, chemistry, biology, and geology of the earth’s climate system. It's a comprehensive introduction to the scientific principles underlying global warming.
26
+
27
+ 2. **[Global Warming Science](https://openlearninglibrary.mit.edu/courses/course-v1:MITx+12.340x+1T2020/about)**: Another offering of the same course by MITx, available through the Open Learning Library. It provides the same in-depth exploration of the earth's climate system.
28
+
29
+ These courses are free and provide a solid foundation in understanding the scientific aspects of global warming. They are suitable for anyone interested in the topic, regardless of prior knowledge.
30
+ <!-- Comment! -->
31
+ `,
32
+ `
33
+ Here are some courses on linear algebra that you can explore:
34
+
35
+ 1. **[Linear Algebra (MIT OpenCourseWare)](https://openlearninglibrary.mit.edu/courses/course-v1:OCW+18.06SC+2T2019/about)**: This course covers matrix theory and linear algebra, emphasizing topics useful in various disciplines such as physics, economics, social sciences, natural sciences, and engineering. It parallels the combination of theory and applications in Professor Strang's textbook "Introduction to Linear Algebra." This course is free and available through MIT OpenCourseWare.
36
+
37
+ 2. **[Mathematical Methods for Quantitative Finance (MITx)](https://www.edx.org/learn/finance/massachusetts-institute-of-technology-mathematical-methods-for-quantitative-finance)**: This course covers the mathematical foundations essential for financial engineering and quantitative finance, including linear algebra, optimization, probability, stochastic processes, statistics, and applied computational techniques in R. It is free and offers certification upon completion.
38
+
39
+ 3. **[Quantum Information Science I, Part 1 (MITx)](https://openlearninglibrary.mit.edu/courses/course-v1:MITx+8.370.1x+1T2018/about)**: While primarily focused on quantum information science, this course requires some knowledge of linear algebra and is suitable for those interested in quantum mechanics. It is free and available through MITx.
40
+
41
+ These courses provide a comprehensive introduction to linear algebra and its applications across various fields.
42
+ <!-- Comment! -->
43
+ `,
44
+ `Here are some courses on quantum computing that offer certificates:
45
+
46
+ 1. [Introduction to Quantum Computing](https://xpro.mit.edu/courses/course-v1:xPRO+QCFx1/)
47
+ - **Description**: This is the first course in the Quantum Computing Fundamentals professional certificate program. You can earn a Professional Certificate and CEUs by completing both courses in the program. Alternatively, you can take this course individually for a certificate of completion and CEUs.
48
+ - **Offered by**: MIT xPRO
49
+ - **Instructors**: Isaac Chuang, William Oliver, Peter Shor, Aram Harrow
50
+
51
+ 2. [Practical Realities of Quantum Computation and Quantum Communication](https://xpro.mit.edu/courses/course-v1:xPRO+QCRx1/)
52
+ - **Description**: This course is part of the Quantum Computing Realities professional certificate program. Completing both courses in the program will earn you a Professional Certificate and CEUs. You can also take this course individually for a certificate of completion and CEUs.
53
+ - **Offered by**: MIT xPRO
54
+ - **Instructors**: Isaac Chuang, William Oliver, Peter Shor, Aram Harrow
55
+
56
+ These courses are part of professional certificate programs, and you can choose to complete the entire program or take individual courses for certification.`,
57
+ ];
58
+ const rand = (min, max) => {
59
+ // min and max included
60
+ return Math.floor(Math.random() * (max - min + 1) + min);
61
+ };
62
+ const getReadableStream = () => {
63
+ let timerId;
64
+ const response = SAMPLE_RESPONSES[rand(0, SAMPLE_RESPONSES.length - 1)];
65
+ const chunks = response.split(" ").reduce((acc, word) => {
66
+ const last = acc[acc.length - 1];
67
+ if (acc.length === 0) {
68
+ acc.push(word);
69
+ }
70
+ else if (Math.random() < 0.75) {
71
+ acc[acc.length - 1] = `${last} ${word}`;
72
+ }
73
+ else {
74
+ acc.push(` ${word}`);
75
+ }
76
+ return acc;
77
+ }, []);
78
+ const num = chunks.length;
79
+ let i = 0;
80
+ return new ReadableStream({
81
+ start(controller) {
82
+ timerId = setInterval(() => {
83
+ const msg = new TextEncoder().encode(chunks[i]);
84
+ controller.enqueue(msg);
85
+ i++;
86
+ if (i === num) {
87
+ controller.close();
88
+ clearInterval(timerId);
89
+ }
90
+ }, 100);
91
+ },
92
+ cancel() {
93
+ if (timerId) {
94
+ clearInterval(timerId);
95
+ }
96
+ },
97
+ });
98
+ };
99
+ const handlers = [
100
+ msw_1.http.post("http://localhost:4567/streaming", (_a) => __awaiter(void 0, [_a], void 0, function* ({ request }) {
101
+ yield (0, msw_1.delay)(600);
102
+ const body = getReadableStream();
103
+ const requestBody = yield request.json();
104
+ if (Array.isArray(requestBody)) {
105
+ const last = requestBody[requestBody.length - 1];
106
+ const { content } = last;
107
+ if (content === "error") {
108
+ return new msw_1.HttpResponse("Internal Server Error", {
109
+ status: 500,
110
+ });
111
+ }
112
+ }
113
+ return new msw_1.HttpResponse(body, {
114
+ headers: {
115
+ "Content-Type": "text/plain",
116
+ },
117
+ });
118
+ })),
119
+ msw_1.http.post("http://localhost:4567/json", () => __awaiter(void 0, void 0, void 0, function* () {
120
+ const message = SAMPLE_RESPONSES[rand(0, SAMPLE_RESPONSES.length - 1)];
121
+ yield (0, msw_1.delay)(800);
122
+ return msw_1.HttpResponse.json({ message });
123
+ })),
124
+ ];
125
+ exports.handlers = handlers;
@@ -0,0 +1,82 @@
1
+ import { RefAttributes } from "react";
2
+ type Role = "assistant" | "user";
3
+ type AiChatMessage = {
4
+ id: string;
5
+ content: string;
6
+ role: Role;
7
+ };
8
+ type RequestOpts = {
9
+ apiUrl: string;
10
+ /**
11
+ * Transforms array of chat messages into request body. Messages
12
+ * are ordered oldest to newest.
13
+ *
14
+ * JSON.stringify is applied to the return value.
15
+ */
16
+ transformBody?: (messages: AiChatMessage[]) => unknown;
17
+ /**
18
+ * Extra options to pass to fetch.
19
+ */
20
+ fetchOpts?: RequestInit;
21
+ onFinish?: (message: AiChatMessage) => void;
22
+ };
23
+ type AiChatProps = {
24
+ /**
25
+ * Changing the `chatId` will reset the chat. Changing the `chatId` to a
26
+ * previously used value will restore the session state.
27
+ */
28
+ chatId?: string;
29
+ /**
30
+ * If provided, renders the "AskTIM" title motif followed by the text.
31
+ */
32
+ askTimTitle?: string;
33
+ /**
34
+ * Placeholder message for chat input.
35
+ */
36
+ placeholder?: string;
37
+ className?: string;
38
+ /**
39
+ * Set to false to disable the entry screen and load the chat immediately.
40
+ * Defaults to true.
41
+ */
42
+ entryScreenEnabled?: boolean;
43
+ /**
44
+ * Title to display on the entry screen, also the initial assistant message if not overridden by `initialMessages`.
45
+ */
46
+ entryScreenTitle?: string;
47
+ /**
48
+ * Initial messages to display on the chat. If not provided, the entry screen title will be used as the initial message.
49
+ */
50
+ initialMessages?: Omit<AiChatMessage, "id">[];
51
+ /**
52
+ * Prompt suggestions for the user, clickable on the entry screen or in the chat if the entry screen is not enabled.
53
+ */
54
+ conversationStarters?: {
55
+ content: string;
56
+ }[];
57
+ /**
58
+ * Options for making requests to the AI service.
59
+ */
60
+ requestOpts: RequestOpts;
61
+ parseContent?: (content: unknown) => string;
62
+ /**
63
+ * A message to display while the component is in a loading state.
64
+ *
65
+ * Identical consecutive messages may not be read on some screen readers.
66
+ */
67
+ srLoadingMessages?: {
68
+ delay: number;
69
+ text: string;
70
+ }[];
71
+ /**
72
+ * If provided, element to use for rendering avatar images.
73
+ * By default, the theme's ImageAdater is used.
74
+ */
75
+ ImgComponent?: React.ElementType;
76
+ /**
77
+ * Where the scroll container is provided by the component,
78
+ * the AiChat will scroll to the bottom as chat messages are added.
79
+ */
80
+ scrollElement?: HTMLElement | null;
81
+ } & RefAttributes<HTMLDivElement>;
82
+ export type { RequestOpts, AiChatProps, AiChatMessage };
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ // Some of these are based on (compatible, but simplified / restricted) versions of ai/react types.
3
+ Object.defineProperty(exports, "__esModule", { value: true });