@ada-support/embed2 1.13.1 → 1.13.3

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.
@@ -11,6 +11,7 @@ interface Props {
11
11
  interface State {
12
12
  currentIndex: number;
13
13
  imageLoaded: boolean;
14
+ imageError: boolean;
14
15
  }
15
16
  export declare class LightboxOverlay extends Component<Props, State> {
16
17
  state: State;
@@ -20,6 +21,8 @@ export declare class LightboxOverlay extends Component<Props, State> {
20
21
  goToPrev: () => void;
21
22
  goToNext: () => void;
22
23
  handleImageLoad: () => void;
24
+ handleImageError: () => void;
25
+ handleOpenInNewTab: () => void;
23
26
  handleDownload: () => Promise<void>;
24
27
  handlePrint: () => Promise<void>;
25
28
  get currentImage(): LightboxImage | undefined;
@@ -17,6 +17,7 @@ type StartOptionsWithHostTelemetry = StartOptions & {
17
17
  };
18
18
  export declare function resolveHostTelemetryFromStartOptions(adaSettings: StartOptionsWithHostTelemetry, options?: {
19
19
  pathname?: string;
20
+ protocol?: string;
20
21
  }): HostTelemetryContext;
21
22
  export declare function serializeHostTelemetry(hostTelemetry: HostTelemetryContext): string;
22
23
  export declare function shouldPropagateHostTelemetry(hostTelemetry: HostTelemetryContext): boolean;
@@ -15919,7 +15919,7 @@ const client = new BrowserClient({
15919
15919
  return event;
15920
15920
  },
15921
15921
  environment: "production",
15922
- release: "1.13.1-955cc04",
15922
+ release: "1.13.3-cb98dc4",
15923
15923
  sampleRate: 0.25,
15924
15924
  autoSessionTracking: false,
15925
15925
  // Integrations don't seem to work with Sentry: https://github.com/getsentry/sentry-javascript/issues/2541
@@ -16509,7 +16509,7 @@ function getEmbedURL(_ref) {
16509
16509
  } else {
16510
16510
  host = `http://${handle}.localhost:${ports.localhost.default}`;
16511
16511
  }
16512
- return `${host}/embed/${frameName}/${"955cc04"}/index.html`;
16512
+ return `${host}/embed/${frameName}/${"cb98dc4"}/index.html`;
16513
16513
  }
16514
16514
  function constructQueryString(query) {
16515
16515
  return Object.keys(query).map(key => {
@@ -17697,9 +17697,9 @@ async function log(message, extra, options) {
17697
17697
  service: "embed",
17698
17698
  env: "production",
17699
17699
  embedVersion: 2,
17700
- version: "1.13.1",
17700
+ version: "1.13.3",
17701
17701
  isNpm: true,
17702
- commitHash: "955cc04"
17702
+ commitHash: "cb98dc4"
17703
17703
  }))
17704
17704
  });
17705
17705
  }
@@ -18880,7 +18880,8 @@ class LightboxOverlay extends preact_module_d {
18880
18880
  super(...arguments);
18881
18881
  _defineProperty(this, "state", {
18882
18882
  currentIndex: this.props.initialIndex,
18883
- imageLoaded: false
18883
+ imageLoaded: false,
18884
+ imageError: false
18884
18885
  });
18885
18886
  _defineProperty(this, "handleKeyDown", e => {
18886
18887
  if (e.key === "Escape") {
@@ -18894,13 +18895,15 @@ class LightboxOverlay extends preact_module_d {
18894
18895
  _defineProperty(this, "goToPrev", () => {
18895
18896
  this.setState(s => ({
18896
18897
  currentIndex: Math.max(0, s.currentIndex - 1),
18897
- imageLoaded: false
18898
+ imageLoaded: false,
18899
+ imageError: false
18898
18900
  }));
18899
18901
  });
18900
18902
  _defineProperty(this, "goToNext", () => {
18901
18903
  this.setState(s => ({
18902
18904
  currentIndex: Math.min(this.props.images.length - 1, s.currentIndex + 1),
18903
- imageLoaded: false
18905
+ imageLoaded: false,
18906
+ imageError: false
18904
18907
  }));
18905
18908
  });
18906
18909
  _defineProperty(this, "handleImageLoad", () => {
@@ -18908,6 +18911,22 @@ class LightboxOverlay extends preact_module_d {
18908
18911
  imageLoaded: true
18909
18912
  });
18910
18913
  });
18914
+ _defineProperty(this, "handleImageError", () => {
18915
+ this.setState({
18916
+ imageError: true,
18917
+ imageLoaded: false
18918
+ });
18919
+ });
18920
+ _defineProperty(this, "handleOpenInNewTab", () => {
18921
+ const {
18922
+ onClose
18923
+ } = this.props;
18924
+ const image = this.currentImage;
18925
+ if (image) {
18926
+ window.open(image.url, "_blank", "noopener,noreferrer");
18927
+ }
18928
+ onClose();
18929
+ });
18911
18930
  _defineProperty(this, "handleDownload", async () => {
18912
18931
  const image = this.currentImage;
18913
18932
  if (!image) {
@@ -18921,7 +18940,7 @@ class LightboxOverlay extends preact_module_d {
18921
18940
  link.click();
18922
18941
  URL.revokeObjectURL(objectUrl);
18923
18942
  } catch {
18924
- window.open(image.url);
18943
+ window.open(image.url, "_blank", "noopener,noreferrer");
18925
18944
  }
18926
18945
  });
18927
18946
  _defineProperty(this, "handlePrint", async () => {
@@ -18953,7 +18972,7 @@ class LightboxOverlay extends preact_module_d {
18953
18972
  URL.revokeObjectURL(objectUrl);
18954
18973
  }
18955
18974
  } catch {
18956
- window.open(image.url);
18975
+ window.open(image.url, "_blank", "noopener,noreferrer");
18957
18976
  }
18958
18977
  });
18959
18978
  }
@@ -18989,7 +19008,8 @@ class LightboxOverlay extends preact_module_d {
18989
19008
  } = this.props;
18990
19009
  const {
18991
19010
  currentIndex,
18992
- imageLoaded
19011
+ imageLoaded,
19012
+ imageError
18993
19013
  } = this.state;
18994
19014
  const {
18995
19015
  currentImage
@@ -19054,7 +19074,8 @@ class LightboxOverlay extends preact_module_d {
19054
19074
  flexDirection: "column",
19055
19075
  alignItems: "center"
19056
19076
  }
19057
- }, !imageLoaded && v("div", {
19077
+ }, !imageLoaded && !imageError && v("div", {
19078
+ "data-testid": "lightbox-spinner",
19058
19079
  style: {
19059
19080
  width: "40px",
19060
19081
  height: "40px",
@@ -19063,10 +19084,35 @@ class LightboxOverlay extends preact_module_d {
19063
19084
  borderRadius: "50%",
19064
19085
  animation: "ada-spin 0.8s linear infinite"
19065
19086
  }
19066
- }), currentImage && v("img", {
19087
+ }), imageError && v("div", {
19088
+ role: "alert",
19089
+ style: {
19090
+ color: "#ffffff",
19091
+ textAlign: "center",
19092
+ padding: "20px"
19093
+ }
19094
+ }, v("p", {
19095
+ style: {
19096
+ margin: "0 0 12px"
19097
+ }
19098
+ }, "Unable to load image"), v("button", {
19099
+ type: "button",
19100
+ onClick: this.handleOpenInNewTab,
19101
+ style: {
19102
+ padding: "8px 16px",
19103
+ background: "#ffffff",
19104
+ color: "#000000",
19105
+ border: "none",
19106
+ borderRadius: "6px",
19107
+ cursor: "pointer",
19108
+ fontFamily: FONT_FAMILY,
19109
+ fontSize: "14px"
19110
+ }
19111
+ }, "Open in new tab")), currentImage && !imageError && v("img", {
19067
19112
  src: currentImage.url,
19068
19113
  alt: currentImage.altText ?? "",
19069
19114
  onLoad: this.handleImageLoad,
19115
+ onError: this.handleImageError,
19070
19116
  style: {
19071
19117
  maxWidth: "100%",
19072
19118
  maxHeight: "80vh",
@@ -19123,6 +19169,19 @@ const SEMVER_TAG_VALUE_PATTERN = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/;
19123
19169
 
19124
19170
  // Private mobile-sdk handshake used only on the trusted /mobile-sdk-webview/ page.
19125
19171
 
19172
+ // `metaFields.sdkType` is a long-standing convention set by every legacy
19173
+ // mobile wrapper — iOS SDK (`"IOS"`), Android SDK (`"ANDROID"`), React Native
19174
+ // SDK (`"REACTNATIVE"`). The new Messaging wrappers pass the richer
19175
+ // `hostTelemetry` handshake instead, so this map is only consulted as a
19176
+ // legacy-attribution fallback.
19177
+ const LEGACY_SDK_TYPE_PLATFORM_MAP = {
19178
+ IOS: "ios",
19179
+ ANDROID: "android",
19180
+ REACTNATIVE: "react-native",
19181
+ "REACT-NATIVE": "react-native",
19182
+ REACT_NATIVE: "react-native"
19183
+ };
19184
+
19126
19185
  // Keep this normalization logic in sync with
19127
19186
  // chat/src/shared/services/host-telemetry.ts. Both sides normalize across the
19128
19187
  // embed/chat iframe boundary on purpose.
@@ -19234,20 +19293,58 @@ function isTrustedMobileSdkHostPage() {
19234
19293
  let pathname = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : window.location.pathname;
19235
19294
  return pathname === TRUSTED_MOBILE_SDK_PATH || pathname === TRUSTED_MOBILE_SDK_PATH.slice(0, -1);
19236
19295
  }
19296
+ function isHttpOrigin() {
19297
+ let protocol = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : window.location.protocol;
19298
+ return protocol === "http:" || protocol === "https:";
19299
+ }
19300
+ function resolveLegacySdkTypePlatform(metaFields) {
19301
+ const record = asRecord(metaFields);
19302
+ const raw = record === null || record === void 0 ? void 0 : record.sdkType;
19303
+ if (typeof raw !== "string") {
19304
+ return undefined;
19305
+ }
19306
+ return LEGACY_SDK_TYPE_PLATFORM_MAP[raw.trim().toUpperCase()];
19307
+ }
19308
+ function resolveLegacySdkTypeFingerprint(metaFields, trustedMobileContext) {
19309
+ if (!trustedMobileContext) {
19310
+ return undefined;
19311
+ }
19312
+ const hostPlatform = resolveLegacySdkTypePlatform(metaFields);
19313
+ if (!hostPlatform) {
19314
+ return undefined;
19315
+ }
19316
+ return {
19317
+ surface: "mobile",
19318
+ hostPlatform,
19319
+ webSdkOrigin: "legacy",
19320
+ mobileShell: "legacy-sdk"
19321
+ };
19322
+ }
19237
19323
  function resolveHostTelemetryFromStartOptions(adaSettings) {
19238
19324
  let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
19239
19325
  const trustedMobileSdkHostPage = isTrustedMobileSdkHostPage(options.pathname);
19326
+ // Non-http origins are assumed to be native WebView hosts (file://,
19327
+ // react-native asset URIs) — legacy AndroidSDK and react-native-sdk both
19328
+ // load a bundled `embed.html` from file://, so the trusted-path check alone
19329
+ // misses them. Gating sdkType attribution on this prevents a web customer
19330
+ // from incidentally tagging themselves as mobile via `metaFields.sdkType`.
19331
+ const trustedMobileContext = trustedMobileSdkHostPage || !isHttpOrigin(options.protocol);
19240
19332
  // Treat the presence of the hostTelemetry property as authoritative, even if
19241
19333
  // normalization fails, so broken new-wrapper payloads are not downgraded
19242
19334
  // into the legacy mobile-shell bucket.
19243
19335
  const hasExplicitHostTelemetry = trustedMobileSdkHostPage && Object.prototype.hasOwnProperty.call(adaSettings, "hostTelemetry");
19244
19336
  const explicit = hasExplicitHostTelemetry ? normalizeHostTelemetry(adaSettings.hostTelemetry) : undefined;
19245
- const webSdkOrigin = (explicit === null || explicit === void 0 ? void 0 : explicit.webSdkOrigin) ?? "legacy";
19246
- const hostPlatform = (explicit === null || explicit === void 0 ? void 0 : explicit.hostPlatform) ?? (trustedMobileSdkHostPage ? "unknown" : "web");
19247
- const surface = (explicit === null || explicit === void 0 ? void 0 : explicit.surface) ?? (trustedMobileSdkHostPage ? "mobile" : "browser");
19337
+ // Legacy wrappers (iOS SDK, AndroidSDK, react-native-sdk) all set
19338
+ // `metaFields.sdkType` before calling `adaEmbed.start(...)`. They do not
19339
+ // know about the newer `hostTelemetry` handshake, so this fingerprint is
19340
+ // the only way to attribute their traffic to the right platform.
19341
+ const legacyFingerprint = !hasExplicitHostTelemetry ? resolveLegacySdkTypeFingerprint(adaSettings.metaFields, trustedMobileContext) : undefined;
19342
+ const webSdkOrigin = (explicit === null || explicit === void 0 ? void 0 : explicit.webSdkOrigin) ?? (legacyFingerprint === null || legacyFingerprint === void 0 ? void 0 : legacyFingerprint.webSdkOrigin) ?? "legacy";
19343
+ const hostPlatform = (explicit === null || explicit === void 0 ? void 0 : explicit.hostPlatform) ?? (legacyFingerprint === null || legacyFingerprint === void 0 ? void 0 : legacyFingerprint.hostPlatform) ?? (trustedMobileSdkHostPage ? "unknown" : "web");
19344
+ const surface = (explicit === null || explicit === void 0 ? void 0 : explicit.surface) ?? (legacyFingerprint === null || legacyFingerprint === void 0 ? void 0 : legacyFingerprint.surface) ?? (trustedMobileSdkHostPage ? "mobile" : "browser");
19248
19345
  const mobilePackage = explicit === null || explicit === void 0 ? void 0 : explicit.mobilePackage;
19249
19346
  const mobileVersion = explicit === null || explicit === void 0 ? void 0 : explicit.mobileVersion;
19250
- const mobileShell = deriveMessagingMobileShell(mobilePackage) ?? (explicit === null || explicit === void 0 ? void 0 : explicit.mobileShell) ?? (!hasExplicitHostTelemetry ? deriveLegacyMobileShell(surface, hostPlatform) : undefined);
19347
+ const mobileShell = deriveMessagingMobileShell(mobilePackage) ?? (explicit === null || explicit === void 0 ? void 0 : explicit.mobileShell) ?? (legacyFingerprint === null || legacyFingerprint === void 0 ? void 0 : legacyFingerprint.mobileShell) ?? (!hasExplicitHostTelemetry ? deriveLegacyMobileShell(surface, hostPlatform) : undefined);
19251
19348
  return host_telemetry_objectSpread(host_telemetry_objectSpread(host_telemetry_objectSpread({
19252
19349
  surface,
19253
19350
  hostPlatform,
@@ -19500,7 +19597,7 @@ class ChatFrame extends preact_module_d {
19500
19597
  log("Chat frame mount", {
19501
19598
  handle,
19502
19599
  chatUrl: this.url,
19503
- embedVersion: "955cc04".slice(0, 7),
19600
+ embedVersion: "cb98dc4".slice(0, 7),
19504
19601
  embedSettings: adaSettings
19505
19602
  });
19506
19603
 
@@ -19588,7 +19685,7 @@ class ChatFrame extends preact_module_d {
19588
19685
  const hostPageUrlParams = new URL(window.location.href).searchParams;
19589
19686
  const smsToken = hostPageUrlParams.get("adaSMSToken");
19590
19687
  const queryParams = {
19591
- embedVersion: "955cc04".slice(0, 7),
19688
+ embedVersion: "cb98dc4".slice(0, 7),
19592
19689
  greeting,
19593
19690
  language,
19594
19691
  skipGreeting,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ada-support/embed2",
3
- "version": "1.13.1",
3
+ "version": "1.13.3",
4
4
  "description": "",
5
5
  "main": "dist/npm-entry",
6
6
  "typings": "dist/npm-entry/index-npm.d.ts",
@@ -122,4 +122,4 @@
122
122
  "publishConfig": {
123
123
  "access": "public"
124
124
  }
125
- }
125
+ }