@constructor-io/constructorio-ui-pia 2.1.0 → 2.1.2

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 (120) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +219 -15
  3. package/dist/constructorio-ui-pia-bundled.js +12 -12
  4. package/lib/cjs/components/Answer/Answer.js +13 -0
  5. package/lib/cjs/components/Answer/AnswerStyles.css +8 -0
  6. package/lib/cjs/components/CioPia/CioPia.js +76 -0
  7. package/lib/cjs/components/CioPia/CioPiaStyles.css +32 -0
  8. package/lib/cjs/components/CioPia/Disclaimer.js +16 -0
  9. package/lib/cjs/components/CioPia/PiaCustomCarousel.js +41 -0
  10. package/lib/cjs/components/CioPia/index.js +6 -0
  11. package/lib/cjs/components/ConversationHistory/ConversationHistory.js +36 -0
  12. package/lib/cjs/components/ConversationHistory/ConversationHistoryStyles.css +51 -0
  13. package/lib/cjs/components/Error/ErrorBlock.js +23 -0
  14. package/lib/cjs/components/Error/ErrorStyles.css +46 -0
  15. package/lib/cjs/components/Feedback/Feedback.js +28 -0
  16. package/lib/cjs/components/Feedback/FeedbackStyles.css +31 -0
  17. package/lib/cjs/components/Input/Input.js +40 -0
  18. package/lib/cjs/components/Input/InputStyles.css +102 -0
  19. package/lib/cjs/components/LoadingSkeleton/LoadingSkeleton.js +11 -0
  20. package/lib/cjs/components/LoadingSkeleton/LoadingSkeletonStyles.css +32 -0
  21. package/lib/cjs/components/PiaConversation/PiaConversation.js +20 -0
  22. package/lib/cjs/components/PiaConversation/PiaConversationStyles.css +91 -0
  23. package/lib/cjs/components/PiaConversation/PiaModal.js +74 -0
  24. package/lib/cjs/components/SuggestedQuestion/SuggestedQuestion.js +16 -0
  25. package/lib/cjs/components/SuggestedQuestion/SuggestedQuestionStyles.css +33 -0
  26. package/lib/cjs/components/SuggestedQuestionsContainer/SuggestedQuestionsContainer.js +14 -0
  27. package/lib/cjs/components/SuggestedQuestionsContainer/SuggestedQuestionsContainerStyles.css +37 -0
  28. package/lib/cjs/components/SuggestedQuestionsContainer/SuggestedQuestionsSkeleton.js +11 -0
  29. package/lib/cjs/constants.js +17 -0
  30. package/lib/cjs/hooks/mocks/MockConstructorIOClient.js +20 -0
  31. package/lib/cjs/hooks/mocks/agent.js +146 -0
  32. package/lib/cjs/hooks/mocks/types.js +2 -0
  33. package/lib/cjs/hooks/useAnswerResults.js +62 -0
  34. package/lib/cjs/hooks/useCioClient.js +21 -0
  35. package/lib/cjs/hooks/useCioPia.js +29 -0
  36. package/lib/cjs/hooks/useConversation.js +74 -0
  37. package/lib/cjs/hooks/useSuggestedQuestions.js +52 -0
  38. package/lib/cjs/stories/assets/storybook-styles.css +112 -0
  39. package/lib/cjs/styles.css +26 -0
  40. package/lib/cjs/types.js +10 -0
  41. package/lib/cjs/utils/index.js +4 -0
  42. package/lib/cjs/utils/styleHelpers.js +14 -0
  43. package/lib/cjs/utils/transformers.js +29 -0
  44. package/lib/cjs/utils/translate.js +29 -0
  45. package/lib/cjs/version.js +3 -0
  46. package/lib/mjs/components/Answer/Answer.js +10 -0
  47. package/lib/mjs/components/Answer/AnswerStyles.css +8 -0
  48. package/lib/mjs/components/CioPia/CioPia.js +72 -0
  49. package/lib/mjs/components/CioPia/CioPiaStyles.css +32 -0
  50. package/lib/mjs/components/CioPia/Disclaimer.js +12 -0
  51. package/lib/mjs/components/CioPia/PiaCustomCarousel.js +37 -0
  52. package/lib/mjs/components/CioPia/index.js +3 -0
  53. package/lib/mjs/components/ConversationHistory/ConversationHistory.js +32 -0
  54. package/lib/mjs/components/ConversationHistory/ConversationHistoryStyles.css +51 -0
  55. package/lib/mjs/components/Error/ErrorBlock.js +20 -0
  56. package/lib/mjs/components/Error/ErrorStyles.css +46 -0
  57. package/lib/mjs/components/Feedback/Feedback.js +24 -0
  58. package/lib/mjs/components/Feedback/FeedbackStyles.css +31 -0
  59. package/lib/mjs/components/Input/Input.js +37 -0
  60. package/lib/mjs/components/Input/InputStyles.css +102 -0
  61. package/lib/mjs/components/LoadingSkeleton/LoadingSkeleton.js +7 -0
  62. package/lib/mjs/components/LoadingSkeleton/LoadingSkeletonStyles.css +32 -0
  63. package/lib/mjs/components/PiaConversation/PiaConversation.js +16 -0
  64. package/lib/mjs/components/PiaConversation/PiaConversationStyles.css +91 -0
  65. package/lib/mjs/components/PiaConversation/PiaModal.js +70 -0
  66. package/lib/mjs/components/SuggestedQuestion/SuggestedQuestion.js +13 -0
  67. package/lib/mjs/components/SuggestedQuestion/SuggestedQuestionStyles.css +33 -0
  68. package/lib/mjs/components/SuggestedQuestionsContainer/SuggestedQuestionsContainer.js +10 -0
  69. package/lib/mjs/components/SuggestedQuestionsContainer/SuggestedQuestionsContainerStyles.css +37 -0
  70. package/lib/mjs/components/SuggestedQuestionsContainer/SuggestedQuestionsSkeleton.js +7 -0
  71. package/lib/mjs/constants.js +14 -0
  72. package/lib/mjs/hooks/mocks/MockConstructorIOClient.js +35 -0
  73. package/lib/mjs/hooks/mocks/agent.js +138 -0
  74. package/lib/mjs/hooks/mocks/types.js +1 -0
  75. package/lib/mjs/hooks/useAnswerResults.js +57 -0
  76. package/lib/mjs/hooks/useCioClient.js +23 -0
  77. package/lib/mjs/hooks/useCioPia.js +25 -0
  78. package/lib/mjs/hooks/useConversation.js +71 -0
  79. package/lib/mjs/hooks/useSuggestedQuestions.js +48 -0
  80. package/lib/mjs/index.js +6 -0
  81. package/lib/mjs/stories/assets/storybook-styles.css +112 -0
  82. package/lib/mjs/styles.css +26 -0
  83. package/lib/mjs/types.js +6 -0
  84. package/lib/mjs/utils/index.js +1 -0
  85. package/lib/mjs/utils/styleHelpers.js +9 -0
  86. package/lib/mjs/utils/transformers.js +30 -0
  87. package/lib/mjs/utils/translate.js +25 -0
  88. package/lib/mjs/version.js +1 -0
  89. package/lib/types/components/Answer/Answer.d.ts +9 -0
  90. package/lib/types/components/CioPia/CioPia.d.ts +17 -0
  91. package/lib/types/components/CioPia/Disclaimer.d.ts +8 -0
  92. package/lib/types/components/CioPia/PiaCustomCarousel.d.ts +10 -0
  93. package/lib/types/components/CioPia/index.d.ts +3 -0
  94. package/lib/types/components/ConversationHistory/ConversationHistory.d.ts +14 -0
  95. package/lib/types/components/Error/ErrorBlock.d.ts +7 -0
  96. package/lib/types/components/Feedback/Feedback.d.ts +10 -0
  97. package/lib/types/components/Input/Input.d.ts +12 -0
  98. package/lib/types/components/LoadingSkeleton/LoadingSkeleton.d.ts +2 -0
  99. package/lib/types/components/PiaConversation/PiaConversation.d.ts +8 -0
  100. package/lib/types/components/PiaConversation/PiaModal.d.ts +12 -0
  101. package/lib/types/components/SuggestedQuestion/SuggestedQuestion.d.ts +7 -0
  102. package/lib/types/components/SuggestedQuestionsContainer/SuggestedQuestionsContainer.d.ts +10 -0
  103. package/lib/types/components/SuggestedQuestionsContainer/SuggestedQuestionsSkeleton.d.ts +2 -0
  104. package/lib/types/constants.d.ts +8 -0
  105. package/lib/types/hooks/mocks/MockConstructorIOClient.d.ts +14 -0
  106. package/lib/types/hooks/mocks/agent.d.ts +10 -0
  107. package/lib/types/hooks/mocks/types.d.ts +75 -0
  108. package/lib/types/hooks/useAnswerResults.d.ts +18 -0
  109. package/lib/types/hooks/useCioClient.d.ts +13 -0
  110. package/lib/types/hooks/useCioPia.d.ts +17 -0
  111. package/lib/types/hooks/useConversation.d.ts +19 -0
  112. package/lib/types/hooks/useSuggestedQuestions.d.ts +16 -0
  113. package/lib/types/index.d.ts +5 -0
  114. package/lib/types/types.d.ts +102 -0
  115. package/lib/types/utils/index.d.ts +1 -0
  116. package/lib/types/utils/styleHelpers.d.ts +1 -0
  117. package/lib/types/utils/transformers.d.ts +7 -0
  118. package/lib/types/utils/translate.d.ts +10 -0
  119. package/lib/types/version.d.ts +2 -0
  120. package/package.json +15 -4
@@ -0,0 +1,31 @@
1
+ .cio-pia-feedback-container {
2
+ display: flex;
3
+ align-items: center;
4
+ justify-content: start;
5
+ height: 20px;
6
+ gap: 8px;
7
+ }
8
+
9
+ .cio-pia-feedback-text {
10
+ font-size: 12px;
11
+ font-weight: 400;
12
+ letter-spacing: -0.5%;
13
+ color: rgba(15, 19, 36, 0.7);
14
+ }
15
+
16
+ .cio-pia-feedback-button {
17
+ display: flex;
18
+ align-items: center;
19
+ justify-content: center;
20
+ width: fit-content;
21
+ background: none;
22
+ border: 0px;
23
+ cursor: pointer;
24
+ padding: 0;
25
+ transition: transform 0.2s ease;
26
+ position: relative;
27
+ }
28
+
29
+ .cio-pia-feedback-button:hover {
30
+ opacity: 0.8;
31
+ }
@@ -0,0 +1,37 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import { translate } from '../../utils/translate';
3
+ function SendIcon() {
4
+ return (React.createElement("svg", { width: '16', height: '16', viewBox: '0 0 16 16', fill: 'none', xmlns: 'http://www.w3.org/2000/svg' },
5
+ React.createElement("g", { id: '.icon-send' },
6
+ React.createElement("path", { id: 'Vector', d: 'M14.8934 7.09533L14.8884 7.09314L1.54219 1.55752C1.42993 1.51053 1.30778 1.49211 1.18666 1.50388C1.06554 1.51566 0.949225 1.55728 0.848125 1.62502C0.741311 1.69501 0.653573 1.79045 0.592805 1.90277C0.532037 2.01509 0.500145 2.14075 0.5 2.26845V5.80877C0.50006 5.98335 0.561019 6.15243 0.67237 6.28689C0.783722 6.42134 0.938491 6.51274 1.11 6.54533L8.38906 7.89127C8.41767 7.89669 8.44348 7.91193 8.46205 7.93435C8.48062 7.95677 8.49078 7.98497 8.49078 8.01408C8.49078 8.04319 8.48062 8.07139 8.46205 8.09381C8.44348 8.11623 8.41767 8.13147 8.38906 8.13689L1.11031 9.48283C0.938851 9.51533 0.784092 9.60661 0.67269 9.74094C0.561288 9.87528 0.500219 10.0443 0.5 10.2188V13.7597C0.499917 13.8816 0.530111 14.0017 0.587871 14.1091C0.645632 14.2165 0.729152 14.3079 0.830938 14.375C0.953375 14.4564 1.09706 14.4998 1.24406 14.5C1.34626 14.4999 1.4474 14.4794 1.54156 14.4397L14.8875 8.93564L14.8934 8.93283C15.0731 8.85563 15.2262 8.72745 15.3337 8.56415C15.4413 8.40086 15.4986 8.20961 15.4986 8.01408C15.4986 7.81855 15.4413 7.6273 15.3337 7.46401C15.2262 7.30071 15.0731 7.17253 14.8934 7.09533Z', fill: 'white' }))));
7
+ }
8
+ function Input({ value: providedValue, placeholder, disabled = false, onSubmit, translations, }) {
9
+ const [value, setValue] = useState(providedValue || '');
10
+ useEffect(() => {
11
+ if (providedValue) {
12
+ setValue(providedValue);
13
+ }
14
+ }, [providedValue]);
15
+ const handleSubmit = () => {
16
+ if (value.trim()) {
17
+ onSubmit(value.trim());
18
+ setValue('');
19
+ }
20
+ };
21
+ const handleSubmitOnEnter = (e) => {
22
+ if (e.key === 'Enter') {
23
+ e.preventDefault();
24
+ handleSubmit();
25
+ }
26
+ };
27
+ // Priority: translations > placeholder prop > default
28
+ const resolvedPlaceholder = translations?.['Ask anything'] !== undefined
29
+ ? translate('Ask anything', translations)
30
+ : (placeholder ?? translate('Ask anything'));
31
+ return (React.createElement("div", { className: 'cio-pia-input-container' },
32
+ React.createElement("input", { type: 'text', value: value, onChange: (e) => setValue(e.target.value), onKeyDown: handleSubmitOnEnter, placeholder: resolvedPlaceholder, disabled: disabled, className: 'cio-pia-input' }),
33
+ React.createElement("button", { type: 'button', onClick: handleSubmit, className: 'cio-pia-send-button', disabled: disabled },
34
+ translate('Send', translations),
35
+ React.createElement(SendIcon, null))));
36
+ }
37
+ export default Input;
@@ -0,0 +1,102 @@
1
+ /* Input Container */
2
+ .cio-pia-input-container {
3
+ display: flex;
4
+ width: 100%;
5
+ height: 40px;
6
+ position: relative;
7
+ gap: 8px;
8
+ }
9
+
10
+ /* Input */
11
+ .cio-pia-input {
12
+ width: 100%;
13
+ padding: 8px 80px 8px 12px;
14
+ border: 1px solid #dee0e3;
15
+ border-radius: 4px;
16
+ font-size: 14px;
17
+ background: #ffffff;
18
+ box-shadow:
19
+ 1px 1px 2px 0px rgba(18, 18, 105, 0.1) inset,
20
+ 0px 1px 4px 0px rgba(18, 18, 105, 0.05) inset,
21
+ 1px 1px 1px 0px rgba(18, 18, 105, 0.05) inset;
22
+ }
23
+
24
+ /* Input Hover */
25
+ .cio-pia-input:hover {
26
+ border: 1px solid #c8cad0;
27
+ }
28
+
29
+ /* Input Focus */
30
+ .cio-pia-input:focus {
31
+ outline: none;
32
+ border: 1px solid #a980ff;
33
+ box-shadow: 0px 0px 0px 2px rgba(201, 176, 254, 0.7);
34
+ }
35
+
36
+ /* Input Active */
37
+ .cio-pia-input:focus:active {
38
+ outline: none;
39
+ border: 1px solid #000000;
40
+ box-shadow:
41
+ 0px 1px 4px 0px rgba(18, 18, 105, 0.14) inset,
42
+ 2.1px 2px 2px 0px rgba(18, 18, 105, 0.1) inset,
43
+ 0px 1.5px 3px 0px rgba(18, 18, 105, 0.05) inset;
44
+ }
45
+
46
+ /* Input Placeholder */
47
+ .cio-pia-input::placeholder {
48
+ display: none;
49
+ }
50
+
51
+ /* Input Disabled */
52
+ .cio-pia-input:disabled {
53
+ border: 1px solid #e9eaec;
54
+ cursor: not-allowed;
55
+ box-shadow: none;
56
+ }
57
+
58
+ /* Input Disabled Placeholder */
59
+ .cio-pia-input:disabled::placeholder {
60
+ color: #ffffff;
61
+ }
62
+
63
+ /* Send Button */
64
+ .cio-pia-send-button {
65
+ display: flex;
66
+ align-items: center;
67
+ gap: 6px;
68
+ background: #14151a;
69
+ color: #ffffff;
70
+ border: none;
71
+ border-radius: 4px;
72
+ padding: 4px 8px;
73
+ cursor: pointer;
74
+ font-size: 13px;
75
+ font-weight: 500;
76
+ position: absolute;
77
+ right: 8px;
78
+ top: 50%;
79
+ transform: translateY(-50%);
80
+ box-shadow:
81
+ 0px 0.4px 1px 0px rgba(18, 18, 105, 0.13),
82
+ 0px 0.9px 6px 0px rgba(18, 18, 105, 0.05),
83
+ 0px 1px 3px 0px rgba(18, 18, 105, 0.05);
84
+ }
85
+
86
+ /* Send Button */
87
+ .cio-pia-send-button:hover {
88
+ background: #2b2d36;
89
+ }
90
+
91
+ /* Send Button Disabled */
92
+ .cio-pia-send-button:disabled {
93
+ background: #e9eaec;
94
+ color: #0a0f2940;
95
+ border: none;
96
+ box-shadow: none;
97
+ }
98
+
99
+ /* Send Button Disabled SVG */
100
+ .cio-pia-send-button:disabled svg path {
101
+ fill: #0a0f2940;
102
+ }
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ export default function LoadingSkeleton() {
3
+ return (React.createElement("div", { className: 'cio-pia-loading-skeleton', "data-testid": 'loading-skeleton' },
4
+ React.createElement("div", { className: 'skeleton-bar' }),
5
+ React.createElement("div", { className: 'skeleton-bar' }),
6
+ React.createElement("div", { className: 'skeleton-bar skeleton-short' })));
7
+ }
@@ -0,0 +1,32 @@
1
+ .cio-pia-loading-skeleton {
2
+ min-width: 430px;
3
+ max-width: 100%;
4
+ display: flex;
5
+ flex-direction: column;
6
+ gap: 8px;
7
+ }
8
+
9
+ .skeleton-bar {
10
+ background-color: rgba(0, 0, 0, 0.05);
11
+ height: 16px;
12
+ border-radius: 4px;
13
+ width: 100%;
14
+ animation: loading-animation 2s infinite ease-in-out;
15
+ }
16
+
17
+ .skeleton-short {
18
+ width: 80%;
19
+ }
20
+
21
+ /* Animation for the loader */
22
+ @keyframes loading-animation {
23
+ 0% {
24
+ background-color: rgba(0, 0, 0, 0.05);
25
+ }
26
+ 50% {
27
+ background-color: rgba(0, 0, 0, 0.1);
28
+ }
29
+ 100% {
30
+ background-color: rgba(0, 0, 0, 0.05);
31
+ }
32
+ }
@@ -0,0 +1,16 @@
1
+ import React from 'react';
2
+ import Input from '../Input/Input';
3
+ import SuggestedQuestionsContainer from '../SuggestedQuestionsContainer/SuggestedQuestionsContainer';
4
+ import SuggestedQuestionsSkeleton from '../SuggestedQuestionsContainer/SuggestedQuestionsSkeleton';
5
+ import { translate } from '../../utils/translate';
6
+ import ConversationHistory from '../ConversationHistory/ConversationHistory';
7
+ export default function PiaConversation({ conversationHistory, isLoading, error, currentItems, showFeedback, learnMoreUrl, translations, callbacks, componentOverrides, displayedQuestions, handleSubmitQuestion, }) {
8
+ const hasHistory = conversationHistory.length > 0;
9
+ return (React.createElement("div", { className: 'cio-pia-container cio-pia-conversation', "data-testid": 'cio-pia-container' },
10
+ !hasHistory && (React.createElement("p", { className: 'cio-pia-title', "data-testid": 'cio-pia-title' }, translate('Any questions about this product?', translations))),
11
+ React.createElement(ConversationHistory, { conversationHistory: conversationHistory, isLoading: isLoading, error: error, currentItems: currentItems, showFeedback: showFeedback, learnMoreUrl: learnMoreUrl, translations: translations, callbacks: callbacks, componentOverrides: componentOverrides }),
12
+ React.createElement("div", { className: 'cio-pia-conversation-footer' },
13
+ isLoading && !error && React.createElement(SuggestedQuestionsSkeleton, null),
14
+ !isLoading && !error && (React.createElement(SuggestedQuestionsContainer, { questions: displayedQuestions, onQuestionClick: handleSubmitQuestion, componentOverride: componentOverrides?.suggestedQuestions })),
15
+ React.createElement(Input, { onSubmit: handleSubmitQuestion, disabled: isLoading, translations: translations }))));
16
+ }
@@ -0,0 +1,91 @@
1
+ .cio-pia-conversation {
2
+ max-height: var(--cio-pia-conversation-max-height);
3
+ }
4
+
5
+ .cio-pia-conversation-footer {
6
+ display: flex;
7
+ flex-direction: column;
8
+ gap: 8px;
9
+ flex-shrink: 0;
10
+ }
11
+
12
+ body.cio-pia-modal-open {
13
+ overflow: hidden;
14
+ }
15
+
16
+ .cio-pia-modal {
17
+ border: none;
18
+ border-radius: 12px;
19
+ padding: 0;
20
+ width: 90%;
21
+ max-width: var(--cio-pia-modal-max-width);
22
+ min-width: var(--cio-pia-modal-min-width);
23
+ max-height: var(--cio-pia-modal-height);
24
+ overflow: hidden;
25
+ box-shadow:
26
+ 0px 8px 32px rgba(0, 0, 0, 0.12),
27
+ 0px 2px 8px rgba(0, 0, 0, 0.08);
28
+ }
29
+
30
+ .cio-pia-modal::backdrop {
31
+ background: rgba(0, 0, 0, 0.5);
32
+ }
33
+
34
+ .cio-pia-modal-content {
35
+ display: flex;
36
+ flex-direction: column;
37
+ height: var(--cio-pia-modal-height);
38
+ max-height: var(--cio-pia-modal-height);
39
+ }
40
+
41
+ .cio-pia-modal-header {
42
+ display: flex;
43
+ align-items: center;
44
+ justify-content: space-between;
45
+ padding: 16px 20px;
46
+ box-shadow: 0px 1px 4px 0px rgba(18, 18, 105, 0.1);
47
+ flex-shrink: 0;
48
+ }
49
+
50
+ .cio-pia-modal-close-button {
51
+ background: none;
52
+ border: none;
53
+ cursor: pointer;
54
+ padding: 4px;
55
+ display: flex;
56
+ align-items: center;
57
+ color: rgba(15, 19, 36, 0.6);
58
+ border-radius: 4px;
59
+ }
60
+
61
+ .cio-pia-modal-close-button:hover {
62
+ color: #14151a;
63
+ background: rgba(0, 0, 0, 0.05);
64
+ }
65
+
66
+ .cio-pia-modal-body {
67
+ flex: 1;
68
+ overflow: hidden;
69
+ display: flex;
70
+ flex-direction: column;
71
+ }
72
+
73
+ .cio-pia-modal-body .cio-pia-conversation {
74
+ max-height: none;
75
+ flex: 1;
76
+ min-height: 0;
77
+ }
78
+
79
+ .cio-pia-modal-body .cio-pia-conversation-history {
80
+ max-height: none;
81
+ flex: 1;
82
+ padding: 16px 20px 0;
83
+ }
84
+
85
+ .cio-pia-modal-body .cio-pia-conversation-footer {
86
+ padding: 0 20px 20px;
87
+ }
88
+
89
+ .cio-pia-modal-body .cio-pia-title {
90
+ padding: 0 20px;
91
+ }
@@ -0,0 +1,70 @@
1
+ import React, { useCallback, useEffect, useRef, useState } from 'react';
2
+ import Input from '../Input/Input';
3
+ import { translate } from '../../utils/translate';
4
+ import SuggestedQuestionsContainer from '../SuggestedQuestionsContainer/SuggestedQuestionsContainer';
5
+ const OVERFLOW_HIDDEN_CLASS = 'cio-pia-modal-open';
6
+ function CloseIcon() {
7
+ return (React.createElement("svg", { width: '20', height: '20', viewBox: '0 0 20 20', fill: 'none', xmlns: 'http://www.w3.org/2000/svg' },
8
+ React.createElement("path", { d: 'M15.8334 5.34166L14.6584 4.16666L10.0001 8.82499L5.34175 4.16666L4.16675 5.34166L8.82508 9.99999L4.16675 14.6583L5.34175 15.8333L10.0001 11.175L14.6584 15.8333L15.8334 14.6583L11.1751 9.99999L15.8334 5.34166Z', fill: 'currentColor' })));
9
+ }
10
+ export default function PiaModal({ initialQuestions, handleSubmitQuestion, isLoading, componentOverrides, translations, onClose, children, }) {
11
+ const [isOpen, setIsOpen] = useState(false);
12
+ const dialogRef = useRef(null);
13
+ const openModal = useCallback(() => {
14
+ setIsOpen(true);
15
+ }, []);
16
+ const closeModal = useCallback(() => {
17
+ setIsOpen(false);
18
+ onClose?.();
19
+ }, [onClose]);
20
+ useEffect(() => {
21
+ const dialog = dialogRef.current;
22
+ if (!dialog)
23
+ return undefined;
24
+ if (isOpen) {
25
+ dialog.showModal();
26
+ document.body.classList.add(OVERFLOW_HIDDEN_CLASS);
27
+ }
28
+ else if (dialog.open) {
29
+ dialog.close();
30
+ document.body.classList.remove(OVERFLOW_HIDDEN_CLASS);
31
+ }
32
+ return () => {
33
+ document.body.classList.remove(OVERFLOW_HIDDEN_CLASS);
34
+ };
35
+ }, [isOpen]);
36
+ useEffect(() => {
37
+ const dialog = dialogRef.current;
38
+ if (!dialog)
39
+ return undefined;
40
+ const handleCancel = (e) => {
41
+ e.preventDefault();
42
+ closeModal();
43
+ };
44
+ const handleClick = (e) => {
45
+ if (e.target === dialog)
46
+ closeModal();
47
+ };
48
+ dialog.addEventListener('cancel', handleCancel);
49
+ dialog.addEventListener('click', handleClick);
50
+ return () => {
51
+ dialog.removeEventListener('cancel', handleCancel);
52
+ dialog.removeEventListener('click', handleClick);
53
+ };
54
+ }, [closeModal]);
55
+ const handleQuestion = useCallback((question) => {
56
+ handleSubmitQuestion(question);
57
+ openModal();
58
+ }, [handleSubmitQuestion, openModal]);
59
+ return (React.createElement("div", { className: 'cio-pia-container', "data-testid": 'cio-pia-container' },
60
+ React.createElement("p", { className: 'cio-pia-title', "data-testid": 'cio-pia-title' }, translate('Any questions about this product?', translations)),
61
+ React.createElement(Input, { onSubmit: handleQuestion, disabled: isLoading || isOpen, translations: translations }),
62
+ initialQuestions.length > 0 && (React.createElement(SuggestedQuestionsContainer, { questions: initialQuestions, onQuestionClick: handleQuestion, componentOverride: componentOverrides?.suggestedQuestions })),
63
+ React.createElement("dialog", { ref: dialogRef, className: 'cio-pia-modal', "aria-labelledby": 'cio-pia-modal-title' },
64
+ React.createElement("div", { className: 'cio-pia-modal-content' },
65
+ React.createElement("div", { className: 'cio-pia-modal-header' },
66
+ React.createElement("p", { className: 'cio-pia-title', id: 'cio-pia-modal-title' }, translate('Ask about this product', translations)),
67
+ React.createElement("button", { type: 'button', className: 'cio-pia-modal-close-button', "aria-label": 'Close', onClick: closeModal },
68
+ React.createElement(CloseIcon, null))),
69
+ React.createElement("div", { className: 'cio-pia-modal-body' }, children)))));
70
+ }
@@ -0,0 +1,13 @@
1
+ import React from 'react';
2
+ function QuestionSvg() {
3
+ return (React.createElement("div", { className: 'cio-pia-suggested-question-icon' },
4
+ React.createElement("svg", { width: '16', height: '16', viewBox: '0 0 16 16', fill: 'none', xmlns: 'http://www.w3.org/2000/svg' },
5
+ React.createElement("g", { id: 'help' },
6
+ React.createElement("path", { id: 'Vector', d: 'M8.00004 1.33331C4.32004 1.33331 1.33337 4.31998 1.33337 7.99998C1.33337 11.68 4.32004 14.6666 8.00004 14.6666C11.68 14.6666 14.6667 11.68 14.6667 7.99998C14.6667 4.31998 11.68 1.33331 8.00004 1.33331ZM8.66671 12.6666H7.33337V11.3333H8.66671V12.6666ZM10.0467 7.49998L9.44671 8.11331C8.96671 8.59998 8.66671 8.99998 8.66671 9.99998H7.33337V9.66665C7.33337 8.93331 7.63337 8.26665 8.11337 7.77998L8.94004 6.93998C9.18671 6.69998 9.33337 6.36665 9.33337 5.99998C9.33337 5.26665 8.73337 4.66665 8.00004 4.66665C7.26671 4.66665 6.66671 5.26665 6.66671 5.99998H5.33337C5.33337 4.52665 6.52671 3.33331 8.00004 3.33331C9.47337 3.33331 10.6667 4.52665 10.6667 5.99998C10.6667 6.58665 10.4267 7.11998 10.0467 7.49998Z', fill: '#0F1324', fillOpacity: '0.6' })))));
7
+ }
8
+ function SuggestedQuestion({ question, onClick }) {
9
+ return (React.createElement("button", { type: 'button', className: 'cio-pia-suggested-question', onClick: onClick },
10
+ React.createElement(QuestionSvg, null),
11
+ question));
12
+ }
13
+ export default SuggestedQuestion;
@@ -0,0 +1,33 @@
1
+ .cio-pia-suggested-question {
2
+ background: #ffffff;
3
+ border: 1px solid #dee0e3;
4
+ border-radius: 4px;
5
+ padding: 4px 12px 4px 4px;
6
+ display: flex;
7
+ flex: 0 0 auto;
8
+ justify-content: center;
9
+ align-items: center;
10
+ min-width: fit-content;
11
+ font-size: 12px;
12
+ font-style: normal;
13
+ font-weight: 500;
14
+ color: #14151a;
15
+ cursor: pointer;
16
+ box-shadow:
17
+ 0px 0.4px 1px 0px rgba(18, 18, 105, 0.13),
18
+ 0px 0.9px 6px 0px rgba(18, 18, 105, 0.05),
19
+ 0px 1px 3px 0px rgba(18, 18, 105, 0.05);
20
+ gap: 2px;
21
+ transition: all 0.2s ease;
22
+ }
23
+
24
+ .cio-pia-suggested-question:hover {
25
+ background-color: #f8f9fa;
26
+ border-color: #c4c7cc;
27
+ transform: translateY(-1px);
28
+ }
29
+
30
+ .cio-pia-suggested-question-icon {
31
+ display: flex;
32
+ padding: 4px;
33
+ }
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import { RenderPropsWrapper, } from '@constructor-io/constructorio-ui-components';
3
+ import SuggestedQuestion from '../SuggestedQuestion/SuggestedQuestion';
4
+ export default function SuggestedQuestionsContainer({ questions, onQuestionClick, componentOverride, }) {
5
+ if (!questions || questions.length === 0) {
6
+ return null;
7
+ }
8
+ return (React.createElement(RenderPropsWrapper, { props: { questions, onQuestionClick }, override: componentOverride?.reactNode },
9
+ React.createElement("div", { className: 'cio-pia-suggested-questions-container', "data-testid": 'suggested-questions-list' }, questions.map((question) => (React.createElement(SuggestedQuestion, { key: question.value, question: question.value, onClick: () => onQuestionClick(question.value) }))))));
10
+ }
@@ -0,0 +1,37 @@
1
+ .cio-pia-suggested-questions-container {
2
+ display: grid;
3
+ grid-template-columns: repeat(3, 1fr);
4
+ gap: 16px;
5
+ width: 100%;
6
+ }
7
+
8
+ @media (max-width: 768px) {
9
+ .cio-pia-suggested-questions-container {
10
+ display: flex;
11
+ flex-wrap: nowrap;
12
+ overflow-x: auto;
13
+ gap: 8px;
14
+ padding: 4px 0px;
15
+ width: 100%;
16
+ max-width: 85vw;
17
+
18
+ scroll-behavior: smooth;
19
+ scrollbar-width: none;
20
+ }
21
+ }
22
+
23
+ .cio-pia-suggested-question-skeleton {
24
+ height: 28px;
25
+ border-radius: 4px;
26
+ background-color: rgba(0, 0, 0, 0.05);
27
+ animation: loading-animation 2s infinite ease-in-out;
28
+ &:nth-child(1) {
29
+ animation-delay: 0.3s;
30
+ }
31
+ &:nth-child(2) {
32
+ animation-delay: 0.6s;
33
+ }
34
+ &:nth-child(3) {
35
+ animation-delay: 0.9s;
36
+ }
37
+ }
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ export default function SuggestedQuestionsSkeleton() {
3
+ return (React.createElement("div", { className: 'cio-pia-suggested-questions-container', "data-testid": 'suggested-questions-skeleton', "aria-busy": 'true', "aria-label": 'Loading suggestions' },
4
+ React.createElement("div", { className: 'cio-pia-suggested-question-skeleton' }),
5
+ React.createElement("div", { className: 'cio-pia-suggested-question-skeleton' }),
6
+ React.createElement("div", { className: 'cio-pia-suggested-question-skeleton' })));
7
+ }
@@ -0,0 +1,14 @@
1
+ // eslint-disable-next-line import/prefer-default-export
2
+ export const DEMO_API_KEY = 'key_13TO6qN9H3BP3Wrn';
3
+ export const DEMO_ITEM_ID = '149100215';
4
+ export const DEMO_QUESTION = 'What is the nutritional content of this shake?';
5
+ export const DEMO_QUESTION_ALTERNATIVE_PRODUCTS = 'What alternative products are available for this item?';
6
+ export const MOCK_QUESTIONS = [
7
+ { value: 'What is the nutritional content per serving?' },
8
+ { value: 'How many calories does each bottle contain?' },
9
+ { value: 'What is the shelf life of this product?' },
10
+ { value: 'Is this shake suitable for specific dietary needs?' },
11
+ { value: 'What flavor options are available for Ensure shakes?' },
12
+ { value: 'What is the serving size and calorie count?' },
13
+ ];
14
+ export const DISCLAIMER_TEXT = 'AI-generated answers aim to help, but they may occasionally miss details or be inaccurate. Double-check important information before purchasing.';
@@ -0,0 +1,35 @@
1
+ import ConstructorioClient from '@constructor-io/constructorio-client-javascript';
2
+ import MockAgent from './agent';
3
+ import version from '../../version';
4
+ class MockConstructorIOClient {
5
+ options;
6
+ search;
7
+ browse;
8
+ recommendations;
9
+ tracker;
10
+ quizzes;
11
+ agent;
12
+ constructor(options) {
13
+ this.options = {
14
+ version: options.version || `cio-ui-pia-${version}`,
15
+ serviceUrl: options.serviceUrl || 'https://ac.cnstrc.com',
16
+ quizzesServiceUrl: options.quizzesServiceUrl || 'https://quizzes.cnstrc.com',
17
+ agentServiceUrl: options.agentServiceUrl || 'https://agent.cnstrc.com',
18
+ sessionId: options.sessionId || 0,
19
+ clientId: options.clientId || 'this-is-a-random-client-id',
20
+ sendTrackingEvents: options.sendTrackingEvents !== undefined ? options.sendTrackingEvents : true,
21
+ beaconMode: options.beaconMode !== undefined ? options.beaconMode : true,
22
+ networkParameters: options.networkParameters || {},
23
+ ...options,
24
+ };
25
+ const cioClient = new ConstructorioClient(this.options);
26
+ this.search = cioClient.search;
27
+ this.browse = cioClient.browse;
28
+ this.recommendations = cioClient.recommendations;
29
+ this.tracker = cioClient.tracker;
30
+ this.quizzes = cioClient.quizzes;
31
+ // Use the mock agent instead of the one from the client
32
+ this.agent = new MockAgent(this.options);
33
+ }
34
+ }
35
+ export default MockConstructorIOClient;