@meetelise/chat 1.20.57 → 1.20.59

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/src/MEChat.ts CHANGED
@@ -43,8 +43,8 @@ export default class MEChat {
43
43
  this.handleBuildingslug(meChat, opts.building);
44
44
  meChat.setAttribute("class", "meetelise-chat");
45
45
  meChat.setAttribute("role", "dialog");
46
- meChat.setAttribute("aria-labelledby", "aria-label");
47
- meChat.setAttribute("aria-describedby", "aria-describe");
46
+ meChat.setAttribute("aria-label", "EliseAI Widget");
47
+ meChat.setAttribute("aria-describedby", "aria-describe-info");
48
48
  meChat.setAttribute("aria-modal", "true");
49
49
  if (opts.themeId) {
50
50
  meChat.setAttribute("themeId", opts.themeId);
@@ -2,7 +2,7 @@ import { css, html, LitElement, PropertyValueMap, TemplateResult } from "lit";
2
2
  import { customElement, property, query, state } from "lit/decorators.js";
3
3
  import {
4
4
  shortcutKeyIsPressed,
5
- formatToPhone,
5
+ formatToPhoneInput,
6
6
  isPrintableCharacter,
7
7
  } from "../actions/formatPhoneNumber";
8
8
  import "./tour-type-option.ts";
@@ -180,7 +180,7 @@ export class TourScheduler extends LitElement {
180
180
  this.phoneNumber.slice(0, cursorPosition) +
181
181
  e.key +
182
182
  this.phoneNumber.slice(cursorPosition);
183
- this.phoneNumber = formatToPhone(updated.replace(/\D/g, ""));
183
+ this.phoneNumber = formatToPhoneInput(updated.replace(/\D/g, ""));
184
184
  this.phoneInput.value = this.phoneNumber;
185
185
  } else if (e.key === "Backspace") {
186
186
  /*
@@ -216,7 +216,7 @@ export class TourScheduler extends LitElement {
216
216
  0,
217
217
  -1
218
218
  )}${digitsAfterCursor}`;
219
- this.phoneNumber = formatToPhone(updatedDigits);
219
+ this.phoneNumber = formatToPhoneInput(updatedDigits);
220
220
  this.phoneInput.value = this.phoneNumber;
221
221
  const numOfCharactersDeleted =
222
222
  originalCharacterCount - this.phoneNumber.length;
@@ -287,7 +287,7 @@ export class TourScheduler extends LitElement {
287
287
  const numbersAfterCursor = cursorPosition
288
288
  ? this.phoneInput.value.slice(cursorPosition).replace(/\D/g, "")
289
289
  : "";
290
- this.phoneNumber = formatToPhone(this.phoneInput.value);
290
+ this.phoneNumber = formatToPhoneInput(this.phoneInput.value);
291
291
 
292
292
  // EXAMPLES: (123)| 4 numbersAfterCursor will be '4'.
293
293
  let cursorNegativeIndex = 0;
@@ -1109,7 +1109,7 @@ export class TourScheduler extends LitElement {
1109
1109
  if (!e.target) {
1110
1110
  return;
1111
1111
  }
1112
- this.phoneNumber = formatToPhone(
1112
+ this.phoneNumber = formatToPhoneInput(
1113
1113
  (e.target as HTMLInputElement).value
1114
1114
  );
1115
1115
  }}
@@ -8,7 +8,7 @@ import postLeadSources from "../../postLeadSources";
8
8
  import "../me-select.ts";
9
9
  import { MESelect } from "../me-select";
10
10
  import {
11
- formatToPhone,
11
+ formatToPhoneInput,
12
12
  isModifierKey,
13
13
  isNumericInput,
14
14
  } from "./formatPhoneNumber";
@@ -177,7 +177,7 @@ export class EmailUsWindow extends LitElement {
177
177
  }
178
178
  const inputElement = e.target as HTMLInputElement;
179
179
 
180
- this.phoneNumber = formatToPhone(inputElement.value);
180
+ this.phoneNumber = formatToPhoneInput(inputElement.value);
181
181
 
182
182
  this.phoneNumberInputRef.value.value = this.phoneNumber;
183
183
  };
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * For now, only handles the US phone number case.....
3
+ * Formats into phone number as you type
3
4
  */
4
- export const formatToPhone = (phoneNumber: string): string => {
5
+ export const formatToPhoneInput = (phoneNumber: string): string => {
5
6
  const input = phoneNumber.replace(/\D/g, "").substring(0, 10);
6
7
  const areaCode = input.substring(0, 3);
7
8
  const middle = input.substring(3, 6);
@@ -19,6 +20,19 @@ export const formatToPhone = (phoneNumber: string): string => {
19
20
  return "";
20
21
  };
21
22
 
23
+ /**
24
+ * Formats a phone number into a human-readable format.
25
+ */
26
+ export const formatPhoneNumber = (phoneNumberString: string): string => {
27
+ const cleaned = ("" + phoneNumberString).replace(/\D/g, "");
28
+ const match = cleaned.match(/^(1|)?(\d{3})(\d{3})(\d{4})$/);
29
+ if (match) {
30
+ const intlCode = match[1] ? "+1 " : "";
31
+ return [intlCode, "(", match[2], ") ", match[3], "-", match[4]].join("");
32
+ }
33
+ return phoneNumberString;
34
+ };
35
+
22
36
  export const isNumericInput = (event: KeyboardEvent): boolean => {
23
37
  const key = event.keyCode;
24
38
  return (key >= 48 && key <= 57) || (key >= 96 && key <= 105);
@@ -4,7 +4,7 @@ import { createRef, ref, Ref } from "lit/directives/ref.js";
4
4
  import { installActionConfirmButton } from "./action-confirm-button";
5
5
  import { installDetailsWindow } from "./details-window";
6
6
  import {
7
- formatToPhone,
7
+ formatToPhoneInput,
8
8
  isModifierKey,
9
9
  isNumericInput,
10
10
  } from "./formatPhoneNumber";
@@ -95,7 +95,7 @@ export class TextUsWindow extends LitElement {
95
95
  }
96
96
  const inputElement = e.target as HTMLInputElement;
97
97
 
98
- this.phoneNumber = formatToPhone(inputElement.value);
98
+ this.phoneNumber = formatToPhoneInput(inputElement.value);
99
99
 
100
100
  this.phoneNumberInputRef.value.value = this.phoneNumber;
101
101
  };
@@ -330,6 +330,7 @@ export const launcherStyles = css`
330
330
  padding: 0;
331
331
  cursor: pointer;
332
332
  z-index: 1;
333
+ box-shadow: rgba(99, 99, 99, 0.2) 0px 2px 8px 0px;
333
334
  }
334
335
  .minimize-bttn:hover {
335
336
  filter: brightness(0.9);
@@ -16,6 +16,9 @@ import fetchBuildingABTestType, {
16
16
  abTestTypes,
17
17
  } from "../fetchBuildingABTestType";
18
18
  import fetchCurrentParsedLeadSource from "../fetchCurrentParsedLeadSource";
19
+ import fetchPhoneNumberFromSource, {
20
+ NumberForSelectedSource,
21
+ } from "../fetchPhoneNumberFromSource";
19
22
  import { getTheme, Theme, ThemeIdString } from "../themes";
20
23
  import { isMobile } from "../utils";
21
24
  import { installLauncher } from "./Launcher";
@@ -33,6 +36,7 @@ import {
33
36
  TabletWhiteStrokeIcon,
34
37
  WhiteStrokeTourIcon,
35
38
  } from "../svgIcons";
39
+ import { formatPhoneNumber } from "./actions/formatPhoneNumber";
36
40
 
37
41
  export interface Options {
38
42
  building: string;
@@ -150,6 +154,8 @@ export class MEChat extends LitElement {
150
154
  private featureFlagShowDropdown: FeatureFlagsShowDropdown =
151
155
  FeatureFlagsShowDropdown.always;
152
156
  @state()
157
+ private phoneNumberForSource: NumberForSelectedSource | null = null;
158
+ @state()
153
159
  private hasMounted = false;
154
160
  @state()
155
161
  private hideLauncher = false;
@@ -186,12 +192,29 @@ export class MEChat extends LitElement {
186
192
  fetchCurrentParsedLeadSource(this.buildingSlug, document.referrer),
187
193
  ]);
188
194
 
195
+ building.phoneNumber = formatPhoneNumber(building.phoneNumber);
189
196
  this.building = building;
190
197
  this.buildingABTestType = buildingABTest?.abTestType ?? "";
191
198
  this.leadSources = leadSources;
192
199
  this.featureFlagShowDropdown = featureFlagShowDropdown;
193
200
  this.currentLeadSource = currentLeadSource;
194
201
 
202
+ const phoneNumberForSource = await fetchPhoneNumberFromSource(
203
+ this.buildingSlug,
204
+ this.currentLeadSource
205
+ );
206
+
207
+ // if the building does NOT have IVR setup, we want to use the building's phone number
208
+ if (!phoneNumberForSource) {
209
+ this.phoneNumberForSource = {
210
+ number: this.building.phoneNumber,
211
+ isMatch: false,
212
+ isPropertyWebsiteCatchall: true,
213
+ };
214
+ } else {
215
+ this.phoneNumberForSource = phoneNumberForSource;
216
+ }
217
+
195
218
  if (this.currentLeadSource) {
196
219
  if (!this.leadSources.includes(this.currentLeadSource)) {
197
220
  this.leadSources.push(this.currentLeadSource);
@@ -434,9 +457,8 @@ export class MEChat extends LitElement {
434
457
  this.isMobile;
435
458
 
436
459
  return html`
437
- <div>
438
- <div id="aria-label" style="display: none;">EliseAI Widget</div>
439
- <div id="aria-describe" style="display: none;">
460
+ <meta name="viewport" content="width=device-width, initial-scale=1 user-scalable=1">
461
+ <div id="aria-describe-info" style="display: none;">
440
462
  EliseAI widget that allows you to chat with a virtual assistant, book
441
463
  a tour, contact the leasing office, and more.
442
464
  </div>
@@ -469,53 +491,58 @@ export class MEChat extends LitElement {
469
491
  ["hideTab"]: this.isLoading,
470
492
  })}
471
493
  >
472
- ${this.building
473
- ? html`<meetelise-launcher
474
- ${ref(this.launcherRef)}
475
- .isMobile=${this.isMobile}
476
- .isFirstMount=${!this.hasMounted}
477
- .isMini=${this.useMiniWidget}
478
- .buildingId=${this.building?.id ?? 0}
479
- .layoutOptions=${this.building?.layoutOptionsV2 ?? []}
480
- .unitOptions=${this.building?.unitOptionsV2 ?? []}
481
- .tourTypeOptions=${this.building?.tourTypeOptions ?? []}
482
- .launcherStyles=${this.launcherStyles}
483
- .autoOpenChatWidget=${this.building.autoOpenChatWidget ?? false}
484
- chatCallUsHeader=${this.building?.chatCallUsHeader ?? ""}
485
- chatId="${this.chatId}"
486
- phoneNumber="${this.building?.phoneNumber ?? ""}"
487
- textColor="${this.theme.chatHeader.textColor}"
488
- backgroundColor="${this.theme.chatPaneBackgroundColor}"
489
- orgSlug="${this.orgSlug}"
490
- buildingSlug="${this.buildingSlug}"
491
- sgtUrl="${this.building?.sgtUrl ?? ""}"
492
- buildingABTestType="${this.buildingABTestType ?? ""}"
493
- currentLeadSource="${this.currentLeadSource ?? ""}"
494
- featureFlagShowDropdown="${this.featureFlagShowDropdown}"
495
- .leadSources="${this.leadSources ?? []}"
496
- escortedToursLink="${this.building?.escortedToursLink ?? ""}"
497
- virtualToursLink="${this.building?.virtualToursLink ?? ""}"
498
- ?hidden=${this.hideLauncher}
499
- ?hasCallUsEnabled=${!this.building?.chatWidgets
500
- ? true
501
- : this.building?.chatWidgets.includes("CALL")}
502
- ?hasChatEnabled=${!this.building?.chatWidgets
503
- ? true
504
- : this.building?.chatWidgets.includes("CHAT")}
505
- ?hasEmailEnabled=${!this.building?.chatWidgets
506
- ? true
507
- : this.building?.chatWidgets.includes("EMAIL")}
508
- ?hasTextUsEnabled=${!this.building?.chatWidgets
509
- ? true
510
- : this.building?.chatWidgets.includes("SMS")}
511
- ?hasSSTEnabled=${!this.building?.chatWidgets
512
- ? true
513
- : this.building?.chatWidgets.includes("SST")}
514
- >
515
- </meetelise-launcher>`
516
- : ""}
494
+ ${
495
+ this.building
496
+ ? html`<meetelise-launcher
497
+ ${ref(this.launcherRef)}
498
+ .isMobile=${this.isMobile}
499
+ .isFirstMount=${!this.hasMounted}
500
+ .isMini=${this.useMiniWidget}
501
+ .buildingId=${this.building?.id ?? 0}
502
+ .layoutOptions=${this.building?.layoutOptionsV2 ?? []}
503
+ .unitOptions=${this.building?.unitOptionsV2 ?? []}
504
+ .tourTypeOptions=${this.building?.tourTypeOptions ?? []}
505
+ .launcherStyles=${this.launcherStyles}
506
+ .autoOpenChatWidget=${this.building.autoOpenChatWidget ??
507
+ false}
508
+ chatCallUsHeader=${this.building?.chatCallUsHeader ?? ""}
509
+ chatId="${this.chatId}"
510
+ phoneNumber="${this.phoneNumberForSource?.number ??
511
+ this.building?.phoneNumber ??
512
+ ""}"
513
+ textColor="${this.theme.chatHeader.textColor}"
514
+ backgroundColor="${this.theme.chatPaneBackgroundColor}"
515
+ orgSlug="${this.orgSlug}"
516
+ buildingSlug="${this.buildingSlug}"
517
+ sgtUrl="${this.building?.sgtUrl ?? ""}"
518
+ buildingABTestType="${this.buildingABTestType ?? ""}"
519
+ currentLeadSource="${this.currentLeadSource ?? ""}"
520
+ featureFlagShowDropdown="${this.featureFlagShowDropdown}"
521
+ .leadSources="${this.leadSources ?? []}"
522
+ escortedToursLink="${this.building?.escortedToursLink ?? ""}"
523
+ virtualToursLink="${this.building?.virtualToursLink ?? ""}"
524
+ ?hidden=${this.hideLauncher}
525
+ ?hasCallUsEnabled=${!this.building?.chatWidgets
526
+ ? true
527
+ : this.building?.chatWidgets.includes("CALL")}
528
+ ?hasChatEnabled=${!this.building?.chatWidgets
529
+ ? true
530
+ : this.building?.chatWidgets.includes("CHAT")}
531
+ ?hasEmailEnabled=${!this.building?.chatWidgets
532
+ ? true
533
+ : this.building?.chatWidgets.includes("EMAIL")}
534
+ ?hasTextUsEnabled=${!this.building?.chatWidgets
535
+ ? true
536
+ : this.building?.chatWidgets.includes("SMS")}
537
+ ?hasSSTEnabled=${!this.building?.chatWidgets
538
+ ? true
539
+ : this.building?.chatWidgets.includes("SST")}
540
+ >
541
+ </meetelise-launcher>`
542
+ : ""
543
+ }
517
544
  </div>
518
- </div>
545
+ </meta>
519
546
  `;
520
547
  }
521
548
 
@@ -0,0 +1,31 @@
1
+ import axios from "axios";
2
+ import { formatPhoneNumber } from "./WebComponent/actions/formatPhoneNumber";
3
+
4
+ export interface NumberForSelectedSource {
5
+ number: string;
6
+ isMatch: boolean;
7
+ isPropertyWebsiteCatchall: boolean;
8
+ }
9
+
10
+ export default async function fetchPhoneNumberFromSource(
11
+ buildingSlug: string,
12
+ source: string | null
13
+ ): Promise<NumberForSelectedSource | null> {
14
+ const host = "https://app.meetelise.com";
15
+ try {
16
+ const phoneNumberResponse = await axios.get(
17
+ `${host}/platformApi/webchat/${buildingSlug}/phone-number-by-source?source=${source}`
18
+ );
19
+ if (phoneNumberResponse.data) {
20
+ return {
21
+ number: formatPhoneNumber(phoneNumberResponse.data.number),
22
+ isMatch: phoneNumberResponse.data.isMatch,
23
+ isPropertyWebsiteCatchall:
24
+ phoneNumberResponse.data.isPropertyWebsiteCatchall,
25
+ };
26
+ }
27
+ return null;
28
+ } catch (_) {
29
+ return null;
30
+ }
31
+ }