@mitodl/smoot-design 0.0.0-a2e4e1e → 0.0.0-bafccd3

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 (98) hide show
  1. package/README.md +4 -0
  2. package/dist/bundles/{remoteTutorDrawer.es.js → aiDrawerManager.es.js} +17612 -17240
  3. package/dist/bundles/aiDrawerManager.es.js.map +1 -0
  4. package/dist/bundles/aiDrawerManager.umd.js +245 -0
  5. package/dist/bundles/aiDrawerManager.umd.js.map +1 -0
  6. package/dist/cjs/VERSION.d.ts +12 -0
  7. package/dist/cjs/VERSION.js +15 -0
  8. package/dist/cjs/ai.d.ts +3 -3
  9. package/dist/cjs/ai.js +5 -1
  10. package/dist/cjs/bundles/{RemoteTutorDrawer/RemoteTutorDrawer.d.ts → AiDrawer/AiDrawer.d.ts} +11 -13
  11. package/dist/cjs/bundles/{RemoteTutorDrawer/RemoteTutorDrawer.js → AiDrawer/AiDrawer.js} +27 -41
  12. package/dist/cjs/bundles/{RemoteTutorDrawer/RemoteTutorDrawer.stories.d.ts → AiDrawer/AiDrawer.stories.d.ts} +4 -3
  13. package/dist/cjs/bundles/{RemoteTutorDrawer/RemoteTutorDrawer.stories.js → AiDrawer/AiDrawer.stories.js} +32 -51
  14. package/dist/cjs/bundles/AiDrawer/AiDrawerManager.d.ts +12 -0
  15. package/dist/cjs/bundles/AiDrawer/AiDrawerManager.js +51 -0
  16. package/dist/cjs/bundles/AiDrawer/AiDrawerManager.stories.d.ts +6 -0
  17. package/dist/cjs/bundles/AiDrawer/AiDrawerManager.stories.js +267 -0
  18. package/dist/cjs/bundles/{RemoteTutorDrawer/RemoteTutorDrawer.test.js → AiDrawer/AiDrawerManager.test.js} +22 -18
  19. package/dist/cjs/bundles/{RemoteTutorDrawer → AiDrawer}/FlashcardsScreen.js +1 -1
  20. package/dist/cjs/bundles/aiDrawerManager.d.ts +6 -0
  21. package/dist/cjs/bundles/aiDrawerManager.js +44 -0
  22. package/dist/cjs/components/AiChat/AiChat.d.ts +3 -3
  23. package/dist/cjs/components/AiChat/AiChat.js +65 -53
  24. package/dist/cjs/components/AiChat/AiChat.stories.d.ts +0 -4
  25. package/dist/cjs/components/AiChat/AiChat.stories.js +5 -54
  26. package/dist/cjs/components/AiChat/AiChatContext.d.ts +26 -0
  27. package/dist/cjs/components/AiChat/AiChatContext.js +106 -0
  28. package/dist/cjs/components/AiChat/AiChatContext.stories.d.ts +14 -0
  29. package/dist/cjs/components/AiChat/AiChatContext.stories.js +75 -0
  30. package/dist/cjs/components/AiChat/AiChatMarkdown.stories.d.ts +15 -0
  31. package/dist/cjs/components/AiChat/AiChatMarkdown.stories.js +282 -0
  32. package/dist/cjs/components/AiChat/Markdown.d.ts +7 -0
  33. package/dist/cjs/components/AiChat/Markdown.js +14 -0
  34. package/dist/cjs/components/AiChat/test-utils/api.js +40 -1
  35. package/dist/cjs/components/AiChat/types.d.ts +25 -11
  36. package/dist/cjs/components/AiChat/types.js +1 -1
  37. package/dist/cjs/components/AiChat/utils.d.ts +1 -1
  38. package/dist/cjs/components/AiChat/utils.js +1 -1
  39. package/dist/cjs/components/LinkAdapter/LinkAdapter.js +1 -1
  40. package/dist/cjs/components/TabButtons/TabButtonList.js +1 -1
  41. package/dist/cjs/index.d.ts +1 -0
  42. package/dist/cjs/index.js +3 -1
  43. package/dist/cjs/utils/retryingFetch.d.ts +19 -0
  44. package/dist/cjs/utils/retryingFetch.js +98 -0
  45. package/dist/cjs/utils/retryingFetch.test.js +48 -0
  46. package/dist/esm/VERSION.d.ts +12 -0
  47. package/dist/esm/VERSION.js +12 -0
  48. package/dist/esm/ai.d.ts +3 -3
  49. package/dist/esm/ai.js +2 -1
  50. package/dist/esm/bundles/{RemoteTutorDrawer/RemoteTutorDrawer.d.ts → AiDrawer/AiDrawer.d.ts} +11 -13
  51. package/dist/esm/bundles/{RemoteTutorDrawer/RemoteTutorDrawer.js → AiDrawer/AiDrawer.js} +26 -40
  52. package/dist/esm/bundles/{RemoteTutorDrawer/RemoteTutorDrawer.stories.d.ts → AiDrawer/AiDrawer.stories.d.ts} +4 -3
  53. package/dist/esm/bundles/{RemoteTutorDrawer/RemoteTutorDrawer.stories.js → AiDrawer/AiDrawer.stories.js} +31 -50
  54. package/dist/esm/bundles/AiDrawer/AiDrawerManager.d.ts +12 -0
  55. package/dist/esm/bundles/AiDrawer/AiDrawerManager.js +48 -0
  56. package/dist/esm/bundles/AiDrawer/AiDrawerManager.stories.d.ts +6 -0
  57. package/dist/esm/bundles/AiDrawer/AiDrawerManager.stories.js +264 -0
  58. package/dist/esm/bundles/AiDrawer/AiDrawerManager.test.d.ts +1 -0
  59. package/dist/esm/bundles/{RemoteTutorDrawer/RemoteTutorDrawer.test.js → AiDrawer/AiDrawerManager.test.js} +22 -18
  60. package/dist/esm/bundles/{RemoteTutorDrawer → AiDrawer}/FlashcardsScreen.js +1 -1
  61. package/dist/esm/bundles/aiDrawerManager.d.ts +6 -0
  62. package/dist/esm/bundles/aiDrawerManager.js +41 -0
  63. package/dist/esm/components/AiChat/AiChat.d.ts +3 -3
  64. package/dist/esm/components/AiChat/AiChat.js +65 -54
  65. package/dist/esm/components/AiChat/AiChat.stories.d.ts +0 -4
  66. package/dist/esm/components/AiChat/AiChat.stories.js +4 -53
  67. package/dist/esm/components/AiChat/AiChatContext.d.ts +26 -0
  68. package/dist/esm/components/AiChat/AiChatContext.js +102 -0
  69. package/dist/esm/components/AiChat/AiChatContext.stories.d.ts +14 -0
  70. package/dist/esm/components/AiChat/AiChatContext.stories.js +72 -0
  71. package/dist/esm/components/AiChat/AiChatMarkdown.stories.d.ts +15 -0
  72. package/dist/esm/components/AiChat/AiChatMarkdown.stories.js +279 -0
  73. package/dist/esm/components/AiChat/Markdown.d.ts +7 -0
  74. package/dist/esm/components/AiChat/Markdown.js +12 -0
  75. package/dist/esm/components/AiChat/test-utils/api.js +40 -1
  76. package/dist/esm/components/AiChat/types.d.ts +25 -11
  77. package/dist/esm/components/AiChat/types.js +1 -1
  78. package/dist/esm/components/AiChat/utils.d.ts +1 -1
  79. package/dist/esm/components/AiChat/utils.js +1 -1
  80. package/dist/esm/components/LinkAdapter/LinkAdapter.js +1 -1
  81. package/dist/esm/components/TabButtons/TabButtonList.js +1 -1
  82. package/dist/esm/index.d.ts +1 -0
  83. package/dist/esm/index.js +1 -0
  84. package/dist/esm/utils/retryingFetch.d.ts +19 -0
  85. package/dist/esm/utils/retryingFetch.js +96 -0
  86. package/dist/esm/utils/retryingFetch.test.d.ts +1 -0
  87. package/dist/esm/utils/retryingFetch.test.js +46 -0
  88. package/dist/tsconfig.tsbuildinfo +1 -1
  89. package/package.json +11 -7
  90. package/dist/bundles/remoteTutorDrawer.umd.js +0 -207
  91. package/dist/cjs/bundles/remoteTutorDrawer.d.ts +0 -7
  92. package/dist/cjs/bundles/remoteTutorDrawer.js +0 -40
  93. package/dist/esm/bundles/remoteTutorDrawer.d.ts +0 -7
  94. package/dist/esm/bundles/remoteTutorDrawer.js +0 -37
  95. /package/dist/cjs/bundles/{RemoteTutorDrawer/RemoteTutorDrawer.test.d.ts → AiDrawer/AiDrawerManager.test.d.ts} +0 -0
  96. /package/dist/cjs/bundles/{RemoteTutorDrawer → AiDrawer}/FlashcardsScreen.d.ts +0 -0
  97. /package/dist/{esm/bundles/RemoteTutorDrawer/RemoteTutorDrawer.test.d.ts → cjs/utils/retryingFetch.test.d.ts} +0 -0
  98. /package/dist/esm/bundles/{RemoteTutorDrawer → AiDrawer}/FlashcardsScreen.d.ts +0 -0
@@ -0,0 +1,12 @@
1
+ /**
2
+ * This file is auto-generated at build time.
3
+ * Run node ./scripts/set_version.js to update the version.
4
+ * Do not update this file manually.
5
+ *
6
+ * NOTES:
7
+ * - In development, VERSION will always be "0.0.0"
8
+ * - The version should not simply be imported from package.json. This would
9
+ * result in all of the package.json being included in the bundled code, which
10
+ * is not desired.
11
+ */
12
+ export declare const VERSION = "0.0.0-bafccd3";
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.VERSION = void 0;
4
+ /**
5
+ * This file is auto-generated at build time.
6
+ * Run node ./scripts/set_version.js to update the version.
7
+ * Do not update this file manually.
8
+ *
9
+ * NOTES:
10
+ * - In development, VERSION will always be "0.0.0"
11
+ * - The version should not simply be imported from package.json. This would
12
+ * result in all of the package.json being included in the bundled code, which
13
+ * is not desired.
14
+ */
15
+ exports.VERSION = "0.0.0-bafccd3";
package/dist/cjs/ai.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- export { AiChat } from "./components/AiChat/AiChat";
2
- export type { AiChatProps } from "./components/AiChat/AiChat";
3
- export type { AiChatMessage } from "./components/AiChat/types";
1
+ export { AiChat, AiChatDisplay } from "./components/AiChat/AiChat";
2
+ export { AiChatProvider, useAiChat } from "./components/AiChat/AiChatContext";
3
+ export type { AiChatMessage, AiChatContextProps, AiChatDisplayProps, AiChatProps, } from "./components/AiChat/types";
package/dist/cjs/ai.js CHANGED
@@ -1,5 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.AiChat = void 0;
3
+ exports.useAiChat = exports.AiChatProvider = exports.AiChatDisplay = exports.AiChat = void 0;
4
4
  var AiChat_1 = require("./components/AiChat/AiChat");
5
5
  Object.defineProperty(exports, "AiChat", { enumerable: true, get: function () { return AiChat_1.AiChat; } });
6
+ Object.defineProperty(exports, "AiChatDisplay", { enumerable: true, get: function () { return AiChat_1.AiChatDisplay; } });
7
+ var AiChatContext_1 = require("./components/AiChat/AiChatContext");
8
+ Object.defineProperty(exports, "AiChatProvider", { enumerable: true, get: function () { return AiChatContext_1.AiChatProvider; } });
9
+ Object.defineProperty(exports, "useAiChat", { enumerable: true, get: function () { return AiChatContext_1.useAiChat; } });
@@ -1,8 +1,7 @@
1
1
  import { FC } from "react";
2
- import { AiChatMessage } from "../../components/AiChat/types";
3
- import type { AiChatProps } from "../../components/AiChat/AiChat";
4
- type RemoteTutorDrawerInitMessage = {
5
- type: "smoot-design::tutor-drawer-open";
2
+ import type { AiChatProps, AiChatMessage } from "../../components/AiChat/types";
3
+ type AiDrawerInitMessage = {
4
+ type: "smoot-design::ai-drawer-open" | "smoot-design::tutor-drawer-open";
6
5
  payload: {
7
6
  blockType?: "problem" | "video";
8
7
  target?: string;
@@ -24,13 +23,8 @@ type RemoteTutorDrawerInitMessage = {
24
23
  };
25
24
  };
26
25
  };
27
- type RemoteTutorDrawerProps = {
26
+ type AiDrawerProps = {
28
27
  className?: string;
29
- /**
30
- * The origin of the messages that will be received to open the chat.
31
- * The drawer will ignore all message events not from this origin.
32
- */
33
- messageOrigin: string;
34
28
  /**
35
29
  * Transform the body of the request before sending it to the server.
36
30
  * Its result will be merged with the per-message requestBody opt, with
@@ -50,8 +44,12 @@ type RemoteTutorDrawerProps = {
50
44
  /**
51
45
  * Pass to target a specific drawer instance where multiple are on the page.
52
46
  */
47
+ /** @deprecated The AiDrawerManager now handles multiple AiDrawer instance removing the need to target */
53
48
  target?: string;
49
+ payload?: AiDrawerInitMessage["payload"];
50
+ open?: boolean;
51
+ onClose?: () => void;
54
52
  };
55
- declare const RemoteTutorDrawer: FC<RemoteTutorDrawerProps>;
56
- export { RemoteTutorDrawer };
57
- export type { RemoteTutorDrawerProps, RemoteTutorDrawerInitMessage };
53
+ declare const AiDrawer: FC<AiDrawerProps>;
54
+ export { AiDrawer };
55
+ export type { AiDrawerProps, AiDrawerInitMessage };
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.RemoteTutorDrawer = void 0;
12
+ exports.AiDrawer = void 0;
13
13
  // @format
14
14
  const React = require("react");
15
15
  const react_1 = require("react");
@@ -25,6 +25,7 @@ const TabPanel_1 = require("@mui/lab/TabPanel");
25
25
  const AiChat_1 = require("../../components/AiChat/AiChat");
26
26
  const ActionButton_1 = require("../../components/Button/ActionButton");
27
27
  const FlashcardsScreen_1 = require("./FlashcardsScreen");
28
+ const VERSION_1 = require("../../VERSION");
28
29
  const Header = styled_1.default.div(({ theme }) => ({
29
30
  display: "flex",
30
31
  alignItems: "center",
@@ -152,6 +153,12 @@ const useContentFetch = (contentUrl) => {
152
153
  }, [contentUrl]);
153
154
  return { response, loading };
154
155
  };
156
+ const DEFAULT_PROBLEM_INITIAL_MESSAGES = [
157
+ {
158
+ role: "assistant",
159
+ content: "Let's try to work on this problem together. It would be great to hear how you're thinking about solving it. Can you walk me through the approach you're considering?",
160
+ },
161
+ ];
155
162
  const DEFAULT_VIDEO_ENTRY_SCREEN_TITLE = "What do you want to know about this video?";
156
163
  const DEFAULT_VIDEO_STARTERS = [
157
164
  { content: "What are the most important concepts introduced in the video?" },
@@ -160,23 +167,21 @@ const DEFAULT_VIDEO_STARTERS = [
160
167
  },
161
168
  { content: "What are the key terms introduced in this video?" },
162
169
  ];
163
- const ChatComponent = ({ payload, transformBody, fetchOpts, scrollElement, entryScreenEnabled, entryScreenTitle, conversationStarters, hasTabs, }) => {
170
+ const ChatComponent = ({ payload, transformBody, fetchOpts, scrollElement, entryScreenEnabled, entryScreenTitle, conversationStarters, initialMessages, hasTabs, needsMathJax, }) => {
164
171
  if (!payload)
165
172
  return null;
166
- return (React.createElement(StyledAiChat, { chatId: payload.chatId, conversationStarters: conversationStarters, initialMessages: payload.initialMessages, scrollElement: scrollElement, entryScreenEnabled: entryScreenEnabled, entryScreenTitle: entryScreenTitle, requestOpts: {
173
+ return (React.createElement(StyledAiChat, { key: payload.chatId, chatId: payload.chatId, conversationStarters: conversationStarters, initialMessages: initialMessages, scrollElement: scrollElement, entryScreenEnabled: entryScreenEnabled, entryScreenTitle: entryScreenTitle, requestOpts: {
167
174
  transformBody: (messages) => (Object.assign(Object.assign({}, payload.requestBody), transformBody === null || transformBody === void 0 ? void 0 : transformBody(messages))),
168
175
  apiUrl: payload.apiUrl,
169
176
  fetchOpts: Object.assign(Object.assign({}, DEFAULT_FETCH_OPTS), fetchOpts),
170
- }, hasTabs: hasTabs }));
177
+ }, hasTabs: hasTabs, useMathJax: needsMathJax }));
171
178
  };
172
179
  const randomItems = (array, count) => {
173
180
  const shuffled = [...array].sort(() => 0.5 - Math.random());
174
181
  return shuffled.slice(0, count);
175
182
  };
176
- const RemoteTutorDrawer = ({ messageOrigin, transformBody = identity, className, fetchOpts, target, }) => {
177
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
178
- const [open, setOpen] = (0, react_1.useState)(false);
179
- const [payload, setPayload] = (0, react_1.useState)(null);
183
+ const AiDrawer = ({ transformBody = identity, className, fetchOpts, payload, open, onClose, }) => {
184
+ var _a, _b, _c, _d, _e, _f, _g;
180
185
  const [tab, setTab] = (0, react_1.useState)("chat");
181
186
  const { response } = useContentFetch((_a = payload === null || payload === void 0 ? void 0 : payload.summary) === null || _a === void 0 ? void 0 : _a.apiUrl);
182
187
  const [_wasKeyboardFocus, setWasKeyboardFocus] = (0, react_1.useState)(false);
@@ -196,25 +201,6 @@ const RemoteTutorDrawer = ({ messageOrigin, transformBody = identity, className,
196
201
  setScrollElement(node);
197
202
  }
198
203
  };
199
- (0, react_1.useEffect)(() => {
200
- const cb = (event) => {
201
- if (event.origin !== messageOrigin) {
202
- if (process.env.NODE_ENV === "development") {
203
- console.warn(`RemoteTutorDrawer: received message from unexpected origin: ${event.origin}`);
204
- }
205
- return;
206
- }
207
- if (event.data.type === "smoot-design::tutor-drawer-open" &&
208
- event.data.payload.target === target) {
209
- setOpen(true);
210
- setPayload(event.data.payload);
211
- }
212
- };
213
- window.addEventListener("message", cb);
214
- return () => {
215
- window.removeEventListener("message", cb);
216
- };
217
- }, [messageOrigin, target]);
218
204
  (0, react_1.useEffect)(() => {
219
205
  var _a;
220
206
  (_a = scrollElement === null || scrollElement === void 0 ? void 0 : scrollElement.scrollTo) === null || _a === void 0 ? void 0 : _a.call(scrollElement, {
@@ -233,11 +219,11 @@ const RemoteTutorDrawer = ({ messageOrigin, transformBody = identity, className,
233
219
  : DEFAULT_VIDEO_STARTERS));
234
220
  }, [payload, response]);
235
221
  if (!payload) {
236
- return React.createElement("div", { "data-testid": "remote-tutor-drawer-waiting" });
222
+ return React.createElement("div", { "data-testid": "ai-drawer-waiting" });
237
223
  }
238
- const { blockType, chat } = payload;
224
+ const { title, blockType, chat } = payload;
239
225
  const hasTabs = blockType === "video";
240
- return (React.createElement(Drawer_1.default, { "data-testid": "remote-tutor-drawer", className: className, PaperProps: {
226
+ return (React.createElement(Drawer_1.default, { "data-smoot-version": VERSION_1.VERSION, className: className, PaperProps: {
241
227
  ref: paperRefCallback,
242
228
  sx: {
243
229
  width: "900px",
@@ -248,29 +234,29 @@ const RemoteTutorDrawer = ({ messageOrigin, transformBody = identity, className,
248
234
  md: "0 32px",
249
235
  },
250
236
  },
251
- }, anchor: "right", open: open, onClose: () => setOpen(false) },
237
+ }, anchor: "right", open: open, onClose: onClose, role: "dialog", "aria-modal": "true", keepMounted: true },
252
238
  React.createElement(Header, null,
253
239
  React.createElement(Title, null,
254
- payload.title ? React.createElement(react_2.RiSparkling2Line, null) : null,
255
- React.createElement(Typography_1.default, { variant: "body1", component: "h2" }, ((_b = payload.title) === null || _b === void 0 ? void 0 : _b.includes("AskTIM")) ? (React.createElement(React.Fragment, null,
240
+ title ? React.createElement(react_2.RiSparkling2Line, null) : null,
241
+ React.createElement(Typography_1.default, { variant: "body1", component: "h1" }, (title === null || title === void 0 ? void 0 : title.includes("AskTIM")) ? (React.createElement(React.Fragment, null,
256
242
  "Ask",
257
243
  React.createElement("strong", null, "TIM"),
258
- payload.title.replace("AskTIM", ""))) : (payload.title))),
259
- React.createElement(CloseButton, { variant: "text", size: "medium", onClick: () => setOpen(false), "aria-label": "Close" },
244
+ title.replace("AskTIM", ""))) : (title))),
245
+ React.createElement(CloseButton, { variant: "text", size: "medium", onClick: onClose, "aria-label": "Close" },
260
246
  React.createElement(react_2.RiCloseLine, null))),
261
- blockType === "problem" ? (React.createElement(ChatComponent, { payload: chat, transformBody: transformBody, fetchOpts: fetchOpts, scrollElement: scrollElement, entryScreenEnabled: (_d = (_c = payload.chat) === null || _c === void 0 ? void 0 : _c.entryScreenEnabled) !== null && _d !== void 0 ? _d : false, entryScreenTitle: payload.chat.entryScreenTitle, hasTabs: hasTabs })) : null,
247
+ blockType === "problem" ? (React.createElement(ChatComponent, { payload: chat, transformBody: transformBody, fetchOpts: fetchOpts, scrollElement: scrollElement, entryScreenEnabled: (_b = chat === null || chat === void 0 ? void 0 : chat.entryScreenEnabled) !== null && _b !== void 0 ? _b : false, entryScreenTitle: chat.entryScreenTitle, initialMessages: chat.initialMessages || DEFAULT_PROBLEM_INITIAL_MESSAGES, hasTabs: hasTabs, needsMathJax: true })) : null,
262
248
  blockType === "video" ? (React.createElement(TabContext_1.default, { value: tab },
263
249
  React.createElement(StyledTabButtonList, { styleVariant: "chat", onChange: (e, tab) => setTab(tab) },
264
250
  React.createElement(TabButtonList_1.TabButton, { value: "chat", label: "Chat" }),
265
- ((_e = response === null || response === void 0 ? void 0 : response.flashcards) === null || _e === void 0 ? void 0 : _e.length) ? (React.createElement(TabButtonList_1.TabButton, { value: "flashcards", label: "Flashcards", onMouseDown: handleMouseDown, onFocus: handleFocus })) : null,
251
+ ((_c = response === null || response === void 0 ? void 0 : response.flashcards) === null || _c === void 0 ? void 0 : _c.length) ? (React.createElement(TabButtonList_1.TabButton, { value: "flashcards", label: "Flashcards", onMouseDown: handleMouseDown, onFocus: handleFocus })) : null,
266
252
  React.createElement(TabButtonList_1.TabButton, { value: "summary", label: "Summary" })),
267
253
  React.createElement(StyledTabPanel, { value: "chat", keepMounted: true },
268
- React.createElement(ChatComponent, { payload: Object.assign({}, chat), transformBody: transformBody, fetchOpts: fetchOpts, scrollElement: scrollElement, entryScreenEnabled: (_g = (_f = payload.chat) === null || _f === void 0 ? void 0 : _f.entryScreenEnabled) !== null && _g !== void 0 ? _g : true, entryScreenTitle: (_h = payload.chat.entryScreenTitle) !== null && _h !== void 0 ? _h : DEFAULT_VIDEO_ENTRY_SCREEN_TITLE, conversationStarters: conversationStarters, hasTabs: hasTabs })),
269
- ((_j = response === null || response === void 0 ? void 0 : response.flashcards) === null || _j === void 0 ? void 0 : _j.length) ? (React.createElement(StyledTabPanel, { value: "flashcards" },
254
+ React.createElement(ChatComponent, { payload: chat, transformBody: transformBody, fetchOpts: fetchOpts, scrollElement: scrollElement, entryScreenEnabled: (_d = chat === null || chat === void 0 ? void 0 : chat.entryScreenEnabled) !== null && _d !== void 0 ? _d : true, entryScreenTitle: (_e = chat.entryScreenTitle) !== null && _e !== void 0 ? _e : DEFAULT_VIDEO_ENTRY_SCREEN_TITLE, conversationStarters: conversationStarters, initialMessages: chat.initialMessages, hasTabs: hasTabs, needsMathJax: false })),
255
+ ((_f = response === null || response === void 0 ? void 0 : response.flashcards) === null || _f === void 0 ? void 0 : _f.length) ? (React.createElement(StyledTabPanel, { value: "flashcards" },
270
256
  React.createElement(FlashcardsScreen_1.FlashcardsScreen, { flashcards: response === null || response === void 0 ? void 0 : response.flashcards, wasKeyboardFocus: _wasKeyboardFocus }))) : null,
271
257
  React.createElement(StyledTabPanel, { value: "summary" },
272
258
  React.createElement(Typography_1.default, { variant: "h4", component: "h4" }),
273
259
  React.createElement(StyledHTML, null,
274
- React.createElement(react_markdown_1.default, { rehypePlugins: [rehype_raw_1.default] }, (_k = response === null || response === void 0 ? void 0 : response.summary) !== null && _k !== void 0 ? _k : ""))))) : null));
260
+ React.createElement(react_markdown_1.default, { rehypePlugins: [rehype_raw_1.default] }, (_g = response === null || response === void 0 ? void 0 : response.summary) !== null && _g !== void 0 ? _g : ""))))) : null));
275
261
  };
276
- exports.RemoteTutorDrawer = RemoteTutorDrawer;
262
+ exports.AiDrawer = AiDrawer;
@@ -1,9 +1,10 @@
1
1
  import type { Meta, StoryObj } from "@storybook/react";
2
- import { RemoteTutorDrawer } from "./RemoteTutorDrawer";
3
- declare const meta: Meta<typeof RemoteTutorDrawer>;
2
+ import { AiDrawer } from "./AiDrawer";
3
+ declare const meta: Meta<typeof AiDrawer>;
4
4
  export default meta;
5
- type Story = StoryObj<typeof RemoteTutorDrawer>;
5
+ type Story = StoryObj<typeof AiDrawer>;
6
6
  export declare const ProblemStory: Story;
7
+ export declare const ProblemDefaultInitialMessagesStory: Story;
7
8
  export declare const EntryScreenStory: Story;
8
9
  /**
9
10
  * The chat entry screen is shown by default for the video blocks Tutor drawer.
@@ -1,12 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.FlashcardConversationStartersStory = exports.VideoStory = exports.EntryScreenStory = exports.ProblemStory = void 0;
3
+ exports.FlashcardConversationStartersStory = exports.VideoStory = exports.EntryScreenStory = exports.ProblemDefaultInitialMessagesStory = exports.ProblemStory = void 0;
4
4
  /* eslint-disable react-hooks/rules-of-hooks */
5
5
  const React = require("react");
6
- const tiny_invariant_1 = require("tiny-invariant");
7
6
  const msw_1 = require("msw");
8
7
  const api_1 = require("../../components/AiChat/test-utils/api");
9
- const RemoteTutorDrawer_1 = require("./RemoteTutorDrawer");
8
+ const AiDrawer_1 = require("./AiDrawer");
9
+ const better_react_mathjax_1 = require("better-react-mathjax");
10
+ const Button_1 = require("@mui/material/Button");
10
11
  const TEST_API_STREAMING = "http://localhost:4567/streaming";
11
12
  const CONTENT_FILE_URL = "http://localhost:4567/api/v1/contentfiles/?edx_module_id=1";
12
13
  const INITIAL_MESSAGES = [
@@ -20,50 +21,22 @@ const STARTERS = [
20
21
  { content: "I want to understand global warming. " },
21
22
  { content: "I am curious about AI applications for business" },
22
23
  ];
23
- const buildIFrame = (payload) => (el) => {
24
- var _a;
25
- if (!el)
26
- return;
27
- const doc = el.contentDocument;
28
- const parent = (_a = el.contentWindow) === null || _a === void 0 ? void 0 : _a.parent;
29
- (0, tiny_invariant_1.default)(doc && parent);
30
- const button = doc.createElement("button");
31
- button.textContent = "Open drawer (send message to parent)";
32
- doc.body.appendChild(button);
33
- const div = doc.createElement("div");
34
- doc.body.appendChild(div);
35
- const label = doc.createElement("label");
36
- label.textContent = "Message Data:";
37
- div.appendChild(label);
38
- const textarea = doc.createElement("textarea");
39
- div.append(textarea);
40
- textarea.style["display"] = "block";
41
- textarea.style["width"] = "100%";
42
- textarea.style["height"] = "500px";
43
- const message = {
44
- type: "smoot-design::tutor-drawer-open",
45
- payload,
46
- };
47
- textarea.value = JSON.stringify(message, null, 2);
48
- button.addEventListener("click", () => {
49
- parent.postMessage(JSON.parse(textarea.value));
50
- });
51
- };
52
- const IFrame = ({ payload }) => {
53
- return (React.createElement("iframe", { width: "100%", height: "600px", ref: buildIFrame(payload), title: "button frame" }));
54
- };
55
24
  const meta = {
56
- title: "smoot-design/AI/RemoteTutorDrawer",
57
- render: ({ target }, { parameters: { payload } }) => (React.createElement(React.Fragment, null,
58
- React.createElement(IFrame, { payload: payload }),
59
- React.createElement(RemoteTutorDrawer_1.RemoteTutorDrawer, { target: target, messageOrigin: "http://localhost:6006" }))),
25
+ title: "smoot-design/AI/AiDrawer",
26
+ component: AiDrawer_1.AiDrawer,
27
+ render: ({ payload }) => {
28
+ const [open, setOpen] = React.useState(false);
29
+ return (React.createElement(React.Fragment, null,
30
+ React.createElement(Button_1.default, { variant: "outlined", onClick: () => setOpen(true) }, "Open Drawer"),
31
+ React.createElement("p", null, "Message data:"),
32
+ React.createElement("pre", null, JSON.stringify({ payload }, null, 2)),
33
+ React.createElement(better_react_mathjax_1.MathJaxContext, null,
34
+ React.createElement(AiDrawer_1.AiDrawer, { payload: payload, open: open, onClose: () => setOpen(false) }))));
35
+ },
60
36
  };
61
37
  exports.default = meta;
62
38
  exports.ProblemStory = {
63
39
  args: {
64
- target: "problem-frame",
65
- },
66
- parameters: {
67
40
  payload: {
68
41
  blockType: "problem",
69
42
  target: "problem-frame",
@@ -76,11 +49,21 @@ exports.ProblemStory = {
76
49
  },
77
50
  },
78
51
  };
79
- exports.EntryScreenStory = {
52
+ exports.ProblemDefaultInitialMessagesStory = {
80
53
  args: {
81
- target: "entry-screen-frame",
54
+ payload: {
55
+ blockType: "problem",
56
+ target: "problem-frame-default-initial-messages",
57
+ title: "AskTIM for help with Problem: Derivatives 1.1",
58
+ chat: {
59
+ apiUrl: TEST_API_STREAMING,
60
+ conversationStarters: STARTERS,
61
+ },
62
+ },
82
63
  },
83
- parameters: {
64
+ };
65
+ exports.EntryScreenStory = {
66
+ args: {
84
67
  payload: {
85
68
  blockType: "problem",
86
69
  target: "entry-screen-frame",
@@ -99,9 +82,6 @@ exports.EntryScreenStory = {
99
82
  */
100
83
  exports.VideoStory = {
101
84
  args: {
102
- target: "video-frame",
103
- },
104
- parameters: {
105
85
  payload: {
106
86
  blockType: "video",
107
87
  target: "video-frame",
@@ -113,6 +93,8 @@ exports.VideoStory = {
113
93
  apiUrl: CONTENT_FILE_URL,
114
94
  },
115
95
  },
96
+ },
97
+ parameters: {
116
98
  msw: {
117
99
  handlers: [
118
100
  msw_1.http.get(CONTENT_FILE_URL, () => {
@@ -129,9 +111,6 @@ exports.VideoStory = {
129
111
  */
130
112
  exports.FlashcardConversationStartersStory = {
131
113
  args: {
132
- target: "starters-frame",
133
- },
134
- parameters: {
135
114
  payload: {
136
115
  blockType: "video",
137
116
  target: "starters-frame",
@@ -142,6 +121,8 @@ exports.FlashcardConversationStartersStory = {
142
121
  apiUrl: CONTENT_FILE_URL,
143
122
  },
144
123
  },
124
+ },
125
+ parameters: {
145
126
  msw: {
146
127
  handlers: [
147
128
  msw_1.http.get(CONTENT_FILE_URL, () => {
@@ -0,0 +1,12 @@
1
+ import * as React from "react";
2
+ import type { AiDrawerProps } from "./AiDrawer";
3
+ type AiDrawerManagerProps = {
4
+ /**
5
+ * The origin of the messages that will be received to open the chat.
6
+ * The drawer will ignore all message events not from this origin.
7
+ */
8
+ messageOrigin: string;
9
+ } & AiDrawerProps;
10
+ declare const AiDrawerManager: ({ className, messageOrigin, transformBody, fetchOpts, target, }: AiDrawerManagerProps) => React.JSX.Element;
11
+ export { AiDrawerManager };
12
+ export type { AiDrawerManagerProps };
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AiDrawerManager = void 0;
4
+ const React = require("react");
5
+ const react_1 = require("react");
6
+ const AiDrawer_1 = require("./AiDrawer");
7
+ const better_react_mathjax_1 = require("better-react-mathjax");
8
+ const hashPayload = (payload) => {
9
+ const str = JSON.stringify(payload);
10
+ let hash = 5381;
11
+ for (let i = 0; i < str.length; i++) {
12
+ hash = (hash << 5) + hash + str.charCodeAt(i);
13
+ hash = hash & hash;
14
+ }
15
+ return Math.abs(hash).toString(36);
16
+ };
17
+ const AiDrawerManager = ({ className, messageOrigin, transformBody, fetchOpts, target, }) => {
18
+ const [drawerStates, setDrawerStates] = (0, react_1.useState)({});
19
+ (0, react_1.useEffect)(() => {
20
+ const cb = (event) => {
21
+ if (event.origin !== messageOrigin) {
22
+ if (process.env.NODE_ENV === "development") {
23
+ console.warn(`AiDrawerManager: received message from unexpected origin: ${event.origin}`);
24
+ }
25
+ return;
26
+ }
27
+ if ([
28
+ "smoot-design::ai-drawer-open",
29
+ "smoot-design::tutor-drawer-open", // legacy
30
+ ].includes(event.data.type)) {
31
+ const key = hashPayload(event.data.payload);
32
+ event.data.payload.chat.chatId = event.data.payload.chat.chatId || key;
33
+ setDrawerStates((prev) => (Object.assign(Object.assign({}, prev), { [key]: { key, open: false, payload: event.data.payload } })));
34
+ requestAnimationFrame(() => {
35
+ setDrawerStates((prev) => (Object.assign(Object.assign({}, prev), { [key]: Object.assign(Object.assign({}, prev[key]), { open: true }) })));
36
+ });
37
+ }
38
+ };
39
+ window.addEventListener("message", cb);
40
+ return () => {
41
+ window.removeEventListener("message", cb);
42
+ };
43
+ }, [messageOrigin, target]);
44
+ if (Object.values(drawerStates).length === 0) {
45
+ return React.createElement("div", { "data-testid": "ai-drawer-manager-waiting" });
46
+ }
47
+ return (React.createElement(better_react_mathjax_1.MathJaxContext, null, Object.values(drawerStates).map(({ key, open, payload }) => (React.createElement(AiDrawer_1.AiDrawer, { key: key, className: className, transformBody: transformBody, fetchOpts: fetchOpts, payload: payload, open: open, onClose: () => {
48
+ setDrawerStates((prev) => (Object.assign(Object.assign({}, prev), { [key]: Object.assign(Object.assign({}, prev[key]), { open: false }) })));
49
+ } })))));
50
+ };
51
+ exports.AiDrawerManager = AiDrawerManager;
@@ -0,0 +1,6 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { AiDrawerManager } from "./AiDrawerManager";
3
+ declare const meta: Meta<typeof AiDrawerManager>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof AiDrawerManager>;
6
+ export declare const AiDrawerManagerStory: Story;