@envive-ai/react-widgets-v3 0.3.12 → 0.3.14

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 (91) hide show
  1. package/dist/CXIntegration/implementations/useEightByEightUnifiedCXButton.cjs +54 -0
  2. package/dist/CXIntegration/implementations/useEightByEightUnifiedCXButton.js +53 -0
  3. package/dist/CXIntegration/implementations/useHelpScoutUnifiedCXButton.cjs +65 -0
  4. package/dist/CXIntegration/implementations/useHelpScoutUnifiedCXButton.js +64 -0
  5. package/dist/CXIntegration/implementations/useTalkdeskUnifiedCXButton.cjs +64 -0
  6. package/dist/CXIntegration/implementations/useTalkdeskUnifiedCXButton.js +63 -0
  7. package/dist/CXIntegration/implementations/useZendeskUnifiedCXButton.cjs +2 -2
  8. package/dist/CXIntegration/implementations/useZendeskUnifiedCXButton.js +2 -2
  9. package/dist/CXIntegration/types.cjs +3 -0
  10. package/dist/CXIntegration/types.js +3 -0
  11. package/dist/CXIntegration/utils/functions.cjs +6 -0
  12. package/dist/CXIntegration/utils/functions.js +6 -0
  13. package/dist/hocs/withBaseWidget/withBaseWidget.d.cts +2 -2
  14. package/dist/packages/widgets/dist/SearchResults/SearchResults.d.ts +2 -2
  15. package/dist/packages/widgets/dist/SearchResults/SearchResultsWidget.d.ts +2 -2
  16. package/dist/packages/widgets/dist/SearchZeroState/SearchZeroStateWidget.d.ts +2 -2
  17. package/dist/packages/widgets/dist/SuggestionBar/SuggestionBar.d.ts +2 -2
  18. package/dist/widgets/ChatPreviewComparisonWidget/ChatPreviewComparisonWidget.d.cts +3 -3
  19. package/dist/widgets/ChatPreviewComparisonWidget/ChatPreviewComparisonWidget.d.ts +3 -3
  20. package/dist/widgets/ChatPreviewLoadingWidget/ChatPreviewLoadingWidget.d.cts +3 -3
  21. package/dist/widgets/ChatPreviewWidget/ChatPreviewWidget.d.cts +3 -3
  22. package/dist/widgets/ChatPreviewWidget/ChatPreviewWidget.d.ts +3 -3
  23. package/dist/widgets/FloatingChatWidget/FloatingChatWidget.d.cts +2 -2
  24. package/dist/widgets/FloatingChatWidget/FloatingChatWidget.d.ts +2 -2
  25. package/dist/widgets/FullPageSalesAgentWidget/FullPageSalesAgentWidget.d.cts +2 -2
  26. package/dist/widgets/FullPageSalesAgentWidget/FullPageSalesAgentWidget.d.ts +2 -2
  27. package/dist/widgets/ProductCardWidget/ProductCardWidget.cjs +19 -3
  28. package/dist/widgets/ProductCardWidget/ProductCardWidget.d.cts +2 -2
  29. package/dist/widgets/ProductCardWidget/ProductCardWidget.d.ts +2 -2
  30. package/dist/widgets/ProductCardWidget/ProductCardWidget.js +20 -4
  31. package/dist/widgets/PromptButtonCarouselWithImageWidget/PromptButtonCarouselWithImageWidget.cjs +10 -0
  32. package/dist/widgets/PromptButtonCarouselWithImageWidget/PromptButtonCarouselWithImageWidget.d.cts +3 -3
  33. package/dist/widgets/PromptButtonCarouselWithImageWidget/PromptButtonCarouselWithImageWidget.d.ts +3 -3
  34. package/dist/widgets/PromptButtonCarouselWithImageWidget/PromptButtonCarouselWithImageWidget.js +12 -2
  35. package/dist/widgets/PromptCarouselWidget/PromptCarouselWidget.cjs +2 -9
  36. package/dist/widgets/PromptCarouselWidget/PromptCarouselWidget.d.cts +2 -2
  37. package/dist/widgets/PromptCarouselWidget/PromptCarouselWidget.d.ts +2 -2
  38. package/dist/widgets/PromptCarouselWidget/PromptCarouselWidget.js +1 -8
  39. package/dist/widgets/SocialProofFlowWidget/SocialProofFlowWidget.cjs +8 -8
  40. package/dist/widgets/SocialProofFlowWidget/SocialProofFlowWidget.d.cts +2 -2
  41. package/dist/widgets/SocialProofFlowWidget/SocialProofFlowWidget.d.ts +2 -2
  42. package/dist/widgets/SocialProofFlowWidget/SocialProofFlowWidget.js +8 -8
  43. package/dist/widgets/SocialProofWidget/SocialProofWidget.cjs +10 -0
  44. package/dist/widgets/SocialProofWidget/SocialProofWidget.d.cts +3 -3
  45. package/dist/widgets/SocialProofWidget/SocialProofWidget.d.ts +3 -3
  46. package/dist/widgets/SocialProofWidget/SocialProofWidget.js +12 -2
  47. package/dist/widgets/TitledPromptCarouselWidget/TitledPromptCarouselWidget.cjs +11 -0
  48. package/dist/widgets/TitledPromptCarouselWidget/TitledPromptCarouselWidget.d.cts +2 -2
  49. package/dist/widgets/TitledPromptCarouselWidget/TitledPromptCarouselWidget.d.ts +2 -2
  50. package/dist/widgets/TitledPromptCarouselWidget/TitledPromptCarouselWidget.js +12 -1
  51. package/dist/widgets/TypingAnimationFlowWidget/TypingAnimationFlowWidget.cjs +8 -8
  52. package/dist/widgets/TypingAnimationFlowWidget/TypingAnimationFlowWidget.d.cts +2 -2
  53. package/dist/widgets/TypingAnimationFlowWidget/TypingAnimationFlowWidget.d.ts +2 -2
  54. package/dist/widgets/TypingAnimationFlowWidget/TypingAnimationFlowWidget.js +8 -8
  55. package/dist/widgets/TypingAnimationWidget/TypingAnimationWidget.cjs +23 -3
  56. package/dist/widgets/TypingAnimationWidget/TypingAnimationWidget.d.cts +3 -3
  57. package/dist/widgets/TypingAnimationWidget/TypingAnimationWidget.d.ts +3 -3
  58. package/dist/widgets/TypingAnimationWidget/TypingAnimationWidget.js +24 -4
  59. package/dist/widgets/dist/SearchResults/SearchResults.d.cts +2 -2
  60. package/dist/widgets/dist/SearchResults/SearchResultsWidget.d.cts +2 -2
  61. package/dist/widgets/dist/SearchZeroState/SearchZeroStateWidget.d.cts +2 -2
  62. package/dist/widgets/dist/SuggestionBar/SuggestionBar.d.cts +2 -2
  63. package/dist/widgets/utils/functions.cjs +9 -0
  64. package/dist/widgets/utils/functions.js +9 -1
  65. package/package.json +1 -1
  66. package/src/CXIntegration/implementations/useEightByEightUnifiedCXButton.ts +91 -0
  67. package/src/CXIntegration/implementations/useHelpScoutUnifiedCXButton.ts +108 -0
  68. package/src/CXIntegration/implementations/useTalkdeskUnifiedCXButton.ts +94 -0
  69. package/src/CXIntegration/implementations/useZendeskUnifiedCXButton.ts +4 -2
  70. package/src/CXIntegration/types.ts +3 -0
  71. package/src/CXIntegration/utils/functions.ts +12 -0
  72. package/src/hocs/withBaseWidget/__tests__/withBaseWidget.test.tsx +15 -3
  73. package/src/widgets/ChatPreviewWidget/__tests__/ChatPreviewWidget.test.tsx +114 -0
  74. package/src/widgets/FloatingChatWidget/__tests__/FloatingChatWidget.test.tsx +119 -0
  75. package/src/widgets/ProductCardWidget/ProductCardWidget.tsx +15 -3
  76. package/src/widgets/ProductCardWidget/__tests__/ProductCardWidget.test.tsx +144 -0
  77. package/src/widgets/PromptButtonCarouselWithImageWidget/PromptButtonCarouselWithImageWidget.tsx +12 -1
  78. package/src/widgets/PromptButtonCarouselWithImageWidget/__tests__/PromptButtonCarouselWithImageWidget.test.tsx +179 -0
  79. package/src/widgets/PromptCarouselWidget/PromptCarouselWidget.tsx +1 -14
  80. package/src/widgets/PromptCarouselWidget/__tests__/PromptCarouselWidget.test.tsx +150 -0
  81. package/src/widgets/SocialProofFlowWidget/SocialProofFlowWidget.tsx +12 -12
  82. package/src/widgets/SocialProofWidget/SocialProofWidget.tsx +12 -1
  83. package/src/widgets/SocialProofWidget/__tests__/SocialProofWidget.test.tsx +184 -0
  84. package/src/widgets/TitledPromptCarouselWidget/TitledPromptCarouselWidget.tsx +12 -0
  85. package/src/widgets/TitledPromptCarouselWidget/__tests__/TitledPromptCarouselWidget.test.tsx +150 -0
  86. package/src/widgets/TypingAnimationFlowWidget/TypingAnimationFlowWidget.tsx +12 -12
  87. package/src/widgets/TypingAnimationWidget/TypingAnimationWidget.tsx +19 -2
  88. package/src/widgets/TypingAnimationWidget/__tests__/TypingAnimationWidget.test.tsx +163 -0
  89. package/src/widgets/__tests__/testUtils.tsx +63 -0
  90. package/src/widgets/__tests__/trackEventCanary.test.ts +45 -0
  91. package/src/widgets/utils/functions.ts +16 -0
@@ -11,21 +11,21 @@ let __envive_ai_react_toolkit_v3_ChatPreviewLoading = require("@envive-ai/react-
11
11
  //#region src/widgets/TypingAnimationFlowWidget/TypingAnimationFlowWidget.tsx
12
12
  const TypingAnimationFlowWidget = ({ widgetConfigId }) => {
13
13
  const { userHasInteractedValue, userHasNotInteractedValue, isLoadingValue, isProductComparisonValue } = require_useGetWidgetStatus.default();
14
- if (userHasInteractedValue) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_ChatPreviewWidget.ChatPreviewWidgetWithBaseWidget, {
14
+ if (userHasInteractedValue && isLoadingValue) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_ChatPreviewLoadingWidget.ChatPreviewLoadingWidgetWithBaseWidget, {
15
15
  widgetConfigId,
16
- widgetType: __envive_ai_react_hooks_contexts_typesV3.WidgetTypeV3.ChatPreviewV3
16
+ widgetType: __envive_ai_react_hooks_contexts_typesV3.WidgetTypeV3.ChatPreviewLoadingV3
17
17
  });
18
- if (userHasNotInteractedValue) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_TypingAnimationWidget.TypingAnimationWithBaseWidget, {
18
+ if (userHasInteractedValue && isProductComparisonValue) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_ChatPreviewComparisonWidget.ChatPreviewComparisonWidgetWithBaseWidget, {
19
19
  widgetConfigId,
20
- widgetType: __envive_ai_react_hooks_contexts_typesV3.WidgetTypeV3.TypingAnimationV3
20
+ widgetType: __envive_ai_react_hooks_contexts_typesV3.WidgetTypeV3.ChatPreviewComparisonV3
21
21
  });
22
- if (isLoadingValue) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_ChatPreviewLoadingWidget.ChatPreviewLoadingWidgetWithBaseWidget, {
22
+ if (userHasInteractedValue) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_ChatPreviewWidget.ChatPreviewWidgetWithBaseWidget, {
23
23
  widgetConfigId,
24
- widgetType: __envive_ai_react_hooks_contexts_typesV3.WidgetTypeV3.ChatPreviewLoadingV3
24
+ widgetType: __envive_ai_react_hooks_contexts_typesV3.WidgetTypeV3.ChatPreviewV3
25
25
  });
26
- if (isProductComparisonValue) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_ChatPreviewComparisonWidget.ChatPreviewComparisonWidgetWithBaseWidget, {
26
+ if (userHasNotInteractedValue) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_TypingAnimationWidget.TypingAnimationWithBaseWidget, {
27
27
  widgetConfigId,
28
- widgetType: __envive_ai_react_hooks_contexts_typesV3.WidgetTypeV3.ChatPreviewComparisonV3
28
+ widgetType: __envive_ai_react_hooks_contexts_typesV3.WidgetTypeV3.TypingAnimationV3
29
29
  });
30
30
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__envive_ai_react_toolkit_v3_ChatPreviewLoading.ChatPreviewLoading, { fullIsLoading: true });
31
31
  };
@@ -1,4 +1,4 @@
1
- import * as react_jsx_runtime1 from "react/jsx-runtime";
1
+ import * as react_jsx_runtime0 from "react/jsx-runtime";
2
2
 
3
3
  //#region src/widgets/TypingAnimationFlowWidget/TypingAnimationFlowWidget.d.ts
4
4
  interface TypingAnimationFlowWidgetProps {
@@ -7,7 +7,7 @@ interface TypingAnimationFlowWidgetProps {
7
7
  declare const TypingAnimationFlowWidget: {
8
8
  ({
9
9
  widgetConfigId
10
- }: TypingAnimationFlowWidgetProps): react_jsx_runtime1.JSX.Element;
10
+ }: TypingAnimationFlowWidgetProps): react_jsx_runtime0.JSX.Element;
11
11
  displayName: string;
12
12
  };
13
13
  //#endregion
@@ -1,4 +1,4 @@
1
- import * as react_jsx_runtime8 from "react/jsx-runtime";
1
+ import * as react_jsx_runtime1 from "react/jsx-runtime";
2
2
 
3
3
  //#region src/widgets/TypingAnimationFlowWidget/TypingAnimationFlowWidget.d.ts
4
4
  interface TypingAnimationFlowWidgetProps {
@@ -7,7 +7,7 @@ interface TypingAnimationFlowWidgetProps {
7
7
  declare const TypingAnimationFlowWidget: {
8
8
  ({
9
9
  widgetConfigId
10
- }: TypingAnimationFlowWidgetProps): react_jsx_runtime8.JSX.Element;
10
+ }: TypingAnimationFlowWidgetProps): react_jsx_runtime1.JSX.Element;
11
11
  displayName: string;
12
12
  };
13
13
  //#endregion
@@ -10,21 +10,21 @@ import { ChatPreviewLoading } from "@envive-ai/react-toolkit-v3/ChatPreviewLoadi
10
10
  //#region src/widgets/TypingAnimationFlowWidget/TypingAnimationFlowWidget.tsx
11
11
  const TypingAnimationFlowWidget = ({ widgetConfigId }) => {
12
12
  const { userHasInteractedValue, userHasNotInteractedValue, isLoadingValue, isProductComparisonValue } = useGetWidgetStatus_default();
13
- if (userHasInteractedValue) return /* @__PURE__ */ jsx(ChatPreviewWidgetWithBaseWidget, {
13
+ if (userHasInteractedValue && isLoadingValue) return /* @__PURE__ */ jsx(ChatPreviewLoadingWidgetWithBaseWidget, {
14
14
  widgetConfigId,
15
- widgetType: WidgetTypeV3.ChatPreviewV3
15
+ widgetType: WidgetTypeV3.ChatPreviewLoadingV3
16
16
  });
17
- if (userHasNotInteractedValue) return /* @__PURE__ */ jsx(TypingAnimationWithBaseWidget, {
17
+ if (userHasInteractedValue && isProductComparisonValue) return /* @__PURE__ */ jsx(ChatPreviewComparisonWidgetWithBaseWidget, {
18
18
  widgetConfigId,
19
- widgetType: WidgetTypeV3.TypingAnimationV3
19
+ widgetType: WidgetTypeV3.ChatPreviewComparisonV3
20
20
  });
21
- if (isLoadingValue) return /* @__PURE__ */ jsx(ChatPreviewLoadingWidgetWithBaseWidget, {
21
+ if (userHasInteractedValue) return /* @__PURE__ */ jsx(ChatPreviewWidgetWithBaseWidget, {
22
22
  widgetConfigId,
23
- widgetType: WidgetTypeV3.ChatPreviewLoadingV3
23
+ widgetType: WidgetTypeV3.ChatPreviewV3
24
24
  });
25
- if (isProductComparisonValue) return /* @__PURE__ */ jsx(ChatPreviewComparisonWidgetWithBaseWidget, {
25
+ if (userHasNotInteractedValue) return /* @__PURE__ */ jsx(TypingAnimationWithBaseWidget, {
26
26
  widgetConfigId,
27
- widgetType: WidgetTypeV3.ChatPreviewComparisonV3
27
+ widgetType: WidgetTypeV3.TypingAnimationV3
28
28
  });
29
29
  return /* @__PURE__ */ jsx(ChatPreviewLoading, { fullIsLoading: true });
30
30
  };
@@ -1,6 +1,7 @@
1
1
  const require_rolldown_runtime = require('../../_virtual/rolldown_runtime.cjs');
2
2
  const require_withBaseWidget = require('../../hocs/withBaseWidget/withBaseWidget.cjs');
3
3
  require('../../hocs/withBaseWidget/index.cjs');
4
+ const require_functions = require('../utils/functions.cjs');
4
5
  let react = require("react");
5
6
  let __envive_ai_react_hooks_contexts_amplitudeContext = require("@envive-ai/react-hooks/contexts/amplitudeContext");
6
7
  let react_jsx_runtime = require("react/jsx-runtime");
@@ -28,7 +29,7 @@ const mockHintText = "Ask me anything";
28
29
  const TypingAnimationWidgetHandler = (props) => {
29
30
  const { onTypedMessageSubmitted } = (0, __envive_ai_react_hooks_contexts_salesAgentContext.useSalesAgent)();
30
31
  const onToggle = (0, jotai.useSetAtom)(__envive_ai_react_hooks_atoms_chat_chatState.chatOnToggleAtom);
31
- const { hardcopyContent, widgetConfig, isLoading, widgetConfigId } = props;
32
+ const { hardcopyContent, widgetConfig, uiConfig, isLoading, widgetConfigId } = props;
32
33
  const titleLabel = hardcopyContent?.values?.titleLabel || "";
33
34
  const headlineText = hardcopyContent?.values?.headlineText || "";
34
35
  const animatedTextSequence = hardcopyContent?.values?.animatedTextSequence || [];
@@ -43,6 +44,8 @@ const TypingAnimationWidgetHandler = (props) => {
43
44
  const promptButtonType = typingAnimationWidgetConfig?.promptButtonType || __envive_ai_react_toolkit_v3_PromptButton_types.PromptButtonVariant.LIGHT;
44
45
  const promptCarouselRows = typingAnimationWidgetConfig?.promptCarouselRows || __envive_ai_react_toolkit_v3_PromptCarousel.PromptCarouselRows.ALWAYS_ONE;
45
46
  const showTextField = typingAnimationWidgetConfig?.showTextField !== false;
47
+ const logoSrc = uiConfig?.lookAndFeel?.widgetLogoSrc;
48
+ const hideLogo = uiConfig?.lookAndFeel?.hideWidgetLogo;
46
49
  const { trackEvent } = (0, __envive_ai_react_hooks_contexts_amplitudeContext.useAmplitude)();
47
50
  (0, react.useEffect)(() => {
48
51
  trackEvent({
@@ -54,13 +57,28 @@ const TypingAnimationWidgetHandler = (props) => {
54
57
  });
55
58
  }, [trackEvent, widgetConfigId]);
56
59
  const handleButtonClick = (0, react.useCallback)((text) => {
60
+ const rawValues = hardcopyContent?.rawValues;
61
+ const stringId = require_functions.getStringIdForText(rawValues, text);
62
+ trackEvent({
63
+ eventName: __envive_ai_react_hooks_contexts_amplitudeContext.EnviveMetricsEventName.WidgetTextClicked,
64
+ eventProps: {
65
+ response_id: hardcopyContent?.responseId,
66
+ string_id: stringId,
67
+ text
68
+ }
69
+ });
57
70
  onTypedMessageSubmitted({
58
71
  query: text,
59
72
  userTyped: false,
60
73
  displayLocation: __envive_ai_react_hooks_application_models.ChatElementDisplayLocationV3.TYPING_ANIMATION
61
74
  });
62
75
  onToggle(__envive_ai_react_hooks_application_models.ChatElementDisplayLocationV3.TYPING_ANIMATION);
63
- }, [onTypedMessageSubmitted, onToggle]);
76
+ }, [
77
+ hardcopyContent,
78
+ trackEvent,
79
+ onTypedMessageSubmitted,
80
+ onToggle
81
+ ]);
64
82
  const handleTextFieldClick = (0, react.useCallback)(() => {
65
83
  onToggle(__envive_ai_react_hooks_application_models.ChatElementDisplayLocationV3.TYPING_ANIMATION);
66
84
  }, [onToggle]);
@@ -72,7 +90,9 @@ const TypingAnimationWidgetHandler = (props) => {
72
90
  animatedTextSequence: isLoading ? mockAnimatedTextSequence : animatedTextSequence,
73
91
  promptButtonTexts: buttonTexts,
74
92
  hintText: isLoading ? mockHintText : hintText,
75
- textFieldAriaLabel
93
+ textFieldAriaLabel,
94
+ logoSrc: logoSrc ?? void 0,
95
+ hideLogo: hideLogo ?? false
76
96
  },
77
97
  widgetStyleProps: {
78
98
  widgetVariant,
@@ -1,9 +1,9 @@
1
1
  import { BaseWidgetProps } from "../../hocs/withBaseWidget/types.cjs";
2
- import * as react_jsx_runtime2 from "react/jsx-runtime";
2
+ import * as react_jsx_runtime16 from "react/jsx-runtime";
3
3
 
4
4
  //#region src/widgets/TypingAnimationWidget/TypingAnimationWidget.d.ts
5
5
  declare const TypingAnimationWithBaseWidget: {
6
- (props: BaseWidgetProps): react_jsx_runtime2.JSX.Element;
6
+ (props: BaseWidgetProps): react_jsx_runtime16.JSX.Element;
7
7
  displayName: string;
8
8
  };
9
9
  interface TypingAnimationWidgetProps {
@@ -12,7 +12,7 @@ interface TypingAnimationWidgetProps {
12
12
  declare const TypingAnimationWidget: {
13
13
  ({
14
14
  widgetConfigId
15
- }: TypingAnimationWidgetProps): react_jsx_runtime2.JSX.Element;
15
+ }: TypingAnimationWidgetProps): react_jsx_runtime16.JSX.Element;
16
16
  displayName: string;
17
17
  };
18
18
  //#endregion
@@ -1,9 +1,9 @@
1
1
  import { BaseWidgetProps } from "../../hocs/withBaseWidget/types.js";
2
- import * as react_jsx_runtime5 from "react/jsx-runtime";
2
+ import * as react_jsx_runtime0 from "react/jsx-runtime";
3
3
 
4
4
  //#region src/widgets/TypingAnimationWidget/TypingAnimationWidget.d.ts
5
5
  declare const TypingAnimationWithBaseWidget: {
6
- (props: BaseWidgetProps): react_jsx_runtime5.JSX.Element;
6
+ (props: BaseWidgetProps): react_jsx_runtime0.JSX.Element;
7
7
  displayName: string;
8
8
  };
9
9
  interface TypingAnimationWidgetProps {
@@ -12,7 +12,7 @@ interface TypingAnimationWidgetProps {
12
12
  declare const TypingAnimationWidget: {
13
13
  ({
14
14
  widgetConfigId
15
- }: TypingAnimationWidgetProps): react_jsx_runtime5.JSX.Element;
15
+ }: TypingAnimationWidgetProps): react_jsx_runtime0.JSX.Element;
16
16
  displayName: string;
17
17
  };
18
18
  //#endregion
@@ -1,7 +1,8 @@
1
1
  import { withBaseWidget } from "../../hocs/withBaseWidget/withBaseWidget.js";
2
2
  import "../../hocs/withBaseWidget/index.js";
3
+ import { getStringIdForText } from "../utils/functions.js";
3
4
  import { useCallback, useEffect } from "react";
4
- import { SpiffyMetricsEventName, useAmplitude } from "@envive-ai/react-hooks/contexts/amplitudeContext";
5
+ import { EnviveMetricsEventName, SpiffyMetricsEventName, useAmplitude } from "@envive-ai/react-hooks/contexts/amplitudeContext";
5
6
  import { jsx } from "react/jsx-runtime";
6
7
  import { WidgetTypeV3 } from "@envive-ai/react-hooks/contexts/typesV3";
7
8
  import { useSetAtom } from "jotai";
@@ -27,7 +28,7 @@ const mockHintText = "Ask me anything";
27
28
  const TypingAnimationWidgetHandler = (props) => {
28
29
  const { onTypedMessageSubmitted } = useSalesAgent();
29
30
  const onToggle = useSetAtom(chatOnToggleAtom);
30
- const { hardcopyContent, widgetConfig, isLoading, widgetConfigId } = props;
31
+ const { hardcopyContent, widgetConfig, uiConfig, isLoading, widgetConfigId } = props;
31
32
  const titleLabel = hardcopyContent?.values?.titleLabel || "";
32
33
  const headlineText = hardcopyContent?.values?.headlineText || "";
33
34
  const animatedTextSequence = hardcopyContent?.values?.animatedTextSequence || [];
@@ -42,6 +43,8 @@ const TypingAnimationWidgetHandler = (props) => {
42
43
  const promptButtonType = typingAnimationWidgetConfig?.promptButtonType || PromptButtonVariant.LIGHT;
43
44
  const promptCarouselRows = typingAnimationWidgetConfig?.promptCarouselRows || PromptCarouselRows.ALWAYS_ONE;
44
45
  const showTextField = typingAnimationWidgetConfig?.showTextField !== false;
46
+ const logoSrc = uiConfig?.lookAndFeel?.widgetLogoSrc;
47
+ const hideLogo = uiConfig?.lookAndFeel?.hideWidgetLogo;
45
48
  const { trackEvent } = useAmplitude();
46
49
  useEffect(() => {
47
50
  trackEvent({
@@ -53,13 +56,28 @@ const TypingAnimationWidgetHandler = (props) => {
53
56
  });
54
57
  }, [trackEvent, widgetConfigId]);
55
58
  const handleButtonClick = useCallback((text) => {
59
+ const rawValues = hardcopyContent?.rawValues;
60
+ const stringId = getStringIdForText(rawValues, text);
61
+ trackEvent({
62
+ eventName: EnviveMetricsEventName.WidgetTextClicked,
63
+ eventProps: {
64
+ response_id: hardcopyContent?.responseId,
65
+ string_id: stringId,
66
+ text
67
+ }
68
+ });
56
69
  onTypedMessageSubmitted({
57
70
  query: text,
58
71
  userTyped: false,
59
72
  displayLocation: ChatElementDisplayLocationV3.TYPING_ANIMATION
60
73
  });
61
74
  onToggle(ChatElementDisplayLocationV3.TYPING_ANIMATION);
62
- }, [onTypedMessageSubmitted, onToggle]);
75
+ }, [
76
+ hardcopyContent,
77
+ trackEvent,
78
+ onTypedMessageSubmitted,
79
+ onToggle
80
+ ]);
63
81
  const handleTextFieldClick = useCallback(() => {
64
82
  onToggle(ChatElementDisplayLocationV3.TYPING_ANIMATION);
65
83
  }, [onToggle]);
@@ -71,7 +89,9 @@ const TypingAnimationWidgetHandler = (props) => {
71
89
  animatedTextSequence: isLoading ? mockAnimatedTextSequence : animatedTextSequence,
72
90
  promptButtonTexts: buttonTexts,
73
91
  hintText: isLoading ? mockHintText : hintText,
74
- textFieldAriaLabel
92
+ textFieldAriaLabel,
93
+ logoSrc: logoSrc ?? void 0,
94
+ hideLogo: hideLogo ?? false
75
95
  },
76
96
  widgetStyleProps: {
77
97
  widgetVariant,
@@ -1,5 +1,5 @@
1
1
  import { SearchResultsEntryPointWidgetConfig } from "./types.cjs";
2
- import * as react_jsx_runtime0 from "react/jsx-runtime";
2
+ import * as react_jsx_runtime1 from "react/jsx-runtime";
3
3
  import { SearchResultsHocProps } from "@envive-ai/react-hooks/hooks/Search";
4
4
 
5
5
  //#region ../widgets/dist/SearchResults/SearchResults.d.ts
@@ -7,7 +7,7 @@ import { SearchResultsHocProps } from "@envive-ai/react-hooks/hooks/Search";
7
7
  interface SearchResultsProps extends SearchResultsHocProps {
8
8
  widgetConfig: SearchResultsEntryPointWidgetConfig;
9
9
  }
10
- declare const SearchResults: (props: Omit<SearchResultsProps, string | number | symbol>) => react_jsx_runtime0.JSX.Element;
10
+ declare const SearchResults: (props: Omit<SearchResultsProps, string | number | symbol>) => react_jsx_runtime1.JSX.Element;
11
11
  //#endregion
12
12
 
13
13
  //#endregion
@@ -1,8 +1,8 @@
1
- import * as react_jsx_runtime1 from "react/jsx-runtime";
1
+ import * as react_jsx_runtime3 from "react/jsx-runtime";
2
2
 
3
3
  //#region ../widgets/dist/SearchResults/SearchResultsWidget.d.ts
4
4
  //#region src/SearchResults/SearchResultsWidget.d.ts
5
- declare const SearchResultsWidget: () => react_jsx_runtime1.JSX.Element;
5
+ declare const SearchResultsWidget: () => react_jsx_runtime3.JSX.Element;
6
6
  //#endregion
7
7
 
8
8
  //#endregion
@@ -1,4 +1,4 @@
1
- import * as react_jsx_runtime3 from "react/jsx-runtime";
1
+ import * as react_jsx_runtime0 from "react/jsx-runtime";
2
2
 
3
3
  //#region ../widgets/dist/SearchZeroState/SearchZeroStateWidget.d.ts
4
4
  //#region src/SearchZeroState/SearchZeroStateWidget.d.ts
@@ -11,7 +11,7 @@ declare const SearchZeroStateWidget: ({
11
11
  initialIsOpen,
12
12
  widgetConfigId,
13
13
  entryPointRef
14
- }: SearchZeroStateWidgetProps) => react_jsx_runtime3.JSX.Element;
14
+ }: SearchZeroStateWidgetProps) => react_jsx_runtime0.JSX.Element;
15
15
  //#endregion
16
16
 
17
17
  //#endregion
@@ -1,5 +1,5 @@
1
1
  import { SuggestionBarLocationForMetrics } from "./types.cjs";
2
- import * as react_jsx_runtime2 from "react/jsx-runtime";
2
+ import * as react_jsx_runtime0 from "react/jsx-runtime";
3
3
  import { SuggestionButtonVariant } from "@envive-ai/react-hooks/contexts/types";
4
4
  import { Message } from "postcss";
5
5
 
@@ -30,7 +30,7 @@ declare function SuggestionBar({
30
30
  buttonBorderRadius,
31
31
  handleReply,
32
32
  dataTestId
33
- }: Readonly<SuggestionBarProps>): react_jsx_runtime2.JSX.Element;
33
+ }: Readonly<SuggestionBarProps>): react_jsx_runtime0.JSX.Element;
34
34
  //#endregion
35
35
  //#endregion
36
36
  export { SuggestionBar };
@@ -44,11 +44,20 @@ const isProductComparison = (lastMsg) => {
44
44
  if (lastMsg) return lastMsg?.filter((msg) => msg.type === __envive_ai_react_hooks_application_models.MessageType.Product).length === 2;
45
45
  return (0, __envive_ai_react_hooks_atoms_atomStore.getAtomStore)().get(__envive_ai_react_hooks_atoms_chat.lastAssistantMessageAtom)?.filter((msg) => msg.type === __envive_ai_react_hooks_application_models.MessageType.Product).length === 2;
46
46
  };
47
+ /** Finds the string_id (id) from raw widget text values for the given display text */
48
+ const getStringIdForText = (rawValues, text) => {
49
+ if (!rawValues) return void 0;
50
+ for (const raw of Object.values(rawValues)) {
51
+ const found = (Array.isArray(raw) ? raw : [raw]).find((s) => s.value === text);
52
+ if (found) return found.id;
53
+ }
54
+ };
47
55
 
48
56
  //#endregion
49
57
  exports.getMessageText = getMessageText;
50
58
  exports.getProductImageUrl = getProductImageUrl;
51
59
  exports.getRecentProductImageUrls = getRecentProductImageUrls;
60
+ exports.getStringIdForText = getStringIdForText;
52
61
  exports.isLoading = isLoading;
53
62
  exports.isProductComparison = isProductComparison;
54
63
  exports.userHasInteracted = userHasInteracted;
@@ -43,6 +43,14 @@ const isProductComparison = (lastMsg) => {
43
43
  if (lastMsg) return lastMsg?.filter((msg) => msg.type === MessageType.Product).length === 2;
44
44
  return getAtomStore().get(lastAssistantMessageAtom)?.filter((msg) => msg.type === MessageType.Product).length === 2;
45
45
  };
46
+ /** Finds the string_id (id) from raw widget text values for the given display text */
47
+ const getStringIdForText = (rawValues, text) => {
48
+ if (!rawValues) return void 0;
49
+ for (const raw of Object.values(rawValues)) {
50
+ const found = (Array.isArray(raw) ? raw : [raw]).find((s) => s.value === text);
51
+ if (found) return found.id;
52
+ }
53
+ };
46
54
 
47
55
  //#endregion
48
- export { getMessageText, getProductImageUrl, getRecentProductImageUrls, isLoading, isProductComparison, userHasInteracted, userHasNotInteracted };
56
+ export { getMessageText, getProductImageUrl, getRecentProductImageUrls, getStringIdForText, isLoading, isProductComparison, userHasInteracted, userHasNotInteracted };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@envive-ai/react-widgets-v3",
3
- "version": "0.3.12",
3
+ "version": "0.3.14",
4
4
  "description": "React widget library v3 for Envive services.",
5
5
  "keywords": [
6
6
  "react",
@@ -0,0 +1,91 @@
1
+ import { SelectorFactory } from '@envive-ai/react-hooks/application/utils';
2
+ import { useElementObserver } from '@envive-ai/react-hooks/hooks/ElementObserver';
3
+ import { FLOATING_BUTTON_ID } from '../../widgets/FloatingChatWidget/constants';
4
+ import { CustomerServiceImplProps, UnifiedCXButton } from '../types';
5
+
6
+ interface UseEightByEightUnifiedCXButtonProps extends CustomerServiceImplProps {}
7
+
8
+ const EIGHT_BY_EIGHT_BUBBLE_SELECTOR = 'div[id^="__8x8-chat-button-container-script"]';
9
+
10
+ const EIGHT_BY_EIGHT_BUTTON_SELECTOR = `${EIGHT_BY_EIGHT_BUBBLE_SELECTOR} a[data-type="online"], ${EIGHT_BY_EIGHT_BUBBLE_SELECTOR} a[data-type="offline"]`;
11
+
12
+ const EIGHT_BY_EIGHT_CHAT_WINDOW_SELECTOR = 'div.__8x8Chat-Container';
13
+
14
+ export const useEightByEightUnifiedCXButton = ({
15
+ onSwitchToAgent,
16
+ onCXClose,
17
+ suppressMerchantButton,
18
+ }: UseEightByEightUnifiedCXButtonProps): UnifiedCXButton => {
19
+ const eightByEightBubble = useElementObserver(
20
+ SelectorFactory.query(EIGHT_BY_EIGHT_BUBBLE_SELECTOR),
21
+ );
22
+ const eightByEightChatWindow = useElementObserver(
23
+ SelectorFactory.query(EIGHT_BY_EIGHT_CHAT_WINDOW_SELECTOR),
24
+ );
25
+ const enviveFloatingButton = useElementObserver(SelectorFactory.id(FLOATING_BUTTON_ID));
26
+
27
+ const isEightByEightEnabled = () => !!document.querySelector(EIGHT_BY_EIGHT_BUTTON_SELECTOR);
28
+
29
+ const toggle = () => {
30
+ const button = document.querySelector(EIGHT_BY_EIGHT_BUTTON_SELECTOR) as HTMLElement | null;
31
+
32
+ if (!button) {
33
+ return;
34
+ }
35
+
36
+ onSwitchToAgent();
37
+ enviveFloatingButton.hide();
38
+
39
+ button.click();
40
+ };
41
+
42
+ const isSwitchEnabled = () => isEightByEightEnabled();
43
+
44
+ eightByEightBubble.onAdd(el => {
45
+ if (suppressMerchantButton && el) {
46
+ eightByEightBubble.hide();
47
+ }
48
+ enviveFloatingButton.show();
49
+ });
50
+
51
+ eightByEightBubble.onChange(el => {
52
+ if (!el || !suppressMerchantButton) return;
53
+
54
+ const styles = window.getComputedStyle(el);
55
+ const display = styles.getPropertyValue('display');
56
+ if (display !== 'none') {
57
+ eightByEightBubble.hide();
58
+ }
59
+ });
60
+
61
+ eightByEightChatWindow.onChange(el => {
62
+ if (!el) return;
63
+
64
+ const rect = el.getBoundingClientRect();
65
+ const isOpen = rect.width > 50 && rect.height > 50;
66
+
67
+ if (isOpen) {
68
+ enviveFloatingButton.hide();
69
+ return;
70
+ }
71
+
72
+ onCXClose?.();
73
+ if (suppressMerchantButton) {
74
+ eightByEightBubble.hide();
75
+ }
76
+ enviveFloatingButton.show();
77
+ });
78
+
79
+ eightByEightChatWindow.onRemove(() => {
80
+ onCXClose?.();
81
+ if (suppressMerchantButton) {
82
+ eightByEightBubble.hide();
83
+ }
84
+ enviveFloatingButton.show();
85
+ });
86
+
87
+ return {
88
+ toggle,
89
+ isSwitchEnabled,
90
+ };
91
+ };
@@ -0,0 +1,108 @@
1
+ import { SelectorFactory } from '@envive-ai/react-hooks/application/utils';
2
+ import { useElementObserver } from '@envive-ai/react-hooks/hooks/ElementObserver';
3
+ import { FLOATING_BUTTON_ID } from '../../widgets/FloatingChatWidget/constants';
4
+ import { CustomerServiceImplProps, UnifiedCXButton } from '../types';
5
+
6
+ const BEACON_CONTAINER_ID = 'beacon-container';
7
+
8
+ interface UseHelpScoutUnifiedCXButtonProps extends CustomerServiceImplProps {}
9
+
10
+ export const useHelpScoutUnifiedCXButton = ({
11
+ onSwitchToAgent,
12
+ suppressMerchantButton,
13
+ }: UseHelpScoutUnifiedCXButtonProps): UnifiedCXButton => {
14
+ const beaconContainer = useElementObserver(SelectorFactory.id(BEACON_CONTAINER_ID));
15
+ const enviveFloatingButton = useElementObserver(SelectorFactory.id(FLOATING_BUTTON_ID));
16
+
17
+ const toggle = () => {
18
+ onSwitchToAgent();
19
+
20
+ // Try using the Help Scout Beacon API first
21
+ if (typeof (window as any).Beacon !== 'undefined') {
22
+ (window as any).Beacon('open');
23
+ } else {
24
+ // Fallback: Find and click the FAB button
25
+ const container = document.getElementById(BEACON_CONTAINER_ID);
26
+ const fabButton = container?.querySelector('.BeaconFabButtonFrame') as HTMLElement;
27
+ if (fabButton) {
28
+ fabButton.style.display = '';
29
+ fabButton.click();
30
+ }
31
+ }
32
+
33
+ if (suppressMerchantButton) {
34
+ enviveFloatingButton.hide();
35
+ }
36
+ };
37
+
38
+ const isHelpScoutButtonEnabled = () => {
39
+ // Check for the main Help Scout Beacon container
40
+ const beaconContainerEl = document.getElementById('beacon-container');
41
+ if (!beaconContainerEl) return false;
42
+
43
+ // Check for the FAB button (Floating Action Button) or the global Beacon API
44
+ const fabButton = beaconContainerEl.querySelector('.BeaconFabButtonFrame');
45
+ const hasBeaconAPI = typeof (window as any).Beacon !== 'undefined';
46
+
47
+ return !!(fabButton || hasBeaconAPI);
48
+ };
49
+
50
+ const isSwitchEnabled = () => isHelpScoutButtonEnabled();
51
+
52
+ // Hide Help Scout FAB button when beacon container is added
53
+ beaconContainer.onAdd(() => {
54
+ if (suppressMerchantButton) {
55
+ const fabButton = document
56
+ .getElementById(BEACON_CONTAINER_ID)
57
+ ?.querySelector('.BeaconFabButtonFrame') as HTMLElement;
58
+ if (fabButton) {
59
+ fabButton.style.display = 'none';
60
+ }
61
+ enviveFloatingButton.show();
62
+ }
63
+ });
64
+
65
+ // Observe the beacon container for visibility changes
66
+ // Help Scout Beacon adds/removes classes to show/hide the widget
67
+ beaconContainer.onChange(el => {
68
+ if (el && suppressMerchantButton) {
69
+ // Check if the BeaconContainer widget is open
70
+ const beaconWidget = el.querySelector('.BeaconContainer');
71
+ const fabButton = el.querySelector('.BeaconFabButtonFrame') as HTMLElement;
72
+
73
+ if (beaconWidget && fabButton) {
74
+ const { classList } = beaconWidget;
75
+
76
+ // When beacon is open (has enter-done class)
77
+ if (
78
+ classList.contains('BeaconContainer-enter-done') ||
79
+ classList.contains('BeaconContainer-enter-active')
80
+ ) {
81
+ fabButton.style.display = '';
82
+ enviveFloatingButton.hide();
83
+ }
84
+
85
+ // When beacon is closed (has exit class)
86
+ if (
87
+ classList.contains('BeaconContainer-exit') ||
88
+ classList.contains('BeaconContainer-exit-active')
89
+ ) {
90
+ fabButton.style.display = 'none';
91
+ enviveFloatingButton.show();
92
+ }
93
+ }
94
+ }
95
+ });
96
+
97
+ // Cleanup when container is removed
98
+ beaconContainer.onRemove(() => {
99
+ if (suppressMerchantButton) {
100
+ enviveFloatingButton.show();
101
+ }
102
+ });
103
+
104
+ return {
105
+ toggle,
106
+ isSwitchEnabled,
107
+ };
108
+ };