@meetelise/chat 1.9.1 → 1.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/.eslintrc.cjs +1 -0
  2. package/.github/workflows/release.yml +1 -0
  3. package/.vscode/settings.json +6 -1
  4. package/CONTRIBUTING.md +8 -0
  5. package/package.json +9 -10
  6. package/public/demo/index.html +78 -11
  7. package/public/dist/index.js +1714 -1
  8. package/public/dist/index.js.LICENSE.txt +26 -14
  9. package/public/index.html +2 -1
  10. package/src/MEChat.test.ts +5 -5
  11. package/src/MEChat.ts +53 -0
  12. package/src/WebComponent/InHouseLauncher.ts +446 -0
  13. package/src/WebComponent/MEChat.css +5 -0
  14. package/src/WebComponent/MEChat.ts +282 -0
  15. package/src/WebComponent/OfficeHours.ts +73 -0
  16. package/src/WebComponent/Scheduler/date-picker.ts +320 -0
  17. package/src/WebComponent/Scheduler/me-select.ts +244 -0
  18. package/src/WebComponent/Scheduler/time-picker.ts +101 -0
  19. package/src/WebComponent/Scheduler/tour-scheduler.ts +383 -0
  20. package/src/WebComponent/Scheduler/tour-type-option.ts +92 -0
  21. package/src/WebComponent/actions/ActionConfirmButton.ts +94 -0
  22. package/src/WebComponent/actions/CallUsWindow.ts +110 -0
  23. package/src/WebComponent/actions/DetailsWindow.ts +109 -0
  24. package/src/WebComponent/actions/EmailUsWindow.ts +432 -0
  25. package/src/WebComponent/actions/InputStyles.ts +31 -0
  26. package/src/WebComponent/actions/TextUsWindow.ts +226 -0
  27. package/src/WebComponent/actions/formatPhoneNumber.ts +42 -0
  28. package/src/WebComponent/inHouseLauncherStyles.ts +300 -0
  29. package/src/WebComponent/index.ts +2 -0
  30. package/src/WebComponent/utils.ts +82 -0
  31. package/src/analytics.ts +48 -15
  32. package/src/assetUrls.ts +4 -0
  33. package/src/fetchBuildingInfo.ts +1 -0
  34. package/src/getAvailabilities.ts +71 -0
  35. package/src/themes.ts +5 -3
  36. package/tsconfig.json +9 -3
  37. package/web-test-runner.config.js +0 -6
  38. package/webpack.config.cjs +8 -25
  39. package/public/dist/index.d.ts +0 -1
  40. package/public/dist/src/ChatButton.d.ts +0 -9
  41. package/public/dist/src/ChatIcon.d.ts +0 -6
  42. package/public/dist/src/InHouseLauncher.d.ts +0 -11
  43. package/public/dist/src/MEChat.d.ts +0 -73
  44. package/public/dist/src/analytics.d.ts +0 -18
  45. package/public/dist/src/chatID.d.ts +0 -11
  46. package/public/dist/src/createConversation.d.ts +0 -4
  47. package/public/dist/src/fetchBuildingInfo.d.ts +0 -25
  48. package/public/dist/src/themes.d.ts +0 -52
  49. package/public/dist/src/utils.d.ts +0 -2
  50. package/src/ChatButton.module.scss +0 -52
  51. package/src/ChatButton.tsx +0 -26
  52. package/src/ChatIcon.tsx +0 -26
  53. package/src/DemoApp.tsx +0 -113
  54. package/src/InHouseLauncher.module.scss +0 -140
  55. package/src/InHouseLauncher.tsx +0 -65
  56. package/src/MEChat.module.scss +0 -22
  57. package/src/MEChat.tsx +0 -293
@@ -0,0 +1,383 @@
1
+ import { css, html, LitElement, TemplateResult } from "lit";
2
+ import { customElement, property, state } from "lit/decorators.js";
3
+ import "./tour-type-option.ts";
4
+ import "./date-picker.ts";
5
+ import "./time-picker.ts";
6
+ import "./me-select.ts";
7
+
8
+ @customElement("tour-scheduler")
9
+ export class TourScheduler extends LitElement {
10
+ @property({ attribute: false })
11
+ availability?: Availability; // TODO: shouldn't be optional?
12
+
13
+ @property({ attribute: false })
14
+ onSchedule?: (tour: Tour) => void;
15
+
16
+ // state: type, date, time, name, email, phone, unit type, layout type
17
+ @state()
18
+ private tourType = TourType.Guided;
19
+
20
+ static styles = css`
21
+ @import url("https://fonts.googleapis.com/css2?family=Poppins:wght@400;600;700;900&display=swap");
22
+
23
+ * {
24
+ box-sizing: border-box;
25
+ }
26
+
27
+ .tour-scheduler {
28
+ position: fixed;
29
+ left: 50%;
30
+ top: 50%;
31
+ transform: translate(-50%, -50%);
32
+ width: 1018px;
33
+ height: 573px;
34
+ background: #ffffff;
35
+ box-shadow: 0px 16px 18px 10px rgba(21, 21, 21, 0.4);
36
+ border-radius: 10px;
37
+ font-family: "Poppins";
38
+ color: #202020;
39
+ padding: 0 27px 0 25px;
40
+
41
+ /* grid stuff */
42
+ display: grid;
43
+ grid-template-columns: 225px 400px 330px;
44
+ grid-template-rows: 44px 54px 32px 195px 152px 1px;
45
+ }
46
+
47
+ h1,
48
+ h2 {
49
+ margin: 0;
50
+ }
51
+
52
+ .tour-scheduler > :is(h1, h2) {
53
+ align-self: end;
54
+ }
55
+
56
+ h1 {
57
+ font-size: 14px;
58
+ font-weight: 700;
59
+ }
60
+
61
+ h1#scheduleATour {
62
+ grid-row: 1 / 2;
63
+ grid-column: 1;
64
+ align-self: end;
65
+ }
66
+
67
+ button#closeButton {
68
+ grid-row: 1 / 2;
69
+ grid-column: -1;
70
+ height: max-content;
71
+ aspect-ratio: 1;
72
+ background: none;
73
+ border: none;
74
+ align-self: end;
75
+ }
76
+
77
+ #tourTypeMenu {
78
+ grid-row: 4 / 5;
79
+ grid-column: 1;
80
+ align-self: start;
81
+ display: flex;
82
+ flex-direction: column;
83
+ gap: 15px;
84
+ }
85
+
86
+ h2 {
87
+ font-weight: 600;
88
+ font-size: 14px;
89
+ grid-row: label-row;
90
+ }
91
+
92
+ h2#tourType {
93
+ grid-column: 1;
94
+ grid-row: 2;
95
+ }
96
+
97
+ h2#dateAndTime {
98
+ grid-column: 2;
99
+ grid-row: 2;
100
+ }
101
+
102
+ h2#yourInformation {
103
+ grid-column: 3;
104
+ grid-row: 2;
105
+ }
106
+
107
+ #datePicker {
108
+ display: flex;
109
+ }
110
+
111
+ #dateAndTimeMenu {
112
+ grid-row: 4 / 5;
113
+ grid-column: 2;
114
+ align-self: start;
115
+ display: flex;
116
+ flex-direction: column;
117
+ }
118
+
119
+ #yourInformationMenu {
120
+ grid-row: 4 / 5;
121
+ grid-column: 3;
122
+ display: flex;
123
+ flex-direction: column;
124
+ gap: 12px;
125
+ }
126
+
127
+ #yourInformationMenu > input {
128
+ width: 305px;
129
+ height: 49px;
130
+ border: 1px solid #83818e;
131
+ padding: 13px 11px 14px 11px;
132
+ }
133
+
134
+ #yourInformationMenu > input::placeholder {
135
+ font-family: "Poppins";
136
+ font-style: normal;
137
+ font-weight: 400;
138
+ font-size: 14px;
139
+ color: #202020;
140
+ }
141
+
142
+ #unitChoiceMenu {
143
+ grid-row: 5 / 6;
144
+ grid-column: 3;
145
+ align-self: start;
146
+ display: flex;
147
+ flex-direction: column;
148
+ }
149
+
150
+ h2#unitChoice {
151
+ margin-bottom: 7px;
152
+ }
153
+
154
+ #unitOptions {
155
+ display: flex;
156
+ flex-direction: column;
157
+ gap: 8px;
158
+ }
159
+
160
+ hr {
161
+ grid-row: 6;
162
+ grid-column: 1 / 5;
163
+ /* remove side margins because of this
164
+ * (https://stackoverflow.com/questions/34365271/hr-inside-container-with-display-flex-become-corrupted)
165
+ * and top/bottom margins to position the line exactly at the gridline
166
+ */
167
+ margin: 0;
168
+ }
169
+
170
+ p {
171
+ font-weight: 400;
172
+ font-size: 12px;
173
+ grid-row: 7;
174
+ grid-column: 1 / 3;
175
+ align-self: start;
176
+ margin: 0;
177
+ padding-top: 32px;
178
+ }
179
+
180
+ /* TODO: button styling depends on disabled which depends on whether form is ready for submission */
181
+ button#schedule {
182
+ width: 145px;
183
+ height: 50px;
184
+ background: #e7e7e7;
185
+ border: 1px solid #ffffff;
186
+ border-radius: 10px;
187
+ grid-row: 7;
188
+ grid-column: 3;
189
+ justify-self: end;
190
+ align-self: start;
191
+ margin-top: 18px;
192
+ font-family: "Poppins";
193
+ font-weight: 700;
194
+ font-size: 14px;
195
+ color: #ffffff;
196
+ }
197
+ `;
198
+
199
+ render(): TemplateResult {
200
+ return html`
201
+ <div class="tour-scheduler">
202
+ <h1 id="scheduleATour">Schedule a tour</h1>
203
+ <button id="closeButton">
204
+ <svg
205
+ width="19"
206
+ height="19"
207
+ viewBox="0 0 19 19"
208
+ fill="none"
209
+ xmlns="http://www.w3.org/2000/svg"
210
+ >
211
+ <line
212
+ x1="0.986863"
213
+ y1="18.2746"
214
+ x2="18.2929"
215
+ y2="0.968593"
216
+ stroke="#202020"
217
+ stroke-width="2"
218
+ />
219
+ <path
220
+ d="M1.01394 0.999997L18.0103 18.0243"
221
+ stroke="#202020"
222
+ stroke-width="2"
223
+ />
224
+ </svg>
225
+ </button>
226
+
227
+ <h2 id="tourType">Tour Type</h2>
228
+ <div id="tourTypeMenu">
229
+ <tour-type-option
230
+ tourtype="guided"
231
+ heading="Guided tour"
232
+ subtitle="with an agent"
233
+ @click="${() => {
234
+ this.tourType = TourType.Guided;
235
+ }}"
236
+ @keydown="${(e: KeyboardEvent) => {
237
+ if ([" ", "Enter"].includes(e.key)) {
238
+ e.preventDefault();
239
+ this.tourType = TourType.Guided;
240
+ }
241
+ }}"
242
+ ?selected="${this.tourType === TourType.Guided}"
243
+ >
244
+ <svg
245
+ slot="icon"
246
+ width="31"
247
+ height="31"
248
+ viewBox="0 0 31 31"
249
+ fill="none"
250
+ xmlns="http://www.w3.org/2000/svg"
251
+ >
252
+ <path
253
+ d="M0.833252 30.1666C0.833252 27.1608 2.0273 24.2782 4.15271 22.1527C6.27812 20.0273 9.1608 18.8333 12.1666 18.8333C15.1724 18.8333 18.0551 20.0273 20.1805 22.1527C22.3059 24.2782 23.4999 27.1608 23.4999 30.1666H0.833252ZM12.1666 17.4166C7.47034 17.4166 3.66659 13.6129 3.66659 8.91663C3.66659 4.22038 7.47034 0.416626 12.1666 0.416626C16.8628 0.416626 20.6666 4.22038 20.6666 8.91663C20.6666 13.6129 16.8628 17.4166 12.1666 17.4166ZM22.5975 20.58C24.7645 21.137 26.7006 22.3634 28.13 24.0846C29.5595 25.8059 30.4096 27.9342 30.5592 30.1666H26.3333C26.3333 26.4691 24.9166 23.1031 22.5975 20.58ZM19.7316 17.3557C20.9187 16.2939 21.8681 14.9932 22.5175 13.5388C23.167 12.0845 23.5017 10.5094 23.4999 8.91663C23.5029 6.9807 23.0078 5.07657 22.062 3.38738C23.6666 3.70979 25.11 4.5779 26.1469 5.84415C27.1838 7.1104 27.7502 8.69666 27.7499 10.3333C27.7503 11.3426 27.5349 12.3404 27.1182 13.2597C26.7016 14.179 26.0932 14.9986 25.3339 15.6636C24.5746 16.3285 23.6819 16.8236 22.7157 17.1154C21.7495 17.4072 20.7321 17.4892 19.7316 17.3557V17.3557Z"
254
+ fill="${this.tourType === TourType.Guided
255
+ ? "#ffffff"
256
+ : "#202020"}"
257
+ />
258
+ </svg>
259
+ </tour-type-option>
260
+ <tour-type-option
261
+ tourtype="self"
262
+ heading="Take a tour"
263
+ subtitle="on your own"
264
+ @click="${() => {
265
+ this.tourType = TourType.Self;
266
+ }}"
267
+ @keydown="${(e: KeyboardEvent) => {
268
+ if ([" ", "Enter"].includes(e.key)) {
269
+ e.preventDefault();
270
+ this.tourType = TourType.Self;
271
+ }
272
+ }}"
273
+ ?selected="${this.tourType === TourType.Self}"
274
+ >
275
+ <svg
276
+ slot="icon"
277
+ width="28"
278
+ height="31"
279
+ viewBox="0 0 28 31"
280
+ fill="none"
281
+ xmlns="http://www.w3.org/2000/svg"
282
+ >
283
+ <path
284
+ d="M14.8334 19.1903V30.1667H0.666687C0.666248 28.4367 1.06183 26.7297 1.82311 25.1763C2.58439 23.6229 3.69118 22.2644 5.05866 21.2049C6.42614 20.1453 8.01802 19.4129 9.71232 19.0637C11.4066 18.7145 13.1584 18.7578 14.8334 19.1903ZM12 17.4167C7.30377 17.4167 3.50002 13.6129 3.50002 8.91666C3.50002 4.22041 7.30377 0.416656 12 0.416656C16.6963 0.416656 20.5 4.22041 20.5 8.91666C20.5 13.6129 16.6963 17.4167 12 17.4167ZM20.5 23.0833V18.125L27.5834 24.5L20.5 30.875V25.9167H16.25V23.0833H20.5Z"
285
+ fill="${this.tourType === TourType.Self
286
+ ? "#ffffff"
287
+ : "#202020"}"
288
+ />
289
+ </svg>
290
+ </tour-type-option>
291
+ <tour-type-option
292
+ tourtype="guided"
293
+ heading="Virtual tour"
294
+ subtitle="over video"
295
+ @click="${() => {
296
+ this.tourType = TourType.Virtual;
297
+ }}"
298
+ @keydown="${(e: KeyboardEvent) => {
299
+ if ([" ", "Enter"].includes(e.key)) {
300
+ e.preventDefault();
301
+ this.tourType = TourType.Virtual;
302
+ }
303
+ }}"
304
+ ?selected="${this.tourType === TourType.Virtual}"
305
+ >
306
+ <svg
307
+ slot="icon"
308
+ width="26"
309
+ height="25"
310
+ viewBox="0 0 26 25"
311
+ fill="none"
312
+ xmlns="http://www.w3.org/2000/svg"
313
+ >
314
+ <path
315
+ d="M15.6 19.5V22.1L18.2 23.4V24.7H7.80004L7.79484 23.4052L10.4 22.1V19.5H1.28965C1.11894 19.4989 0.950113 19.4642 0.792841 19.3979C0.635568 19.3315 0.492943 19.2347 0.373141 19.1131C0.253339 18.9915 0.158715 18.8474 0.0946936 18.6892C0.0306718 18.5309 -0.00148955 18.3616 5.29696e-05 18.1909V1.3091C5.29696e-05 0.586299 0.591552 0 1.28965 0H24.7104C25.4228 0 26 0.583699 26 1.3091V18.1909C26 18.9137 25.4085 19.5 24.7104 19.5H15.6ZM2.60005 14.3V16.9H23.4V14.3H2.60005Z"
316
+ fill="${this.tourType === TourType.Virtual
317
+ ? "#ffffff"
318
+ : "#202020"}"
319
+ />
320
+ </svg>
321
+ </tour-type-option>
322
+ </div>
323
+
324
+ <h2 id="dateAndTime">Date and Time</h2>
325
+ <div id="dateAndTimeMenu">
326
+ <!-- TODO: pass currently selected date as attribute if any -->
327
+ <div id="datePicker">
328
+ <date-picker></date-picker>
329
+ <time-picker></time-picker>
330
+ </div>
331
+ </div>
332
+
333
+ <h2 id="yourInformation">Your information</h2>
334
+ <div id="yourInformationMenu">
335
+ <input type="text" placeholder="Name" />
336
+ <input type="email" placeholder="Email" />
337
+ <input type="tel" placeholder="Phone" />
338
+ </div>
339
+ <div id="unitChoiceMenu">
340
+ <h2 id="unitChoice">What would you like to view?</h2>
341
+ <div id="unitOptions">
342
+ <me-select
343
+ id="unitType"
344
+ placeholder="Select type"
345
+ .options="${["Studio", "1 Bedroom", "2 Bedroom", "3 Bedroom"]}"
346
+ defaultOption="Studio"
347
+ >Studio
348
+ </me-select>
349
+ <me-select
350
+ id="layout"
351
+ placeholder="Select layout"
352
+ .options="${["Standard layout", "Weird layout"]}"
353
+ >
354
+ </me-select>
355
+ </div>
356
+ </div>
357
+ <hr />
358
+ <p id="explanation">
359
+ We’ll send a confirmation and any follow-ups to your email address.
360
+ </p>
361
+ <button id="schedule">Schedule tour</button>
362
+ </div>
363
+ `;
364
+ }
365
+ }
366
+
367
+ // TODO: what should this look like? what date format? etc.
368
+ interface Availability {
369
+ [date: string]: { time: Date }[];
370
+ }
371
+
372
+ export enum TourType {
373
+ Guided,
374
+ Self,
375
+ Virtual,
376
+ }
377
+
378
+ interface Tour {
379
+ start: Date;
380
+ type: TourType;
381
+ // TODO: enum? or leave as string for flexibility? or autogen from backend?
382
+ layout: string;
383
+ }
@@ -0,0 +1,92 @@
1
+ import { css, html, LitElement, TemplateResult } from "lit";
2
+ import { customElement, property } from "lit/decorators.js";
3
+ import { TourType } from "./tour-scheduler";
4
+
5
+ @customElement("tour-type-option")
6
+ export class TourTypeOption extends LitElement {
7
+ @property({ type: String })
8
+ tourtype = "";
9
+ @property({ type: String })
10
+ heading = "";
11
+ @property({ type: String })
12
+ subtitle = "";
13
+ @property({ type: Boolean })
14
+ selected = false;
15
+
16
+ @property({ attribute: false })
17
+ onClick?: (tourType: TourType) => void;
18
+
19
+ static styles = [
20
+ css`
21
+ @import url("https://fonts.googleapis.com/css2?family=Poppins:wght@400;600;700;900&display=swap");
22
+
23
+ .tour-type-option {
24
+ height: 90px;
25
+ width: 200px;
26
+ background: #e7e7e7;
27
+ border: 1px solid #ffffff;
28
+ border-radius: 10px;
29
+ position: relative;
30
+ user-select: none;
31
+ box-sizing: border-box;
32
+ }
33
+
34
+ :host([selected]) .tour-type-option {
35
+ background: #202020;
36
+ border: 3px solid #83818e;
37
+ }
38
+
39
+ .content {
40
+ display: flex;
41
+ align-items: center;
42
+ justify-content: center;
43
+ /* TODO: may need to use grid, or something else, to get the icons/text to align */
44
+ gap: 15px;
45
+ width: 100%;
46
+ position: absolute;
47
+ top: 50%;
48
+ left: 50%;
49
+ transform: translate(-50%, -50%);
50
+ }
51
+
52
+ .text {
53
+ display: flex;
54
+ flex-direction: column;
55
+ color: #202020;
56
+ font-family: "Poppins";
57
+ }
58
+
59
+ :host([selected]) .text {
60
+ color: #ffffff;
61
+ }
62
+
63
+ h1,
64
+ h2 {
65
+ font-size: 15px;
66
+ margin: 0;
67
+ }
68
+
69
+ h1 {
70
+ font-weight: 600;
71
+ }
72
+
73
+ h2 {
74
+ font-weight: 400;
75
+ }
76
+ `,
77
+ ];
78
+
79
+ render(): TemplateResult {
80
+ return html`
81
+ <div class="tour-type-option" tabindex="0">
82
+ <div class="content">
83
+ <slot name="icon"></slot>
84
+ <div class="text">
85
+ <h1>${this.heading}</h1>
86
+ <h2>${this.subtitle}</h2>
87
+ </div>
88
+ </div>
89
+ </div>
90
+ `;
91
+ }
92
+ }
@@ -0,0 +1,94 @@
1
+ import { css, html, LitElement, TemplateResult } from "lit";
2
+ import { customElement, property } from "lit/decorators.js";
3
+
4
+ @customElement("action-confirm-button")
5
+ export class ActionConfirmButton extends LitElement {
6
+ static styles = [
7
+ css`
8
+ @import url("https://fonts.googleapis.com/css2?family=Poppins:wght@400;600;700;900&display=swap");
9
+ .action-confirm-button {
10
+ background: #1e1e1e;
11
+ border: 2px solid #ffffff;
12
+ box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.5);
13
+ border-radius: 10px;
14
+ color: #ffffff;
15
+ font-family: "Poppins";
16
+ font-style: normal;
17
+ font-weight: 700;
18
+ font-size: 14px;
19
+ line-height: 22px;
20
+ padding-left: 20px;
21
+ padding-right: 20px;
22
+ padding-top: 12px;
23
+ padding-bottom: 12px;
24
+ cursor: pointer;
25
+ }
26
+
27
+ .action-confirm-button:active {
28
+ transform: translateY(2px);
29
+ box-shadow: 0px 0px 0px rgba(36, 53, 141, 0.25);
30
+ }
31
+
32
+ .lds-ring {
33
+ display: inline-block;
34
+ position: relative;
35
+ width: 48px;
36
+ height: 48px;
37
+ }
38
+ .lds-ring div {
39
+ box-sizing: border-box;
40
+ display: block;
41
+ position: absolute;
42
+ width: 32px;
43
+ height: 32px;
44
+ margin: 8px;
45
+ border: 8px solid #fff;
46
+ border-radius: 50%;
47
+ animation: lds-ring 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;
48
+ border-color: #fff transparent transparent transparent;
49
+ }
50
+ .lds-ring div:nth-child(1) {
51
+ animation-delay: -0.45s;
52
+ }
53
+ .lds-ring div:nth-child(2) {
54
+ animation-delay: -0.3s;
55
+ }
56
+ .lds-ring div:nth-child(3) {
57
+ animation-delay: -0.15s;
58
+ }
59
+ @keyframes lds-ring {
60
+ 0% {
61
+ transform: rotate(0deg);
62
+ }
63
+ 100% {
64
+ transform: rotate(360deg);
65
+ }
66
+ }
67
+ `,
68
+ ];
69
+ @property()
70
+ onClick?: () => void;
71
+ @property()
72
+ text = "Submit";
73
+ @property({ attribute: false })
74
+ isLoading = false;
75
+
76
+ render = (): TemplateResult => {
77
+ return html`<button class="action-confirm-button" @click=${this.onClick}>
78
+ ${!this.isLoading
79
+ ? this.text
80
+ : html`<div class="lds-ring">
81
+ <div></div>
82
+ <div></div>
83
+ <div></div>
84
+ <div></div>
85
+ </div>`}
86
+ </button>`;
87
+ };
88
+ }
89
+
90
+ export const installActionConfirmButton = (): void => {
91
+ if (!window.customElements.get("action-confirm-button")) {
92
+ window.customElements.define("action-confirm-button", ActionConfirmButton);
93
+ }
94
+ };
@@ -0,0 +1,110 @@
1
+ import { css, html, LitElement, TemplateResult } from "lit";
2
+ import { customElement, property } from "lit/decorators.js";
3
+
4
+ import { getOfficeHourText } from "../OfficeHours";
5
+
6
+ @customElement("call-us-window")
7
+ export class CallUsWindow extends LitElement {
8
+ static styles = [
9
+ css`
10
+ .call-us-window__content-wrapper {
11
+ font-family: Poppins;
12
+ color: 11ee1e;
13
+ }
14
+
15
+ .call-us-window__call-us-text {
16
+ margin-top: 54px;
17
+ margin-bottom: 28px;
18
+ font-family: "Poppins";
19
+ font-size: 18px;
20
+ line-height: 24px;
21
+ }
22
+
23
+ .call-us-window__office-hours-header {
24
+ text-decoration: underline;
25
+ font-size: 12px;
26
+ margin-bottom: 10px;
27
+ }
28
+
29
+ .call-us-window__day-of-week {
30
+ width: 112px;
31
+ text-transform: Capitalize;
32
+ }
33
+
34
+ .call-us-window__day-of-week-wrapper {
35
+ display: flex;
36
+ align-items: center;
37
+ margin-bottom: 10px;
38
+ font-size: 12px;
39
+ }
40
+
41
+ .call-us-window__open-times {
42
+ text-transform: lowercase;
43
+ }
44
+ `,
45
+ ];
46
+
47
+ @property({ attribute: false })
48
+ onCloseClicked?: (e: MouseEvent) => void;
49
+
50
+ @property()
51
+ phoneNumber = "1-855-531-5131";
52
+ @property({ attribute: false })
53
+ buildingId = 0;
54
+
55
+ firstUpdated = async (): Promise<void> => {
56
+ if (!this.buildingId) {
57
+ return;
58
+ }
59
+ this.officeHoursTextInfo = await getOfficeHourText(this.buildingId);
60
+ };
61
+
62
+ @property({ attribute: false })
63
+ officeHoursTextInfo: (
64
+ | string
65
+ | { dayOfWeek: string; startTime: string; endTime: string }
66
+ )[] = [];
67
+
68
+ render = (): TemplateResult => {
69
+ return html`
70
+ <details-window
71
+ height="443px"
72
+ headerText="Call us"
73
+ .onCloseClick=${this.onCloseClicked}
74
+ >
75
+ <div class="call-us-window__content-wrapper">
76
+ <div class="call-us-window__call-us-text">
77
+ Contact our leasing team at <br />${this.phoneNumber}
78
+ </div>
79
+ <div class="call-us-window__office-hours-wrapper">
80
+ <div class="call-us-window__office-hours-header">Office hours</div>
81
+ </div>
82
+ ${this.officeHoursTextInfo.map((oh) => {
83
+ if (typeof oh === "string") {
84
+ return html`
85
+ <div class="call-us-window__day-of-week-wrapper">
86
+ <div class="call-us-window__day-of-week">${oh}</div>
87
+ <div class="call-us-window__closed">Closed</div>
88
+ </div>
89
+ `;
90
+ }
91
+ return html`
92
+ <div class="call-us-window__day-of-week-wrapper">
93
+ <div class="call-us-window__day-of-week">${oh.dayOfWeek}</div>
94
+ <div class="call-us-window__open-times">
95
+ ${oh.startTime}&nbsp;&ndash;&nbsp;${oh.endTime}
96
+ </div>
97
+ </div>
98
+ `;
99
+ })}
100
+ </div>
101
+ </details-window>
102
+ `;
103
+ };
104
+ }
105
+
106
+ export const installCallUsWindow = (): void => {
107
+ if (!window.customElements.get("call-us-window")) {
108
+ window.customElements.define("call-us-window", CallUsWindow);
109
+ }
110
+ };