@meetelise/chat 1.34.7 → 1.35.1

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 (282) hide show
  1. package/dist/src/MyPubnub.d.ts +116 -0
  2. package/dist/src/WebComponent/FeeCalculator/components/addons/addon-item-matrix-qty-selector/addon-item-matrix-qty-selector-styles.d.ts +2 -0
  3. package/dist/src/WebComponent/FeeCalculator/components/addons/addon-item-matrix-qty-selector/addon-item-matrix-qty-selector.d.ts +28 -0
  4. package/dist/src/WebComponent/FeeCalculator/components/addons/addon-item-qty-selector/addon-item-qty-selector-styles.d.ts +2 -0
  5. package/dist/src/WebComponent/FeeCalculator/components/addons/addon-item-qty-selector/addon-item-qty-selector.d.ts +18 -0
  6. package/dist/src/WebComponent/FeeCalculator/components/addons/common-addon-styles.d.ts +2 -0
  7. package/dist/src/WebComponent/FeeCalculator/components/addons/rentable-item-qty-selector/rentable-item-qty-selector-styles.d.ts +2 -0
  8. package/dist/src/WebComponent/FeeCalculator/components/addons/rentable-item-qty-selector/rentable-item-qty-selector.d.ts +22 -0
  9. package/dist/src/WebComponent/FeeCalculator/components/fee-calculator-layout/fee-calculator-layout-styles.d.ts +2 -0
  10. package/dist/src/WebComponent/FeeCalculator/components/fee-calculator-layout/fee-calculator-layout.d.ts +46 -0
  11. package/dist/src/WebComponent/FeeCalculator/components/fee-card/fee-card-styles.d.ts +2 -0
  12. package/dist/src/WebComponent/FeeCalculator/components/fee-card/fee-card.d.ts +21 -0
  13. package/dist/src/WebComponent/FeeCalculator/components/fee-item/fee-item-styles.d.ts +2 -0
  14. package/dist/src/WebComponent/FeeCalculator/components/fee-item/fee-item.d.ts +13 -0
  15. package/dist/src/WebComponent/FeeCalculator/components/floor-plan-selector/floor-plan-selector-styles.d.ts +2 -0
  16. package/dist/src/WebComponent/FeeCalculator/components/floor-plan-selector/floor-plan-selector.d.ts +34 -0
  17. package/dist/src/WebComponent/FeeCalculator/components/floorplan-image-card/floorplan-image-card-styles.d.ts +2 -0
  18. package/dist/src/WebComponent/FeeCalculator/components/floorplan-image-card/floorplan-image-card.d.ts +18 -0
  19. package/dist/src/WebComponent/FeeCalculator/components/incentive-banner/incentive-banner-styles.d.ts +1 -0
  20. package/dist/src/WebComponent/FeeCalculator/components/incentive-banner/incentive-banner.d.ts +8 -0
  21. package/dist/src/WebComponent/FeeCalculator/components/incentive-banner/index.d.ts +1 -0
  22. package/dist/src/WebComponent/FeeCalculator/components/index.d.ts +5 -0
  23. package/dist/src/WebComponent/FeeCalculator/components/promo-card/promo-card-styles.d.ts +2 -0
  24. package/dist/src/WebComponent/FeeCalculator/components/promo-card/promo-card.d.ts +13 -0
  25. package/dist/src/WebComponent/FeeCalculator/constants.d.ts +3 -0
  26. package/dist/src/WebComponent/FeeCalculator/fee-calculator-styles.d.ts +1 -0
  27. package/dist/src/WebComponent/FeeCalculator/fee-calculator.d.ts +55 -0
  28. package/dist/src/WebComponent/FeeCalculator/index.d.ts +2 -0
  29. package/dist/src/WebComponent/FeeCalculator/model/building-fee-view.d.ts +41 -0
  30. package/dist/src/WebComponent/FeeCalculator/model/building-fee.d.ts +82 -0
  31. package/dist/src/WebComponent/FeeCalculator/model/desired-addon.d.ts +5 -0
  32. package/dist/src/WebComponent/FeeCalculator/model/desired-rentable-item.d.ts +4 -0
  33. package/dist/src/WebComponent/FeeCalculator/model/index.d.ts +13 -0
  34. package/dist/src/WebComponent/FeeCalculator/model/item-combination.d.ts +6 -0
  35. package/dist/src/WebComponent/FeeCalculator/model/item-quantity.d.ts +4 -0
  36. package/dist/src/WebComponent/FeeCalculator/model/pricing-matrix.d.ts +18 -0
  37. package/dist/src/WebComponent/FeeCalculator/model/pricing-rule.d.ts +8 -0
  38. package/dist/src/WebComponent/FeeCalculator/model/rent-frequency.d.ts +1 -0
  39. package/dist/src/WebComponent/FeeCalculator/model/rentable-item-summary.d.ts +9 -0
  40. package/dist/src/WebComponent/FeeCalculator/model/rentable-item.d.ts +9 -0
  41. package/dist/src/WebComponent/FeeCalculator/model/transaction-category.d.ts +23 -0
  42. package/dist/src/WebComponent/FeeCalculator/model/unit-fee-bundle.d.ts +31 -0
  43. package/dist/src/WebComponent/LeadSourceClient.d.ts +46 -0
  44. package/dist/src/WebComponent/OfficeHours.d.ts +21 -0
  45. package/dist/src/WebComponent/Scheduler/date-picker.d.ts +28 -0
  46. package/dist/src/WebComponent/Scheduler/time-picker.d.ts +16 -0
  47. package/dist/src/WebComponent/Scheduler/tour-scheduler.d.ts +102 -0
  48. package/dist/src/WebComponent/Scheduler/tour-type-option.d.ts +13 -0
  49. package/dist/src/WebComponent/Scheduler/tourSchedulerStyles.d.ts +1 -0
  50. package/dist/src/WebComponent/actions/InputStyles.d.ts +1 -0
  51. package/dist/src/WebComponent/actions/action-confirm-button.d.ts +13 -0
  52. package/dist/src/WebComponent/actions/call-us-window.d.ts +37 -0
  53. package/dist/src/WebComponent/actions/collapse-expand-button.d.ts +8 -0
  54. package/dist/src/WebComponent/actions/details-window.d.ts +14 -0
  55. package/dist/src/WebComponent/actions/email-us-window.d.ts +46 -0
  56. package/dist/src/WebComponent/actions/formatPhoneNumber.d.ts +17 -0
  57. package/dist/src/WebComponent/actions/minimize-expand-button.d.ts +8 -0
  58. package/dist/src/WebComponent/chat-additional-actions.d.ts +28 -0
  59. package/dist/src/WebComponent/health-chat.d.ts +47 -0
  60. package/dist/src/WebComponent/healthchat-styles.d.ts +1 -0
  61. package/dist/src/WebComponent/icons/ApplyOutlineIcon.d.ts +2 -0
  62. package/dist/src/WebComponent/icons/BookTourOutlineIcon.d.ts +2 -0
  63. package/dist/src/WebComponent/icons/CalculatorOutlineIcon.d.ts +2 -0
  64. package/dist/src/WebComponent/icons/ChatOutlineIcon.d.ts +2 -0
  65. package/dist/src/WebComponent/icons/ChevronLeftIcon.d.ts +2 -0
  66. package/dist/src/WebComponent/icons/ChevronRightIcon.d.ts +2 -0
  67. package/dist/src/WebComponent/icons/ContactResidentIcon.d.ts +2 -0
  68. package/dist/src/WebComponent/icons/DollarOutlineIcon.d.ts +7 -0
  69. package/dist/src/WebComponent/icons/EmailOutlineIcon.d.ts +2 -0
  70. package/dist/src/WebComponent/icons/HeyThereEmojiIcon.d.ts +2 -0
  71. package/dist/src/WebComponent/icons/PhoneOutlineIcon.d.ts +2 -0
  72. package/dist/src/WebComponent/icons/SendMessageIcon.d.ts +3 -0
  73. package/dist/src/WebComponent/icons/TourSelfGuidedIcon.d.ts +2 -0
  74. package/dist/src/WebComponent/icons/TourVirtuallyIcon.d.ts +2 -0
  75. package/dist/src/WebComponent/icons/TourWithAgentIcon.d.ts +2 -0
  76. package/dist/src/WebComponent/icons/XOutlineIcon.d.ts +2 -0
  77. package/dist/src/WebComponent/index.d.ts +2 -0
  78. package/dist/src/WebComponent/launcher/Launcher.d.ts +99 -0
  79. package/dist/src/WebComponent/launcher/launcherStyles.d.ts +1 -0
  80. package/dist/src/WebComponent/launcher/mobile-launcher.d.ts +27 -0
  81. package/dist/src/WebComponent/launcher/typeEmojiStyles.d.ts +1 -0
  82. package/dist/src/WebComponent/launcher/typeMiniStyles.d.ts +1 -0
  83. package/dist/src/WebComponent/launcher/typeMobileStyles.d.ts +1 -0
  84. package/dist/src/WebComponent/leasing-chat-styles.d.ts +1 -0
  85. package/dist/src/WebComponent/loaders/index.d.ts +4 -0
  86. package/dist/src/WebComponent/loaders/mega-loader.d.ts +7 -0
  87. package/dist/src/WebComponent/loaders/skeleton-card.d.ts +12 -0
  88. package/dist/src/WebComponent/loaders/skeleton-loader-styles.d.ts +3 -0
  89. package/dist/src/WebComponent/loaders/skeleton-loader.d.ts +13 -0
  90. package/dist/src/WebComponent/me-chat.d.ts +91 -0
  91. package/dist/src/WebComponent/me-select.d.ts +24 -0
  92. package/dist/src/WebComponent/mini-loader.d.ts +5 -0
  93. package/dist/src/WebComponent/pubnub-chat-styles.d.ts +1 -0
  94. package/dist/src/WebComponent/pubnub-chat.d.ts +48 -0
  95. package/dist/src/WebComponent/pubnub-media.d.ts +14 -0
  96. package/dist/src/WebComponent/pubnub-message-styles.d.ts +1 -0
  97. package/dist/src/WebComponent/pubnub-message.d.ts +39 -0
  98. package/dist/src/WebComponent/simple-launcher/simple-launcher-styles.d.ts +1 -0
  99. package/dist/src/WebComponent/simple-launcher/simple-launcher.d.ts +12 -0
  100. package/dist/src/WebComponent/utilities-chat.d.ts +47 -0
  101. package/dist/src/WebComponent/utilities-styles.d.ts +1 -0
  102. package/dist/src/WebComponent/utils.d.ts +31 -0
  103. package/dist/src/analytics.d.ts +64 -0
  104. package/dist/src/disclaimers.d.ts +16 -0
  105. package/dist/src/fetchBuildingABTestType.d.ts +8 -0
  106. package/dist/src/fetchBuildingInfo.d.ts +58 -0
  107. package/dist/src/fetchBuildingWebchatView.d.ts +124 -0
  108. package/dist/src/fetchFeatureFlag.d.ts +14 -0
  109. package/dist/src/fetchLeadSources.d.ts +4 -0
  110. package/dist/src/fetchPhoneNumberFromSource.d.ts +6 -0
  111. package/dist/src/getAvailabilities.d.ts +46 -0
  112. package/dist/src/getBuildingPhoneNumber.d.ts +1 -0
  113. package/dist/src/getShouldAllowScheduling.d.ts +1 -0
  114. package/dist/src/getShouldShowWebchat.d.ts +3 -0
  115. package/dist/src/getTimezoneString.d.ts +1 -0
  116. package/dist/src/globals.d.ts +2 -0
  117. package/dist/src/gtm.d.ts +6 -0
  118. package/dist/src/handleChatId.d.ts +11 -0
  119. package/dist/src/insertDNIIntoWebsite.d.ts +5 -0
  120. package/dist/src/insertLeadSourceIntoSchedulerLinks.d.ts +4 -0
  121. package/dist/src/main/MEChat.d.ts +74 -0
  122. package/dist/src/main/utils.d.ts +2 -0
  123. package/dist/src/postLeadSources.d.ts +3 -0
  124. package/dist/src/rentgrata.d.ts +4 -0
  125. package/dist/src/replaceSelectButtonsWithNewLink.d.ts +5 -0
  126. package/dist/src/services/fees/calculateQuote.d.ts +14 -0
  127. package/dist/src/services/fees/fetchBuildingFeesV2.d.ts +10 -0
  128. package/dist/src/services/fees/fetchBuildingUnits.d.ts +29 -0
  129. package/dist/src/services/fees/utils.d.ts +1 -0
  130. package/dist/src/svgIcons.d.ts +5 -0
  131. package/dist/src/themes.d.ts +5 -0
  132. package/dist/src/types/incentive-v2.d.ts +23 -0
  133. package/dist/src/types/rest-sdk.types.d.ts +11 -0
  134. package/dist/src/types/webchat-no-show-reason.d.ts +1 -0
  135. package/dist/src/utils/getWidgetOverrides.d.ts +39 -0
  136. package/dist/src/utils/queryParamBuilder.d.ts +8 -0
  137. package/dist/src/utils.d.ts +13 -0
  138. package/package.json +1 -1
  139. package/public/dist/index.js +41 -41
  140. package/src/MyPubnub.ts +792 -0
  141. package/src/WebComponent/FeeCalculator/components/addons/addon-item-matrix-qty-selector/addon-item-matrix-qty-selector-styles.ts +35 -0
  142. package/src/WebComponent/FeeCalculator/components/addons/addon-item-matrix-qty-selector/addon-item-matrix-qty-selector.ts +206 -0
  143. package/src/WebComponent/FeeCalculator/components/addons/addon-item-qty-selector/addon-item-qty-selector-styles.ts +6 -0
  144. package/src/WebComponent/FeeCalculator/components/addons/addon-item-qty-selector/addon-item-qty-selector.ts +101 -0
  145. package/src/WebComponent/FeeCalculator/components/addons/common-addon-styles.ts +82 -0
  146. package/src/WebComponent/FeeCalculator/components/addons/rentable-item-qty-selector/rentable-item-qty-selector-styles.ts +9 -0
  147. package/src/WebComponent/FeeCalculator/components/addons/rentable-item-qty-selector/rentable-item-qty-selector.ts +124 -0
  148. package/src/WebComponent/FeeCalculator/components/fee-calculator-layout/fee-calculator-layout-styles.ts +142 -0
  149. package/src/WebComponent/FeeCalculator/components/fee-calculator-layout/fee-calculator-layout.ts +243 -0
  150. package/src/WebComponent/FeeCalculator/components/fee-card/fee-card-styles.ts +65 -0
  151. package/src/WebComponent/FeeCalculator/components/fee-card/fee-card.ts +91 -0
  152. package/src/WebComponent/FeeCalculator/components/fee-item/fee-item-styles.ts +44 -0
  153. package/src/WebComponent/FeeCalculator/components/fee-item/fee-item.ts +38 -0
  154. package/src/WebComponent/FeeCalculator/components/floor-plan-selector/floor-plan-selector-styles.ts +151 -0
  155. package/src/WebComponent/FeeCalculator/components/floor-plan-selector/floor-plan-selector.ts +248 -0
  156. package/src/WebComponent/FeeCalculator/components/floorplan-image-card/floorplan-image-card-styles.ts +82 -0
  157. package/src/WebComponent/FeeCalculator/components/floorplan-image-card/floorplan-image-card.ts +76 -0
  158. package/src/WebComponent/FeeCalculator/components/incentive-banner/incentive-banner-styles.ts +40 -0
  159. package/src/WebComponent/FeeCalculator/components/incentive-banner/incentive-banner.ts +43 -0
  160. package/src/WebComponent/FeeCalculator/components/incentive-banner/index.ts +1 -0
  161. package/src/WebComponent/FeeCalculator/components/index.ts +5 -0
  162. package/src/WebComponent/FeeCalculator/components/promo-card/promo-card-styles.ts +39 -0
  163. package/src/WebComponent/FeeCalculator/components/promo-card/promo-card.ts +39 -0
  164. package/src/WebComponent/FeeCalculator/constants.ts +5 -0
  165. package/src/WebComponent/FeeCalculator/fee-calculator-styles.ts +310 -0
  166. package/src/WebComponent/FeeCalculator/fee-calculator.ts +341 -0
  167. package/src/WebComponent/FeeCalculator/index.ts +4 -0
  168. package/src/WebComponent/FeeCalculator/model/building-fee-view.ts +84 -0
  169. package/src/WebComponent/FeeCalculator/model/building-fee.ts +126 -0
  170. package/src/WebComponent/FeeCalculator/model/desired-addon.ts +6 -0
  171. package/src/WebComponent/FeeCalculator/model/desired-rentable-item.ts +4 -0
  172. package/src/WebComponent/FeeCalculator/model/index.ts +13 -0
  173. package/src/WebComponent/FeeCalculator/model/item-combination.ts +16 -0
  174. package/src/WebComponent/FeeCalculator/model/item-quantity.ts +4 -0
  175. package/src/WebComponent/FeeCalculator/model/pricing-matrix.ts +45 -0
  176. package/src/WebComponent/FeeCalculator/model/pricing-rule.ts +9 -0
  177. package/src/WebComponent/FeeCalculator/model/rent-frequency.ts +1 -0
  178. package/src/WebComponent/FeeCalculator/model/rentable-item-summary.ts +10 -0
  179. package/src/WebComponent/FeeCalculator/model/rentable-item.ts +10 -0
  180. package/src/WebComponent/FeeCalculator/model/transaction-category.ts +23 -0
  181. package/src/WebComponent/FeeCalculator/model/unit-fee-bundle.ts +54 -0
  182. package/src/WebComponent/LeadSourceClient.ts +332 -0
  183. package/src/WebComponent/MEChat.css +5 -0
  184. package/src/WebComponent/OfficeHours.ts +73 -0
  185. package/src/WebComponent/Scheduler/date-picker.ts +405 -0
  186. package/src/WebComponent/Scheduler/time-picker.ts +195 -0
  187. package/src/WebComponent/Scheduler/tour-scheduler.ts +1430 -0
  188. package/src/WebComponent/Scheduler/tour-type-option.ts +112 -0
  189. package/src/WebComponent/Scheduler/tourSchedulerStyles.ts +418 -0
  190. package/src/WebComponent/actions/InputStyles.ts +57 -0
  191. package/src/WebComponent/actions/action-confirm-button.ts +125 -0
  192. package/src/WebComponent/actions/call-us-window.ts +467 -0
  193. package/src/WebComponent/actions/collapse-expand-button.ts +65 -0
  194. package/src/WebComponent/actions/details-window.ts +150 -0
  195. package/src/WebComponent/actions/email-us-window.ts +556 -0
  196. package/src/WebComponent/actions/formatPhoneNumber.ts +72 -0
  197. package/src/WebComponent/actions/minimize-expand-button.ts +93 -0
  198. package/src/WebComponent/chat-additional-actions.ts +135 -0
  199. package/src/WebComponent/health-chat.ts +270 -0
  200. package/src/WebComponent/healthchat-styles.ts +119 -0
  201. package/src/WebComponent/icons/ApplyOutlineIcon.ts +22 -0
  202. package/src/WebComponent/icons/BookTourOutlineIcon.ts +13 -0
  203. package/src/WebComponent/icons/CalculatorOutlineIcon.ts +22 -0
  204. package/src/WebComponent/icons/ChatOutlineIcon.ts +10 -0
  205. package/src/WebComponent/icons/ChevronLeftIcon.ts +7 -0
  206. package/src/WebComponent/icons/ChevronRightIcon.ts +7 -0
  207. package/src/WebComponent/icons/ContactResidentIcon.ts +9 -0
  208. package/src/WebComponent/icons/DollarOutlineIcon.ts +26 -0
  209. package/src/WebComponent/icons/EmailOutlineIcon.ts +7 -0
  210. package/src/WebComponent/icons/HeyThereEmojiIcon.ts +12 -0
  211. package/src/WebComponent/icons/PhoneOutlineIcon.ts +7 -0
  212. package/src/WebComponent/icons/SendMessageIcon.ts +17 -0
  213. package/src/WebComponent/icons/TourSelfGuidedIcon.ts +17 -0
  214. package/src/WebComponent/icons/TourVirtuallyIcon.ts +17 -0
  215. package/src/WebComponent/icons/TourWithAgentIcon.ts +17 -0
  216. package/src/WebComponent/icons/XOutlineIcon.ts +8 -0
  217. package/src/WebComponent/index.ts +2 -0
  218. package/src/WebComponent/launcher/Launcher.ts +1284 -0
  219. package/src/WebComponent/launcher/launcherStyles.ts +500 -0
  220. package/src/WebComponent/launcher/mobile-launcher.ts +162 -0
  221. package/src/WebComponent/launcher/typeEmojiStyles.ts +161 -0
  222. package/src/WebComponent/launcher/typeMiniStyles.ts +60 -0
  223. package/src/WebComponent/launcher/typeMobileStyles.ts +50 -0
  224. package/src/WebComponent/leasing-chat-styles.ts +114 -0
  225. package/src/WebComponent/loaders/index.ts +7 -0
  226. package/src/WebComponent/loaders/mega-loader.ts +36 -0
  227. package/src/WebComponent/loaders/skeleton-card.ts +31 -0
  228. package/src/WebComponent/loaders/skeleton-loader-styles.ts +112 -0
  229. package/src/WebComponent/loaders/skeleton-loader.ts +34 -0
  230. package/src/WebComponent/me-chat.ts +1264 -0
  231. package/src/WebComponent/me-select.ts +322 -0
  232. package/src/WebComponent/mini-loader.ts +28 -0
  233. package/src/WebComponent/pubnub-chat-styles.ts +204 -0
  234. package/src/WebComponent/pubnub-chat.ts +771 -0
  235. package/src/WebComponent/pubnub-media.ts +208 -0
  236. package/src/WebComponent/pubnub-message-styles.ts +54 -0
  237. package/src/WebComponent/pubnub-message.ts +431 -0
  238. package/src/WebComponent/simple-launcher/simple-launcher-styles.ts +34 -0
  239. package/src/WebComponent/simple-launcher/simple-launcher.ts +100 -0
  240. package/src/WebComponent/utilities-chat.ts +270 -0
  241. package/src/WebComponent/utilities-styles.ts +110 -0
  242. package/src/WebComponent/utils.ts +82 -0
  243. package/src/analytics.ts +217 -0
  244. package/src/assetUrls.ts +6 -0
  245. package/src/disclaimers.ts +301 -0
  246. package/src/fetchBuildingABTestType.ts +21 -0
  247. package/src/fetchBuildingInfo.ts +88 -0
  248. package/src/fetchBuildingWebchatView.ts +176 -0
  249. package/src/fetchFeatureFlag.ts +250 -0
  250. package/src/fetchLeadSources.ts +98 -0
  251. package/src/fetchPhoneNumberFromSource.ts +31 -0
  252. package/src/fetchWebchatPreferences.ts +54 -0
  253. package/src/getAvailabilities.ts +189 -0
  254. package/src/getBuildingPhoneNumber.ts +26 -0
  255. package/src/getShouldAllowScheduling.ts +16 -0
  256. package/src/getShouldShowWebchat.ts +114 -0
  257. package/src/getTimezoneString.ts +40 -0
  258. package/src/globals.ts +3 -0
  259. package/src/gtm.ts +17 -0
  260. package/src/handleChatId.ts +101 -0
  261. package/src/insertDNIIntoWebsite.ts +146 -0
  262. package/src/insertLeadSourceIntoSchedulerLinks.ts +71 -0
  263. package/src/main/MEChat.test.ts +110 -0
  264. package/src/main/MEChat.ts +404 -0
  265. package/src/main/utils.ts +70 -0
  266. package/src/postLeadSources.ts +44 -0
  267. package/src/rentgrata.ts +74 -0
  268. package/src/replaceSelectButtonsWithNewLink.ts +91 -0
  269. package/src/services/fees/calculateQuote.ts +74 -0
  270. package/src/services/fees/fetchBuildingFees.ts +50 -0
  271. package/src/services/fees/fetchBuildingFeesV2.ts +56 -0
  272. package/src/services/fees/fetchBuildingFloorplans.ts +74 -0
  273. package/src/services/fees/fetchBuildingUnits.ts +86 -0
  274. package/src/services/fees/utils.ts +4 -0
  275. package/src/svgIcons.ts +14 -0
  276. package/src/themes.ts +65 -0
  277. package/src/types/incentive-v2.ts +24 -0
  278. package/src/types/rest-sdk.types.ts +13 -0
  279. package/src/types/webchat-no-show-reason.ts +6 -0
  280. package/src/utils/getWidgetOverrides.ts +91 -0
  281. package/src/utils/queryParamBuilder.ts +28 -0
  282. package/src/utils.ts +121 -0
@@ -0,0 +1,71 @@
1
+ // DEPRECATED: This function is no longer used. It was used to insert the lead source into the scheduler links.
2
+ // We now prevent the redirect and force tour SST widget to open instead in replaceSSTLinkWithTourWidgetTrigger.ts.
3
+ export const insertLeadSourceIntoSchedulerLinks = (
4
+ leadSource: string
5
+ ): void => {
6
+ const links = document.querySelectorAll("a");
7
+ links.forEach(function (link) {
8
+ const href = link.getAttribute("href");
9
+ if (href && href.startsWith("https://app.meetelise.com/")) {
10
+ const separator = href.includes("?") ? "&" : "?";
11
+ link.setAttribute(
12
+ "href",
13
+ href +
14
+ separator +
15
+ `eliseParsedLeadSource=${encodeURIComponent(leadSource)}`
16
+ );
17
+ }
18
+ });
19
+ };
20
+
21
+ export const replaceSSTLinkWithTourWidgetTrigger = (
22
+ handleTourClicked: (e: MouseEvent) => void
23
+ ): void => {
24
+ const sstRedirectElements = document.querySelectorAll("a");
25
+ sstRedirectElements.forEach(function (element) {
26
+ const href = element.getAttribute("href");
27
+ if (href && href.startsWith("https://app.meetelise.com/")) {
28
+ element.addEventListener("click", (event) => {
29
+ event.preventDefault(); // Prevents the default href redirect
30
+ handleTourClicked(event as MouseEvent);
31
+ });
32
+ }
33
+ });
34
+ };
35
+
36
+ export const replacePageRedirectElementWithTourWidgetTrigger = (
37
+ handleTourClicked: (e: MouseEvent) => void
38
+ ): void => {
39
+ // Gets any elements in format like <a href="/apartments/oh/westerville/schedule-a-tour" class=" ">Schedule a Tour</a>
40
+ const scheduleLinks = document.querySelectorAll('a[href$="schedule-a-tour"]');
41
+ scheduleLinks.forEach((linkElement) => {
42
+ if (!linkElement) {
43
+ return;
44
+ }
45
+ linkElement.addEventListener("click", (event) => {
46
+ event.preventDefault(); // Prevents the default href redirect
47
+ handleTourClicked(event as MouseEvent);
48
+ });
49
+ });
50
+ };
51
+
52
+ export const replaceTourTriggerElementWithTourWidgetTrigger = (
53
+ handleTourClicked: (e: MouseEvent) => void
54
+ ): void => {
55
+ const scheduleLinks = document.querySelectorAll(
56
+ 'a[href^="#leaseleads-tour-open"]'
57
+ );
58
+ scheduleLinks.forEach((linkElement) => {
59
+ if (!linkElement) {
60
+ return;
61
+ }
62
+ const newLink = document.createElement("a");
63
+ newLink.innerHTML = linkElement.innerHTML;
64
+ newLink.style.cursor = "pointer";
65
+ newLink.addEventListener("click", (event) => {
66
+ event.preventDefault();
67
+ handleTourClicked(event as MouseEvent);
68
+ });
69
+ linkElement.parentNode?.replaceChild(newLink, linkElement);
70
+ });
71
+ };
@@ -0,0 +1,110 @@
1
+ import { expect } from "@esm-bundle/chai";
2
+ import { stub, restore } from "sinon/pkg/sinon-esm";
3
+ import MEChat from "../../public/dist/index";
4
+
5
+ const stubResponse = {
6
+ json: stub().resolves({
7
+ id: 42,
8
+ userId: 42.1,
9
+ orgId: 42.2,
10
+ name: "Unit Test Building",
11
+ themeId: null,
12
+ avatarSrc: null,
13
+ avatarType: "",
14
+ userFirstName: "Ella",
15
+ userLastName: "",
16
+ logoSrc:
17
+ "https://eliseusercontent.meetelise.com/building/3660/test-logo.png",
18
+ chatTitle: "Elise",
19
+ chatSubtitle: "Leasing Agent ExtraordinAIre",
20
+ welcomeMessage:
21
+ "Welcome, I'm Elise! If you have any questions about Unit Test Building or would like to schedule a tour, I'm happy to help.",
22
+ systemWelcomeMessage: "I am an AI and may record this conversation!",
23
+ conversationMaintenanceMode: false,
24
+ }),
25
+ };
26
+
27
+ const waitForElementWithSelectorToExist = async (
28
+ selector: string,
29
+ target: Node = document.body
30
+ ): Promise<void> => {
31
+ return new Promise<void>((resolve) => {
32
+ // in case the element already exists
33
+ if (document.querySelector(selector)) {
34
+ resolve();
35
+ }
36
+ const observer = new MutationObserver(() => {
37
+ if (document.querySelector(selector)) {
38
+ resolve();
39
+ }
40
+ });
41
+ observer.observe(target, { subtree: true, childList: true });
42
+ });
43
+ };
44
+
45
+ // const wait = (delay, ...args) =>
46
+ // new Promise((resolve) => setTimeout(resolve, delay, ...args));
47
+
48
+ afterEach(() => {
49
+ restore();
50
+ });
51
+
52
+ it.skip("shows the launcher", async function () {
53
+ // Given an API that returns this building theme
54
+ stub(window, "fetch").resolves(stubResponse);
55
+
56
+ // When I start MEChat
57
+ MEChat.start({
58
+ organization: "unit-test-org",
59
+ building: "unit-test-building",
60
+ });
61
+ await waitForElementWithSelectorToExist(".meetelise-chat.launcher > div");
62
+
63
+ // Then I should see a launcher
64
+ const launcher = document.querySelector<HTMLDivElement>(
65
+ ".meetelise-chat.launcher"
66
+ ).firstChild as HTMLDivElement;
67
+
68
+ // And the popup should be hidden
69
+ const popup = document.querySelector<HTMLSpanElement>(".__talkjs_popup");
70
+ expect(popup).to.be.an.instanceof(HTMLSpanElement);
71
+ const popupStyle = window.getComputedStyle(popup);
72
+ const popupDisplay = popupStyle.getPropertyValue("display");
73
+ expect(popupDisplay).to.equal("none");
74
+
75
+ launcher.click();
76
+ // Without waiting, the popup doesn't open in time for the next assertion
77
+ //await wait.skip(0);
78
+
79
+ // Then the popup should be visible
80
+ const popupStyle2 = window.getComputedStyle(popup);
81
+ const popupDisplay2 = popupStyle2.getPropertyValue("display");
82
+ expect(popupDisplay2).not.to.equal("none");
83
+
84
+ // Ideally, expect welcome message, but we can't select inside the iframe
85
+ // Ideally, expect theme colors, but we can't select inside the iframe
86
+ });
87
+
88
+ it.skip("works via the programmatic interface", async function () {
89
+ // Given an API that returns this building theme
90
+ stub(window, "fetch").resolves(stubResponse);
91
+
92
+ // When I start MEChat
93
+ const chat = MEChat.start({
94
+ organization: "unit-test-org",
95
+ building: "unit-test-building",
96
+ });
97
+
98
+ await waitForElementWithSelectorToExist(".meetelise-chat.launcher > div");
99
+
100
+ // Ideally, verify behavior, but this will at least verify nothing throws
101
+ chat.show();
102
+ chat.hide();
103
+ chat.setTheme({
104
+ avatarInitials: "G",
105
+ });
106
+ chat.open();
107
+ chat.close();
108
+ chat.restartConversation();
109
+ chat.remove();
110
+ });
@@ -0,0 +1,404 @@
1
+ import axios from "axios";
2
+ import { StyleInfo } from "lit/directives/style-map";
3
+ import "../WebComponent/me-chat";
4
+ import { MEChat as MEChatLitElement } from "../WebComponent/me-chat";
5
+ import "../WebComponent/health-chat";
6
+ import { HealthChat as HealthChatLitElement } from "../WebComponent/health-chat";
7
+ import "../WebComponent/utilities-chat";
8
+ import { UtilitiesChat as UtilitiesChatElement } from "../WebComponent/utilities-chat";
9
+
10
+ import { tintColor } from "../themes";
11
+ import { LogType, sendLoggingEvent } from "../analytics";
12
+ import { findBuildingSlugFromSite, handleRentgrataOverride } from "./utils";
13
+
14
+ /**
15
+ * The interface to MeetElise chat.
16
+ *
17
+ * To add meetelise chat to the screen, call its static method
18
+ * `start()` with your building and organization slug.
19
+ *
20
+ * @example
21
+ * MEChat.start({
22
+ * organization: 'the-jacobson-group',
23
+ * building: 'twin-rivers-pointe'
24
+ * });
25
+ */
26
+
27
+ interface PositioningOptions {
28
+ right?: number;
29
+ bottom?: number;
30
+ top?: number;
31
+ left?: number;
32
+ }
33
+
34
+ export interface HealthcareOptions extends PositioningOptions {
35
+ id: string;
36
+ }
37
+ export default class MEChat {
38
+ static meChat: MEChatLitElement | null = null;
39
+ static healthChat: HealthChatLitElement | null = null;
40
+ static utilitiesChat: UtilitiesChatElement | null = null;
41
+ static orgSlug = "";
42
+ static mutationObserver: MutationObserver | null = null;
43
+ static previousUrl = "";
44
+ static hasBuildingSlug: boolean | null = null;
45
+ static brandColor = "";
46
+ static backgroundColor = "";
47
+ static healthcareId = "";
48
+ static overridePlacement: {
49
+ right?: number;
50
+ bottom?: number;
51
+ top?: number;
52
+ left?: number;
53
+ } = {};
54
+
55
+ static healthcareStart(opts: HealthcareOptions, isInitialStart = true): void {
56
+ if (isInitialStart) {
57
+ this.healthcareId = opts.id;
58
+ this.overridePlacement = {
59
+ right: opts.right,
60
+ bottom: opts.bottom,
61
+ top: opts.top,
62
+ left: opts.left,
63
+ };
64
+ }
65
+ installFont();
66
+ const healthChat = document.createElement("health-chat");
67
+ healthChat.setAttribute("class", "health-chat");
68
+ healthChat.setAttribute("role", "dialog");
69
+ healthChat.setAttribute("aria-label", "EliseAI Healthcare Widget");
70
+ healthChat.setAttribute("aria-describedby", "aria-describe-info");
71
+ healthChat.setAttribute("aria-modal", "true");
72
+ healthChat.setAttribute("healthcareId", opts.id);
73
+
74
+ healthChat.setAttribute("right", opts.right?.toString() || "unset");
75
+ healthChat.setAttribute("bottom", opts.bottom?.toString() || "unset");
76
+ healthChat.setAttribute("top", opts.top?.toString() || "unset");
77
+ healthChat.setAttribute("left", opts.left?.toString() || "unset");
78
+
79
+ document.body.appendChild(healthChat);
80
+ MEChat.healthChat = healthChat;
81
+ }
82
+
83
+ static start(opts: Options, isInitialStart = true): void {
84
+ // If clients are Yardi and have a resident portal with rentcafe,
85
+ // we do NOT want to display the launcher (if following in shows up anywhere in url).
86
+ if (
87
+ window.location.pathname.includes("residentservices") ||
88
+ window.location.pathname.includes("onlineleasing")
89
+ ) {
90
+ return;
91
+ }
92
+ if (isInitialStart) {
93
+ this.orgSlug =
94
+ opts.organization === "Pacific Urban Residential"
95
+ ? "cbc11aba-21c4-4571-bc43-ff9d86a029e3"
96
+ : opts.organization;
97
+ this.hasBuildingSlug = !!opts.building;
98
+ this.overridePlacement = {
99
+ right: opts?.position?.right,
100
+ bottom: opts?.position?.bottom,
101
+ top: opts?.position?.top,
102
+ left: opts?.position?.left,
103
+ };
104
+ }
105
+ installFont();
106
+
107
+ let meChatElement:
108
+ | MEChatLitElement
109
+ | UtilitiesChatElement
110
+ | HealthChatLitElement
111
+ | null = null;
112
+
113
+ switch (opts.widgetType) {
114
+ case WidgetType.Healthcare:
115
+ throw new Error(
116
+ "Healthcare widget is not supported yet, please use the healthcareStart method instead."
117
+ );
118
+ case WidgetType.Default:
119
+ meChatElement = document.createElement("me-chat");
120
+ break;
121
+ case WidgetType.Utilities:
122
+ meChatElement = document.createElement("utilities-chat");
123
+ break;
124
+ default:
125
+ meChatElement = document.createElement("me-chat");
126
+ }
127
+
128
+ if (!meChatElement) {
129
+ throw new Error("Invalid widget type");
130
+ }
131
+
132
+ meChatElement.setAttribute(
133
+ "orgSlug",
134
+ opts.organization === "Pacific Urban Residential"
135
+ ? "cbc11aba-21c4-4571-bc43-ff9d86a029e3"
136
+ : opts.organization
137
+ );
138
+ meChatElement.setAttribute(
139
+ "widgetType",
140
+ opts.widgetType || WidgetType.Default
141
+ );
142
+ meChatElement.setAttribute("class", "meetelise-chat");
143
+ meChatElement.setAttribute("role", "dialog");
144
+ meChatElement.setAttribute("aria-label", "EliseAI Widget");
145
+ meChatElement.setAttribute("aria-describedby", "aria-describe-info");
146
+ meChatElement.setAttribute("aria-modal", "true");
147
+
148
+ if (opts.brandColor) {
149
+ this.brandColor = opts.brandColor;
150
+ // we must tint the brand color, to ensure it is visible.
151
+ meChatElement.setAttribute(
152
+ "primaryColor",
153
+ tintColor(opts.brandColor, 0.3)
154
+ );
155
+ }
156
+ if (opts.backgroundColor) {
157
+ this.backgroundColor = opts.backgroundColor;
158
+ }
159
+
160
+ if (meChatElement instanceof MEChatLitElement) {
161
+ this.handleBuildingslug(
162
+ meChatElement as MEChatLitElement,
163
+ opts.organization,
164
+ opts.building
165
+ );
166
+ if (opts.launcherStyles) {
167
+ meChatElement.launcherStyles = opts.launcherStyles;
168
+ }
169
+ if (opts.mobileStyles) {
170
+ meChatElement.mobileStyles = opts.mobileStyles;
171
+ }
172
+ if (opts.onWidgetLoaded) {
173
+ meChatElement.onWidgetLoaded = opts.onWidgetLoaded;
174
+ }
175
+ if (opts.overrideRentgrata) {
176
+ handleRentgrataOverride();
177
+ meChatElement.overrideRentgrata = true;
178
+ }
179
+ if (opts.onSstClose) {
180
+ meChatElement.onSstClose = opts.onSstClose;
181
+ }
182
+ }
183
+
184
+ if (opts.position) {
185
+ meChatElement.setAttribute(
186
+ "right",
187
+ opts.position.right?.toString() || "unset"
188
+ );
189
+ meChatElement.setAttribute(
190
+ "bottom",
191
+ opts.position.bottom?.toString() || "unset"
192
+ );
193
+ meChatElement.setAttribute(
194
+ "top",
195
+ opts.position.top?.toString() || "unset"
196
+ );
197
+ meChatElement.setAttribute(
198
+ "left",
199
+ opts.position.left?.toString() || "unset"
200
+ );
201
+ }
202
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
203
+ (window as any).eliseAi = {};
204
+ document.body.appendChild(meChatElement);
205
+
206
+ if (meChatElement instanceof MEChatLitElement) {
207
+ MEChat.meChat = meChatElement;
208
+ }
209
+ if (meChatElement instanceof UtilitiesChatElement) {
210
+ MEChat.utilitiesChat = meChatElement;
211
+ }
212
+ }
213
+
214
+ static async restartConversation(): Promise<void> {
215
+ if (!this.meChat) {
216
+ return;
217
+ }
218
+ await this.meChat.restartConversation();
219
+ }
220
+
221
+ static async remove(): Promise<void> {
222
+ if (!this.meChat) {
223
+ return;
224
+ }
225
+ await this.meChat.remove();
226
+ document.body.removeChild(this.meChat);
227
+ MEChat.meChat = null;
228
+ }
229
+
230
+ static async handleBuildingslug(
231
+ meChat: MEChatLitElement,
232
+ orgSlug?: string,
233
+ buildingSlug?: string
234
+ ): Promise<void> {
235
+ if (buildingSlug) {
236
+ meChat.setAttribute("buildingSlug", buildingSlug);
237
+ // TODO(JMB): Uncomment this when we want to start logging mismatches instead of just the "no match found" case
238
+ // this.calculateBuildingSlugForLogging(buildingSlug);
239
+ return;
240
+ }
241
+
242
+ if (this.mutationObserver) {
243
+ return;
244
+ }
245
+ if (!orgSlug) {
246
+ return;
247
+ }
248
+ const foundBuildingSlugFromSite = await findBuildingSlugFromSite(orgSlug);
249
+ if (foundBuildingSlugFromSite) {
250
+ const opts = {
251
+ organization: orgSlug,
252
+ building: foundBuildingSlugFromSite,
253
+ brandColor: this.brandColor,
254
+ backgroundColor: this.backgroundColor,
255
+ };
256
+ this.start(opts, false);
257
+ }
258
+ this.previousUrl = window.location.href;
259
+
260
+ document.body.addEventListener(
261
+ "click",
262
+ () => {
263
+ requestAnimationFrame(() => {
264
+ if (
265
+ this.previousUrl === window.location.href ||
266
+ this.hasBuildingSlug
267
+ ) {
268
+ return;
269
+ }
270
+ this.previousUrl = window.location.href;
271
+ findBuildingSlugFromSite(orgSlug).then(
272
+ (foundBuildingSlugFromSite) => {
273
+ if (!foundBuildingSlugFromSite) {
274
+ return;
275
+ }
276
+ const opts = {
277
+ organization: orgSlug,
278
+ building: foundBuildingSlugFromSite,
279
+ brandColor: this.brandColor,
280
+ backgroundColor: this.backgroundColor,
281
+ };
282
+ this.start(opts, false);
283
+ }
284
+ );
285
+ });
286
+ },
287
+ true
288
+ );
289
+ }
290
+
291
+ static async handleSingleFamilyUrl(): Promise<void> {
292
+ if (this.hasBuildingSlug) {
293
+ return;
294
+ }
295
+ this.remove();
296
+ const url = window.location.href;
297
+ const requestUrl = `https://app.meetelise.com/platformApi/webchat/microsite_slug?uri=${encodeURIComponent(
298
+ url
299
+ )}`;
300
+ const buildingSlug = await axios.get<string | null>(requestUrl, {
301
+ headers: { ["org-slug"]: this.orgSlug },
302
+ });
303
+ // TODO: Figure out whether we only want to sample a percentage of these
304
+ if (Math.random() < 0.2) {
305
+ sendLoggingEvent({
306
+ logType:
307
+ buildingSlug && buildingSlug.data ? LogType.info : LogType.warn,
308
+ logTitle: `[BUILDING_SLUG_CALCULATED_${
309
+ buildingSlug ? "SUCCESS" : "FAILURE"
310
+ }]`,
311
+ logData: {
312
+ calculatedBuildingSlug: buildingSlug.data,
313
+ url,
314
+ orgSlug: this.orgSlug,
315
+ givenBuildingSlug: null,
316
+ reason: buildingSlug && buildingSlug.data ? null : "No match found",
317
+ },
318
+ });
319
+ }
320
+ if (!buildingSlug || !buildingSlug.data) {
321
+ return;
322
+ }
323
+ const opts = {
324
+ organization: this.orgSlug,
325
+ building: buildingSlug.data,
326
+ brandColor: this.brandColor,
327
+ backgroundColor: this.backgroundColor,
328
+ };
329
+ this.start(opts, false);
330
+ }
331
+
332
+ static async calculateBuildingSlugForLogging(
333
+ givenBuildingSlug: string
334
+ ): Promise<void> {
335
+ // TODO: Figure out whether we only want to sample a percentage of these
336
+ const url = window.location.href;
337
+ const requestUrl = `https://app.meetelise.com/platformApi/webchat/microsite_slug?uri=${encodeURIComponent(
338
+ url
339
+ )}`;
340
+ const buildingSlug = await axios.get<string | null>(requestUrl, {
341
+ headers: { ["org-slug"]: this.orgSlug },
342
+ });
343
+ if (Math.random() < 0.2) {
344
+ sendLoggingEvent({
345
+ logType:
346
+ buildingSlug && buildingSlug.data === givenBuildingSlug
347
+ ? LogType.info
348
+ : LogType.warn,
349
+ logTitle: `[BUILDING_SLUG_CALCULATED_${
350
+ buildingSlug && buildingSlug.data === givenBuildingSlug
351
+ ? "SUCCESS"
352
+ : "FAILURE"
353
+ }]`,
354
+ logData: {
355
+ calculatedBuildingSlug: buildingSlug.data,
356
+ url,
357
+ orgSlug: this.orgSlug,
358
+ givenBuildingSlug,
359
+ reason:
360
+ buildingSlug && buildingSlug.data === givenBuildingSlug
361
+ ? null
362
+ : buildingSlug && !buildingSlug.data
363
+ ? "No match found"
364
+ : buildingSlug && buildingSlug.data !== givenBuildingSlug
365
+ ? "Mismatch"
366
+ : "No match found",
367
+ },
368
+ });
369
+ }
370
+ if (!buildingSlug || !buildingSlug.data) {
371
+ return;
372
+ }
373
+ }
374
+ }
375
+
376
+ export interface Options {
377
+ building: string;
378
+ organization: string;
379
+ avatarSrc?: string;
380
+ mini?: boolean;
381
+ launcherStyles?: StyleInfo;
382
+ brandColor?: string;
383
+ backgroundColor?: string;
384
+ mobileStyles?: StyleInfo;
385
+ position?: PositioningOptions;
386
+ onWidgetLoaded?: () => void;
387
+ overrideRentgrata?: boolean;
388
+ widgetType?: string;
389
+ onSstClose?: () => void;
390
+ }
391
+
392
+ export enum WidgetType {
393
+ Default = "default",
394
+ Healthcare = "healthcare",
395
+ Utilities = "utilities",
396
+ }
397
+
398
+ /** You can't install a font from CSS in a shadow DOM, so we use JS to do it here in the regular DOM. */
399
+ const installFont = () => {
400
+ const link = document.createElement("link");
401
+ link.setAttribute("rel", "stylesheet");
402
+ link.setAttribute("type", "text/css");
403
+ document.head.appendChild(link);
404
+ };
@@ -0,0 +1,70 @@
1
+ import { LogType, sendLoggingEvent } from "../analytics";
2
+ import axios from "axios";
3
+
4
+ export const findBuildingSlugFromSite = async (
5
+ orgSlug: string
6
+ ): Promise<string | null> => {
7
+ const url = window.location.href;
8
+ const requestUrl = `https://app.meetelise.com/platformApi/webchat/microsite_slug?uri=${encodeURIComponent(
9
+ url
10
+ )}`;
11
+ const buildingSlug = await axios.get<string | null>(requestUrl, {
12
+ headers: { ["org-slug"]: orgSlug },
13
+ });
14
+ // TODO: Figure out whether we only want to sample a percentage of these
15
+ if (Math.random() < 0.2) {
16
+ sendLoggingEvent({
17
+ logType: buildingSlug && buildingSlug.data ? LogType.info : LogType.warn,
18
+ logTitle: `[BUILDING_SLUG_CALCULATED_${
19
+ buildingSlug ? "SUCCESS" : "FAILURE"
20
+ }]`,
21
+ logData: {
22
+ calculatedBuildingSlug: buildingSlug.data,
23
+ url,
24
+ orgSlug: orgSlug,
25
+ givenBuildingSlug: null,
26
+ reason: buildingSlug && buildingSlug.data ? null : "No match found",
27
+ },
28
+ });
29
+ }
30
+ return buildingSlug.data;
31
+ };
32
+
33
+ export const handleRentgrataOverride = async (): Promise<void> => {
34
+ const rentgrataWrapperElement = await waitForElement("rg-widget-compact");
35
+ if (!rentgrataWrapperElement) {
36
+ return;
37
+ }
38
+ rentgrataWrapperElement.setAttribute("style", "display: none");
39
+ };
40
+
41
+ const waitForElement = async (
42
+ elementId: string,
43
+ timeout = 5000
44
+ ): Promise<Element> => {
45
+ return new Promise((resolve, reject) => {
46
+ const observer = new MutationObserver((mutationsList, observer) => {
47
+ const element = document.getElementById(elementId);
48
+ if (element) {
49
+ observer.disconnect();
50
+ resolve(element);
51
+ }
52
+ });
53
+
54
+ observer.observe(document.body, { childList: true, subtree: true });
55
+
56
+ const timeoutId = setTimeout(() => {
57
+ observer.disconnect();
58
+ reject(
59
+ new Error(`Element ${elementId} did not appear within ${timeout}ms`)
60
+ );
61
+ }, timeout);
62
+
63
+ const element = document.querySelector(elementId);
64
+ if (element) {
65
+ clearTimeout(timeoutId);
66
+ observer.disconnect();
67
+ resolve(element);
68
+ }
69
+ });
70
+ };
@@ -0,0 +1,44 @@
1
+ export function getUrlQueryParameters(): { [queryKey: string]: string } | null {
2
+ if (isQueryMalformed()) {
3
+ return getMalformedQueryParameters();
4
+ }
5
+ return getStandardUrlQueryParameters();
6
+ }
7
+
8
+ function getStandardUrlQueryParameters(): {
9
+ [queryKey: string]: string;
10
+ } | null {
11
+ const queryParams = new URLSearchParams(window.location.search);
12
+
13
+ const hasUtmContent = queryParams.has("utm_content");
14
+ const hasUtmSource = queryParams.has("utm_source");
15
+
16
+ // If utm_content exists and utm_source does not, replace utm_content with utm_source
17
+ if (hasUtmContent && !hasUtmSource) {
18
+ const utmContentValue = queryParams.get("utm_content");
19
+ queryParams.delete("utm_content");
20
+ queryParams.set("utm_source", utmContentValue as string);
21
+ }
22
+
23
+ return Object.fromEntries(queryParams);
24
+ }
25
+
26
+ // Some clients are sending malformed query parameters, so we need to handle those
27
+ // i.e. .../?switch_cls[id]=94593/?utm_source=MillCreekPlaces&utm_medium=Community+Portfolio+Page
28
+ function getMalformedQueryParameters(): { [queryKey: string]: string } | null {
29
+ const url = window.location.search;
30
+ const allParams: { [queryKey: string]: string } = {};
31
+ const malformedParts = url.split("?").slice(1).join("&");
32
+ const pairs = malformedParts.split("&");
33
+ pairs.forEach((pair) => {
34
+ const [key, value] = pair.split("=");
35
+ if (key && value) {
36
+ allParams[decodeURIComponent(key)] = decodeURIComponent(value);
37
+ }
38
+ });
39
+
40
+ return allParams;
41
+ }
42
+
43
+ const isQueryMalformed = (): boolean =>
44
+ (window.location.search.match(/\?/g) || []).length > 1;