@meetelise/chat 1.25.1 → 1.25.2

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 (209) hide show
  1. package/coverage/lcov-report/index.html +1 -1
  2. package/coverage/lcov-report/index.js.html +1 -1
  3. package/package.json +1 -1
  4. package/.prettierignore +0 -2
  5. package/dist/src/MyPubnub.d.ts +0 -116
  6. package/dist/src/WebComponent/FeeCalculator/components/collapsible-fee-section/collapsible-fee-section-styles.d.ts +0 -2
  7. package/dist/src/WebComponent/FeeCalculator/components/collapsible-fee-section/collapsible-fee-section.d.ts +0 -20
  8. package/dist/src/WebComponent/FeeCalculator/components/fee-item/fee-item-styles.d.ts +0 -2
  9. package/dist/src/WebComponent/FeeCalculator/components/fee-item/fee-item.d.ts +0 -14
  10. package/dist/src/WebComponent/FeeCalculator/components/floor-plan-selector/floor-plan-selector-styles.d.ts +0 -2
  11. package/dist/src/WebComponent/FeeCalculator/components/floor-plan-selector/floor-plan-selector.d.ts +0 -17
  12. package/dist/src/WebComponent/FeeCalculator/components/index.d.ts +0 -3
  13. package/dist/src/WebComponent/FeeCalculator/components/promo-card/promo-card-styles.d.ts +0 -2
  14. package/dist/src/WebComponent/FeeCalculator/components/promo-card/promo-card.d.ts +0 -13
  15. package/dist/src/WebComponent/FeeCalculator/fee-calculator-styles.d.ts +0 -1
  16. package/dist/src/WebComponent/FeeCalculator/fee-calculator.d.ts +0 -31
  17. package/dist/src/WebComponent/FeeCalculator/index.d.ts +0 -2
  18. package/dist/src/WebComponent/FeeCalculator/model/building-fee.d.ts +0 -75
  19. package/dist/src/WebComponent/FeeCalculator/model/transaction-category.d.ts +0 -23
  20. package/dist/src/WebComponent/LeadSourceClient.d.ts +0 -46
  21. package/dist/src/WebComponent/OfficeHours.d.ts +0 -21
  22. package/dist/src/WebComponent/Scheduler/date-picker.d.ts +0 -28
  23. package/dist/src/WebComponent/Scheduler/time-picker.d.ts +0 -14
  24. package/dist/src/WebComponent/Scheduler/tour-scheduler.d.ts +0 -99
  25. package/dist/src/WebComponent/Scheduler/tour-type-option.d.ts +0 -13
  26. package/dist/src/WebComponent/Scheduler/tourSchedulerStyles.d.ts +0 -1
  27. package/dist/src/WebComponent/actions/InputStyles.d.ts +0 -1
  28. package/dist/src/WebComponent/actions/action-confirm-button.d.ts +0 -13
  29. package/dist/src/WebComponent/actions/call-us-window.d.ts +0 -37
  30. package/dist/src/WebComponent/actions/collapse-expand-button.d.ts +0 -8
  31. package/dist/src/WebComponent/actions/details-window.d.ts +0 -14
  32. package/dist/src/WebComponent/actions/email-us-window.d.ts +0 -46
  33. package/dist/src/WebComponent/actions/formatPhoneNumber.d.ts +0 -17
  34. package/dist/src/WebComponent/actions/minimize-expand-button.d.ts +0 -8
  35. package/dist/src/WebComponent/chat-additional-actions.d.ts +0 -28
  36. package/dist/src/WebComponent/health-chat.d.ts +0 -47
  37. package/dist/src/WebComponent/healthchat-styles.d.ts +0 -1
  38. package/dist/src/WebComponent/icons/ApplyOutlineIcon.d.ts +0 -2
  39. package/dist/src/WebComponent/icons/BookTourOutlineIcon.d.ts +0 -2
  40. package/dist/src/WebComponent/icons/CalculatorOutlineIcon.d.ts +0 -2
  41. package/dist/src/WebComponent/icons/ChatOutlineIcon.d.ts +0 -2
  42. package/dist/src/WebComponent/icons/ChevronLeftIcon.d.ts +0 -2
  43. package/dist/src/WebComponent/icons/ChevronRightIcon.d.ts +0 -2
  44. package/dist/src/WebComponent/icons/ContactResidentIcon.d.ts +0 -2
  45. package/dist/src/WebComponent/icons/DollarOutlineIcon.d.ts +0 -3
  46. package/dist/src/WebComponent/icons/EmailOutlineIcon.d.ts +0 -2
  47. package/dist/src/WebComponent/icons/HeyThereEmojiIcon.d.ts +0 -2
  48. package/dist/src/WebComponent/icons/PhoneOutlineIcon.d.ts +0 -2
  49. package/dist/src/WebComponent/icons/SendMessageIcon.d.ts +0 -3
  50. package/dist/src/WebComponent/icons/TourSelfGuidedIcon.d.ts +0 -2
  51. package/dist/src/WebComponent/icons/TourVirtuallyIcon.d.ts +0 -2
  52. package/dist/src/WebComponent/icons/TourWithAgentIcon.d.ts +0 -2
  53. package/dist/src/WebComponent/icons/XOutlineIcon.d.ts +0 -2
  54. package/dist/src/WebComponent/index.d.ts +0 -2
  55. package/dist/src/WebComponent/launcher/Launcher.d.ts +0 -98
  56. package/dist/src/WebComponent/launcher/launcherStyles.d.ts +0 -1
  57. package/dist/src/WebComponent/launcher/mobile-launcher.d.ts +0 -26
  58. package/dist/src/WebComponent/launcher/typeEmojiStyles.d.ts +0 -1
  59. package/dist/src/WebComponent/launcher/typeMiniStyles.d.ts +0 -1
  60. package/dist/src/WebComponent/launcher/typeMobileStyles.d.ts +0 -1
  61. package/dist/src/WebComponent/leasing-chat-styles.d.ts +0 -1
  62. package/dist/src/WebComponent/me-chat.d.ts +0 -91
  63. package/dist/src/WebComponent/me-select.d.ts +0 -24
  64. package/dist/src/WebComponent/mini-loader.d.ts +0 -5
  65. package/dist/src/WebComponent/pubnub-chat-styles.d.ts +0 -1
  66. package/dist/src/WebComponent/pubnub-chat.d.ts +0 -49
  67. package/dist/src/WebComponent/pubnub-media.d.ts +0 -14
  68. package/dist/src/WebComponent/pubnub-message-styles.d.ts +0 -1
  69. package/dist/src/WebComponent/pubnub-message.d.ts +0 -39
  70. package/dist/src/WebComponent/simple-launcher/simple-launcher-styles.d.ts +0 -1
  71. package/dist/src/WebComponent/simple-launcher/simple-launcher.d.ts +0 -12
  72. package/dist/src/WebComponent/utilities-chat.d.ts +0 -47
  73. package/dist/src/WebComponent/utilities-styles.d.ts +0 -1
  74. package/dist/src/WebComponent/utils.d.ts +0 -31
  75. package/dist/src/analytics.d.ts +0 -64
  76. package/dist/src/disclaimers.d.ts +0 -8
  77. package/dist/src/fetchBuildingABTestType.d.ts +0 -8
  78. package/dist/src/fetchBuildingInfo.d.ts +0 -57
  79. package/dist/src/fetchBuildingWebchatView.d.ts +0 -122
  80. package/dist/src/fetchFeatureFlag.d.ts +0 -14
  81. package/dist/src/fetchLeadSources.d.ts +0 -4
  82. package/dist/src/fetchPhoneNumberFromSource.d.ts +0 -6
  83. package/dist/src/getAvailabilities.d.ts +0 -44
  84. package/dist/src/getBuildingPhoneNumber.d.ts +0 -1
  85. package/dist/src/getShouldAllowScheduling.d.ts +0 -1
  86. package/dist/src/getShouldShowWebchat.d.ts +0 -3
  87. package/dist/src/getTimezoneString.d.ts +0 -1
  88. package/dist/src/globals.d.ts +0 -1
  89. package/dist/src/gtm.d.ts +0 -6
  90. package/dist/src/handleChatId.d.ts +0 -11
  91. package/dist/src/insertDNIIntoWebsite.d.ts +0 -5
  92. package/dist/src/insertLeadSourceIntoSchedulerLinks.d.ts +0 -4
  93. package/dist/src/main/MEChat.d.ts +0 -74
  94. package/dist/src/main/utils.d.ts +0 -2
  95. package/dist/src/postLeadSources.d.ts +0 -3
  96. package/dist/src/rentgrata.d.ts +0 -4
  97. package/dist/src/replaceSelectButtonsWithNewLink.d.ts +0 -5
  98. package/dist/src/services/fees/fetchBuildingFees.d.ts +0 -3
  99. package/dist/src/svgIcons.d.ts +0 -5
  100. package/dist/src/themes.d.ts +0 -5
  101. package/dist/src/types/rest-sdk.types.d.ts +0 -11
  102. package/dist/src/types/webchat-no-show-reason.d.ts +0 -1
  103. package/dist/src/utils.d.ts +0 -13
  104. package/public/demo/index.html +0 -347
  105. package/public/demo/secret.html +0 -63
  106. package/src/MyPubnub.ts +0 -792
  107. package/src/WebComponent/FeeCalculator/components/collapsible-fee-section/collapsible-fee-section-styles.ts +0 -86
  108. package/src/WebComponent/FeeCalculator/components/collapsible-fee-section/collapsible-fee-section.ts +0 -94
  109. package/src/WebComponent/FeeCalculator/components/fee-item/fee-item-styles.ts +0 -47
  110. package/src/WebComponent/FeeCalculator/components/fee-item/fee-item.ts +0 -50
  111. package/src/WebComponent/FeeCalculator/components/floor-plan-selector/floor-plan-selector-styles.ts +0 -46
  112. package/src/WebComponent/FeeCalculator/components/floor-plan-selector/floor-plan-selector.ts +0 -70
  113. package/src/WebComponent/FeeCalculator/components/index.ts +0 -3
  114. package/src/WebComponent/FeeCalculator/components/promo-card/promo-card-styles.ts +0 -39
  115. package/src/WebComponent/FeeCalculator/components/promo-card/promo-card.ts +0 -39
  116. package/src/WebComponent/FeeCalculator/fee-calculator-styles.ts +0 -280
  117. package/src/WebComponent/FeeCalculator/fee-calculator.ts +0 -256
  118. package/src/WebComponent/FeeCalculator/index.ts +0 -4
  119. package/src/WebComponent/FeeCalculator/model/building-fee.ts +0 -83
  120. package/src/WebComponent/FeeCalculator/model/transaction-category.ts +0 -23
  121. package/src/WebComponent/LeadSourceClient.ts +0 -332
  122. package/src/WebComponent/MEChat.css +0 -5
  123. package/src/WebComponent/OfficeHours.ts +0 -73
  124. package/src/WebComponent/Scheduler/date-picker.ts +0 -405
  125. package/src/WebComponent/Scheduler/time-picker.ts +0 -190
  126. package/src/WebComponent/Scheduler/tour-scheduler.ts +0 -1352
  127. package/src/WebComponent/Scheduler/tour-type-option.ts +0 -112
  128. package/src/WebComponent/Scheduler/tourSchedulerStyles.ts +0 -418
  129. package/src/WebComponent/actions/InputStyles.ts +0 -57
  130. package/src/WebComponent/actions/action-confirm-button.ts +0 -125
  131. package/src/WebComponent/actions/call-us-window.ts +0 -445
  132. package/src/WebComponent/actions/collapse-expand-button.ts +0 -65
  133. package/src/WebComponent/actions/details-window.ts +0 -150
  134. package/src/WebComponent/actions/email-us-window.ts +0 -555
  135. package/src/WebComponent/actions/formatPhoneNumber.ts +0 -72
  136. package/src/WebComponent/actions/minimize-expand-button.ts +0 -93
  137. package/src/WebComponent/chat-additional-actions.ts +0 -135
  138. package/src/WebComponent/health-chat.ts +0 -270
  139. package/src/WebComponent/healthchat-styles.ts +0 -119
  140. package/src/WebComponent/icons/ApplyOutlineIcon.ts +0 -22
  141. package/src/WebComponent/icons/BookTourOutlineIcon.ts +0 -13
  142. package/src/WebComponent/icons/CalculatorOutlineIcon.ts +0 -22
  143. package/src/WebComponent/icons/ChatOutlineIcon.ts +0 -10
  144. package/src/WebComponent/icons/ChevronLeftIcon.ts +0 -7
  145. package/src/WebComponent/icons/ChevronRightIcon.ts +0 -7
  146. package/src/WebComponent/icons/ContactResidentIcon.ts +0 -9
  147. package/src/WebComponent/icons/DollarOutlineIcon.ts +0 -18
  148. package/src/WebComponent/icons/EmailOutlineIcon.ts +0 -7
  149. package/src/WebComponent/icons/HeyThereEmojiIcon.ts +0 -12
  150. package/src/WebComponent/icons/PhoneOutlineIcon.ts +0 -7
  151. package/src/WebComponent/icons/SendMessageIcon.ts +0 -17
  152. package/src/WebComponent/icons/TourSelfGuidedIcon.ts +0 -17
  153. package/src/WebComponent/icons/TourVirtuallyIcon.ts +0 -17
  154. package/src/WebComponent/icons/TourWithAgentIcon.ts +0 -17
  155. package/src/WebComponent/icons/XOutlineIcon.ts +0 -8
  156. package/src/WebComponent/index.ts +0 -2
  157. package/src/WebComponent/launcher/Launcher.ts +0 -1193
  158. package/src/WebComponent/launcher/launcherStyles.ts +0 -500
  159. package/src/WebComponent/launcher/mobile-launcher.ts +0 -159
  160. package/src/WebComponent/launcher/typeEmojiStyles.ts +0 -161
  161. package/src/WebComponent/launcher/typeMiniStyles.ts +0 -60
  162. package/src/WebComponent/launcher/typeMobileStyles.ts +0 -50
  163. package/src/WebComponent/leasing-chat-styles.ts +0 -114
  164. package/src/WebComponent/me-chat.ts +0 -1257
  165. package/src/WebComponent/me-select.ts +0 -322
  166. package/src/WebComponent/mini-loader.ts +0 -28
  167. package/src/WebComponent/pubnub-chat-styles.ts +0 -204
  168. package/src/WebComponent/pubnub-chat.ts +0 -928
  169. package/src/WebComponent/pubnub-media.ts +0 -208
  170. package/src/WebComponent/pubnub-message-styles.ts +0 -54
  171. package/src/WebComponent/pubnub-message.ts +0 -431
  172. package/src/WebComponent/simple-launcher/simple-launcher-styles.ts +0 -34
  173. package/src/WebComponent/simple-launcher/simple-launcher.ts +0 -100
  174. package/src/WebComponent/utilities-chat.ts +0 -270
  175. package/src/WebComponent/utilities-styles.ts +0 -110
  176. package/src/WebComponent/utils.ts +0 -82
  177. package/src/analytics.ts +0 -217
  178. package/src/assetUrls.ts +0 -6
  179. package/src/disclaimers.ts +0 -58
  180. package/src/fetchBuildingABTestType.ts +0 -21
  181. package/src/fetchBuildingInfo.ts +0 -87
  182. package/src/fetchBuildingWebchatView.ts +0 -154
  183. package/src/fetchFeatureFlag.ts +0 -250
  184. package/src/fetchLeadSources.ts +0 -98
  185. package/src/fetchPhoneNumberFromSource.ts +0 -31
  186. package/src/fetchWebchatPreferences.ts +0 -54
  187. package/src/getAvailabilities.ts +0 -174
  188. package/src/getBuildingPhoneNumber.ts +0 -26
  189. package/src/getShouldAllowScheduling.ts +0 -16
  190. package/src/getShouldShowWebchat.ts +0 -114
  191. package/src/getTimezoneString.ts +0 -39
  192. package/src/globals.ts +0 -1
  193. package/src/gtm.ts +0 -17
  194. package/src/handleChatId.ts +0 -101
  195. package/src/insertDNIIntoWebsite.ts +0 -146
  196. package/src/insertLeadSourceIntoSchedulerLinks.ts +0 -71
  197. package/src/main/MEChat.test.ts +0 -110
  198. package/src/main/MEChat.ts +0 -404
  199. package/src/main/utils.ts +0 -70
  200. package/src/postLeadSources.ts +0 -44
  201. package/src/rentgrata.ts +0 -74
  202. package/src/replaceSelectButtonsWithNewLink.ts +0 -68
  203. package/src/services/fees/fetchBuildingFees.ts +0 -28
  204. package/src/svgIcons.ts +0 -14
  205. package/src/themes.ts +0 -65
  206. package/src/types/rest-sdk.types.ts +0 -13
  207. package/src/types/webchat-no-show-reason.ts +0 -6
  208. package/src/utils.ts +0 -121
  209. package/tsconfig.json +0 -84
@@ -1,208 +0,0 @@
1
- import { css, html, LitElement, PropertyValues, TemplateResult } from "lit";
2
- import { customElement, property, state } from "lit/decorators.js";
3
- import MyPubnub, { SimpleMediaChatMessage } from "../MyPubnub";
4
- import { classMap } from "lit/directives/class-map.js";
5
- import { InputStyles } from "./actions/InputStyles";
6
- import { pubnubChatStyles } from "./pubnub-chat-styles";
7
-
8
- @customElement("pubnub-media")
9
- export class PubnubMedia extends LitElement {
10
- static styles = [
11
- InputStyles,
12
- pubnubChatStyles,
13
- css`
14
- .carousel {
15
- position: relative;
16
- max-width: 400px;
17
- height: max-content;
18
- min-height: 140px;
19
- margin: auto;
20
- overflow: hidden;
21
- display: flex;
22
- align-items: center;
23
- justify-content: flex-start;
24
- scroll-snap-type: x mandatory;
25
- }
26
- .carousel .image-container {
27
- display: flex;
28
- will-change: transform;
29
- transition: transform 0.5s ease-in-out;
30
- align-items: flex-start;
31
- width: 100%;
32
- }
33
- .carousel img {
34
- width: 100%;
35
- max-width: none;
36
- flex-shrink: 0;
37
- opacity: 0.5;
38
- transition: opacity 0.5s ease;
39
- height: 100%;
40
- object-fit: contain;
41
- display: block;
42
- }
43
- .image-item {
44
- width: 100%;
45
- max-width: none;
46
- flex-shrink: 0;
47
- display: flex;
48
- flex-direction: column;
49
- gap: 10px;
50
- }
51
- .image-link {
52
- width: 100%;
53
- max-width: none;
54
- flex-shrink: 0;
55
- }
56
- .carousel img.active {
57
- opacity: 1;
58
- }
59
- .button {
60
- position: absolute;
61
- top: 50%;
62
- transform: translateY(-50%);
63
- background-color: rgba(0, 0, 0, 0.1);
64
- color: white;
65
- border: none;
66
- border-radius: 2px;
67
- cursor: pointer;
68
- padding: 10px;
69
- z-index: 100;
70
- height: 64px;
71
- width: 32px;
72
- transition: background-color 0.3s ease;
73
- }
74
- .button:hover {
75
- background-color: rgba(0, 0, 0, 0.5);
76
- }
77
- .prev {
78
- left: 2px;
79
- }
80
- .next {
81
- right: 2px;
82
- }
83
- .image-info {
84
- display: flex;
85
- flex-direction: column;
86
- gap: 5px;
87
- }
88
- .image-info p {
89
- margin: 0;
90
- padding: 0;
91
- white-space: wrap;
92
- overflow: hidden;
93
- word-wrap: break-word;
94
- }
95
- .image-info .img-header {
96
- color: #333;
97
- font-size: 14px;
98
- }
99
- .image-info .img-desc {
100
- color: #666;
101
- font-size: 12px;
102
- max-height: 200px;
103
- overflow-y: auto;
104
- }
105
- `,
106
- ];
107
-
108
- @property({
109
- attribute: true,
110
- })
111
- message: SimpleMediaChatMessage | undefined;
112
-
113
- @property({ attribute: true })
114
- myPubnub: MyPubnub | undefined;
115
-
116
- @property({ attribute: true })
117
- onMount: () => void = () => ({});
118
-
119
- updated(changedProperties: PropertyValues<this>): void {
120
- this.onMount();
121
- if (!changedProperties.has("message")) return;
122
- }
123
-
124
- @state()
125
- showMediaAsCarousel = true;
126
-
127
- @state()
128
- activeIndex = 0;
129
-
130
- private prevImage(): void {
131
- if (!this.message) return;
132
- if (this.activeIndex === 0) {
133
- this.activeIndex = this.message.media.length - 1;
134
- } else {
135
- this.activeIndex -= 1;
136
- }
137
- }
138
-
139
- private nextImage(): void {
140
- if (!this.message) return;
141
- if (this.activeIndex === this.message.media.length - 1) {
142
- this.activeIndex = 0;
143
- } else {
144
- this.activeIndex += 1;
145
- }
146
- }
147
-
148
- render(): TemplateResult {
149
- if (!this.message) return html``;
150
-
151
- if (this.showMediaAsCarousel) {
152
- return html`<div class="message-inner-body">
153
- <div class="carousel">
154
- <div
155
- class="image-container"
156
- style="transform: translateX(-${this.activeIndex * 100}%);"
157
- >
158
- ${this.message.media.map(
159
- (image, index) => html`
160
- <div class="image-item">
161
- <a
162
- class="image-link"
163
- href="${image.url}"
164
- target="_blank"
165
- rel="noopener noreferrer"
166
- >
167
- <img
168
- class=${classMap({ active: index === this.activeIndex })}
169
- src=${image.url}
170
- alt=""
171
- />
172
- </a>
173
- <div class="image-info">
174
- ${image.title
175
- ? html`<p class="img-header">${image.title}</p>`
176
- : ""}
177
- ${image.description
178
- ? html`<p class="img-desc">${image.description}</p>`
179
- : ""}
180
- </div>
181
- </div>
182
- `
183
- )}
184
- </div>
185
- ${this.message.media.length > 1
186
- ? html` <button class="button prev" @click=${this.prevImage}>
187
- &#10094;
188
- </button>
189
- <button class="button next" @click=${this.nextImage}>
190
- &#10095;
191
- </button>`
192
- : ""}
193
- </div>
194
- </div>`;
195
- } else {
196
- return html`<div class="message-inner-body">
197
- ${this.message.media.map((image) => {
198
- return html`<a
199
- href="${image.url}"
200
- target="_blank"
201
- rel="noopener noreferrer"
202
- ><img class=${"displayed-message-image"} src=${image.url} alt=""
203
- /></a>`;
204
- })}
205
- </div>`;
206
- }
207
- }
208
- }
@@ -1,54 +0,0 @@
1
- import { css } from "lit";
2
-
3
- export const pubnubMessageStyles = css`
4
- .website-preview {
5
- border: 1px solid rgba(0, 0, 0, 0.2);
6
- border-radius: 8px;
7
- overflow: hidden;
8
- display: flex;
9
- align-items: center;
10
- flex-direction: column;
11
- justify-content: center;
12
-
13
- margin: 0px 6px 6px;
14
- }
15
- .website-preview-image {
16
- max-width: 100%;
17
- max-height: 200px;
18
- width: auto;
19
- height: auto;
20
- }
21
- .website-preview-body {
22
- padding: 8px 0px 12px;
23
- }
24
- .website-preview-title {
25
- font-size: 12px;
26
- font-weight: bold;
27
- margin: 0;
28
- display: -webkit-box;
29
- -webkit-box-orient: vertical;
30
- -webkit-line-clamp: 2;
31
- overflow: hidden;
32
- text-overflow: ellipsis;
33
- max-height: 24px;
34
- }
35
- .website-preview-description {
36
- font-size: 10px;
37
- margin: 0;
38
-
39
- display: -webkit-box;
40
- -webkit-box-orient: vertical;
41
- -webkit-line-clamp: 3;
42
- overflow: hidden;
43
- text-overflow: ellipsis;
44
- max-height: 34px;
45
- }
46
- .redirect-link-preview {
47
- color: inherit;
48
- text-decoration: none;
49
- }
50
-
51
- .hidden {
52
- display: none !important;
53
- }
54
- `;
@@ -1,431 +0,0 @@
1
- import DOMPurify from "dompurify";
2
- import { css, html, LitElement, PropertyValues, TemplateResult } from "lit";
3
- import { customElement, property, state } from "lit/decorators.js";
4
- import { unsafeHTML } from "lit/directives/unsafe-html.js";
5
- import MyPubnub, { SimpleTextChatMessage } from "../MyPubnub";
6
- import { v4 as uuid } from "uuid";
7
- import axios from "axios";
8
- import { classMap } from "lit/directives/class-map.js";
9
- import { InputStyles } from "./actions/InputStyles";
10
- import { isMobile } from "../utils";
11
- import { LogType, sendLoggingEvent } from "../analytics";
12
- import { pubnubChatStyles } from "./pubnub-chat-styles";
13
- import "./mini-loader";
14
- import { WidgetType } from "../main/MEChat";
15
-
16
- interface WebsitePreview {
17
- title: string | null;
18
- description: string | null;
19
- image: string | null;
20
- favicon: string | null;
21
- link: string;
22
- }
23
-
24
- interface ImageToDisplay {
25
- redirectTo: string;
26
- source: string;
27
- }
28
- @customElement("pubnub-message")
29
- export class PubnubMessage extends LitElement {
30
- static styles = [
31
- InputStyles,
32
- pubnubChatStyles,
33
- css`
34
- .message-inner-body {
35
- position: relative;
36
- }
37
- .message-loader {
38
- position: absolute;
39
- bottom: -2px;
40
- right: -2px;
41
- }
42
- `,
43
- ];
44
-
45
- @property({ attribute: true })
46
- buildingSlug: string | undefined;
47
-
48
- @property({
49
- attribute: true,
50
- })
51
- message: SimpleTextChatMessage | undefined;
52
-
53
- @property({ attribute: true })
54
- myPubnub: MyPubnub | undefined;
55
-
56
- @property({ attribute: true })
57
- onMount: () => void = () => ({});
58
-
59
- @state()
60
- loadingPreviews = true;
61
-
62
- @state()
63
- parsedMessage: TemplateResult | undefined;
64
-
65
- @state()
66
- websitePreviewInfo: WebsitePreview[] = [];
67
-
68
- @state()
69
- imagesToDisplay: ImageToDisplay[] = [];
70
-
71
- @state()
72
- imageUrlError: string[] = [];
73
-
74
- @property({ type: Boolean })
75
- isLeadMessage = false;
76
-
77
- @property({ attribute: true })
78
- widgetType: WidgetType = WidgetType.Default;
79
-
80
- isMessageStillStreamingChunks(): boolean {
81
- if (!this.message) return false;
82
- const messageChunkMarkedAsDone = this.message.chunks.find(
83
- (chunk) => chunk.isDone
84
- );
85
- if (!messageChunkMarkedAsDone) return true;
86
-
87
- // We check to see if ALL the chunks have been received
88
- return this.message.chunks.length === messageChunkMarkedAsDone.order;
89
- }
90
-
91
- updated(changedProperties: PropertyValues<this>): void {
92
- this.onMount();
93
- if (!changedProperties.has("message")) return;
94
- if (!this.message) return;
95
-
96
- try {
97
- if (
98
- !this.isMessageStillStreamingChunks() &&
99
- !this.isLeadMessage &&
100
- this.invalidMarkdownText(this.message.message)
101
- ) {
102
- sendLoggingEvent({
103
- logType: LogType.error,
104
- logTitle: "INVALID_MARKDOWN",
105
- logData: {
106
- message: this.message.message,
107
- chatId: this.myPubnub?.channel,
108
- },
109
- buildingSlug: this.buildingSlug,
110
- });
111
- }
112
- } catch (error) {
113
- // eslint-disable-next-line no-console
114
- console.error("Error parsing markdown:", error);
115
- }
116
-
117
- const { hyperlinks, markedText } = this.mapAndMarkHyperLinks(
118
- this.message.message
119
- );
120
- const urlRegex = /(https?:\/\/[^\s]+)/g; // Regular expression to match URLs
121
- const loadingWebsitePreviews: Promise<WebsitePreview>[] = [];
122
- const imagesToDisplay: ImageToDisplay[] = [];
123
- this.parsedMessage = html`${markedText
124
- .trim()
125
- .split("\n")
126
- .map((line) => {
127
- const sanitizedLine = this.sanitizeMarkdownText(line);
128
- const allWords = this.preserveHTMLTags(sanitizedLine);
129
- if (!allWords) return html``;
130
- return html`${allWords.map((word) => {
131
- if (hyperlinks.find((obj) => obj.id === word)) {
132
- // EliseAI made hyperlink
133
- const link = hyperlinks.find((obj) => obj.id === word);
134
- if (!link) return;
135
- imagesToDisplay.push({
136
- redirectTo: link?.link,
137
- source: link?.link,
138
- });
139
- return html`<a
140
- class="redirect-link"
141
- href="${link?.link}"
142
- target="_blank"
143
- rel="noopener noreferrer"
144
- >${link?.hyperlink}
145
- </a>`;
146
- }
147
- if (urlRegex.test(word)) {
148
- // general url
149
- const link = this.removeTrailingPunctuation(word);
150
- loadingWebsitePreviews.push(this.getLinkData(link));
151
- return html`<a
152
- class="redirect-link"
153
- href="${link}"
154
- target="_blank"
155
- rel="noopener noreferrer"
156
- >${link}
157
- </a>`;
158
- } else {
159
- return html`${unsafeHTML(DOMPurify.sanitize(word))} `;
160
- }
161
- })}<br />`;
162
- })}`;
163
- this.imagesToDisplay = imagesToDisplay;
164
- Promise.all(loadingWebsitePreviews).then((results) => {
165
- this.websitePreviewInfo = results;
166
- });
167
- }
168
-
169
- private invalidMarkdownText(text: string): boolean {
170
- try {
171
- const markdownErrors = [
172
- /\*\*[^*\n]*\*$/, // Unclosed bold (excluding newline)
173
- /__[^_\n]*_$/, // Unclosed italic (excluding newline)
174
- /`[^`\n]*`$/, // Unclosed code (excluding newline)
175
- /\[[^\]\n]*\]$/, // Unclosed link text (excluding newline)
176
- /\[[^\]]*\]\([^)\n]*\)$/, // Unclosed link URL (excluding newline)
177
- /^(#+)\s*$/, // Header without text
178
- /(^|[^!])\[[^\]]*\]\(([^)]+)\s*\)$/, // Improperly formatted link
179
- /(?:^|\s)[*_]{1,2}(?:\s|$)/, // Improper use of bold or italic
180
- ];
181
-
182
- return markdownErrors.some((regex) => regex.test(text));
183
- } catch (error) {
184
- return false;
185
- }
186
- }
187
- private preserveHTMLTags(text: string): string[] {
188
- const tagRegex = /(<\/?[a-z][^>]*>[^<]*<\/?[a-z]*>|[^\s]+[.,?!]?|\S)/gi;
189
- const splitTags = text.match(tagRegex);
190
-
191
- return splitTags?.filter((str) => str.trim() !== "") ?? [];
192
- }
193
-
194
- private sanitizeMarkdownText(text: string): string {
195
- const toHTML = text
196
- .replace(/^### (.*$)/gim, "<h3>$1</h3>")
197
- .replace(/^## (.*$)/gim, "<h2>$1</h2>")
198
- .replace(/^# (.*$)/gim, "<h1>$1</h1>")
199
- .replace(/\*\*(.*?)\*\*/gim, "<b>$1</b>")
200
- .replace(/\*(.*?)\*/gim, "<i>$1</i>");
201
-
202
- return toHTML.trim();
203
- }
204
-
205
- private removeTrailingPunctuation(text: string): string {
206
- const punctuation = [".", ",", "!", "?", ":", ";"];
207
- if (punctuation.includes(text[text.length - 1])) {
208
- return this.removeTrailingPunctuation(text.slice(0, -1));
209
- }
210
- return text;
211
- }
212
- private mapAndMarkHyperLinks(text: string): {
213
- hyperlinks: {
214
- link: string;
215
- hyperlink: string;
216
- mark: string;
217
- id: string;
218
- }[];
219
- markedText: string;
220
- } {
221
- // Updated regex to match all formats (EliseAI, embedded links, and markdown)
222
- const regex =
223
- /<https?:\/\/[^|]+\|[^>]+>|<a href="[^"]+"(?: target="[^"]*")?>[^<]+<\/a>|\[.*?\]\([^)]*\.[^)]*\)/g;
224
-
225
- const matches = Array.from(text.matchAll(regex));
226
- const listHyperlinks: {
227
- link: string;
228
- hyperlink: string;
229
- mark: string;
230
- id: string;
231
- }[] = [];
232
-
233
- const matchesParsed = matches.map((match) => {
234
- const matchedLink = match[0];
235
- if (match.index === undefined) return;
236
- const charBefore = text[match.index - 1];
237
- const charAfter = text[match.index + matchedLink.length];
238
-
239
- // Handle for Elise Format
240
- if (matchedLink.startsWith("<https") || matchedLink.startsWith("<http")) {
241
- return {
242
- matchedLink,
243
- link: matchedLink.split("|")[0].replace("<", ""),
244
- hyperlink: matchedLink.split("|")[1].replace(">", ""),
245
- addSpaceBefore: !!(charBefore && charBefore !== " "),
246
- addSpaceAfter: !!(charAfter && charAfter !== " "),
247
- };
248
- } else if (matchedLink.startsWith("<a href=")) {
249
- // Handle for embedded links (<a>...</a>)
250
- const linkMatch = matchedLink.match(/href="([^"]+)"/);
251
- const hyperlinkMatch = matchedLink.match(/>[^<]+</);
252
- return {
253
- matchedLink,
254
- link: linkMatch ? linkMatch[1] : "",
255
- hyperlink: hyperlinkMatch ? hyperlinkMatch[0].slice(1, -1) : "",
256
- addSpaceBefore: !!(charBefore && charBefore !== " "),
257
- addSpaceAfter: !!(charAfter && charAfter !== " "),
258
- };
259
- } else {
260
- // Handle for markdown links
261
- const [hyperlinkMatch, linkMatch] = matchedLink.split("](");
262
- return {
263
- matchedLink,
264
- link: linkMatch ? linkMatch.slice(0, -1) : "",
265
- hyperlink: hyperlinkMatch ? hyperlinkMatch.slice(1) : "",
266
- addSpaceBefore: !!(charBefore && charBefore !== " "),
267
- addSpaceAfter: !!(charAfter && charAfter !== " "),
268
- };
269
- }
270
- });
271
-
272
- matchesParsed.forEach((match) => {
273
- if (!match) return;
274
-
275
- if (match.link && match.hyperlink) {
276
- const uniqueKeyMark = uuid().replace(/-/g, "");
277
- listHyperlinks.push({
278
- link: this.removeTrailingPunctuation(match.link),
279
- hyperlink: this.removeTrailingPunctuation(match.hyperlink),
280
- mark: match.matchedLink,
281
- id: uniqueKeyMark,
282
- });
283
-
284
- text = text.replace(
285
- match.matchedLink,
286
- `${match.addSpaceBefore ? " " : ""}${uniqueKeyMark}${
287
- match.addSpaceAfter ? " " : ""
288
- }`
289
- );
290
- }
291
- });
292
-
293
- return { hyperlinks: listHyperlinks, markedText: text };
294
- }
295
-
296
- private async getLinkData(url: string): Promise<WebsitePreview> {
297
- try {
298
- // Getting link data is unlikely to work unless the site has CORS enabled and/or url is on the same domain
299
- // For dev testing, can visit https://cors-anywhere.herokuapp.com/ and prefix url with it to bypass CORS
300
- const response = await axios.get(url);
301
- const html = response.data;
302
- const parser = new DOMParser(); // creates a temp dom to parse HTML
303
- const doc = parser.parseFromString(html, "text/html");
304
- if (!doc)
305
- return {
306
- title: null,
307
- description: null,
308
- image: null,
309
- favicon: null,
310
- link: url,
311
- };
312
-
313
- return {
314
- title: doc.querySelector("title")?.textContent ?? null,
315
- description:
316
- doc
317
- .querySelector('meta[name="description"]')
318
- ?.getAttribute("content") || null,
319
- image:
320
- doc
321
- .querySelector('meta[property="og:image"]')
322
- ?.getAttribute("content") || null,
323
- favicon: null, // https://meetelise.slack.com/archives/C03HAFYV2NN/p1707339577924899?thread_ts=1707317394.998999&cid=C03HAFYV2NN
324
- link: url,
325
- };
326
- } catch (error) {
327
- // eslint-disable-next-line no-console
328
- console.error("Error fetching website details:", error);
329
- return {
330
- title: null,
331
- description: null,
332
- image: null,
333
- favicon: null,
334
- link: url,
335
- };
336
- }
337
- }
338
-
339
- render(): TemplateResult {
340
- if (!this.message) return html``;
341
- return html`<div class="message-inner-body">
342
- ${this.isMessageStillStreamingChunks()
343
- ? html`<div class="message-loader"><mini-loader></mini-loader></div>`
344
- : ""}
345
- <p
346
- class=${classMap({
347
- ["message-text"]: this.widgetType !== WidgetType.Utilities,
348
- ["message-text-large"]: this.widgetType === WidgetType.Utilities,
349
- ["webchat-font__desktop"]: !isMobile(),
350
- ["webchat-font__mobile"]: isMobile(),
351
- })}
352
- >
353
- ${this.parsedMessage}
354
- </p>
355
- ${this.websitePreviewInfo.length > 0 &&
356
- this.websitePreviewInfo.some(
357
- (preview) => preview.title && (preview.image || preview.favicon)
358
- )
359
- ? html`<br />`
360
- : ""}
361
- ${this.imagesToDisplay.map((image) => {
362
- return html`<a
363
- href="${image.redirectTo}"
364
- target="_blank"
365
- rel="noopener noreferrer"
366
- ><img
367
- class=${this.imageUrlError.includes(image.source)
368
- ? "displayed-message-image-error"
369
- : "displayed-message-image"}
370
- src=${image.source}
371
- alt="displayed message image"
372
- @error=${() => {
373
- // to trigger rerender
374
- this.imageUrlError = [...this.imageUrlError, image.source];
375
- }}
376
- /></a>`;
377
- })}
378
- ${this.websitePreviewInfo.map((preview) => {
379
- if (!preview.title || !(preview.image || preview.favicon)) return;
380
- return html` <a
381
- class="redirect-link-preview"
382
- href=${preview.link}
383
- target="_blank"
384
- rel="noopener noreferrer"
385
- >
386
- <div class="website-preview">
387
- ${
388
- preview.image || preview.favicon
389
- ? html` <img
390
- src=${preview.image ?? preview.favicon}
391
- class="website-preview-image"
392
- alt="website preview image"
393
- width="100%"
394
- height="100%"
395
- />`
396
- : ""
397
- }
398
-
399
- <div class="website-preview-body">
400
- <p class=${classMap({
401
- ["message-text"]: this.widgetType !== WidgetType.Utilities,
402
- ["message-text-large"]:
403
- this.widgetType === WidgetType.Utilities,
404
- ["website-preview-title"]: true,
405
- ["webchat-font__desktop"]: !isMobile(),
406
- ["webchat-font__mobile"]: isMobile(),
407
- })}>${preview.title}</p>
408
- ${
409
- preview.description
410
- ? html`<p
411
- class=${classMap({
412
- ["message-text"]:
413
- this.widgetType !== WidgetType.Utilities,
414
- ["message-text-large"]:
415
- this.widgetType === WidgetType.Utilities,
416
- ["website-preview-description"]: true,
417
- ["webchat-font__desktop"]: !isMobile(),
418
- ["webchat-font__mobile"]: isMobile(),
419
- })}
420
- >
421
- ${preview.description}
422
- </p>`
423
- : ""
424
- }
425
- </div>
426
- </div>
427
- </a></div> `;
428
- })}
429
- </div>`;
430
- }
431
- }