@envive-ai/react-widgets-v3 0.3.7 → 0.3.9
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.
- package/dist/CXIntegration/hooks/useUnifiedCXButton.cjs +3 -2
- package/dist/CXIntegration/hooks/useUnifiedCXButton.js +4 -3
- package/dist/hocs/withBaseWidget/withBaseWidget.d.cts +2 -2
- package/dist/hocs/withBaseWidget/withBaseWidget.d.ts +2 -2
- package/dist/widgets/ChatPreviewComparisonWidget/ChatPreviewComparisonWidget.cjs +6 -13
- package/dist/widgets/ChatPreviewComparisonWidget/ChatPreviewComparisonWidget.d.cts +3 -3
- package/dist/widgets/ChatPreviewComparisonWidget/ChatPreviewComparisonWidget.d.ts +3 -3
- package/dist/widgets/ChatPreviewComparisonWidget/ChatPreviewComparisonWidget.js +6 -13
- package/dist/widgets/ChatPreviewLoadingWidget/ChatPreviewLoadingWidget.d.ts +3 -3
- package/dist/widgets/ChatPreviewWidget/ChatPreviewWidget.cjs +7 -13
- package/dist/widgets/ChatPreviewWidget/ChatPreviewWidget.d.cts +3 -3
- package/dist/widgets/ChatPreviewWidget/ChatPreviewWidget.d.ts +3 -3
- package/dist/widgets/ChatPreviewWidget/ChatPreviewWidget.js +7 -13
- package/dist/widgets/FloatingChatWidget/FloatingChatOverlay.cjs +5 -3
- package/dist/widgets/FloatingChatWidget/FloatingChatOverlay.js +5 -3
- package/dist/widgets/FloatingChatWidget/FloatingChatWidget.cjs +6 -5
- package/dist/widgets/FloatingChatWidget/FloatingChatWidget.d.cts +2 -2
- package/dist/widgets/FloatingChatWidget/FloatingChatWidget.d.ts +2 -2
- package/dist/widgets/FloatingChatWidget/FloatingChatWidget.js +7 -6
- package/dist/widgets/ProductCardWidget/ProductCardWidget.cjs +90 -0
- package/dist/widgets/ProductCardWidget/ProductCardWidget.d.cts +14 -0
- package/dist/widgets/ProductCardWidget/ProductCardWidget.d.ts +14 -0
- package/dist/widgets/ProductCardWidget/ProductCardWidget.js +89 -0
- package/dist/widgets/ProductCardWidget/index.cjs +3 -0
- package/dist/widgets/ProductCardWidget/index.d.cts +2 -0
- package/dist/widgets/ProductCardWidget/index.d.ts +2 -0
- package/dist/widgets/ProductCardWidget/index.js +3 -0
- package/dist/widgets/PromptButtonCarouselWithImageWidget/PromptButtonCarouselWithImageWidget.cjs +14 -2
- package/dist/widgets/PromptButtonCarouselWithImageWidget/PromptButtonCarouselWithImageWidget.d.cts +3 -3
- package/dist/widgets/PromptButtonCarouselWithImageWidget/PromptButtonCarouselWithImageWidget.d.ts +3 -3
- package/dist/widgets/PromptButtonCarouselWithImageWidget/PromptButtonCarouselWithImageWidget.js +16 -4
- package/dist/widgets/PromptCarouselWidget/PromptCarouselWidget.cjs +2 -2
- package/dist/widgets/PromptCarouselWidget/PromptCarouselWidget.d.cts +2 -2
- package/dist/widgets/PromptCarouselWidget/PromptCarouselWidget.d.ts +2 -2
- package/dist/widgets/PromptCarouselWidget/PromptCarouselWidget.js +2 -2
- package/dist/widgets/SocialProofFlowWidget/SocialProofFlowWidget.cjs +1 -1
- package/dist/widgets/SocialProofFlowWidget/SocialProofFlowWidget.d.cts +2 -2
- package/dist/widgets/SocialProofFlowWidget/SocialProofFlowWidget.d.ts +2 -2
- package/dist/widgets/SocialProofFlowWidget/SocialProofFlowWidget.js +1 -1
- package/dist/widgets/SocialProofWidget/SocialProofWidget.cjs +2 -1
- package/dist/widgets/SocialProofWidget/SocialProofWidget.d.cts +3 -3
- package/dist/widgets/SocialProofWidget/SocialProofWidget.d.ts +3 -3
- package/dist/widgets/SocialProofWidget/SocialProofWidget.js +4 -3
- package/dist/widgets/TitledPromptCarouselWidget/TitledPromptCarouselWidget.d.ts +2 -2
- package/dist/widgets/TypingAnimationFlowWidget/TypingAnimationFlowWidget.cjs +1 -1
- package/dist/widgets/TypingAnimationFlowWidget/TypingAnimationFlowWidget.d.cts +2 -2
- package/dist/widgets/TypingAnimationFlowWidget/TypingAnimationFlowWidget.d.ts +2 -2
- package/dist/widgets/TypingAnimationFlowWidget/TypingAnimationFlowWidget.js +1 -1
- package/dist/widgets/TypingAnimationWidget/TypingAnimationWidget.d.cts +3 -3
- package/dist/widgets/dist/SearchResults/SearchResultsWidget.d.cts +2 -2
- package/dist/widgets/dist/SearchResults/SearchResultsWidget.d.ts +2 -2
- package/dist/widgets/dist/SearchZeroState/SearchZeroStateWidget.d.cts +2 -2
- package/dist/widgets/dist/SearchZeroState/SearchZeroStateWidget.d.ts +2 -2
- package/dist/widgets/dist/SuggestionBar/SuggestionBar.d.cts +2 -2
- package/dist/widgets/dist/SuggestionBar/SuggestionBar.d.ts +2 -2
- package/package.json +5 -1
- package/src/CXIntegration/hooks/useUnifiedCXButton.ts +4 -3
- package/src/stories/ProductCardWidget.stories.tsx +58 -0
- package/src/stories/SalesAgentTest/SalesAgentTest.tsx +24 -8
- package/src/widgets/ChatPreviewComparisonWidget/ChatPreviewComparisonWidget.tsx +10 -11
- package/src/widgets/ChatPreviewWidget/ChatPreviewWidget.tsx +11 -12
- package/src/widgets/FloatingChatWidget/FloatingChatOverlay.tsx +2 -3
- package/src/widgets/FloatingChatWidget/FloatingChatWidget.tsx +24 -18
- package/src/widgets/ProductCardWidget/ProductCardWidget.tsx +112 -0
- package/src/widgets/ProductCardWidget/index.ts +2 -0
- package/src/widgets/PromptButtonCarouselWithImageWidget/PromptButtonCarouselWithImageWidget.tsx +32 -4
- package/src/widgets/PromptCarouselWidget/PromptCarouselWidget.tsx +1 -1
- package/src/widgets/SocialProofWidget/SocialProofWidget.tsx +4 -6
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ChatPreviewLoadingWidgetWithBaseWidget } from "../ChatPreviewLoadingWidget/ChatPreviewLoadingWidget.js";
|
|
2
2
|
import { ChatPreviewComparisonWidgetWithBaseWidget } from "../ChatPreviewComparisonWidget/ChatPreviewComparisonWidget.js";
|
|
3
|
-
import { ChatPreviewWidgetWithBaseWidget } from "../ChatPreviewWidget/ChatPreviewWidget.js";
|
|
4
3
|
import useGetWidgetStatus_default from "../hooks/useGetWidgetStatus.js";
|
|
4
|
+
import { ChatPreviewWidgetWithBaseWidget } from "../ChatPreviewWidget/ChatPreviewWidget.js";
|
|
5
5
|
import { TypingAnimationWithBaseWidget } from "../TypingAnimationWidget/TypingAnimationWidget.js";
|
|
6
6
|
import { jsx } from "react/jsx-runtime";
|
|
7
7
|
import { WidgetTypeV3 } from "@envive-ai/react-hooks/contexts/typesV3";
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { BaseWidgetProps } from "../../hocs/withBaseWidget/types.cjs";
|
|
2
|
-
import * as
|
|
2
|
+
import * as react_jsx_runtime3 from "react/jsx-runtime";
|
|
3
3
|
|
|
4
4
|
//#region src/widgets/TypingAnimationWidget/TypingAnimationWidget.d.ts
|
|
5
5
|
declare const TypingAnimationWithBaseWidget: {
|
|
6
|
-
(props: BaseWidgetProps):
|
|
6
|
+
(props: BaseWidgetProps): react_jsx_runtime3.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):
|
|
15
|
+
}: TypingAnimationWidgetProps): react_jsx_runtime3.JSX.Element;
|
|
16
16
|
displayName: string;
|
|
17
17
|
};
|
|
18
18
|
//#endregion
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as react_jsx_runtime0 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: () =>
|
|
5
|
+
declare const SearchResultsWidget: () => react_jsx_runtime0.JSX.Element;
|
|
6
6
|
//#endregion
|
|
7
7
|
|
|
8
8
|
//#endregion
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as react_jsx_runtime0 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: () =>
|
|
5
|
+
declare const SearchResultsWidget: () => react_jsx_runtime0.JSX.Element;
|
|
6
6
|
//#endregion
|
|
7
7
|
|
|
8
8
|
//#endregion
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as react_jsx_runtime2 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) =>
|
|
14
|
+
}: SearchZeroStateWidgetProps) => react_jsx_runtime2.JSX.Element;
|
|
15
15
|
//#endregion
|
|
16
16
|
|
|
17
17
|
//#endregion
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as react_jsx_runtime2 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) =>
|
|
14
|
+
}: SearchZeroStateWidgetProps) => react_jsx_runtime2.JSX.Element;
|
|
15
15
|
//#endregion
|
|
16
16
|
|
|
17
17
|
//#endregion
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SuggestionBarLocationForMetrics } from "./types.cjs";
|
|
2
|
-
import * as
|
|
2
|
+
import * as react_jsx_runtime3 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>):
|
|
33
|
+
}: Readonly<SuggestionBarProps>): react_jsx_runtime3.JSX.Element;
|
|
34
34
|
//#endregion
|
|
35
35
|
//#endregion
|
|
36
36
|
export { SuggestionBar };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SuggestionBarLocationForMetrics } from "./types.js";
|
|
2
|
-
import * as
|
|
2
|
+
import * as react_jsx_runtime3 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>):
|
|
33
|
+
}: Readonly<SuggestionBarProps>): react_jsx_runtime3.JSX.Element;
|
|
34
34
|
//#endregion
|
|
35
35
|
//#endregion
|
|
36
36
|
export { SuggestionBar };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@envive-ai/react-widgets-v3",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.9",
|
|
4
4
|
"description": "React widget library v3 for Envive services.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -120,6 +120,10 @@
|
|
|
120
120
|
"import": "./dist/widgets/FloatingChatWidget/index.js",
|
|
121
121
|
"require": "./dist/widgets/FloatingChatWidget/index.cjs"
|
|
122
122
|
},
|
|
123
|
+
"./widgets/ProductCardWidget": {
|
|
124
|
+
"import": "./dist/widgets/ProductCardWidget/index.js",
|
|
125
|
+
"require": "./dist/widgets/ProductCardWidget/index.cjs"
|
|
126
|
+
},
|
|
123
127
|
"./widgets/PromptButtonCarouselWithImageWidget": {
|
|
124
128
|
"import": "./dist/widgets/PromptButtonCarouselWithImageWidget/index.js",
|
|
125
129
|
"require": "./dist/widgets/PromptButtonCarouselWithImageWidget/index.cjs"
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useAtomValue } from 'jotai';
|
|
2
2
|
|
|
3
|
-
import { hasParsedVariantInfoAtom
|
|
3
|
+
import { hasParsedVariantInfoAtom } from '@envive-ai/react-hooks/atoms/app';
|
|
4
|
+
import { usePage } from '@envive-ai/react-hooks/contexts/pageContext';
|
|
4
5
|
import { findCustomerServiceImpl } from '../utils/functions';
|
|
5
6
|
import { CustomerServiceType, UnifiedCXButton } from '../types';
|
|
6
7
|
|
|
@@ -17,7 +18,7 @@ export const useUnifiedCXButton = ({
|
|
|
17
18
|
suppressMerchantButton = false,
|
|
18
19
|
onSwitchToAgent,
|
|
19
20
|
}: UseUnifiedCXButtonProps): UnifiedCXButton | undefined => {
|
|
20
|
-
const
|
|
21
|
+
const { isSupported } = usePage();
|
|
21
22
|
const hasParsedVariantInfo = useAtomValue(hasParsedVariantInfoAtom);
|
|
22
23
|
|
|
23
24
|
const customerService = findCustomerServiceImpl(provider);
|
|
@@ -30,7 +31,7 @@ export const useUnifiedCXButton = ({
|
|
|
30
31
|
if (!enabled) return undefined;
|
|
31
32
|
|
|
32
33
|
if (suppressMerchantButton) {
|
|
33
|
-
const showUnifiedButton = hasParsedVariantInfo &&
|
|
34
|
+
const showUnifiedButton = hasParsedVariantInfo && isSupported;
|
|
34
35
|
if (!showUnifiedButton) return undefined;
|
|
35
36
|
}
|
|
36
37
|
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { ProductCardWidget } from '../widgets/ProductCardWidget/ProductCardWidget';
|
|
3
|
+
|
|
4
|
+
const meta = {
|
|
5
|
+
title: 'Widgets V3/ProductCardWidget',
|
|
6
|
+
component: ProductCardWidget,
|
|
7
|
+
tags: ['autodocs'],
|
|
8
|
+
args: {
|
|
9
|
+
widgetConfigId: 'product-card-test-widget',
|
|
10
|
+
},
|
|
11
|
+
argTypes: {
|
|
12
|
+
widgetConfigId: {
|
|
13
|
+
control: 'text',
|
|
14
|
+
description:
|
|
15
|
+
'Unique identifier for the widget configuration. The widget will fetch the widget config and hardcopy content based on this ID.',
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
parameters: {
|
|
19
|
+
docs: {
|
|
20
|
+
description: {
|
|
21
|
+
component:
|
|
22
|
+
'ProductCardWidget is a widget wrapper that displays a product card with an image, headline, animated text, prompt carousel, and text input field. It includes base widget functionality such as visibility tracking, widget config fetching and hardcopy content fetching based on the widgetConfigId.',
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
decorators: [
|
|
27
|
+
Story => (
|
|
28
|
+
<div
|
|
29
|
+
style={{
|
|
30
|
+
maxWidth: '350px',
|
|
31
|
+
height: '500px',
|
|
32
|
+
display: 'flex',
|
|
33
|
+
margin: '1rem',
|
|
34
|
+
}}
|
|
35
|
+
>
|
|
36
|
+
<Story />
|
|
37
|
+
</div>
|
|
38
|
+
),
|
|
39
|
+
],
|
|
40
|
+
} satisfies Meta<typeof ProductCardWidget>;
|
|
41
|
+
|
|
42
|
+
export default meta;
|
|
43
|
+
|
|
44
|
+
type Story = StoryObj<typeof meta>;
|
|
45
|
+
|
|
46
|
+
export const Default: Story = {
|
|
47
|
+
args: {
|
|
48
|
+
widgetConfigId: 'product-card-test-widget',
|
|
49
|
+
},
|
|
50
|
+
parameters: {
|
|
51
|
+
docs: {
|
|
52
|
+
description: {
|
|
53
|
+
story:
|
|
54
|
+
'ProductCardWidget with default configuration. The widget displays a product card with image, headline, animated text, prompt carousel, and text input field.',
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
};
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import { FormType } from '@spiffy-ai/commerce-api-client';
|
|
1
2
|
import {
|
|
2
3
|
PageVisitCategory,
|
|
3
4
|
SuggestionCategory,
|
|
4
5
|
useSalesAgent,
|
|
5
6
|
} from '@envive-ai/react-hooks/contexts/salesAgentContext';
|
|
6
7
|
import { useState } from 'react';
|
|
8
|
+
import { ChatElementDisplayLocationV3 } from '@envive-ai/react-hooks/application/models';
|
|
7
9
|
|
|
8
10
|
export const SalesAgentTest = () => {
|
|
9
11
|
const {
|
|
@@ -38,12 +40,15 @@ export const SalesAgentTest = () => {
|
|
|
38
40
|
<button
|
|
39
41
|
type="button"
|
|
40
42
|
onClick={() =>
|
|
41
|
-
onSuggestionClicked(
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
43
|
+
onSuggestionClicked(
|
|
44
|
+
{
|
|
45
|
+
id: '1',
|
|
46
|
+
category: SuggestionCategory.ProductBased,
|
|
47
|
+
content: 'test',
|
|
48
|
+
createdAt: new Date().toISOString(),
|
|
49
|
+
},
|
|
50
|
+
ChatElementDisplayLocationV3.FLOATING_CHAT_PROMPT_BUTTON,
|
|
51
|
+
)
|
|
47
52
|
}
|
|
48
53
|
>
|
|
49
54
|
On Suggestion Clicked
|
|
@@ -75,7 +80,13 @@ export const SalesAgentTest = () => {
|
|
|
75
80
|
<div>
|
|
76
81
|
<button
|
|
77
82
|
type="button"
|
|
78
|
-
onClick={
|
|
83
|
+
onClick={() =>
|
|
84
|
+
onFormResponseSubmitted({
|
|
85
|
+
filledSchema: { order_number: '123456', email: 'test@email.com' },
|
|
86
|
+
formResponseId: 'test-form-response-id',
|
|
87
|
+
formType: FormType.OrderLookup,
|
|
88
|
+
})
|
|
89
|
+
}
|
|
79
90
|
>
|
|
80
91
|
On Form Response Submitted
|
|
81
92
|
</button>
|
|
@@ -100,7 +111,12 @@ export const SalesAgentTest = () => {
|
|
|
100
111
|
}}
|
|
101
112
|
type="button"
|
|
102
113
|
key={suggestion.id}
|
|
103
|
-
onClick={() =>
|
|
114
|
+
onClick={() =>
|
|
115
|
+
onSuggestionClicked(
|
|
116
|
+
suggestion,
|
|
117
|
+
ChatElementDisplayLocationV3.FLOATING_CHAT_PROMPT_BUTTON,
|
|
118
|
+
)
|
|
119
|
+
}
|
|
104
120
|
>
|
|
105
121
|
{suggestion.content}
|
|
106
122
|
</button>
|
|
@@ -11,6 +11,7 @@ import { Theme } from '@envive-ai/react-toolkit-v3/Tokens';
|
|
|
11
11
|
import { useCallback, useMemo } from 'react';
|
|
12
12
|
import {
|
|
13
13
|
ChatElementDisplayLocationV3,
|
|
14
|
+
Suggestion,
|
|
14
15
|
VariantTypeEnum,
|
|
15
16
|
} from '@envive-ai/react-hooks/application/models';
|
|
16
17
|
import { ChatPreviewComparison } from '@envive-ai/react-toolkit-v3/ChatPreviewComparison';
|
|
@@ -22,7 +23,7 @@ import { getMessageText, getRecentProductImageUrls } from '../utils/functions';
|
|
|
22
23
|
import { ChatPreviewLoadingWidgetWithBaseWidget } from '../ChatPreviewLoadingWidget/ChatPreviewLoadingWidget';
|
|
23
24
|
|
|
24
25
|
const ChatPreviewComparisonWidgetHandler = (props: BaseWidgetProps) => {
|
|
25
|
-
const {
|
|
26
|
+
const { onSuggestionClicked } = useSalesAgent();
|
|
26
27
|
const { openChat } = useChatToggle();
|
|
27
28
|
|
|
28
29
|
const lastAssistantMessage = useAtomValue(lastAssistantMessageAtom);
|
|
@@ -32,10 +33,6 @@ const ChatPreviewComparisonWidgetHandler = (props: BaseWidgetProps) => {
|
|
|
32
33
|
|
|
33
34
|
const { suggestions } = useAtomValue(chatAtom);
|
|
34
35
|
|
|
35
|
-
const promptButtonTexts = useMemo(() => {
|
|
36
|
-
return suggestions.map(suggestion => suggestion.content);
|
|
37
|
-
}, [suggestions]);
|
|
38
|
-
|
|
39
36
|
const messageText = useMemo(() => getMessageText(lastAssistantMessage), [lastAssistantMessage]);
|
|
40
37
|
|
|
41
38
|
const productImageUrls = useMemo(
|
|
@@ -62,10 +59,9 @@ const ChatPreviewComparisonWidgetHandler = (props: BaseWidgetProps) => {
|
|
|
62
59
|
headlineText: hardcopyContent?.values?.headlineText,
|
|
63
60
|
textFieldPlaceholderText: hardcopyContent?.values?.textFieldPlaceholderText,
|
|
64
61
|
messageText,
|
|
65
|
-
promptButtonTexts,
|
|
66
62
|
} as Pick<
|
|
67
63
|
ChatPreviewComparisonProps['widgetContentProps'],
|
|
68
|
-
'headlineText' | 'messageText' | '
|
|
64
|
+
'headlineText' | 'messageText' | 'textFieldPlaceholderText' | 'titleLabel'
|
|
69
65
|
>;
|
|
70
66
|
|
|
71
67
|
const logoSrc = uiConfig?.lookAndFeel?.widgetLogoSrc;
|
|
@@ -73,11 +69,14 @@ const ChatPreviewComparisonWidgetHandler = (props: BaseWidgetProps) => {
|
|
|
73
69
|
const hideLogo = uiConfig?.lookAndFeel?.hideWidgetLogo;
|
|
74
70
|
|
|
75
71
|
const handlePromptButtonClick = useCallback(
|
|
76
|
-
(
|
|
77
|
-
|
|
72
|
+
(suggestion: Suggestion) => {
|
|
73
|
+
onSuggestionClicked(
|
|
74
|
+
suggestion,
|
|
75
|
+
ChatElementDisplayLocationV3.CHAT_PREVIEW_COMPARISON_PROMPT_BUTTON,
|
|
76
|
+
);
|
|
78
77
|
openChat(ChatElementDisplayLocationV3.CHAT_PREVIEW_COMPARISON_PROMPT_BUTTON);
|
|
79
78
|
},
|
|
80
|
-
[
|
|
79
|
+
[onSuggestionClicked, openChat],
|
|
81
80
|
);
|
|
82
81
|
|
|
83
82
|
const handleTextFieldClick = useCallback(() => {
|
|
@@ -109,7 +108,7 @@ const ChatPreviewComparisonWidgetHandler = (props: BaseWidgetProps) => {
|
|
|
109
108
|
titleLabel: hardCopyContent?.titleLabel,
|
|
110
109
|
headlineText: hardCopyContent?.headlineText,
|
|
111
110
|
messageText: hardCopyContent?.messageText,
|
|
112
|
-
|
|
111
|
+
promptButtons: suggestions,
|
|
113
112
|
textFieldPlaceholderText: hardCopyContent?.textFieldPlaceholderText,
|
|
114
113
|
images: images ?? [],
|
|
115
114
|
logoSrc: logoSrc ?? undefined,
|
|
@@ -6,7 +6,10 @@ import { chatAtom, lastAssistantMessageAtom } from '@envive-ai/react-hooks/atoms
|
|
|
6
6
|
|
|
7
7
|
import { Theme } from '@envive-ai/react-toolkit-v3/Tokens';
|
|
8
8
|
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
ChatElementDisplayLocationV3,
|
|
11
|
+
Suggestion,
|
|
12
|
+
} from '@envive-ai/react-hooks/application/models';
|
|
10
13
|
import { useCallback, useEffect, useMemo } from 'react';
|
|
11
14
|
import {
|
|
12
15
|
SpiffyMetricsEventName,
|
|
@@ -20,17 +23,13 @@ import { getMessageText } from '../utils/functions';
|
|
|
20
23
|
import { ChatPreviewLoadingWidgetWithBaseWidget } from '../ChatPreviewLoadingWidget/ChatPreviewLoadingWidget';
|
|
21
24
|
|
|
22
25
|
const ChatPreviewWidgetHandler = (props: BaseWidgetProps) => {
|
|
23
|
-
const {
|
|
26
|
+
const { onSuggestionClicked } = useSalesAgent();
|
|
24
27
|
const { openChat } = useChatToggle();
|
|
25
28
|
|
|
26
29
|
const lastAssistantMessage = useAtomValue(lastAssistantMessageAtom);
|
|
27
30
|
|
|
28
31
|
const { suggestions } = useAtomValue(chatAtom);
|
|
29
32
|
|
|
30
|
-
const promptButtonTexts = useMemo(() => {
|
|
31
|
-
return suggestions.map(suggestion => suggestion.content);
|
|
32
|
-
}, [suggestions]);
|
|
33
|
-
|
|
34
33
|
const messageText = useMemo(() => getMessageText(lastAssistantMessage), [lastAssistantMessage]);
|
|
35
34
|
|
|
36
35
|
const { hardcopyContent, widgetConfig, uiConfig, isLoading, widgetConfigId } = props;
|
|
@@ -42,11 +41,11 @@ const ChatPreviewWidgetHandler = (props: BaseWidgetProps) => {
|
|
|
42
41
|
const hardCopyContent = {
|
|
43
42
|
titleLabel: hardcopyContent?.values?.titleLabel,
|
|
44
43
|
textFieldPlaceholderText: hardcopyContent?.values?.textFieldPlaceholderText,
|
|
44
|
+
promptButtons: suggestions,
|
|
45
45
|
messageText,
|
|
46
|
-
promptButtonTexts,
|
|
47
46
|
} as Pick<
|
|
48
47
|
ChatPreviewProps['widgetContentProps'],
|
|
49
|
-
'messageText' | '
|
|
48
|
+
'messageText' | 'promptButtons' | 'textFieldPlaceholderText' | 'titleLabel'
|
|
50
49
|
>;
|
|
51
50
|
|
|
52
51
|
const { trackEvent } = useAmplitude();
|
|
@@ -66,11 +65,11 @@ const ChatPreviewWidgetHandler = (props: BaseWidgetProps) => {
|
|
|
66
65
|
const hideLogo = uiConfig?.lookAndFeel?.hideWidgetLogo;
|
|
67
66
|
|
|
68
67
|
const handlePromptButtonClick = useCallback(
|
|
69
|
-
(
|
|
70
|
-
|
|
68
|
+
(suggestion: Suggestion) => {
|
|
69
|
+
onSuggestionClicked(suggestion, ChatElementDisplayLocationV3.CHAT_PREVIEW_PROMPT_BUTTON);
|
|
71
70
|
openChat(ChatElementDisplayLocationV3.CHAT_PREVIEW_PROMPT_BUTTON);
|
|
72
71
|
},
|
|
73
|
-
[
|
|
72
|
+
[onSuggestionClicked, openChat],
|
|
74
73
|
);
|
|
75
74
|
|
|
76
75
|
const handleTextFieldClick = useCallback(() => {
|
|
@@ -97,7 +96,7 @@ const ChatPreviewWidgetHandler = (props: BaseWidgetProps) => {
|
|
|
97
96
|
const widgetContentProps: ChatPreviewProps['widgetContentProps'] = {
|
|
98
97
|
titleLabel: hardCopyContent?.titleLabel,
|
|
99
98
|
messageText: hardCopyContent?.messageText,
|
|
100
|
-
|
|
99
|
+
promptButtons: hardCopyContent?.promptButtons,
|
|
101
100
|
textFieldPlaceholderText: hardCopyContent?.textFieldPlaceholderText,
|
|
102
101
|
logoSrc: logoSrc ?? undefined,
|
|
103
102
|
};
|
|
@@ -21,7 +21,6 @@ export const FloatingChatOverlay = ({
|
|
|
21
21
|
previewMode = false,
|
|
22
22
|
}: FloatingChatOverlayProps) => {
|
|
23
23
|
const overlayClasses = classNames(
|
|
24
|
-
'envive-floating-chat-overlay',
|
|
25
24
|
previewMode ? 'envive-tw-absolute' : 'envive-tw-fixed',
|
|
26
25
|
'envive-tw-top-0',
|
|
27
26
|
'envive-tw-left-0',
|
|
@@ -32,7 +31,6 @@ export const FloatingChatOverlay = ({
|
|
|
32
31
|
);
|
|
33
32
|
|
|
34
33
|
const backdropClasses = classNames(
|
|
35
|
-
'envive-floating-chat-backdrop',
|
|
36
34
|
'envive-tw-absolute',
|
|
37
35
|
'envive-tw-top-0',
|
|
38
36
|
'envive-tw-left-0',
|
|
@@ -45,7 +43,6 @@ export const FloatingChatOverlay = ({
|
|
|
45
43
|
);
|
|
46
44
|
|
|
47
45
|
const overlayContentClasses = classNames(
|
|
48
|
-
'envive-floating-chat-overlay-content',
|
|
49
46
|
'envive-tw-relative',
|
|
50
47
|
'envive-tw-flex',
|
|
51
48
|
'envive-tw-justify-end',
|
|
@@ -63,6 +60,7 @@ export const FloatingChatOverlay = ({
|
|
|
63
60
|
<motion.div
|
|
64
61
|
key="floating-chat-overlay"
|
|
65
62
|
className={overlayClasses}
|
|
63
|
+
style={{ top: '0px' }}
|
|
66
64
|
initial={{ opacity: 0 }}
|
|
67
65
|
animate={{ opacity: 1 }}
|
|
68
66
|
exit={{ opacity: 0 }}
|
|
@@ -81,6 +79,7 @@ export const FloatingChatOverlay = ({
|
|
|
81
79
|
)}
|
|
82
80
|
<div
|
|
83
81
|
className={overlayContentClasses}
|
|
82
|
+
style={{ top: '0px' }}
|
|
84
83
|
onClick={onClose}
|
|
85
84
|
onKeyDown={e => {
|
|
86
85
|
if (e.key === 'Escape') {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useEffect, useMemo, useRef } from 'react';
|
|
1
|
+
import { Suspense, lazy, useEffect, useMemo, useRef } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
FloatingChatConfig,
|
|
4
4
|
LookAndFeelConfig,
|
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
SpiffyMetricsEventName,
|
|
9
9
|
useAmplitude,
|
|
10
10
|
} from '@envive-ai/react-hooks/contexts/amplitudeContext';
|
|
11
|
-
import { FloatingChat } from '@envive-ai/react-toolkit-v3/FloatingChat';
|
|
12
11
|
import { useSalesAgent } from '@envive-ai/react-hooks/contexts/salesAgentContext';
|
|
13
12
|
import { Theme } from '@envive-ai/react-toolkit-v3/Tokens';
|
|
14
13
|
import {
|
|
@@ -29,6 +28,10 @@ import { FLOATING_BUTTON_ID } from './constants';
|
|
|
29
28
|
import { CustomerServiceType } from '../../CXIntegration/types';
|
|
30
29
|
import { useFloatingButtonVisibility } from './hooks/useFloatingButtonVisibility';
|
|
31
30
|
|
|
31
|
+
const FloatingChat = lazy(async () => ({
|
|
32
|
+
default: (await import('@envive-ai/react-toolkit-v3/FloatingChat')).FloatingChat,
|
|
33
|
+
}));
|
|
34
|
+
|
|
32
35
|
interface FloatingChatWidgetHandlerProps extends BaseWidgetProps {
|
|
33
36
|
previewButtonOnly?: boolean;
|
|
34
37
|
previewChatAlwaysOpen?: boolean;
|
|
@@ -41,7 +44,7 @@ const FloatingChatWidgetHandler = (props: FloatingChatWidgetHandlerProps) => {
|
|
|
41
44
|
const { userHasInteractedValue } = useGetWidgetStatus();
|
|
42
45
|
|
|
43
46
|
// TODO: Get hardcopy
|
|
44
|
-
const { uiConfig, isUiConfigLoading } = props;
|
|
47
|
+
const { uiConfig, isUiConfigLoading, hardcopyContent } = props;
|
|
45
48
|
|
|
46
49
|
// TODO: Figure out the issue and reenable this functionality
|
|
47
50
|
// const { customerServiceIntegration } = uiConfig ?? {};
|
|
@@ -71,7 +74,7 @@ const FloatingChatWidgetHandler = (props: FloatingChatWidgetHandlerProps) => {
|
|
|
71
74
|
|
|
72
75
|
// Override isOpen for preview modes
|
|
73
76
|
const effectiveIsOpen = previewChatAlwaysOpen ? true : isOpen;
|
|
74
|
-
const effectiveShouldRenderFloatingButton = !
|
|
77
|
+
const effectiveShouldRenderFloatingButton = !effectiveIsOpen && shouldShowFloatingButton;
|
|
75
78
|
const buttonShouldRender = previewButtonOnly ? true : effectiveShouldRenderFloatingButton;
|
|
76
79
|
|
|
77
80
|
const theme = useMemo(() => {
|
|
@@ -111,20 +114,23 @@ const FloatingChatWidgetHandler = (props: FloatingChatWidgetHandlerProps) => {
|
|
|
111
114
|
}
|
|
112
115
|
previewMode={!!previewChatAlwaysOpen}
|
|
113
116
|
>
|
|
114
|
-
<
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
117
|
+
<Suspense>
|
|
118
|
+
<FloatingChat
|
|
119
|
+
theme={theme}
|
|
120
|
+
salesAgentData={salesAgentData}
|
|
121
|
+
hardcopyContent={hardcopyContent}
|
|
122
|
+
floatingChatConfig={uiConfig?.floatingChat ?? ({} as FloatingChatConfig)}
|
|
123
|
+
lookAndFeelConfig={uiConfig?.lookAndFeel ?? ({} as LookAndFeelConfig)}
|
|
124
|
+
isCXButtonSwitchEnabled={!!isSwitchEnabled?.()}
|
|
125
|
+
isFloatingChatOpen={effectiveIsOpen}
|
|
126
|
+
onToggleCXButton={toggle}
|
|
127
|
+
onClose={
|
|
128
|
+
previewChatAlwaysOpen
|
|
129
|
+
? () => {}
|
|
130
|
+
: () => closeChat(ChatElementDisplayLocationV3.FLOATING_CHAT_CLOSE_BUTTON)
|
|
131
|
+
}
|
|
132
|
+
/>
|
|
133
|
+
</Suspense>
|
|
128
134
|
</FloatingChatOverlay>
|
|
129
135
|
)}
|
|
130
136
|
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { ProductCardWidgetV3Config, WidgetTypeV3 } from '@envive-ai/react-hooks/contexts/typesV3';
|
|
2
|
+
import { PromptButtonVariant } from '@envive-ai/react-toolkit-v3/PromptButton/types';
|
|
3
|
+
import { useCallback, useEffect } from 'react';
|
|
4
|
+
import {
|
|
5
|
+
SpiffyMetricsEventName,
|
|
6
|
+
useAmplitude,
|
|
7
|
+
} from '@envive-ai/react-hooks/contexts/amplitudeContext';
|
|
8
|
+
import { ChatElementDisplayLocationV3 } from '@envive-ai/react-hooks/application/models';
|
|
9
|
+
import { useSalesAgent } from '@envive-ai/react-hooks/contexts/salesAgentContext';
|
|
10
|
+
import { useChatToggle } from '@envive-ai/react-hooks/hooks/ChatToggle';
|
|
11
|
+
import { ProductCard } from '@envive-ai/react-toolkit-v3/ProductCard';
|
|
12
|
+
import { Theme } from '@envive-ai/react-toolkit-v3/Tokens';
|
|
13
|
+
import { BaseWidgetProps, withBaseWidget } from '../../hocs/withBaseWidget';
|
|
14
|
+
|
|
15
|
+
const mockPrompts = [
|
|
16
|
+
'Loading prompt 1',
|
|
17
|
+
'Loading prompt 2',
|
|
18
|
+
'Loading prompt 3',
|
|
19
|
+
'Loading prompt 4',
|
|
20
|
+
'Loading prompt 5',
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
const mockHeadline = 'Loading...';
|
|
24
|
+
const mockAnimatedText = ['Loading...'];
|
|
25
|
+
|
|
26
|
+
const ProductCardWidgetHandler = (props: BaseWidgetProps) => {
|
|
27
|
+
const { onTypedMessageSubmitted } = useSalesAgent();
|
|
28
|
+
const { openChat } = useChatToggle();
|
|
29
|
+
const { hardcopyContent, widgetConfig, isLoading } = props;
|
|
30
|
+
|
|
31
|
+
const hardCopyHeadline = hardcopyContent?.values?.headline as string | undefined;
|
|
32
|
+
const headline = isLoading ? mockHeadline : hardCopyHeadline || '';
|
|
33
|
+
|
|
34
|
+
const hardCopyAnimatedText = (hardcopyContent?.values?.animatedText as string[]) || [];
|
|
35
|
+
const animatedText = isLoading ? mockAnimatedText : hardCopyAnimatedText;
|
|
36
|
+
|
|
37
|
+
const hardCopyPrompts = (hardcopyContent?.values?.prompts as string[]) || [];
|
|
38
|
+
const prompts = isLoading ? mockPrompts : hardCopyPrompts;
|
|
39
|
+
|
|
40
|
+
const hardCopyPlaceholder = hardcopyContent?.values?.placeholder as string | undefined;
|
|
41
|
+
const placeholder = hardCopyPlaceholder;
|
|
42
|
+
|
|
43
|
+
const productCardWidgetConfig = widgetConfig as ProductCardWidgetV3Config;
|
|
44
|
+
|
|
45
|
+
const carouselId = productCardWidgetConfig?.contentId || '';
|
|
46
|
+
const promptButtonType =
|
|
47
|
+
(productCardWidgetConfig?.promptButtonType as PromptButtonVariant) || PromptButtonVariant.LIGHT;
|
|
48
|
+
const italicizeHeadline = productCardWidgetConfig?.italicizeHeadline;
|
|
49
|
+
const fallbackColor = productCardWidgetConfig?.fallbackColor;
|
|
50
|
+
const imageSrc = productCardWidgetConfig?.imageSrc || '';
|
|
51
|
+
|
|
52
|
+
const { trackEvent } = useAmplitude();
|
|
53
|
+
|
|
54
|
+
const { widgetConfigId } = props;
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
trackEvent({
|
|
57
|
+
eventName: SpiffyMetricsEventName.ChatComponentVisible,
|
|
58
|
+
eventProps: {
|
|
59
|
+
widget_config_id: widgetConfigId,
|
|
60
|
+
widget_type: WidgetTypeV3.ProductCardV3,
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
}, [trackEvent, widgetConfigId]);
|
|
64
|
+
|
|
65
|
+
const handleSelect = useCallback(
|
|
66
|
+
(prompt: string) => {
|
|
67
|
+
onTypedMessageSubmitted({ query: prompt, userTyped: false });
|
|
68
|
+
openChat(ChatElementDisplayLocationV3.PRODUCT_CARD_PROMPT_BUTTON);
|
|
69
|
+
},
|
|
70
|
+
[onTypedMessageSubmitted, openChat],
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
const handleInputClick = useCallback(() => {
|
|
74
|
+
openChat(ChatElementDisplayLocationV3.PRODUCT_CARD_TEXT_FIELD);
|
|
75
|
+
}, [openChat]);
|
|
76
|
+
|
|
77
|
+
return (
|
|
78
|
+
<ProductCard
|
|
79
|
+
theme={Theme.GLOBAL_CUSTOM}
|
|
80
|
+
imageSrc={imageSrc}
|
|
81
|
+
fallbackColor={fallbackColor}
|
|
82
|
+
headline={headline}
|
|
83
|
+
italicizeHeadline={italicizeHeadline}
|
|
84
|
+
animatedText={animatedText}
|
|
85
|
+
prompts={prompts}
|
|
86
|
+
promptButtonType={promptButtonType}
|
|
87
|
+
carouselId={carouselId}
|
|
88
|
+
placeholder={placeholder}
|
|
89
|
+
textTypingDuration={800}
|
|
90
|
+
textTransition={2000}
|
|
91
|
+
onSelect={handleSelect}
|
|
92
|
+
onInputClick={handleInputClick}
|
|
93
|
+
/>
|
|
94
|
+
);
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const ProductCardWidgetWithBaseWidget = withBaseWidget<BaseWidgetProps>(ProductCardWidgetHandler);
|
|
98
|
+
|
|
99
|
+
export interface ProductCardWidgetProps {
|
|
100
|
+
widgetConfigId: string;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export const ProductCardWidget = ({ widgetConfigId }: ProductCardWidgetProps) => {
|
|
104
|
+
return (
|
|
105
|
+
<ProductCardWidgetWithBaseWidget
|
|
106
|
+
widgetConfigId={widgetConfigId}
|
|
107
|
+
widgetType={WidgetTypeV3.ProductCardV3}
|
|
108
|
+
/>
|
|
109
|
+
);
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
ProductCardWidget.displayName = 'ProductCardWidget';
|