@meetelise/chat 1.6.4 → 1.8.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.
- package/index.ts +1 -0
- package/package.json +3 -3
- package/public/dist/index.d.ts +1 -0
- package/public/dist/index.js +2 -0
- package/public/dist/{bundle.js.LICENSE.txt → index.js.LICENSE.txt} +0 -0
- package/public/{ts-loader-build → dist/src}/InHouseLauncher.d.ts +0 -0
- package/public/{ts-loader-build → dist/src}/MEChat.d.ts +6 -3
- package/public/{ts-loader-build → dist/src}/analytics.d.ts +0 -0
- package/public/{ts-loader-build → dist/src}/chatID.d.ts +0 -0
- package/public/dist/src/createConversation.d.ts +4 -0
- package/public/{ts-loader-build → dist/src}/fetchBuildingInfo.d.ts +0 -12
- package/public/{ts-loader-build → dist/src}/launchDarklyManager.d.ts +0 -0
- package/public/dist/src/themes.d.ts +52 -0
- package/public/{ts-loader-build → dist/src}/utils.d.ts +0 -0
- package/public/index.html +1 -1
- package/src/InHouseLauncher.module.scss +7 -2
- package/src/MEChat.test.ts +11 -12
- package/src/MEChat.tsx +62 -54
- package/src/createConversation.ts +15 -21
- package/src/fetchBuildingInfo.ts +0 -14
- package/src/themes.ts +53 -14
- package/tsconfig.json +2 -2
- package/webpack.config.cjs +2 -2
- package/public/dist/bundle.js +0 -2
- package/public/ts-loader-build/createConversation.d.ts +0 -4
- package/public/ts-loader-build/getAvatarUrl.d.ts +0 -13
- package/public/ts-loader-build/getIcons.d.ts +0 -8
- package/public/ts-loader-build/installTalkJSStyles.d.ts +0 -8
- package/public/ts-loader-build/resolveTheme.d.ts +0 -15
- package/public/ts-loader-build/themes.d.ts +0 -179
- package/src/ChatBubble.d.ts +0 -11
- package/src/ChatBubble.module.scss +0 -58
- package/src/ChatBubble.tsx +0 -55
- package/src/getAvatarUrl.ts +0 -39
- package/src/getIcons.ts +0 -51
- package/src/installTalkJSStyles.ts +0 -26
- package/src/resolveTheme.ts +0 -44
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export declare const enum ThemeId {
|
|
2
|
+
Light = "Light",
|
|
3
|
+
Dark = "Dark",
|
|
4
|
+
Purple = "Purple",
|
|
5
|
+
Blue = "Blue",
|
|
6
|
+
Teal = "Teal",
|
|
7
|
+
Green = "Green",
|
|
8
|
+
Yellow = "Yellow",
|
|
9
|
+
Orange = "Orange",
|
|
10
|
+
Pink = "Pink"
|
|
11
|
+
}
|
|
12
|
+
export declare type ThemeIdString = `${ThemeId}`;
|
|
13
|
+
export interface Theme {
|
|
14
|
+
chatHeader: {
|
|
15
|
+
backgroundColor: string;
|
|
16
|
+
textColor: string;
|
|
17
|
+
};
|
|
18
|
+
chatPaneBackgroundColor: string;
|
|
19
|
+
message: {
|
|
20
|
+
user: {
|
|
21
|
+
textColor: string;
|
|
22
|
+
backgroundColor: string;
|
|
23
|
+
};
|
|
24
|
+
agent: {
|
|
25
|
+
textColor: string;
|
|
26
|
+
backgroundColor: string;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export declare const defaultThemeId = ThemeId.Light;
|
|
31
|
+
export declare const lightMessage: {
|
|
32
|
+
user: {
|
|
33
|
+
textColor: string;
|
|
34
|
+
backgroundColor: string;
|
|
35
|
+
};
|
|
36
|
+
agent: {
|
|
37
|
+
textColor: string;
|
|
38
|
+
backgroundColor: string;
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
export declare const darkMessage: {
|
|
42
|
+
user: {
|
|
43
|
+
textColor: string;
|
|
44
|
+
backgroundColor: string;
|
|
45
|
+
};
|
|
46
|
+
agent: {
|
|
47
|
+
textColor: string;
|
|
48
|
+
backgroundColor: string;
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
/** If `themeId` is a valid `ThemeId`, returns the corresponding theme. Otherwise returns the default theme. */
|
|
52
|
+
export declare const getTheme: (themeId?: string | undefined) => Theme;
|
|
File without changes
|
package/public/index.html
CHANGED
|
@@ -87,7 +87,7 @@
|
|
|
87
87
|
</main>
|
|
88
88
|
<script type="module">
|
|
89
89
|
import { debounce } from "https://cdn.skypack.dev/lodash";
|
|
90
|
-
import MEChat from "./dist/
|
|
90
|
+
import MEChat from "./dist/index.js";
|
|
91
91
|
const chat = MEChat.start({
|
|
92
92
|
organization: "test-company",
|
|
93
93
|
building: "e2e-test-yardi-building",
|
|
@@ -12,6 +12,7 @@ $glowBarGif: url("https://s3.us-west-2.amazonaws.com/meetelise.com/HorizontalBar
|
|
|
12
12
|
all: revert;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
user-select: none;
|
|
15
16
|
position: fixed;
|
|
16
17
|
display: flex;
|
|
17
18
|
justify-content: space-evenly;
|
|
@@ -19,11 +20,15 @@ $glowBarGif: url("https://s3.us-west-2.amazonaws.com/meetelise.com/HorizontalBar
|
|
|
19
20
|
color: #202020;
|
|
20
21
|
background-color: rgba(white, 0.8);
|
|
21
22
|
backdrop-filter: blur(10px);
|
|
23
|
+
box-shadow: 0px 8px 8px 4px rgba(0, 0, 0, 0.25);
|
|
22
24
|
font-family: Poppins;
|
|
23
25
|
|
|
24
26
|
&:hover {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
+
background: radial-gradient(
|
|
28
|
+
36.85% 65.32% at 50% 106.31%,
|
|
29
|
+
#03ecc4 0%,
|
|
30
|
+
rgba(131, 129, 142, 1) 100%
|
|
31
|
+
);
|
|
27
32
|
}
|
|
28
33
|
|
|
29
34
|
&.mobile {
|
package/src/MEChat.test.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { expect } from "@esm-bundle/chai";
|
|
2
2
|
import { stub, restore } from "sinon/pkg/sinon-esm";
|
|
3
|
-
import MEChat from "../public/dist/
|
|
4
|
-
|
|
5
|
-
const TIMEOUT = 15000;
|
|
3
|
+
import MEChat from "../public/dist/index";
|
|
6
4
|
|
|
7
5
|
const stubResponse = {
|
|
8
6
|
json: stub().resolves({
|
|
@@ -27,7 +25,7 @@ const stubResponse = {
|
|
|
27
25
|
|
|
28
26
|
const waitForElementWithSelectorToExist = async (
|
|
29
27
|
selector: string,
|
|
30
|
-
target: Node = document.
|
|
28
|
+
target: Node = document.body
|
|
31
29
|
): Promise<void> => {
|
|
32
30
|
return new Promise<void>((resolve) => {
|
|
33
31
|
// in case the element already exists
|
|
@@ -43,12 +41,14 @@ const waitForElementWithSelectorToExist = async (
|
|
|
43
41
|
});
|
|
44
42
|
};
|
|
45
43
|
|
|
44
|
+
const wait = (delay, ...args) =>
|
|
45
|
+
new Promise((resolve) => setTimeout(resolve, delay, ...args));
|
|
46
|
+
|
|
46
47
|
afterEach(() => {
|
|
47
48
|
restore();
|
|
48
49
|
});
|
|
49
50
|
|
|
50
|
-
it
|
|
51
|
-
this.timeout(TIMEOUT);
|
|
51
|
+
it("shows the launcher", async function () {
|
|
52
52
|
// Given an API that returns this building theme
|
|
53
53
|
stub(window, "fetch").resolves(stubResponse);
|
|
54
54
|
|
|
@@ -71,21 +71,20 @@ it.skip("shows the launcher", async function (done) {
|
|
|
71
71
|
const popupDisplay = popupStyle.getPropertyValue("display");
|
|
72
72
|
expect(popupDisplay).to.equal("none");
|
|
73
73
|
|
|
74
|
-
// When I click the launcher
|
|
75
74
|
launcher.click();
|
|
75
|
+
// Without waiting, the popup doesn't open in time for the next assertion
|
|
76
|
+
await wait(0);
|
|
76
77
|
|
|
77
78
|
// Then the popup should be visible
|
|
78
79
|
const popupStyle2 = window.getComputedStyle(popup);
|
|
79
80
|
const popupDisplay2 = popupStyle2.getPropertyValue("display");
|
|
80
81
|
expect(popupDisplay2).not.to.equal("none");
|
|
81
|
-
|
|
82
|
+
|
|
82
83
|
// Ideally, expect welcome message, but we can't select inside the iframe
|
|
83
84
|
// Ideally, expect theme colors, but we can't select inside the iframe
|
|
84
85
|
});
|
|
85
86
|
|
|
86
|
-
it
|
|
87
|
-
this.timeout(TIMEOUT);
|
|
88
|
-
|
|
87
|
+
it("works via the programmatic interface", async function () {
|
|
89
88
|
// Given an API that returns this building theme
|
|
90
89
|
stub(window, "fetch").resolves(stubResponse);
|
|
91
90
|
|
|
@@ -95,7 +94,7 @@ it.skip("works via the programmatic interface", async function () {
|
|
|
95
94
|
building: "unit-test-building",
|
|
96
95
|
});
|
|
97
96
|
|
|
98
|
-
await waitForElementWithSelectorToExist(".meetelise-chat.launcher");
|
|
97
|
+
await waitForElementWithSelectorToExist(".meetelise-chat.launcher > div");
|
|
99
98
|
|
|
100
99
|
// Ideally, verify behavior, but this will at least verify nothing throws
|
|
101
100
|
chat.show();
|
package/src/MEChat.tsx
CHANGED
|
@@ -6,14 +6,15 @@ import Talk from "talkjs";
|
|
|
6
6
|
import fetchBuildingInfo, { Building } from "./fetchBuildingInfo";
|
|
7
7
|
import { getChatID, createChatID } from "./chatID";
|
|
8
8
|
import createConversation from "./createConversation";
|
|
9
|
-
import
|
|
10
|
-
import resolveTheme, { Theme } from "./resolveTheme";
|
|
9
|
+
import { Theme, ThemeIdString } from "./themes";
|
|
11
10
|
import Analytics from "./analytics";
|
|
12
11
|
import { isMobile } from "./utils";
|
|
13
12
|
import InHouseLauncher from "./InHouseLauncher";
|
|
14
13
|
import LaunchDarkly from "./launchDarklyManager";
|
|
15
14
|
import styles from "./MEChat.module.scss";
|
|
16
|
-
import {
|
|
15
|
+
import { getTheme } from "./themes";
|
|
16
|
+
|
|
17
|
+
const LAUNCHER_CLASSES = ["meetelise-chat", "launcher"];
|
|
17
18
|
|
|
18
19
|
/**
|
|
19
20
|
* The interface to MeetElise chat.
|
|
@@ -65,21 +66,26 @@ export default class MEChat {
|
|
|
65
66
|
* Clear all messages from the window and start a new conversation.
|
|
66
67
|
*/
|
|
67
68
|
restartConversation(): void {
|
|
68
|
-
Promise.all([
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
69
|
+
Promise.all([
|
|
70
|
+
MEChat.session,
|
|
71
|
+
this.building,
|
|
72
|
+
this.theme,
|
|
73
|
+
this.avatarSrc,
|
|
74
|
+
this.popup,
|
|
75
|
+
]).then(([session, building, theme, avatarSrc, popup]) => {
|
|
76
|
+
this.chatId = createChatID(this.orgSlug, this.buildingSlug);
|
|
77
|
+
this.analytics.chatId = this.chatId;
|
|
78
|
+
popup.select(
|
|
79
|
+
createConversation(
|
|
80
|
+
session,
|
|
81
|
+
building,
|
|
82
|
+
theme,
|
|
83
|
+
avatarSrc || building.avatarSrc,
|
|
84
|
+
this.chatId,
|
|
85
|
+
this.isMobile
|
|
86
|
+
)
|
|
87
|
+
);
|
|
88
|
+
});
|
|
83
89
|
}
|
|
84
90
|
|
|
85
91
|
/**
|
|
@@ -87,29 +93,28 @@ export default class MEChat {
|
|
|
87
93
|
*
|
|
88
94
|
* @param theme The updated theme
|
|
89
95
|
*/
|
|
90
|
-
|
|
96
|
+
// TODO: probably want to replace theme argument with themeId, avatarSrc
|
|
97
|
+
setTheme(newTheme: Partial<Theme>): void {
|
|
91
98
|
const focusedElement = document.activeElement;
|
|
92
99
|
Promise.all([
|
|
93
100
|
MEChat.session,
|
|
94
101
|
this.building,
|
|
102
|
+
this.theme,
|
|
103
|
+
this.avatarSrc,
|
|
95
104
|
this.popup,
|
|
96
105
|
LaunchDarkly.isReady,
|
|
97
106
|
])
|
|
98
|
-
.then(([session, building, popup]) => {
|
|
99
|
-
const resolvedTheme = (this.theme = resolveTheme(building, {
|
|
100
|
-
...this.theme,
|
|
101
|
-
...theme,
|
|
102
|
-
}));
|
|
107
|
+
.then(([session, building, theme, avatarSrc, popup]) => {
|
|
103
108
|
popup.select(
|
|
104
109
|
createConversation(
|
|
105
110
|
session,
|
|
106
111
|
building,
|
|
107
|
-
|
|
112
|
+
{ ...theme, ...newTheme },
|
|
113
|
+
avatarSrc || building.avatarSrc,
|
|
108
114
|
this.chatId,
|
|
109
115
|
this.isMobile
|
|
110
116
|
)
|
|
111
117
|
);
|
|
112
|
-
installTalkJSStyles(resolvedTheme);
|
|
113
118
|
return new Promise(requestAnimationFrame);
|
|
114
119
|
})
|
|
115
120
|
.then(() => {
|
|
@@ -148,19 +153,15 @@ export default class MEChat {
|
|
|
148
153
|
const chatTappedHandler = async () => {
|
|
149
154
|
ReactDOM.unmountComponentAtNode(targetElement);
|
|
150
155
|
(await this.popup).show();
|
|
156
|
+
this.analytics.ping("open");
|
|
151
157
|
};
|
|
152
|
-
const building = await this.building;
|
|
153
|
-
let theme = themesById[defaultThemeId];
|
|
154
|
-
if (Object.keys(themesById).includes(building.themeId)) {
|
|
155
|
-
theme = themesById[building.themeId as keyof typeof themesById];
|
|
156
|
-
}
|
|
157
158
|
ReactDOM.render(
|
|
158
159
|
<InHouseLauncher
|
|
159
160
|
onChatTapped={chatTappedHandler}
|
|
160
161
|
mobile={this.isMobile}
|
|
161
162
|
firstMount={firstMount}
|
|
162
|
-
backgroundColor={theme.chatPaneBackgroundColor}
|
|
163
|
-
textColor={theme.chatHeader.textColor}
|
|
163
|
+
backgroundColor={(await this.theme).chatPaneBackgroundColor}
|
|
164
|
+
textColor={(await this.theme).chatHeader.textColor}
|
|
164
165
|
/>,
|
|
165
166
|
targetElement
|
|
166
167
|
);
|
|
@@ -170,7 +171,9 @@ export default class MEChat {
|
|
|
170
171
|
const inHouseLauncherTarget = document.createElement("div");
|
|
171
172
|
inHouseLauncherTarget.classList.add(
|
|
172
173
|
styles.inHouseLauncherContainer,
|
|
173
|
-
this.isMobile ? styles.mobile : styles.desktop
|
|
174
|
+
this.isMobile ? styles.mobile : styles.desktop,
|
|
175
|
+
...LAUNCHER_CLASSES,
|
|
176
|
+
styles.shouldBeVisible
|
|
174
177
|
);
|
|
175
178
|
document.body.appendChild(inHouseLauncherTarget);
|
|
176
179
|
this.mountInHouseLauncher(inHouseLauncherTarget, true);
|
|
@@ -185,37 +188,46 @@ export default class MEChat {
|
|
|
185
188
|
private popup: Promise<Talk.Popup>;
|
|
186
189
|
private launcher: Promise<HTMLElement>;
|
|
187
190
|
private building: Promise<Building>;
|
|
188
|
-
private
|
|
191
|
+
private themeId?: ThemeIdString;
|
|
192
|
+
private theme: Promise<Theme>;
|
|
193
|
+
private avatarSrc?: Promise<null | string>;
|
|
189
194
|
private chatId: string;
|
|
190
195
|
private analytics: Analytics;
|
|
191
196
|
private launchDarklyClient: LDClient.LDClient;
|
|
192
197
|
private useInHouseLauncher: boolean;
|
|
193
198
|
private isMobile: boolean;
|
|
194
199
|
|
|
195
|
-
private constructor({ organization, building,
|
|
200
|
+
private constructor({ organization, building, themeId, avatarSrc }: Options) {
|
|
196
201
|
this.orgSlug = organization;
|
|
197
202
|
this.buildingSlug = building;
|
|
198
203
|
this.chatId = getChatID(organization, building);
|
|
199
204
|
this.analytics = new Analytics(organization, building, this.chatId);
|
|
200
205
|
this.launchDarklyClient = LaunchDarkly.getClient(this.chatId);
|
|
201
206
|
this.analytics.ping("load");
|
|
202
|
-
this.theme = theme;
|
|
203
207
|
this.building = fetchBuildingInfo(organization, building);
|
|
208
|
+
this.themeId = themeId;
|
|
209
|
+
this.theme = this.building.then((building) =>
|
|
210
|
+
getTheme(themeId || building.themeId)
|
|
211
|
+
);
|
|
212
|
+
this.avatarSrc = this.building.then(
|
|
213
|
+
(building) => avatarSrc || building.avatarSrc
|
|
214
|
+
);
|
|
204
215
|
this.useInHouseLauncher = true;
|
|
205
216
|
this.isMobile = isMobile();
|
|
206
217
|
|
|
207
218
|
this.popup = Promise.all([
|
|
208
219
|
this.building,
|
|
220
|
+
this.theme,
|
|
221
|
+
this.avatarSrc,
|
|
209
222
|
MEChat.session,
|
|
210
223
|
LaunchDarkly.isReady,
|
|
211
|
-
]).then(async ([building, session]) => {
|
|
212
|
-
const
|
|
213
|
-
installTalkJSStyles(resolvedTheme);
|
|
214
|
-
const p = session.createPopup(
|
|
224
|
+
]).then(async ([building, theme, avatarSrc, session]) => {
|
|
225
|
+
const popup = session.createPopup(
|
|
215
226
|
createConversation(
|
|
216
227
|
session,
|
|
217
228
|
building,
|
|
218
|
-
|
|
229
|
+
theme,
|
|
230
|
+
avatarSrc || building.avatarSrc,
|
|
219
231
|
this.chatId,
|
|
220
232
|
this.isMobile
|
|
221
233
|
),
|
|
@@ -225,9 +237,6 @@ export default class MEChat {
|
|
|
225
237
|
messageField: { placeholder: "Ask a question..." },
|
|
226
238
|
}
|
|
227
239
|
);
|
|
228
|
-
p.on("open", () => {
|
|
229
|
-
this.analytics.ping("open");
|
|
230
|
-
});
|
|
231
240
|
if (building.conversationMaintenanceMode) {
|
|
232
241
|
return new Promise(() => {
|
|
233
242
|
// If in maintenance mode, we return an always-pending Promise
|
|
@@ -237,7 +246,7 @@ export default class MEChat {
|
|
|
237
246
|
);
|
|
238
247
|
});
|
|
239
248
|
}
|
|
240
|
-
await
|
|
249
|
+
await popup.mount({ show: false });
|
|
241
250
|
const talkjsPopupElement = document.querySelector(".__talkjs_popup");
|
|
242
251
|
if (!talkjsPopupElement) throw new Error("Failed to find chat window");
|
|
243
252
|
talkjsPopupElement.classList.add("meetelise-chat", "pane");
|
|
@@ -245,7 +254,7 @@ export default class MEChat {
|
|
|
245
254
|
talkjsPopupElement.classList.add(styles.desktop);
|
|
246
255
|
}
|
|
247
256
|
(talkjsPopupElement as HTMLElement).style.zIndex = "99999999999";
|
|
248
|
-
return
|
|
257
|
+
return popup;
|
|
249
258
|
});
|
|
250
259
|
|
|
251
260
|
this.launcher = Promise.all([this.popup, LaunchDarkly.isReady]).then(
|
|
@@ -262,14 +271,12 @@ export default class MEChat {
|
|
|
262
271
|
if (!talkjsLauncherElement)
|
|
263
272
|
throw new Error("MeetElise Chat: Could not locate launcher.");
|
|
264
273
|
launcherElement = talkjsLauncherElement;
|
|
274
|
+
launcherElement.classList.add(
|
|
275
|
+
...LAUNCHER_CLASSES,
|
|
276
|
+
styles.shouldBeVisible
|
|
277
|
+
);
|
|
265
278
|
}
|
|
266
279
|
|
|
267
|
-
launcherElement.classList.add(
|
|
268
|
-
"meetelise-chat",
|
|
269
|
-
"launcher",
|
|
270
|
-
styles.shouldBeVisible
|
|
271
|
-
);
|
|
272
|
-
|
|
273
280
|
return launcherElement;
|
|
274
281
|
}
|
|
275
282
|
);
|
|
@@ -279,5 +286,6 @@ export default class MEChat {
|
|
|
279
286
|
export interface Options {
|
|
280
287
|
building: string;
|
|
281
288
|
organization: string;
|
|
282
|
-
|
|
289
|
+
themeId?: ThemeIdString;
|
|
290
|
+
avatarSrc?: string;
|
|
283
291
|
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import Talk from "talkjs";
|
|
2
2
|
import { Building } from "./fetchBuildingInfo";
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
import { defaultThemeId, themesById } from "./themes";
|
|
3
|
+
import { Theme } from "./themes";
|
|
4
|
+
import { darkMessage } from "./themes";
|
|
6
5
|
|
|
7
6
|
const defaultAvatarUrl =
|
|
8
7
|
"https://s3.us-west-2.amazonaws.com/meetelise.com/looping-gradient.gif";
|
|
@@ -11,6 +10,7 @@ export default function createConversation(
|
|
|
11
10
|
session: Talk.Session,
|
|
12
11
|
building: Building,
|
|
13
12
|
theme: Theme,
|
|
13
|
+
avatarSrc: Building["avatarSrc"],
|
|
14
14
|
chatID: string,
|
|
15
15
|
isMobile: boolean
|
|
16
16
|
): Talk.ConversationBuilder {
|
|
@@ -18,39 +18,33 @@ export default function createConversation(
|
|
|
18
18
|
id: `building_${building.id}`,
|
|
19
19
|
name: building.userFirstName,
|
|
20
20
|
email: null,
|
|
21
|
-
photoUrl: getAvatarUrl(building),
|
|
22
21
|
role: "Default",
|
|
23
22
|
welcomeMessage: building.welcomeMessage,
|
|
24
23
|
});
|
|
25
24
|
const conversation = session.getOrCreateConversation(chatID);
|
|
26
|
-
conversation.subject = theme.chatTitle;
|
|
27
25
|
conversation.setParticipant(session.me);
|
|
28
26
|
conversation.setParticipant(agent);
|
|
29
|
-
|
|
30
|
-
// TODO: typescript abuse
|
|
31
|
-
let themeId = defaultThemeId;
|
|
32
|
-
if (Object.keys(themesById).includes(building.themeId)) {
|
|
33
|
-
themeId = building.themeId as keyof typeof themesById;
|
|
34
|
-
}
|
|
35
|
-
const _theme = themesById[themeId];
|
|
27
|
+
conversation.subject = building.chatTitle ?? building.userFirstName;
|
|
36
28
|
conversation.custom = {
|
|
37
29
|
buildingId: building.id.toString(),
|
|
38
30
|
userId: building.userId.toString(),
|
|
39
31
|
orgId: building.orgId.toString(),
|
|
40
|
-
subtitle:
|
|
32
|
+
subtitle: building.chatSubtitle,
|
|
41
33
|
url: location.href,
|
|
42
34
|
buildingName: building.name,
|
|
43
35
|
isMobile: isMobile.toString(),
|
|
44
|
-
chatHeaderBackgroundColor:
|
|
45
|
-
chatHeaderTextColor:
|
|
46
|
-
chatPaneBackgroundColor:
|
|
47
|
-
userMessageTextColor:
|
|
48
|
-
userMessageBackgroundColor:
|
|
49
|
-
agentMessageTextColor:
|
|
50
|
-
agentMessageBackgroundColor:
|
|
36
|
+
chatHeaderBackgroundColor: theme.chatHeader.backgroundColor,
|
|
37
|
+
chatHeaderTextColor: theme.chatHeader.textColor,
|
|
38
|
+
chatPaneBackgroundColor: theme.chatPaneBackgroundColor,
|
|
39
|
+
userMessageTextColor: theme.message.user.textColor,
|
|
40
|
+
userMessageBackgroundColor: theme.message.user.backgroundColor,
|
|
41
|
+
agentMessageTextColor: theme.message.agent.textColor,
|
|
42
|
+
agentMessageBackgroundColor: theme.message.agent.backgroundColor,
|
|
43
|
+
// it is sometimes helpful to know inside TalkJS if the theme is a light theme (examples: Light, Teal, Yellow) or a dark theme (Dark, Purple, Green)
|
|
44
|
+
isLightTheme: (theme.message === darkMessage).toString(),
|
|
51
45
|
avatarUrl:
|
|
52
46
|
building.avatarType === "image" && building.avatarSrc
|
|
53
|
-
?
|
|
47
|
+
? avatarSrc
|
|
54
48
|
: defaultAvatarUrl,
|
|
55
49
|
// uncomment this to test changes to the default avatar if your test building has its own avatar
|
|
56
50
|
// avatarUrl: defaultAvatarUrl,
|
package/src/fetchBuildingInfo.ts
CHANGED
|
@@ -3,31 +3,17 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export interface Building {
|
|
5
5
|
id: number;
|
|
6
|
-
|
|
7
6
|
themeId: string;
|
|
8
|
-
avatarInitials: string | null;
|
|
9
7
|
avatarSrc: string | null;
|
|
10
8
|
avatarType: "image" | "initials" | null;
|
|
11
9
|
chatSubtitle: string | null;
|
|
12
10
|
chatTitle: string | null;
|
|
13
|
-
logoSrc: string | null;
|
|
14
11
|
name: string;
|
|
15
|
-
primaryColor: string | null;
|
|
16
12
|
userFirstName: string;
|
|
17
13
|
userId: number;
|
|
18
|
-
userLastName: string | null;
|
|
19
14
|
welcomeMessage: string | null;
|
|
20
15
|
conversationMaintenanceMode: boolean;
|
|
21
16
|
orgId: number;
|
|
22
|
-
// old: not sure if still present in API response, but we're not using (may have mised a few above)
|
|
23
|
-
backgroundColor: string | null;
|
|
24
|
-
bannerColor: string | null;
|
|
25
|
-
bannerTextColor: string | null;
|
|
26
|
-
launchButtonColor: string | null;
|
|
27
|
-
launchButtonIconColor: string | null;
|
|
28
|
-
launchButtonSize: string | null;
|
|
29
|
-
messageColor: string | null;
|
|
30
|
-
messageTextColor: string | null;
|
|
31
17
|
}
|
|
32
18
|
|
|
33
19
|
/**
|
package/src/themes.ts
CHANGED
|
@@ -1,8 +1,39 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
const white = "#FFFFFF";
|
|
2
|
+
const darkGray = "#202020";
|
|
3
|
+
const lightGray = "#83818E";
|
|
4
4
|
|
|
5
|
-
export const
|
|
5
|
+
export const enum ThemeId {
|
|
6
|
+
Light = "Light",
|
|
7
|
+
Dark = "Dark",
|
|
8
|
+
Purple = "Purple",
|
|
9
|
+
Blue = "Blue",
|
|
10
|
+
Teal = "Teal",
|
|
11
|
+
Green = "Green",
|
|
12
|
+
Yellow = "Yellow",
|
|
13
|
+
Orange = "Orange",
|
|
14
|
+
Pink = "Pink",
|
|
15
|
+
}
|
|
16
|
+
export type ThemeIdString = `${ThemeId}`;
|
|
17
|
+
|
|
18
|
+
export interface Theme {
|
|
19
|
+
chatHeader: {
|
|
20
|
+
backgroundColor: string;
|
|
21
|
+
textColor: string;
|
|
22
|
+
};
|
|
23
|
+
chatPaneBackgroundColor: string;
|
|
24
|
+
message: {
|
|
25
|
+
user: {
|
|
26
|
+
textColor: string;
|
|
27
|
+
backgroundColor: string;
|
|
28
|
+
};
|
|
29
|
+
agent: {
|
|
30
|
+
textColor: string;
|
|
31
|
+
backgroundColor: string;
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export const defaultThemeId = ThemeId.Light;
|
|
6
37
|
|
|
7
38
|
export const lightMessage = {
|
|
8
39
|
user: { textColor: white, backgroundColor: lightGray },
|
|
@@ -12,8 +43,8 @@ export const darkMessage = {
|
|
|
12
43
|
user: { textColor: white, backgroundColor: lightGray },
|
|
13
44
|
agent: { textColor: white, backgroundColor: darkGray },
|
|
14
45
|
};
|
|
15
|
-
|
|
16
|
-
Light: {
|
|
46
|
+
const themesById = {
|
|
47
|
+
[ThemeId.Light]: {
|
|
17
48
|
chatHeader: {
|
|
18
49
|
backgroundColor: white,
|
|
19
50
|
textColor: darkGray,
|
|
@@ -21,7 +52,7 @@ export const themesById = {
|
|
|
21
52
|
chatPaneBackgroundColor: "rgba(255, 255, 255, 0.9)",
|
|
22
53
|
message: darkMessage,
|
|
23
54
|
},
|
|
24
|
-
Dark: {
|
|
55
|
+
[ThemeId.Dark]: {
|
|
25
56
|
chatHeader: {
|
|
26
57
|
backgroundColor: darkGray,
|
|
27
58
|
textColor: white,
|
|
@@ -29,7 +60,7 @@ export const themesById = {
|
|
|
29
60
|
chatPaneBackgroundColor: "rgba(32, 32, 32, 0.9)",
|
|
30
61
|
message: lightMessage,
|
|
31
62
|
},
|
|
32
|
-
Purple: {
|
|
63
|
+
[ThemeId.Purple]: {
|
|
33
64
|
chatHeader: {
|
|
34
65
|
backgroundColor: "#550098",
|
|
35
66
|
textColor: white,
|
|
@@ -37,7 +68,7 @@ export const themesById = {
|
|
|
37
68
|
chatPaneBackgroundColor: "rgba(85, 0, 152, 0.6)",
|
|
38
69
|
message: lightMessage,
|
|
39
70
|
},
|
|
40
|
-
Blue: {
|
|
71
|
+
[ThemeId.Blue]: {
|
|
41
72
|
chatHeader: {
|
|
42
73
|
backgroundColor: "#0814E5",
|
|
43
74
|
textColor: white,
|
|
@@ -45,7 +76,7 @@ export const themesById = {
|
|
|
45
76
|
chatPaneBackgroundColor: "rgba(4, 17, 245, 0.6)",
|
|
46
77
|
message: lightMessage,
|
|
47
78
|
},
|
|
48
|
-
Teal: {
|
|
79
|
+
[ThemeId.Teal]: {
|
|
49
80
|
chatHeader: {
|
|
50
81
|
backgroundColor: "#6EE7ED",
|
|
51
82
|
textColor: darkGray,
|
|
@@ -53,7 +84,7 @@ export const themesById = {
|
|
|
53
84
|
chatPaneBackgroundColor: "rgba(115, 247, 253, 0.8)",
|
|
54
85
|
message: darkMessage,
|
|
55
86
|
},
|
|
56
|
-
Green: {
|
|
87
|
+
[ThemeId.Green]: {
|
|
57
88
|
chatHeader: {
|
|
58
89
|
backgroundColor: "#147B0E",
|
|
59
90
|
textColor: white,
|
|
@@ -61,7 +92,7 @@ export const themesById = {
|
|
|
61
92
|
chatPaneBackgroundColor: "rgba(13, 141, 5, 0.6)",
|
|
62
93
|
message: lightMessage,
|
|
63
94
|
},
|
|
64
|
-
Yellow: {
|
|
95
|
+
[ThemeId.Yellow]: {
|
|
65
96
|
chatHeader: {
|
|
66
97
|
backgroundColor: "#F1E54F",
|
|
67
98
|
textColor: darkGray,
|
|
@@ -69,7 +100,7 @@ export const themesById = {
|
|
|
69
100
|
chatPaneBackgroundColor: "rgba(251, 239, 80, 0.9)",
|
|
70
101
|
message: darkMessage,
|
|
71
102
|
},
|
|
72
|
-
Orange: {
|
|
103
|
+
[ThemeId.Orange]: {
|
|
73
104
|
chatHeader: {
|
|
74
105
|
backgroundColor: "#C06C31",
|
|
75
106
|
textColor: white,
|
|
@@ -77,7 +108,7 @@ export const themesById = {
|
|
|
77
108
|
chatPaneBackgroundColor: "rgba(238, 126, 49, 0.7)",
|
|
78
109
|
message: lightMessage,
|
|
79
110
|
},
|
|
80
|
-
Pink: {
|
|
111
|
+
[ThemeId.Pink]: {
|
|
81
112
|
chatHeader: {
|
|
82
113
|
backgroundColor: "#A24599",
|
|
83
114
|
textColor: white,
|
|
@@ -86,3 +117,11 @@ export const themesById = {
|
|
|
86
117
|
message: lightMessage,
|
|
87
118
|
},
|
|
88
119
|
};
|
|
120
|
+
|
|
121
|
+
/** If `themeId` is a valid `ThemeId`, returns the corresponding theme. Otherwise returns the default theme. */
|
|
122
|
+
export const getTheme = (themeId?: ThemeId | string): Theme =>
|
|
123
|
+
themesById[
|
|
124
|
+
themeId && Object.keys(themesById).includes(themeId)
|
|
125
|
+
? (themeId as ThemeIdString)
|
|
126
|
+
: defaultThemeId
|
|
127
|
+
];
|
package/tsconfig.json
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
|
|
18
18
|
"sourceMap": true /* Generates corresponding '.map' file. */,
|
|
19
19
|
// "outFile": "./", /* Concatenate and emit output to single file. */
|
|
20
|
-
"outDir": "./public/
|
|
20
|
+
"outDir": "./public/dist" /* Redirect output structure to the directory. */,
|
|
21
21
|
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
|
22
22
|
// "composite": true, /* Enable project compilation */
|
|
23
23
|
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
|
|
@@ -73,5 +73,5 @@
|
|
|
73
73
|
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */,
|
|
74
74
|
"plugins": [{ "name": "typescript-plugin-css-modules" }]
|
|
75
75
|
},
|
|
76
|
-
"include": ["./src/MEChat.tsx", "declarations.d.ts"]
|
|
76
|
+
"include": ["./src/MEChat.tsx", "declarations.d.ts", "index.ts"]
|
|
77
77
|
}
|
package/webpack.config.cjs
CHANGED
|
@@ -38,8 +38,8 @@ module.exports = (env) => {
|
|
|
38
38
|
outputModule: !env.isDemoApp,
|
|
39
39
|
},
|
|
40
40
|
output: {
|
|
41
|
-
filename: "
|
|
42
|
-
sourceMapFilename: "
|
|
41
|
+
filename: "index.js",
|
|
42
|
+
sourceMapFilename: "index.js.map",
|
|
43
43
|
...(env.isDemoApp
|
|
44
44
|
? {
|
|
45
45
|
path: path.resolve(__dirname, "./public/demo/built"),
|