@meetelise/chat 1.43.39 → 1.43.40

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.
@@ -323,8 +323,19 @@ export class DatePicker extends LitElement {
323
323
  const hasNoAvailabilities =
324
324
  !this.availabilities?.[dateString] ||
325
325
  this.availabilities?.[dateString]?.length === 0;
326
+ const isStartOverflow = index < extraDaysAtBeginningOfMonth.length;
327
+ const isEndOverflow =
328
+ index >= extraDaysAtBeginningOfMonth.length + daysOfMonth.length;
329
+ const cellDate = new Date(
330
+ this.yearShown,
331
+ this.monthShown + (isStartOverflow ? -1 : isEndOverflow ? 1 : 0),
332
+ dayNumber
333
+ );
334
+ const cellAriaLabel = format(cellDate, "MMMM d, y");
326
335
  return html`<button
327
336
  ?disabled=${isPast || hasNoAvailabilities || isDifferentMonth}
337
+ aria-label=${cellAriaLabel}
338
+ aria-pressed=${isSelected ? "true" : "false"}
328
339
  class="dayNumber ${classMap({
329
340
  past: isPast,
330
341
  differentMonth: isDifferentMonth,
@@ -339,7 +350,11 @@ export class DatePicker extends LitElement {
339
350
  const rows = chunk(7, dayElements);
340
351
 
341
352
  return html`
342
- <div id="calendar">
353
+ <div
354
+ id="calendar"
355
+ role="group"
356
+ aria-label="Calendar, ${monthNames[this.monthShown]} ${this.yearShown}"
357
+ >
343
358
  <div id="header">
344
359
  <h2 aria-live="polite" aria-atomic="true">
345
360
  ${monthNames[this.monthShown]} ${this.yearShown}
@@ -108,7 +108,10 @@ export class TimePicker extends LitElement {
108
108
  border-radius: 10px;
109
109
  font-style: normal;
110
110
  font-size: 14px;
111
+ font-family: inherit;
112
+ color: inherit;
111
113
  user-select: none;
114
+ cursor: pointer;
112
115
  }
113
116
 
114
117
  .option.selected {
@@ -179,50 +182,33 @@ export class TimePicker extends LitElement {
179
182
  <div
180
183
  id="optionContainer"
181
184
  @click="${(e: MouseEvent) => {
182
- const target = e.target as HTMLElement | undefined;
183
-
184
- if (target?.closest(".option:not(.selected)"))
185
- this.selected = getDateWithTimezoneOffset(
186
- this.options,
187
- target.innerText
188
- );
185
+ const target = (e.target as HTMLElement | null)?.closest(
186
+ ".option"
187
+ ) as HTMLButtonElement | null;
188
+ if (!target) return;
189
+ const value = target.dataset.displayTimeZoned ?? "";
190
+ const isAlreadySelected =
191
+ value === this.selected?.displayTimeZoned;
192
+ this.selected = isAlreadySelected
193
+ ? undefined
194
+ : getDateWithTimezoneOffset(this.options, value);
189
195
  this.dispatchEvent(
190
196
  new Event("change", { bubbles: true, composed: true })
191
197
  );
192
198
  }}"
193
- @keydown="${(e: KeyboardEvent) => {
194
- const target = e.target as HTMLElement | undefined;
195
- if (
196
- [" ", "Enter"].includes(e.key) &&
197
- target?.closest(".option")
198
- ) {
199
- e.preventDefault();
200
- this.selected =
201
- target.innerText !== this.selected?.displayTimeZoned
202
- ? getDateWithTimezoneOffset(
203
- this.options,
204
- target.innerText
205
- )
206
- : undefined;
207
- this.dispatchEvent(
208
- new Event("change", { bubbles: true, composed: true })
209
- );
210
- }
211
- }}"
212
199
  >
213
- ${this.options.map(
214
- (option) =>
215
- html`<div
216
- class="option ${classMap({
217
- selected:
218
- this.selected?.displayTimeZoned ===
219
- option.displayTimeZoned,
220
- })}"
221
- tabindex="0"
222
- >
223
- <span>${option.displayTimeZoned}</span>
224
- </div>`
225
- )}
200
+ ${this.options.map((option) => {
201
+ const isSelected =
202
+ this.selected?.displayTimeZoned === option.displayTimeZoned;
203
+ return html`<button
204
+ type="button"
205
+ class="option ${classMap({ selected: isSelected })}"
206
+ aria-pressed=${isSelected ? "true" : "false"}
207
+ data-display-time-zoned=${option.displayTimeZoned}
208
+ >
209
+ <span>${option.displayTimeZoned}</span>
210
+ </button>`;
211
+ })}
226
212
  </div>
227
213
  <p class="timezone-display-text">
228
214
  *All times displayed are in the community's local time
@@ -64,6 +64,19 @@ import { LeadSourceMultitouchClient } from "../LeadSourceMultitouchClient";
64
64
 
65
65
  @customElement("tour-scheduler")
66
66
  export class TourScheduler extends LitElement {
67
+ connectedCallback(): void {
68
+ super.connectedCallback();
69
+ if (!this.hasAttribute("role")) {
70
+ this.setAttribute("role", "dialog");
71
+ }
72
+ if (!this.hasAttribute("aria-modal")) {
73
+ this.setAttribute("aria-modal", "true");
74
+ }
75
+ if (!this.hasAttribute("aria-label")) {
76
+ this.setAttribute("aria-label", "Schedule a Tour");
77
+ }
78
+ }
79
+
67
80
  @property({ attribute: false })
68
81
  tourTypeOptions: LabeledOption[] = [];
69
82
  @property({ attribute: true })
@@ -749,8 +762,12 @@ export class TourScheduler extends LitElement {
749
762
  static styles = [tourSchedulerStyles, InputStyles];
750
763
 
751
764
  tourTypeMenu(): TemplateResult {
752
- return html`<h2 class="journey-header">Tour Type</h2>
753
- <div id="tour-type-menu">
765
+ return html`<h2 id="tour-type-heading" class="journey-header">Tour Type</h2>
766
+ <div
767
+ id="tour-type-menu"
768
+ role="radiogroup"
769
+ aria-labelledby="tour-type-heading"
770
+ >
754
771
  ${this.shouldShowTourType[TourType.Self]
755
772
  ? html` <tour-type-option
756
773
  heading="Take a tour"
@@ -933,10 +950,7 @@ export class TourScheduler extends LitElement {
933
950
  if (
934
951
  this.tourType === TourType.Guided &&
935
952
  this.escortedToursLink &&
936
- shouldOpenTourLink(
937
- this.tourType,
938
- this.escortedToursTypeOffered
939
- )
953
+ shouldOpenTourLink(this.tourType, this.escortedToursTypeOffered)
940
954
  ) {
941
955
  window.open(this.escortedToursLink, "_blank");
942
956
  return;
@@ -1054,8 +1068,7 @@ export class TourScheduler extends LitElement {
1054
1068
  return html` <button
1055
1069
  id="close-button"
1056
1070
  @click=${this.onCloseClicked}
1057
- aria-label="Close"
1058
- aria-describedby="close-button"
1071
+ aria-label="Close scheduler"
1059
1072
  >
1060
1073
  <svg
1061
1074
  width="19"
@@ -1445,14 +1458,14 @@ export class TourScheduler extends LitElement {
1445
1458
  <div id="scheduler-container">
1446
1459
  <div>
1447
1460
  <h2 class="journey-header">Reschedule Tour</h2>
1448
- <p class="explanation">
1461
+ <div class="explanation">
1449
1462
  You already have a tour scheduled. Would you like to
1450
1463
  reschedule?
1451
- </p>
1464
+ </div>
1452
1465
  </div>
1453
1466
  </div>
1454
1467
  <div id="tour-scheduler-footer">
1455
- <p class="explanation">
1468
+ <div class="explanation">
1456
1469
  We'll send a confirmation and any follow-ups to your email
1457
1470
  address, please reply to the email to make any appointment
1458
1471
  changes.
@@ -1464,7 +1477,7 @@ export class TourScheduler extends LitElement {
1464
1477
  orgSlug: this.orgSlug,
1465
1478
  clickingButtonText: "schedule tour",
1466
1479
  })}
1467
- </p>
1480
+ </div>
1468
1481
 
1469
1482
  <div class="reschedule-buttons-wrapper">
1470
1483
  <action-confirm-button
@@ -1506,7 +1519,7 @@ export class TourScheduler extends LitElement {
1506
1519
  </div>
1507
1520
  </div>
1508
1521
  <div id="tour-scheduler-footer">
1509
- <p class="explanation">
1522
+ <div class="explanation">
1510
1523
  We'll send a confirmation and any follow-ups to your email
1511
1524
  address, please reply to the email to make any appointment
1512
1525
  changes.
@@ -1518,7 +1531,7 @@ export class TourScheduler extends LitElement {
1518
1531
  orgSlug: this.orgSlug,
1519
1532
  clickingButtonText: "schedule tour",
1520
1533
  })}
1521
- </p>
1534
+ </div>
1522
1535
 
1523
1536
  <action-confirm-button
1524
1537
  id="schedule-bttn"
@@ -1575,10 +1588,10 @@ export class TourScheduler extends LitElement {
1575
1588
  ? html` <div id="scheduler-container">
1576
1589
  <div>
1577
1590
  <h2 class="journey-header">Reschedule Tour</h2>
1578
- <p class="explanation">
1591
+ <div class="explanation">
1579
1592
  You already have a tour scheduled. Would you like to
1580
1593
  reschedule?
1581
- </p>
1594
+ </div>
1582
1595
  </div>
1583
1596
  </div>
1584
1597
  <div id="tour-scheduler-footer">
@@ -67,17 +67,18 @@ export class TourTypeOption extends LitElement {
67
67
  color: #ffffff;
68
68
  }
69
69
 
70
- h1,
71
- h2 {
70
+ .heading,
71
+ .subtitle {
72
72
  font-size: 15px;
73
73
  margin: 0;
74
+ display: block;
74
75
  }
75
76
 
76
- h1 {
77
+ .heading {
77
78
  font-weight: 600;
78
79
  }
79
80
 
80
- h2 {
81
+ .subtitle {
81
82
  font-weight: 400;
82
83
  }
83
84
  `,
@@ -87,7 +88,10 @@ export class TourTypeOption extends LitElement {
87
88
  return html`
88
89
  <div
89
90
  class="tour-type-option"
91
+ role="radio"
90
92
  tabindex="0"
93
+ aria-checked=${this.selected ? "true" : "false"}
94
+ aria-label="${this.heading} ${this.subtitle}"
91
95
  style=${styleMap({
92
96
  background: this.selected ? this.primaryColor : undefined,
93
97
  })}
@@ -102,8 +106,8 @@ export class TourTypeOption extends LitElement {
102
106
  : this.foregroundColorOnSecondaryBackgroundColor,
103
107
  })}
104
108
  >
105
- <h1>${this.heading}</h1>
106
- <h2>${this.subtitle}</h2>
109
+ <span class="heading">${this.heading}</span>
110
+ <span class="subtitle">${this.subtitle}</span>
107
111
  </div>
108
112
  </div>
109
113
  </div>
@@ -4,6 +4,11 @@ import { customElement, property } from "lit/decorators.js";
4
4
 
5
5
  @customElement("action-confirm-button")
6
6
  export class ActionConfirmButton extends LitElement {
7
+ static shadowRootOptions: ShadowRootInit = {
8
+ ...LitElement.shadowRootOptions,
9
+ delegatesFocus: true,
10
+ };
11
+
7
12
  static styles = [
8
13
  css`
9
14
  .action-confirm-button {
@@ -104,7 +109,6 @@ export class ActionConfirmButton extends LitElement {
104
109
  @click=${!this.isLoading ? this.onClick : null}
105
110
  ?disabled=${this.disabled}
106
111
  style=${`height: ${this.height}; width: ${this.width};`}
107
- tabindex="0"
108
112
  >
109
113
  ${!this.isLoading
110
114
  ? this.text
@@ -1101,17 +1101,17 @@ export class Launcher extends LitElement {
1101
1101
  ? `EliseAI options: ${optionLabels.join(", ")}`
1102
1102
  : "EliseAI options";
1103
1103
  return html`
1104
- <nav class="vertical-pill-list" aria-label=${navAriaLabel}>
1105
- <div class="vertical-pill-list">
1106
- ${this.hasChatEnabledDesktop
1107
- ? html`<button
1108
- @click=${this.onClickMinimize}
1109
- class="minimize-button"
1110
- aria-label="Minimize"
1111
- >
1112
- <div class="chevron-down">${ChevronRightIcon("black")}</div>
1113
- </button>`
1114
- : ""}
1104
+ <div class="vertical-pill-list">
1105
+ ${this.hasChatEnabledDesktop
1106
+ ? html`<button
1107
+ @click=${this.onClickMinimize}
1108
+ class="minimize-button"
1109
+ aria-label="Minimize EliseAI widget"
1110
+ >
1111
+ <div class="chevron-down">${ChevronRightIcon("black")}</div>
1112
+ </button>`
1113
+ : ""}
1114
+ <nav class="vertical-pill-list" aria-label=${navAriaLabel}>
1115
1115
  ${pills.map((p) => p.pill)}
1116
1116
  ${this.overrideRentgrata && hasRentgrata()
1117
1117
  ? html`<button
@@ -1137,8 +1137,8 @@ export class Launcher extends LitElement {
1137
1137
  <div class="chevron-right">${ChevronRightIcon("black")}</div>
1138
1138
  </button>`
1139
1139
  : ""}
1140
- </div>
1141
- </nav>
1140
+ </nav>
1141
+ </div>
1142
1142
  `;
1143
1143
  };
1144
1144
 
@@ -204,7 +204,17 @@ export class MESelect extends LitElement {
204
204
  this.meSelect.style.color = "rgba(32, 32, 32, 1)";
205
205
  }
206
206
  };
207
+
208
+ private listboxId = `me-select-listbox-${Math.random()
209
+ .toString(36)
210
+ .slice(2, 9)}`;
211
+
212
+ private optionId = (index: number): string =>
213
+ `${this.listboxId}-opt-${index}`;
214
+
207
215
  render(): TemplateResult {
216
+ const activeIndex = this.activeOptionIndex;
217
+ const accessibleName = this.placeholder ?? "Select";
208
218
  return html`
209
219
  <div id="outer-select-container">
210
220
  <div
@@ -215,6 +225,14 @@ export class MESelect extends LitElement {
215
225
  ["webchat-font__mobile"]: isMobile(),
216
226
  })}
217
227
  tabindex="0"
228
+ role="combobox"
229
+ aria-haspopup="listbox"
230
+ aria-expanded=${this.isOpen ? "true" : "false"}
231
+ aria-controls=${this.listboxId}
232
+ aria-label=${accessibleName}
233
+ aria-activedescendant=${this.isOpen && activeIndex != null
234
+ ? this.optionId(activeIndex)
235
+ : ""}
218
236
  @click=${() => (this.isOpen = !this.isOpen)}
219
237
  @keydown="${(e: KeyboardEvent) => {
220
238
  switch (e.key) {
@@ -270,6 +288,7 @@ export class MESelect extends LitElement {
270
288
  >`
271
289
  : html` <input
272
290
  readonly
291
+ tabindex="-1"
273
292
  placeholder="${this.placeholder}"
274
293
  .value="${this.options.find((o) => o.value === this.value)
275
294
  ?.label ||
@@ -292,24 +311,27 @@ export class MESelect extends LitElement {
292
311
  </svg>
293
312
  </div>
294
313
  ${this.isOpen
295
- ? html`<ul>
314
+ ? html`<ul id=${this.listboxId} role="listbox">
296
315
  ${this.options.map(
297
- (option) =>
316
+ (option, index) =>
298
317
  html`<li
318
+ id=${this.optionId(index)}
319
+ role="option"
320
+ aria-selected=${this.value === option.value
321
+ ? "true"
322
+ : "false"}
299
323
  @click="${() => this.setSelectedOption(option)}"
300
- @keydown="${this.handleKeydown(["Enter", " "], () =>
301
- this.setSelectedOption(option)
302
- )}"
303
324
  @mousemove="${() => {
304
325
  this.activeOption = option;
326
+ this.activeOptionIndex = index;
305
327
  }}"
306
328
  @mouseleave="${() => {
307
329
  this.activeOption = null;
330
+ this.activeOptionIndex = null;
308
331
  }}"
309
332
  class="option ${classMap({
310
333
  active: this.activeOption === option,
311
334
  })}"
312
- tabindex="0"
313
335
  >
314
336
  ${option.label}
315
337
  </li>`
@@ -92,7 +92,18 @@ const formDisclaimer = ({
92
92
  recorded and used by a third party.
93
93
  </div>`;
94
94
  }
95
- return html``;
95
+ // Default: no email or phone entered yet. Still surface the privacy policy
96
+ // link so it's discoverable in the tab order before the user types.
97
+ return html` <div style=${styleMap(disclaimerStyles.container)}>
98
+ By clicking ${clickingButtonText}, you consent to this
99
+ <a
100
+ style=${styleMap(disclaimerStyles.link)}
101
+ href="http://bit.ly/me_privacy_policy"
102
+ target="_blank"
103
+ rel="noopener noreferrer"
104
+ >privacy policy</a
105
+ >.
106
+ </div>`;
96
107
  };
97
108
 
98
109
  export const getConsentPreChatDisclaimer = (