@ada-support/embed2 1.14.5 → 1.14.7

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.
@@ -10,6 +10,15 @@ export interface EmbedRequestPayloadByEvent {
10
10
  duration: number | null;
11
11
  delay?: number;
12
12
  responseId?: string | null;
13
+ image?: {
14
+ url: string;
15
+ alt: string;
16
+ };
17
+ cta?: {
18
+ label: string;
19
+ url: string;
20
+ openInNewTab: boolean;
21
+ };
13
22
  };
14
23
  DELETE_HISTORY: undefined;
15
24
  DISPATCH: StoreDispatchPayload;
@@ -13,6 +13,15 @@ export interface CurrentIntro {
13
13
  style: string;
14
14
  duration: number | null;
15
15
  delay: number;
16
+ image?: {
17
+ url: string;
18
+ alt: string;
19
+ };
20
+ cta?: {
21
+ label: string;
22
+ url: string;
23
+ openInNewTab: boolean;
24
+ };
16
25
  }
17
26
  export interface Features {
18
27
  "ui_customization"?: boolean;
@@ -16125,7 +16125,7 @@ const client = new BrowserClient({
16125
16125
  return event;
16126
16126
  },
16127
16127
  environment: "production",
16128
- release: "1.14.5-b0ec618",
16128
+ release: "1.14.7-4506c4f",
16129
16129
  sampleRate: 0.25,
16130
16130
  autoSessionTracking: false,
16131
16131
  // Integrations don't seem to work with Sentry: https://github.com/getsentry/sentry-javascript/issues/2541
@@ -16751,7 +16751,7 @@ function getEmbedURL(_ref) {
16751
16751
  } else {
16752
16752
  host = `http://${handle}.localhost:${ports.localhost.default}`;
16753
16753
  }
16754
- return `${host}/embed/${frameName}/${"b0ec618"}/index.html`;
16754
+ return `${host}/embed/${frameName}/${"4506c4f"}/index.html`;
16755
16755
  }
16756
16756
  function constructQueryString(query) {
16757
16757
  return Object.keys(query).map(key => {
@@ -17538,9 +17538,9 @@ async function log(message, extra, options) {
17538
17538
  service: "embed",
17539
17539
  env: "production",
17540
17540
  embedVersion: 2,
17541
- version: "1.14.5",
17541
+ version: "1.14.7",
17542
17542
  isNpm: true,
17543
- commitHash: "b0ec618"
17543
+ commitHash: "4506c4f"
17544
17544
  }))
17545
17545
  });
17546
17546
  }
@@ -18685,6 +18685,34 @@ function proactiveShownWithinFrequency(proactiveConversationKey, frequency, hand
18685
18685
  return false;
18686
18686
  }
18687
18687
  }
18688
+
18689
+ // A proactive only fires when `now` is within its optional scheduling window.
18690
+ // Bounds are absolute ISO 8601 UTC instants authored in the dashboard; either
18691
+ // may be unset for an open-ended window. This mirrors the declarative campaign
18692
+ // datetime gating: the start is after-inclusive and the end is before-exclusive,
18693
+ // evaluated through the shared trigger-condition evaluator so the semantics stay
18694
+ // identical across both surfaces.
18695
+ function isWithinSchedule(scheduleStart, scheduleEnd) {
18696
+ const now = new Date();
18697
+ const buildCondition = (operator, datetime) => ({
18698
+ type: "datetime",
18699
+ // Bounds are absolute UTC instants (the stored datetime carries a `Z`
18700
+ // offset). `timezone` is metadata the evaluator doesn't consult, but label
18701
+ // it UTC to match the data and stay correct if the evaluator ever honors it.
18702
+ timezone: "UTC",
18703
+ condition: {
18704
+ operator,
18705
+ datetime
18706
+ }
18707
+ });
18708
+ if (scheduleStart && !evalDatetimeTriggerCondition(buildCondition("after-inclusive", scheduleStart), now)) {
18709
+ return false;
18710
+ }
18711
+ if (scheduleEnd && !evalDatetimeTriggerCondition(buildCondition("before-exclusive", scheduleEnd), now)) {
18712
+ return false;
18713
+ }
18714
+ return true;
18715
+ }
18688
18716
  function addProactiveToStorageString(oldStorageValue, proactiveConversationId) {
18689
18717
  return oldStorageValue ? `${oldStorageValue},${proactiveConversationId}` : proactiveConversationId;
18690
18718
  }
@@ -18705,6 +18733,32 @@ function recordProactiveTrigger(proactiveConversationKey, frequency, handle) {
18705
18733
  break;
18706
18734
  }
18707
18735
  }
18736
+
18737
+ // Rich content (image + single CTA) is optional. The image is keyed by
18738
+ // language; fall back to the first language by sorted key (the URL is shared
18739
+ // across languages — only the alt text is translated — so the fallback is
18740
+ // deterministic rather than relying on object key order).
18741
+ function extractRichContent(proactiveConversation, language) {
18742
+ var _images$language, _images$fallbackLangu;
18743
+ const {
18744
+ images,
18745
+ ctas
18746
+ } = proactiveConversation;
18747
+ const fallbackLanguage = images ? Object.keys(images).sort()[0] : undefined;
18748
+ const imageConfig = (images === null || images === void 0 ? void 0 : (_images$language = images[language]) === null || _images$language === void 0 ? void 0 : _images$language[0]) ?? (fallbackLanguage ? images === null || images === void 0 ? void 0 : (_images$fallbackLangu = images[fallbackLanguage]) === null || _images$fallbackLangu === void 0 ? void 0 : _images$fallbackLangu[0] : undefined);
18749
+ const ctaConfig = ctas === null || ctas === void 0 ? void 0 : ctas[0];
18750
+ return {
18751
+ image: imageConfig ? {
18752
+ url: imageConfig.url,
18753
+ alt: imageConfig.alt
18754
+ } : undefined,
18755
+ cta: ctaConfig ? {
18756
+ label: ctaConfig.cta_label,
18757
+ url: ctaConfig.cta_url,
18758
+ openInNewTab: ctaConfig.cta_open_in_new_tab
18759
+ } : undefined
18760
+ };
18761
+ }
18708
18762
  function proactiveTriggerImpl(_ref) {
18709
18763
  let {
18710
18764
  proactiveConversation,
@@ -18728,13 +18782,19 @@ function proactiveTriggerImpl(_ref) {
18728
18782
  duration,
18729
18783
  delay,
18730
18784
  frequency,
18731
- active
18785
+ active,
18786
+ schedule_start: scheduleStart,
18787
+ schedule_end: scheduleEnd
18732
18788
  } = proactiveConversation.modality_config.chat;
18733
18789
  let proactiveMessage = proactiveConversation.messages[language][0];
18734
18790
  if (!active) {
18735
18791
  warn("Proactive message is not active");
18736
18792
  return;
18737
18793
  }
18794
+ if (!isWithinSchedule(scheduleStart, scheduleEnd)) {
18795
+ warn("Proactive message is outside its scheduled window");
18796
+ return;
18797
+ }
18738
18798
  if (isTemplate) {
18739
18799
  if (Object.keys(params).length === 0) {
18740
18800
  warn("Proactive message is a template but no parameters were provided");
@@ -18768,12 +18828,18 @@ function proactiveTriggerImpl(_ref) {
18768
18828
  key: messageKey,
18769
18829
  params
18770
18830
  });
18831
+ const {
18832
+ image,
18833
+ cta
18834
+ } = extractRichContent(proactiveConversation, language);
18771
18835
  clearProactiveConversation();
18772
18836
  const localChannel = messageService.getChannel("local");
18773
18837
  localChannel.postMessage(CREATE_PROACTIVE, {
18774
18838
  body: proactiveMessage,
18775
18839
  duration,
18776
- delay
18840
+ delay,
18841
+ image,
18842
+ cta
18777
18843
  });
18778
18844
  log("Proactive message displayed", {
18779
18845
  handle,
@@ -20174,7 +20240,7 @@ class ChatFrame extends d {
20174
20240
  log("Chat frame mount", {
20175
20241
  handle,
20176
20242
  chatUrl: this.url,
20177
- embedVersion: "b0ec618".slice(0, 7),
20243
+ embedVersion: "4506c4f".slice(0, 7),
20178
20244
  embedSettings: adaSettings
20179
20245
  });
20180
20246
 
@@ -20262,7 +20328,7 @@ class ChatFrame extends d {
20262
20328
  const hostPageUrlParams = new URL(window.location.href).searchParams;
20263
20329
  const smsToken = hostPageUrlParams.get("adaSMSToken");
20264
20330
  const queryParams = {
20265
- embedVersion: "b0ec618".slice(0, 7),
20331
+ embedVersion: "4506c4f".slice(0, 7),
20266
20332
  greeting,
20267
20333
  language,
20268
20334
  skipGreeting,
@@ -21084,8 +21150,6 @@ class IntroFrame extends d {
21084
21150
  return `display: none`;
21085
21151
  }
21086
21152
  const buttonSize = client.chat_button.size;
21087
- const INTRO_BUTTON_PADDING = 16;
21088
- const introPositionRight = INTRO_BUTTON_PADDING + buttonSize;
21089
21153
  const stylesForHiding = `
21090
21154
  visibility: "hidden";
21091
21155
  top: -9999px !important;
@@ -21093,19 +21157,14 @@ class IntroFrame extends d {
21093
21157
  `;
21094
21158
  const styles = `
21095
21159
  position: fixed;
21096
- ${getAlignment(adaSettings)}: ${introPositionRight}px;
21097
- bottom: 8px;
21098
- z-index: 10000;
21099
- max-height: 300px;
21100
- max-width: 250px;
21160
+ ${getAlignment(adaSettings)}: 0;
21161
+ bottom: ${buttonSize - 20}px;
21162
+ z-index: 9999;
21163
+ max-width: 350px;
21101
21164
  opacity: ${this.isShown ? "1" : "0"};
21102
21165
  height: ${introDimensions.height}px;
21103
21166
  width: ${introDimensions.width}px;
21104
- max-height: auto;
21105
- max-width: 350px;
21106
- z-index: 9999;
21107
- ${getAlignment(adaSettings)}: 0;
21108
- bottom: ${buttonSize - 20}px;
21167
+ transition: height 300ms ease;
21109
21168
  `;
21110
21169
  if (!this.isShown) {
21111
21170
  return styles + stylesForHiding;
@@ -21761,7 +21820,7 @@ class Container extends d {
21761
21820
  let [key, conversation] = _ref;
21762
21821
  const chatConfig = conversation.modality_config.chat;
21763
21822
  const isTemplate = conversation.is_template;
21764
- if (chatConfig.active && !isTemplate && evaluateUrlTriggerConditions(chatConfig.url_trigger_conditions, currentUrl)) {
21823
+ if (chatConfig.active && !isTemplate && isWithinSchedule(chatConfig.schedule_start, chatConfig.schedule_end) && evaluateUrlTriggerConditions(chatConfig.url_trigger_conditions, currentUrl)) {
21765
21824
  this.handleProactiveTrigger(Container_objectSpread({
21766
21825
  key
21767
21826
  }, conversation), "url");
@@ -22025,7 +22084,9 @@ class Container extends d {
22025
22084
  const {
22026
22085
  body,
22027
22086
  duration,
22028
- delay
22087
+ delay,
22088
+ image,
22089
+ cta
22029
22090
  } = payload;
22030
22091
  const EXTRA_PROACTIVE_DELAY = 1000;
22031
22092
  this.setState({
@@ -22041,7 +22102,9 @@ class Container extends d {
22041
22102
  // Not just duration || null because we want to preserve 0 duration
22042
22103
  duration: duration || duration === 0 ? duration : null,
22043
22104
  style: "Text",
22044
- response_id: ""
22105
+ response_id: "",
22106
+ image,
22107
+ cta
22045
22108
  }
22046
22109
  }));
22047
22110
  await setGlobalState({
@@ -1,6 +1,7 @@
1
1
  import type { StartOptions } from "@ada-support/embed-types";
2
2
  import type { MessageService } from "client/lib/message-service";
3
3
  import type { ProactiveConversation, ProactiveConversationTriggerMethod, ProactiveConversationUrlTriggerConditions, RecentProactiveConversationConfig } from "./types";
4
+ export declare function isWithinSchedule(scheduleStart?: string | null, scheduleEnd?: string | null): boolean;
4
5
  export declare function proactiveTriggerImpl({ proactiveConversation, triggerMethod, adaSettings, messageService, language, setRecentProactiveConversationConfig, clearProactiveConversation, }: {
5
6
  proactiveConversation: ProactiveConversation;
6
7
  triggerMethod: ProactiveConversationTriggerMethod | null;
@@ -1,4 +1,13 @@
1
1
  export type ProactiveConversationUrlTriggerConditions = UrlTriggerCondition[] | null;
2
+ export interface ProactiveConversationImage {
3
+ url: string;
4
+ alt: string;
5
+ }
6
+ export interface ProactiveConversationCta {
7
+ cta_label: string;
8
+ cta_url: string;
9
+ cta_open_in_new_tab: boolean;
10
+ }
2
11
  export interface ProactiveConversation {
3
12
  messages: {
4
13
  [language: string]: string[];
@@ -10,11 +19,17 @@ export interface ProactiveConversation {
10
19
  delay: number;
11
20
  duration: number;
12
21
  frequency: ProactiveConversationFrequency;
22
+ schedule_start?: string | null;
23
+ schedule_end?: string | null;
13
24
  };
14
25
  };
15
26
  is_template: boolean;
16
27
  params?: Record<string, string>;
17
28
  key?: string;
29
+ images?: {
30
+ [language: string]: ProactiveConversationImage[];
31
+ };
32
+ ctas?: ProactiveConversationCta[];
18
33
  }
19
34
  export interface ProactiveConversations {
20
35
  [messageKey: string]: ProactiveConversation;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ada-support/embed2",
3
- "version": "1.14.5",
3
+ "version": "1.14.7",
4
4
  "description": "",
5
5
  "main": "dist/npm-entry",
6
6
  "typings": "dist/npm-entry/index-npm.d.ts",