@mitodl/smoot-design 3.7.0 → 4.0.0

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 (38) hide show
  1. package/dist/bundles/remoteTutorDrawer.es.js +37930 -0
  2. package/dist/bundles/remoteTutorDrawer.umd.js +208 -0
  3. package/dist/{esm/bundles/RemoteAiChatDrawer/RemoteAiChatDrawer.d.ts → cjs/bundles/RemoteTutorDrawer/RemoteTutorDrawer.d.ts} +25 -13
  4. package/dist/cjs/bundles/RemoteTutorDrawer/RemoteTutorDrawer.js +182 -0
  5. package/dist/cjs/bundles/RemoteTutorDrawer/RemoteTutorDrawer.stories.d.ts +7 -0
  6. package/dist/cjs/bundles/RemoteTutorDrawer/RemoteTutorDrawer.stories.js +120 -0
  7. package/dist/cjs/bundles/remoteTutorDrawer.d.ts +7 -0
  8. package/dist/cjs/bundles/{remoteAiChatDrawer.js → remoteTutorDrawer.js} +3 -3
  9. package/dist/cjs/components/AiChat/AiChat.js +4 -4
  10. package/dist/cjs/components/AiChat/types.d.ts +5 -0
  11. package/dist/cjs/components/TabButtons/TabButtonList.d.ts +16 -0
  12. package/dist/cjs/components/TabButtons/TabButtonList.js +86 -0
  13. package/dist/cjs/components/TabButtons/TabButtonList.stories.d.ts +24 -0
  14. package/dist/cjs/components/TabButtons/TabButtonList.stories.js +139 -0
  15. package/dist/{cjs/bundles/RemoteAiChatDrawer/RemoteAiChatDrawer.d.ts → esm/bundles/RemoteTutorDrawer/RemoteTutorDrawer.d.ts} +25 -13
  16. package/dist/esm/bundles/RemoteTutorDrawer/RemoteTutorDrawer.js +179 -0
  17. package/dist/esm/bundles/RemoteTutorDrawer/RemoteTutorDrawer.stories.d.ts +7 -0
  18. package/dist/esm/bundles/RemoteTutorDrawer/RemoteTutorDrawer.stories.js +117 -0
  19. package/dist/esm/bundles/remoteTutorDrawer.d.ts +7 -0
  20. package/dist/esm/bundles/{remoteAiChatDrawer.js → remoteTutorDrawer.js} +3 -3
  21. package/dist/esm/components/AiChat/AiChat.js +4 -4
  22. package/dist/esm/components/AiChat/types.d.ts +5 -0
  23. package/dist/esm/components/TabButtons/TabButtonList.d.ts +16 -0
  24. package/dist/esm/components/TabButtons/TabButtonList.js +81 -0
  25. package/dist/esm/components/TabButtons/TabButtonList.stories.d.ts +24 -0
  26. package/dist/esm/components/TabButtons/TabButtonList.stories.js +136 -0
  27. package/dist/tsconfig.tsbuildinfo +1 -1
  28. package/package.json +23 -20
  29. package/dist/bundles/remoteAiChatDrawer.es.js +0 -27901
  30. package/dist/bundles/remoteAiChatDrawer.umd.js +0 -198
  31. package/dist/cjs/bundles/RemoteAiChatDrawer/RemoteAiChatDrawer.js +0 -50
  32. package/dist/cjs/bundles/RemoteAiChatDrawer/RemoteAiChatDrawer.stories.d.ts +0 -6
  33. package/dist/cjs/bundles/RemoteAiChatDrawer/RemoteAiChatDrawer.stories.js +0 -69
  34. package/dist/cjs/bundles/remoteAiChatDrawer.d.ts +0 -7
  35. package/dist/esm/bundles/RemoteAiChatDrawer/RemoteAiChatDrawer.js +0 -47
  36. package/dist/esm/bundles/RemoteAiChatDrawer/RemoteAiChatDrawer.stories.d.ts +0 -6
  37. package/dist/esm/bundles/RemoteAiChatDrawer/RemoteAiChatDrawer.stories.js +0 -66
  38. package/dist/esm/bundles/remoteAiChatDrawer.d.ts +0 -7
@@ -1,18 +1,26 @@
1
- import * as React from "react";
1
+ import { FC } from "react";
2
2
  import { AiChatMessage } from "../../components/AiChat/types";
3
3
  import type { AiChatProps } from "../../components/AiChat/AiChat";
4
- type ChatInitMessage = {
5
- type: "smoot-design::chat-open";
4
+ type RemoteTutorDrawerInitMessage = {
5
+ type: "smoot-design::tutor-drawer-open";
6
6
  payload: {
7
- chatId?: AiChatProps["chatId"];
8
- askTimTitle?: AiChatProps["title"];
9
- conversationStarters?: AiChatProps["conversationStarters"];
10
- initialMessages: AiChatProps["initialMessages"];
11
- apiUrl: AiChatProps["requestOpts"]["apiUrl"];
12
- requestBody?: Record<string, unknown>;
7
+ blockType?: "problem" | "video";
8
+ target?: string;
9
+ chat: {
10
+ chatId?: AiChatProps["chatId"];
11
+ askTimTitle?: AiChatProps["title"];
12
+ conversationStarters?: AiChatProps["conversationStarters"];
13
+ initialMessages: AiChatProps["initialMessages"];
14
+ apiUrl: AiChatProps["requestOpts"]["apiUrl"];
15
+ requestBody?: Record<string, unknown>;
16
+ };
17
+ summary?: {
18
+ contentUrl: string;
19
+ };
13
20
  };
14
21
  };
15
- type AiChatDrawerProps = {
22
+ type RemoteTutorDrawerProps = {
23
+ blockType?: "problem" | "video";
16
24
  className?: string;
17
25
  /**
18
26
  * The origin of the messages that will be received to open the chat.
@@ -35,7 +43,11 @@ type AiChatDrawerProps = {
35
43
  * identifying cookies.
36
44
  */
37
45
  fetchOpts?: AiChatProps["requestOpts"]["fetchOpts"];
46
+ /**
47
+ * Pass to target a specific drawer instance where multiple are on the page.
48
+ */
49
+ target?: string;
38
50
  };
39
- declare const AiChatDrawer: React.FC<AiChatDrawerProps>;
40
- export { AiChatDrawer };
41
- export type { AiChatDrawerProps, ChatInitMessage };
51
+ declare const RemoteTutorDrawer: FC<RemoteTutorDrawerProps>;
52
+ export { RemoteTutorDrawer };
53
+ export type { RemoteTutorDrawerProps, RemoteTutorDrawerInitMessage };
@@ -0,0 +1,182 @@
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.RemoteTutorDrawer = void 0;
13
+ const React = require("react");
14
+ const react_1 = require("react");
15
+ const styled_1 = require("@emotion/styled");
16
+ const react_markdown_1 = require("react-markdown");
17
+ const rehype_raw_1 = require("rehype-raw");
18
+ const react_2 = require("@remixicon/react");
19
+ const Drawer_1 = require("@mui/material/Drawer");
20
+ const TabButtonList_1 = require("../../components/TabButtons/TabButtonList");
21
+ const Typography_1 = require("@mui/material/Typography");
22
+ const TabContext_1 = require("@mui/lab/TabContext");
23
+ const TabPanel_1 = require("@mui/lab/TabPanel");
24
+ const AiChat_1 = require("../../components/AiChat/AiChat");
25
+ const ActionButton_1 = require("../../components/Button/ActionButton");
26
+ const CloseButton = (0, styled_1.default)(ActionButton_1.ActionButton)(({ theme }) => ({
27
+ position: "fixed",
28
+ top: "24px",
29
+ right: "40px",
30
+ backgroundColor: theme.custom.colors.lightGray2,
31
+ "&&:hover": {
32
+ backgroundColor: theme.custom.colors.red,
33
+ color: theme.custom.colors.white,
34
+ },
35
+ zIndex: 2,
36
+ }));
37
+ const StyledTabButtonList = (0, styled_1.default)(TabButtonList_1.TabButtonList)(({ theme }) => ({
38
+ padding: "80px 0 16px",
39
+ backgroundColor: theme.custom.colors.white,
40
+ position: "sticky",
41
+ top: 0,
42
+ zIndex: 1,
43
+ overflow: "visible",
44
+ }));
45
+ const StyledTabPanel = (0, styled_1.default)(TabPanel_1.default)({
46
+ padding: "0",
47
+ height: "calc(100% - 138px)",
48
+ });
49
+ const StyledAiChat = (0, styled_1.default)(AiChat_1.AiChat)({
50
+ ".MitAiChat--title": {
51
+ paddingTop: "8px",
52
+ },
53
+ });
54
+ const StyledHTML = styled_1.default.div(({ theme }) => (Object.assign(Object.assign({ color: theme.custom.colors.darkGray2, backgroundColor: theme.custom.colors.white, padding: "12px 0 100px" }, theme.typography.body2), { "p:first-of-type": {
55
+ marginTop: 0,
56
+ }, "p:last-of-type": {
57
+ marginBottom: 0,
58
+ }, "ol, ul": {
59
+ paddingInlineStart: "32px",
60
+ li: {
61
+ margin: "16px 0",
62
+ },
63
+ }, ul: {
64
+ marginInlineStart: "-16px",
65
+ }, a: {
66
+ color: theme.custom.colors.red,
67
+ fontWeight: "normal",
68
+ } })));
69
+ const identity = (x) => x;
70
+ const DEFAULT_FETCH_OPTS = {
71
+ credentials: "include",
72
+ };
73
+ const parseContent = (contentString) => {
74
+ var _a;
75
+ try {
76
+ const parsed = JSON.parse(contentString);
77
+ const content = (_a = parsed[0]) === null || _a === void 0 ? void 0 : _a.content;
78
+ const unescaped = content
79
+ .replace(/\\n/g, "\n")
80
+ .replace(/\\"/g, '"')
81
+ .replace(/\\'/g, "'");
82
+ return unescaped;
83
+ }
84
+ catch (e) {
85
+ console.warn("Could not parse content:", e);
86
+ return contentString;
87
+ }
88
+ };
89
+ const useContentFetch = (contentUrl) => {
90
+ const [summary, setSummary] = (0, react_1.useState)(null);
91
+ const [error, setError] = (0, react_1.useState)(null);
92
+ const [loading, setLoading] = (0, react_1.useState)(false);
93
+ (0, react_1.useEffect)(() => {
94
+ if (!contentUrl)
95
+ return;
96
+ const fetchData = () => __awaiter(void 0, void 0, void 0, function* () {
97
+ setLoading(true);
98
+ try {
99
+ const response = yield fetch(contentUrl);
100
+ const result = yield response.json();
101
+ const parsedContent = parseContent(result.content);
102
+ setSummary(parsedContent);
103
+ }
104
+ catch (err) {
105
+ setError(err instanceof Error ? err : new Error("Failed to fetch"));
106
+ }
107
+ finally {
108
+ setLoading(false);
109
+ }
110
+ });
111
+ fetchData();
112
+ }, [contentUrl]);
113
+ return { summary, error, loading };
114
+ };
115
+ const ChatComponent = ({ payload, transformBody, fetchOpts, }) => {
116
+ if (!payload)
117
+ return null;
118
+ return (React.createElement(StyledAiChat, { chatId: payload.chatId, askTimTitle: payload.askTimTitle, conversationStarters: payload.conversationStarters, initialMessages: payload.initialMessages, requestOpts: {
119
+ transformBody: (messages) => (Object.assign(Object.assign({}, payload.requestBody), transformBody === null || transformBody === void 0 ? void 0 : transformBody(messages))),
120
+ apiUrl: payload.apiUrl,
121
+ fetchOpts: Object.assign(Object.assign({}, DEFAULT_FETCH_OPTS), fetchOpts),
122
+ } }));
123
+ };
124
+ const RemoteTutorDrawer = ({ messageOrigin, transformBody = identity, className, fetchOpts, target, }) => {
125
+ var _a;
126
+ const [open, setOpen] = (0, react_1.useState)(false);
127
+ const [payload, setPayload] = (0, react_1.useState)(null);
128
+ const [tab, setTab] = (0, react_1.useState)("chat");
129
+ const paperRef = (0, react_1.useRef)(null);
130
+ const { summary } = useContentFetch((_a = payload === null || payload === void 0 ? void 0 : payload.summary) === null || _a === void 0 ? void 0 : _a.contentUrl);
131
+ (0, react_1.useEffect)(() => {
132
+ const cb = (event) => {
133
+ if (event.origin !== messageOrigin) {
134
+ if (process.env.NODE_ENV === "development") {
135
+ console.warn(`RemoteTutorDrawer: received message from unexpected origin: ${event.origin}`);
136
+ }
137
+ return;
138
+ }
139
+ if (event.data.type === "smoot-design::tutor-drawer-open" &&
140
+ event.data.payload.target === target) {
141
+ setOpen(true);
142
+ setPayload(event.data.payload);
143
+ }
144
+ };
145
+ window.addEventListener("message", cb);
146
+ return () => {
147
+ window.removeEventListener("message", cb);
148
+ };
149
+ }, [messageOrigin, target]);
150
+ if (!payload) {
151
+ return null;
152
+ }
153
+ const { blockType, chat } = payload;
154
+ const hasTabs = blockType === "video";
155
+ return (React.createElement(Drawer_1.default, { className: className, PaperProps: {
156
+ ref: paperRef,
157
+ sx: {
158
+ width: "900px",
159
+ maxWidth: "100%",
160
+ boxSizing: "border-box",
161
+ scrollbarGutter: "stable",
162
+ padding: hasTabs ? "0 25px 24px 40px" : "24px 25px 24px 40px",
163
+ ".MitAiChat--title": {
164
+ paddingTop: "0px",
165
+ },
166
+ },
167
+ }, anchor: "right", open: open, onClose: () => setOpen(false) },
168
+ React.createElement(CloseButton, { variant: "text", size: "medium", onClick: () => setOpen(false), "aria-label": "Close" },
169
+ React.createElement(react_2.RiCloseLine, null)),
170
+ blockType === "problem" ? (React.createElement(ChatComponent, { payload: chat, transformBody: transformBody, fetchOpts: fetchOpts })) : null,
171
+ blockType === "video" ? (React.createElement(TabContext_1.default, { value: tab },
172
+ React.createElement(StyledTabButtonList, { styleVariant: "chat", onChange: (_event, val) => setTab(val) },
173
+ React.createElement(TabButtonList_1.TabButton, { value: "chat", label: "Chat" }),
174
+ React.createElement(TabButtonList_1.TabButton, { value: "summary", label: "Summary" })),
175
+ React.createElement(StyledTabPanel, { value: "chat" },
176
+ React.createElement(ChatComponent, { payload: chat, transformBody: transformBody, fetchOpts: fetchOpts })),
177
+ React.createElement(StyledTabPanel, { value: "summary" },
178
+ React.createElement(Typography_1.default, { variant: "h4", component: "h4" }),
179
+ React.createElement(StyledHTML, null,
180
+ React.createElement(react_markdown_1.default, { rehypePlugins: [rehype_raw_1.default] }, summary))))) : null));
181
+ };
182
+ exports.RemoteTutorDrawer = RemoteTutorDrawer;
@@ -0,0 +1,7 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { RemoteTutorDrawer } from "./RemoteTutorDrawer";
3
+ declare const meta: Meta<typeof RemoteTutorDrawer>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof RemoteTutorDrawer>;
6
+ export declare const ProblemStory: Story;
7
+ export declare const VideoStory: Story;