@yassirbenmoussa/aicommerce-sdk 1.8.0 → 1.9.1
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/ai-commerce.min.js +409 -77
- package/dist/index.cjs +483 -56
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +12 -2
- package/dist/index.d.ts +12 -2
- package/dist/index.min.js.map +1 -1
- package/dist/index.mjs +483 -56
- package/dist/index.mjs.map +1 -1
- package/dist/widget.min.js +402 -70
- package/dist/widget.min.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -904,17 +904,22 @@ function createWidgetStyles(config) {
|
|
|
904
904
|
}
|
|
905
905
|
|
|
906
906
|
/* ============================================
|
|
907
|
-
Embedded Mode Styles
|
|
907
|
+
Embedded Mode Styles - ChatGPT Style
|
|
908
908
|
============================================ */
|
|
909
909
|
|
|
910
|
-
/* Embedded container -
|
|
910
|
+
/* Embedded container - starts small, grows to max-height, then scrolls */
|
|
911
911
|
#aicommerce-widget.aicommerce-embedded {
|
|
912
912
|
position: relative;
|
|
913
913
|
bottom: auto;
|
|
914
914
|
left: auto;
|
|
915
915
|
right: auto;
|
|
916
916
|
width: 100%;
|
|
917
|
-
height:
|
|
917
|
+
height: auto;
|
|
918
|
+
min-height: 80px;
|
|
919
|
+
max-height: var(--aic-max-height, 600px);
|
|
920
|
+
display: flex;
|
|
921
|
+
flex-direction: column;
|
|
922
|
+
background: transparent;
|
|
918
923
|
}
|
|
919
924
|
|
|
920
925
|
/* Embedded mode: hide launcher button */
|
|
@@ -922,17 +927,31 @@ function createWidgetStyles(config) {
|
|
|
922
927
|
display: none !important;
|
|
923
928
|
}
|
|
924
929
|
|
|
925
|
-
/* Embedded mode:
|
|
930
|
+
/* Embedded mode: hide the header completely */
|
|
931
|
+
.aicommerce-embedded .aicommerce-header {
|
|
932
|
+
display: none !important;
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
/* Embedded mode: hide close button */
|
|
936
|
+
.aicommerce-embedded .aicommerce-close {
|
|
937
|
+
display: none !important;
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
/* Embedded mode: chat container grows with content */
|
|
926
941
|
.aicommerce-embedded .aicommerce-chat {
|
|
927
942
|
position: relative;
|
|
928
943
|
width: 100%;
|
|
929
|
-
height:
|
|
930
|
-
max-width: 100%;
|
|
944
|
+
height: auto;
|
|
931
945
|
max-height: 100%;
|
|
932
|
-
|
|
946
|
+
max-width: 100%;
|
|
947
|
+
border-radius: 0;
|
|
948
|
+
background: transparent;
|
|
949
|
+
box-shadow: none;
|
|
933
950
|
transform: none !important;
|
|
934
951
|
opacity: 1 !important;
|
|
935
952
|
pointer-events: auto !important;
|
|
953
|
+
display: flex;
|
|
954
|
+
flex-direction: column;
|
|
936
955
|
}
|
|
937
956
|
|
|
938
957
|
/* Embedded mode: no open/close animations */
|
|
@@ -942,21 +961,254 @@ function createWidgetStyles(config) {
|
|
|
942
961
|
pointer-events: auto !important;
|
|
943
962
|
}
|
|
944
963
|
|
|
945
|
-
/* Embedded mode: messages area
|
|
964
|
+
/* Embedded mode: messages area - scrollable when content overflows */
|
|
946
965
|
.aicommerce-embedded .aicommerce-messages {
|
|
947
|
-
flex: 1;
|
|
966
|
+
flex: 1 1 auto;
|
|
948
967
|
min-height: 0;
|
|
968
|
+
max-height: calc(var(--aic-max-height, 600px) - 100px);
|
|
969
|
+
display: flex;
|
|
970
|
+
flex-direction: column;
|
|
971
|
+
justify-content: flex-start;
|
|
972
|
+
overflow-y: auto;
|
|
973
|
+
padding: 16px;
|
|
974
|
+
max-width: 700px;
|
|
975
|
+
margin: 0 auto;
|
|
976
|
+
width: 100%;
|
|
977
|
+
background: transparent;
|
|
978
|
+
gap: 12px;
|
|
979
|
+
scrollbar-width: thin;
|
|
980
|
+
scrollbar-color: var(--aic-border) transparent;
|
|
949
981
|
}
|
|
950
982
|
|
|
951
|
-
/* Embedded mode
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
983
|
+
/* Embedded mode: custom scrollbar for webkit browsers */
|
|
984
|
+
.aicommerce-embedded .aicommerce-messages::-webkit-scrollbar {
|
|
985
|
+
width: 6px;
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
.aicommerce-embedded .aicommerce-messages::-webkit-scrollbar-track {
|
|
989
|
+
background: transparent;
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
.aicommerce-embedded .aicommerce-messages::-webkit-scrollbar-thumb {
|
|
993
|
+
background-color: var(--aic-border);
|
|
994
|
+
border-radius: 3px;
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
.aicommerce-embedded .aicommerce-messages::-webkit-scrollbar-thumb:hover {
|
|
998
|
+
background-color: var(--aic-text-secondary);
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
/* Embedded mode: messages have different styling */
|
|
1002
|
+
.aicommerce-embedded .aicommerce-message {
|
|
1003
|
+
max-width: 100%;
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
.aicommerce-embedded .aicommerce-message-content {
|
|
1007
|
+
background: var(--aic-bg);
|
|
1008
|
+
border: 1px solid var(--aic-border);
|
|
1009
|
+
border-radius: 12px;
|
|
1010
|
+
padding: 12px 16px;
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
.aicommerce-embedded .aicommerce-user .aicommerce-message-content {
|
|
1014
|
+
background: var(--aic-primary);
|
|
1015
|
+
color: white;
|
|
1016
|
+
border-color: var(--aic-primary);
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
/* Embedded mode: input container wrapper - always at bottom */
|
|
1020
|
+
.aicommerce-embedded .aicommerce-input-wrapper {
|
|
1021
|
+
width: 100%;
|
|
1022
|
+
display: flex;
|
|
1023
|
+
flex-direction: column;
|
|
1024
|
+
align-items: center;
|
|
1025
|
+
padding: 16px;
|
|
1026
|
+
flex-shrink: 0;
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
/* Embedded mode: input container styled like ChatGPT */
|
|
1030
|
+
.aicommerce-embedded .aicommerce-input-container {
|
|
1031
|
+
width: 100%;
|
|
1032
|
+
max-width: 700px;
|
|
1033
|
+
background: var(--aic-bg);
|
|
1034
|
+
border: 1px solid var(--aic-border);
|
|
1035
|
+
border-radius: 24px;
|
|
1036
|
+
padding: 8px 12px;
|
|
1037
|
+
display: flex;
|
|
1038
|
+
align-items: flex-end;
|
|
1039
|
+
gap: 8px;
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
/* Embedded mode: textarea field styling - auto-grow */
|
|
1043
|
+
.aicommerce-embedded .aicommerce-input {
|
|
1044
|
+
flex: 1;
|
|
1045
|
+
min-width: 0;
|
|
1046
|
+
border: none;
|
|
1047
|
+
background: transparent;
|
|
1048
|
+
padding: 8px 4px;
|
|
1049
|
+
font-size: 16px;
|
|
1050
|
+
font-family: inherit;
|
|
1051
|
+
color: var(--aic-text);
|
|
1052
|
+
outline: none;
|
|
1053
|
+
resize: none;
|
|
1054
|
+
min-height: 24px;
|
|
1055
|
+
max-height: 150px;
|
|
1056
|
+
line-height: 1.5;
|
|
1057
|
+
overflow-y: auto;
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
.aicommerce-embedded .aicommerce-input::placeholder {
|
|
1061
|
+
color: var(--aic-text-secondary);
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
/* Embedded mode: buttons styling - smaller, no overflow */
|
|
1065
|
+
.aicommerce-embedded .aicommerce-mic,
|
|
1066
|
+
.aicommerce-embedded .aicommerce-send {
|
|
1067
|
+
flex-shrink: 0;
|
|
1068
|
+
width: 36px;
|
|
1069
|
+
height: 36px;
|
|
1070
|
+
min-width: 36px;
|
|
1071
|
+
border-radius: 50%;
|
|
1072
|
+
background: var(--aic-primary);
|
|
1073
|
+
color: white;
|
|
1074
|
+
border: none;
|
|
1075
|
+
display: flex;
|
|
1076
|
+
align-items: center;
|
|
1077
|
+
justify-content: center;
|
|
1078
|
+
cursor: pointer;
|
|
1079
|
+
transition: all 0.2s ease;
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1082
|
+
.aicommerce-embedded .aicommerce-mic:hover,
|
|
1083
|
+
.aicommerce-embedded .aicommerce-send:hover {
|
|
1084
|
+
opacity: 0.9;
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
.aicommerce-embedded .aicommerce-mic {
|
|
1088
|
+
background: transparent;
|
|
1089
|
+
color: var(--aic-text-secondary);
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
.aicommerce-embedded .aicommerce-mic:hover {
|
|
1093
|
+
background: rgba(0, 0, 0, 0.05);
|
|
1094
|
+
color: var(--aic-text);
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
/* Embedded mode: product cards styling - horizontal scroll like widget mode */
|
|
1098
|
+
.aicommerce-embedded .aicommerce-products {
|
|
1099
|
+
display: flex;
|
|
1100
|
+
flex-wrap: nowrap;
|
|
1101
|
+
gap: 12px;
|
|
1102
|
+
margin-top: 12px;
|
|
1103
|
+
overflow-x: auto;
|
|
1104
|
+
padding-bottom: 8px;
|
|
1105
|
+
cursor: grab;
|
|
1106
|
+
scrollbar-width: none;
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
.aicommerce-embedded .aicommerce-products::-webkit-scrollbar {
|
|
1110
|
+
display: none;
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1113
|
+
.aicommerce-embedded .aicommerce-product-card {
|
|
1114
|
+
flex-shrink: 0;
|
|
1115
|
+
width: 180px;
|
|
1116
|
+
background: var(--aic-bg);
|
|
1117
|
+
border: 1px solid var(--aic-border);
|
|
1118
|
+
border-radius: 12px;
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
/* Embedded mode: typing indicator */
|
|
1122
|
+
.aicommerce-embedded .aicommerce-typing {
|
|
1123
|
+
background: var(--aic-bg);
|
|
1124
|
+
border: 1px solid var(--aic-border);
|
|
1125
|
+
border-radius: 12px;
|
|
1126
|
+
padding: 12px 16px;
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
/* Embedded mode responsive - mobile fixes */
|
|
1130
|
+
@media (max-width: 640px) {
|
|
1131
|
+
.aicommerce-embedded .aicommerce-input-container {
|
|
1132
|
+
padding: 6px 10px;
|
|
1133
|
+
gap: 6px;
|
|
1134
|
+
border-radius: 20px;
|
|
955
1135
|
}
|
|
956
1136
|
|
|
957
|
-
.aicommerce-embedded .aicommerce-
|
|
958
|
-
|
|
1137
|
+
.aicommerce-embedded .aicommerce-mic,
|
|
1138
|
+
.aicommerce-embedded .aicommerce-send {
|
|
1139
|
+
width: 32px;
|
|
1140
|
+
height: 32px;
|
|
1141
|
+
min-width: 32px;
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1144
|
+
.aicommerce-embedded .aicommerce-mic svg,
|
|
1145
|
+
.aicommerce-embedded .aicommerce-send svg {
|
|
1146
|
+
width: 16px;
|
|
1147
|
+
height: 16px;
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1150
|
+
.aicommerce-embedded .aicommerce-input {
|
|
1151
|
+
font-size: 16px;
|
|
1152
|
+
padding: 6px 4px;
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1155
|
+
.aicommerce-embedded .aicommerce-messages {
|
|
1156
|
+
padding: 12px;
|
|
959
1157
|
}
|
|
1158
|
+
|
|
1159
|
+
.aicommerce-embedded .aicommerce-input-wrapper {
|
|
1160
|
+
padding: 12px;
|
|
1161
|
+
}
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
/* ============================================
|
|
1165
|
+
Add to Cart Button Styles
|
|
1166
|
+
============================================ */
|
|
1167
|
+
|
|
1168
|
+
.aicommerce-add-to-cart {
|
|
1169
|
+
width: 100%;
|
|
1170
|
+
padding: 8px 12px;
|
|
1171
|
+
background: var(--aic-primary);
|
|
1172
|
+
color: white;
|
|
1173
|
+
border: none;
|
|
1174
|
+
border-radius: 6px;
|
|
1175
|
+
font-size: 12px;
|
|
1176
|
+
font-weight: 500;
|
|
1177
|
+
cursor: pointer;
|
|
1178
|
+
margin-top: 8px;
|
|
1179
|
+
transition: all 0.2s;
|
|
1180
|
+
display: flex;
|
|
1181
|
+
align-items: center;
|
|
1182
|
+
justify-content: center;
|
|
1183
|
+
gap: 6px;
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
.aicommerce-add-to-cart:hover {
|
|
1187
|
+
opacity: 0.9;
|
|
1188
|
+
transform: translateY(-1px);
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
.aicommerce-add-to-cart:active {
|
|
1192
|
+
transform: translateY(0);
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1195
|
+
.aicommerce-add-to-cart:disabled {
|
|
1196
|
+
opacity: 0.7;
|
|
1197
|
+
cursor: not-allowed;
|
|
1198
|
+
transform: none;
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
.aicommerce-add-to-cart svg {
|
|
1202
|
+
flex-shrink: 0;
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1205
|
+
/* Spinner animation for loading state */
|
|
1206
|
+
@keyframes aicommerce-spin {
|
|
1207
|
+
to { transform: rotate(360deg); }
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
.aicommerce-spinner {
|
|
1211
|
+
animation: aicommerce-spin 1s linear infinite;
|
|
960
1212
|
}
|
|
961
1213
|
`;
|
|
962
1214
|
}
|
|
@@ -1036,7 +1288,8 @@ function createWidget(config) {
|
|
|
1036
1288
|
baseUrl: config.baseUrl || detectBaseUrl(),
|
|
1037
1289
|
displayMode,
|
|
1038
1290
|
container: config.container,
|
|
1039
|
-
|
|
1291
|
+
maxHeight: config.maxHeight || "600px",
|
|
1292
|
+
placeholder: config.placeholder || "Ask me anything about our products...",
|
|
1040
1293
|
position: config.position || "bottom-right",
|
|
1041
1294
|
theme: config.theme || "auto",
|
|
1042
1295
|
primaryColor: config.primaryColor || state.storeConfig?.primaryColor || "#6366f1",
|
|
@@ -1045,9 +1298,11 @@ function createWidget(config) {
|
|
|
1045
1298
|
zIndex: config.zIndex || 9999,
|
|
1046
1299
|
buttonText: config.buttonText || "\u{1F4AC}",
|
|
1047
1300
|
hideLauncher: config.hideLauncher || false,
|
|
1301
|
+
addToCartText: config.addToCartText,
|
|
1048
1302
|
onOpen: config.onOpen,
|
|
1049
1303
|
onClose: config.onClose,
|
|
1050
1304
|
onProductClick: config.onProductClick,
|
|
1305
|
+
onAddToCart: config.onAddToCart,
|
|
1051
1306
|
onMessage: config.onMessage
|
|
1052
1307
|
};
|
|
1053
1308
|
const styles = createWidgetStyles(resolvedConfig);
|
|
@@ -1066,7 +1321,7 @@ function createWidget(config) {
|
|
|
1066
1321
|
container = document.createElement("div");
|
|
1067
1322
|
container.id = "aicommerce-widget";
|
|
1068
1323
|
container.className = `aicommerce-widget aicommerce-embedded aicommerce-theme-${resolvedConfig.theme}`;
|
|
1069
|
-
container.style.setProperty("--aic-height", resolvedConfig.
|
|
1324
|
+
container.style.setProperty("--aic-max-height", resolvedConfig.maxHeight);
|
|
1070
1325
|
targetContainer.appendChild(container);
|
|
1071
1326
|
state.isOpen = true;
|
|
1072
1327
|
} else {
|
|
@@ -1076,16 +1331,85 @@ function createWidget(config) {
|
|
|
1076
1331
|
document.body.appendChild(container);
|
|
1077
1332
|
}
|
|
1078
1333
|
render();
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1334
|
+
if (!isEmbedded) {
|
|
1335
|
+
state.messages.push({
|
|
1336
|
+
role: "assistant",
|
|
1337
|
+
content: resolvedConfig.welcomeMessage
|
|
1338
|
+
});
|
|
1339
|
+
}
|
|
1083
1340
|
state.isLoading = false;
|
|
1084
1341
|
render();
|
|
1085
1342
|
}
|
|
1343
|
+
async function addToShopifyCart(variantId, quantity = 1) {
|
|
1344
|
+
let numericVariantId = variantId;
|
|
1345
|
+
if (variantId.includes("gid://")) {
|
|
1346
|
+
const match = variantId.match(/\/(\d+)$/);
|
|
1347
|
+
if (match) {
|
|
1348
|
+
numericVariantId = match[1];
|
|
1349
|
+
}
|
|
1350
|
+
}
|
|
1351
|
+
const response = await fetch("/cart/add.js", {
|
|
1352
|
+
method: "POST",
|
|
1353
|
+
headers: {
|
|
1354
|
+
"Content-Type": "application/json"
|
|
1355
|
+
},
|
|
1356
|
+
body: JSON.stringify({
|
|
1357
|
+
id: numericVariantId,
|
|
1358
|
+
quantity
|
|
1359
|
+
})
|
|
1360
|
+
});
|
|
1361
|
+
if (!response.ok) {
|
|
1362
|
+
throw new Error("Failed to add to cart");
|
|
1363
|
+
}
|
|
1364
|
+
document.dispatchEvent(new CustomEvent("cart:refresh"));
|
|
1365
|
+
}
|
|
1086
1366
|
function render() {
|
|
1087
1367
|
if (!container) return;
|
|
1088
1368
|
const isEmbedded = resolvedConfig.displayMode === "embedded";
|
|
1369
|
+
const hasUserMessages = state.messages.some((m) => m.role === "user");
|
|
1370
|
+
if (isEmbedded) {
|
|
1371
|
+
container.classList.remove("aicommerce-no-messages", "aicommerce-has-messages");
|
|
1372
|
+
container.classList.add(hasUserMessages ? "aicommerce-has-messages" : "aicommerce-no-messages");
|
|
1373
|
+
}
|
|
1374
|
+
const placeholder = resolvedConfig.placeholder || "Ask me anything about our products...";
|
|
1375
|
+
const inputContainerHtml = `
|
|
1376
|
+
<div class="aicommerce-input-container">
|
|
1377
|
+
${isEmbedded ? `
|
|
1378
|
+
<textarea
|
|
1379
|
+
class="aicommerce-input"
|
|
1380
|
+
placeholder="${placeholder}"
|
|
1381
|
+
rows="1"
|
|
1382
|
+
${state.isLoading || state.isRecording ? "disabled" : ""}
|
|
1383
|
+
></textarea>
|
|
1384
|
+
` : `
|
|
1385
|
+
<input
|
|
1386
|
+
type="text"
|
|
1387
|
+
class="aicommerce-input"
|
|
1388
|
+
placeholder="${placeholder}"
|
|
1389
|
+
${state.isLoading || state.isRecording ? "disabled" : ""}
|
|
1390
|
+
/>
|
|
1391
|
+
`}
|
|
1392
|
+
<button class="aicommerce-mic ${state.isRecording ? "aicommerce-recording" : ""}" ${state.isLoading ? "disabled" : ""} aria-label="${state.isRecording ? "Stop recording" : "Voice input"}">
|
|
1393
|
+
${state.isRecording ? `
|
|
1394
|
+
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
|
|
1395
|
+
<rect x="6" y="6" width="12" height="12" rx="2"/>
|
|
1396
|
+
</svg>
|
|
1397
|
+
` : `
|
|
1398
|
+
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
1399
|
+
<path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"/>
|
|
1400
|
+
<path d="M19 10v2a7 7 0 0 1-14 0v-2"/>
|
|
1401
|
+
<line x1="12" y1="19" x2="12" y2="23"/>
|
|
1402
|
+
<line x1="8" y1="23" x2="16" y2="23"/>
|
|
1403
|
+
</svg>
|
|
1404
|
+
`}
|
|
1405
|
+
</button>
|
|
1406
|
+
<button class="aicommerce-send" ${state.isLoading || state.isRecording ? "disabled" : ""} aria-label="Send message">
|
|
1407
|
+
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
1408
|
+
<path d="M22 2L11 13M22 2L15 22L11 13M22 2L2 9L11 13"/>
|
|
1409
|
+
</svg>
|
|
1410
|
+
</button>
|
|
1411
|
+
</div>
|
|
1412
|
+
`;
|
|
1089
1413
|
const html = `
|
|
1090
1414
|
${!isEmbedded && !resolvedConfig.hideLauncher ? `
|
|
1091
1415
|
<button class="aicommerce-launcher ${state.isOpen ? "aicommerce-hidden" : ""}" aria-label="Open chat">
|
|
@@ -1094,6 +1418,7 @@ function createWidget(config) {
|
|
|
1094
1418
|
` : ""}
|
|
1095
1419
|
|
|
1096
1420
|
<div class="aicommerce-chat ${state.isOpen ? "aicommerce-open" : "aicommerce-closed"}">
|
|
1421
|
+
${!isEmbedded ? `
|
|
1097
1422
|
<div class="aicommerce-header">
|
|
1098
1423
|
<div class="aicommerce-header-info">
|
|
1099
1424
|
<div class="aicommerce-avatar">
|
|
@@ -1104,9 +1429,11 @@ function createWidget(config) {
|
|
|
1104
1429
|
<span class="aicommerce-status">Online</span>
|
|
1105
1430
|
</div>
|
|
1106
1431
|
</div>
|
|
1107
|
-
|
|
1432
|
+
<button class="aicommerce-close" aria-label="Close chat">\u2715</button>
|
|
1108
1433
|
</div>
|
|
1434
|
+
` : ""}
|
|
1109
1435
|
|
|
1436
|
+
${isEmbedded && hasUserMessages ? `
|
|
1110
1437
|
<div class="aicommerce-messages">
|
|
1111
1438
|
${state.messages.map((msg, index) => {
|
|
1112
1439
|
const isRtl = isArabic(msg.content);
|
|
@@ -1119,7 +1446,7 @@ function createWidget(config) {
|
|
|
1119
1446
|
${msg.products && msg.products.length > 0 ? `
|
|
1120
1447
|
<div class="aicommerce-products">
|
|
1121
1448
|
${msg.products.map((product) => `
|
|
1122
|
-
<div class="aicommerce-product-card" data-product-id="${product.id}">
|
|
1449
|
+
<div class="aicommerce-product-card" data-product-id="${product.id}" data-variant-id="${product.variantId || ""}">
|
|
1123
1450
|
${product.image || product.imageUrl ? `
|
|
1124
1451
|
<img src="${product.image || product.imageUrl}" alt="${escapeHtml(product.name)}" class="aicommerce-product-image" />
|
|
1125
1452
|
` : `
|
|
@@ -1129,6 +1456,13 @@ function createWidget(config) {
|
|
|
1129
1456
|
<span class="aicommerce-product-name" title="${escapeHtml(product.name)}">${escapeHtml(product.name)}</span>
|
|
1130
1457
|
${product.description ? `<p class="aicommerce-product-desc">${escapeHtml(product.description)}</p>` : ""}
|
|
1131
1458
|
<span class="aicommerce-product-price">${formatPrice(product.price, product.currency)}</span>
|
|
1459
|
+
<button class="aicommerce-add-to-cart" data-product-id="${product.id}">
|
|
1460
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
1461
|
+
<circle cx="9" cy="21" r="1"/><circle cx="20" cy="21" r="1"/>
|
|
1462
|
+
<path d="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6"/>
|
|
1463
|
+
</svg>
|
|
1464
|
+
${resolvedConfig.addToCartText || "Add to Cart"}
|
|
1465
|
+
</button>
|
|
1132
1466
|
</div>
|
|
1133
1467
|
</div>
|
|
1134
1468
|
`).join("")}
|
|
@@ -1145,34 +1479,61 @@ function createWidget(config) {
|
|
|
1145
1479
|
</div>
|
|
1146
1480
|
` : ""}
|
|
1147
1481
|
</div>
|
|
1482
|
+
` : ""}
|
|
1148
1483
|
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1484
|
+
${!isEmbedded ? `
|
|
1485
|
+
<div class="aicommerce-messages">
|
|
1486
|
+
${state.messages.map((msg, index) => {
|
|
1487
|
+
const isRtl = isArabic(msg.content);
|
|
1488
|
+
const isUser = msg.role === "user";
|
|
1489
|
+
return `
|
|
1490
|
+
<div class="aicommerce-message aicommerce-${msg.role}">
|
|
1491
|
+
<div class="aicommerce-message-content ${isRtl ? "aicommerce-rtl" : "aicommerce-ltr"}">
|
|
1492
|
+
${msg.audioUrl ? renderAudioPlayer(msg, index, isUser) : escapeHtml(msg.content)}
|
|
1493
|
+
</div>
|
|
1494
|
+
${msg.products && msg.products.length > 0 ? `
|
|
1495
|
+
<div class="aicommerce-products">
|
|
1496
|
+
${msg.products.map((product) => `
|
|
1497
|
+
<div class="aicommerce-product-card" data-product-id="${product.id}" data-variant-id="${product.variantId || ""}">
|
|
1498
|
+
${product.image || product.imageUrl ? `
|
|
1499
|
+
<img src="${product.image || product.imageUrl}" alt="${escapeHtml(product.name)}" class="aicommerce-product-image" />
|
|
1500
|
+
` : `
|
|
1501
|
+
<div class="aicommerce-product-placeholder">\u{1F4E6}</div>
|
|
1502
|
+
`}
|
|
1503
|
+
<div class="aicommerce-product-info">
|
|
1504
|
+
<span class="aicommerce-product-name" title="${escapeHtml(product.name)}">${escapeHtml(product.name)}</span>
|
|
1505
|
+
${product.description ? `<p class="aicommerce-product-desc">${escapeHtml(product.description)}</p>` : ""}
|
|
1506
|
+
<span class="aicommerce-product-price">${formatPrice(product.price, product.currency)}</span>
|
|
1507
|
+
<button class="aicommerce-add-to-cart" data-product-id="${product.id}">
|
|
1508
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
1509
|
+
<circle cx="9" cy="21" r="1"/><circle cx="20" cy="21" r="1"/>
|
|
1510
|
+
<path d="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6"/>
|
|
1511
|
+
</svg>
|
|
1512
|
+
${resolvedConfig.addToCartText || "Add to Cart"}
|
|
1513
|
+
</button>
|
|
1514
|
+
</div>
|
|
1515
|
+
</div>
|
|
1516
|
+
`).join("")}
|
|
1517
|
+
</div>
|
|
1518
|
+
` : ""}
|
|
1519
|
+
</div>
|
|
1520
|
+
`;
|
|
1521
|
+
}).join("")}
|
|
1522
|
+
${state.isLoading ? `
|
|
1523
|
+
<div class="aicommerce-message aicommerce-assistant">
|
|
1524
|
+
<div class="aicommerce-typing">
|
|
1525
|
+
<span></span><span></span><span></span>
|
|
1526
|
+
</div>
|
|
1527
|
+
</div>
|
|
1528
|
+
` : ""}
|
|
1529
|
+
</div>
|
|
1530
|
+
` : ""}
|
|
1531
|
+
|
|
1532
|
+
${isEmbedded ? `
|
|
1533
|
+
<div class="aicommerce-input-wrapper">
|
|
1534
|
+
${inputContainerHtml}
|
|
1175
1535
|
</div>
|
|
1536
|
+
` : inputContainerHtml}
|
|
1176
1537
|
</div>
|
|
1177
1538
|
`;
|
|
1178
1539
|
container.innerHTML = html;
|
|
@@ -1216,18 +1577,40 @@ function createWidget(config) {
|
|
|
1216
1577
|
const inputEl = container.querySelector(".aicommerce-input");
|
|
1217
1578
|
const sendEl = container.querySelector(".aicommerce-send");
|
|
1218
1579
|
if (inputEl) {
|
|
1219
|
-
inputEl.addEventListener("
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1580
|
+
inputEl.addEventListener("keydown", (e) => {
|
|
1581
|
+
const keyEvent = e;
|
|
1582
|
+
if (keyEvent.key === "Enter") {
|
|
1583
|
+
const isTextarea = inputEl instanceof HTMLTextAreaElement;
|
|
1584
|
+
if (isTextarea && keyEvent.shiftKey) {
|
|
1585
|
+
return;
|
|
1586
|
+
}
|
|
1587
|
+
e.preventDefault();
|
|
1588
|
+
const value = inputEl.value.trim();
|
|
1589
|
+
if (value) {
|
|
1590
|
+
handleSend(value);
|
|
1591
|
+
inputEl.value = "";
|
|
1592
|
+
if (isTextarea) {
|
|
1593
|
+
inputEl.style.height = "auto";
|
|
1594
|
+
}
|
|
1595
|
+
}
|
|
1223
1596
|
}
|
|
1224
1597
|
});
|
|
1598
|
+
if (inputEl instanceof HTMLTextAreaElement) {
|
|
1599
|
+
inputEl.addEventListener("input", () => {
|
|
1600
|
+
inputEl.style.height = "auto";
|
|
1601
|
+
inputEl.style.height = Math.min(inputEl.scrollHeight, 150) + "px";
|
|
1602
|
+
});
|
|
1603
|
+
}
|
|
1225
1604
|
}
|
|
1226
1605
|
if (sendEl && inputEl) {
|
|
1227
1606
|
sendEl.addEventListener("click", () => {
|
|
1228
|
-
|
|
1229
|
-
|
|
1607
|
+
const value = inputEl.value.trim();
|
|
1608
|
+
if (value) {
|
|
1609
|
+
handleSend(value);
|
|
1230
1610
|
inputEl.value = "";
|
|
1611
|
+
if (inputEl instanceof HTMLTextAreaElement) {
|
|
1612
|
+
inputEl.style.height = "auto";
|
|
1613
|
+
}
|
|
1231
1614
|
}
|
|
1232
1615
|
});
|
|
1233
1616
|
}
|
|
@@ -1237,7 +1620,8 @@ function createWidget(config) {
|
|
|
1237
1620
|
}
|
|
1238
1621
|
const productCards = container.querySelectorAll(".aicommerce-product-card");
|
|
1239
1622
|
productCards.forEach((card) => {
|
|
1240
|
-
card.addEventListener("click", () => {
|
|
1623
|
+
card.addEventListener("click", (e) => {
|
|
1624
|
+
if (e.target.closest(".aicommerce-add-to-cart")) return;
|
|
1241
1625
|
const productId = card.getAttribute("data-product-id");
|
|
1242
1626
|
const product = state.messages.flatMap((m) => m.products || []).find((p) => p.id === productId);
|
|
1243
1627
|
if (product) {
|
|
@@ -1249,6 +1633,49 @@ function createWidget(config) {
|
|
|
1249
1633
|
}
|
|
1250
1634
|
});
|
|
1251
1635
|
});
|
|
1636
|
+
const addToCartBtns = container.querySelectorAll(".aicommerce-add-to-cart");
|
|
1637
|
+
addToCartBtns.forEach((btn) => {
|
|
1638
|
+
btn.addEventListener("click", async (e) => {
|
|
1639
|
+
e.stopPropagation();
|
|
1640
|
+
const button = btn;
|
|
1641
|
+
const productCard = button.closest(".aicommerce-product-card");
|
|
1642
|
+
const productId = productCard?.getAttribute("data-product-id");
|
|
1643
|
+
const variantId = productCard?.getAttribute("data-variant-id");
|
|
1644
|
+
const product = state.messages.flatMap((m) => m.products || []).find((p) => p.id === productId);
|
|
1645
|
+
if (!product) return;
|
|
1646
|
+
const originalText = button.innerHTML;
|
|
1647
|
+
button.disabled = true;
|
|
1648
|
+
button.innerHTML = `
|
|
1649
|
+
<svg class="aicommerce-spinner" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
1650
|
+
<circle cx="12" cy="12" r="10" stroke-dasharray="32" stroke-dashoffset="32"/>
|
|
1651
|
+
</svg>
|
|
1652
|
+
Adding...
|
|
1653
|
+
`;
|
|
1654
|
+
try {
|
|
1655
|
+
if (resolvedConfig.onAddToCart) {
|
|
1656
|
+
await resolvedConfig.onAddToCart(product);
|
|
1657
|
+
} else if (variantId && window.Shopify) {
|
|
1658
|
+
await addToShopifyCart(variantId);
|
|
1659
|
+
} else if (product.url) {
|
|
1660
|
+
window.open(product.url, "_blank", "noopener,noreferrer");
|
|
1661
|
+
}
|
|
1662
|
+
button.innerHTML = `
|
|
1663
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
1664
|
+
<polyline points="20 6 9 17 4 12"/>
|
|
1665
|
+
</svg>
|
|
1666
|
+
Added!
|
|
1667
|
+
`;
|
|
1668
|
+
setTimeout(() => {
|
|
1669
|
+
button.innerHTML = originalText;
|
|
1670
|
+
button.disabled = false;
|
|
1671
|
+
}, 2e3);
|
|
1672
|
+
} catch (error) {
|
|
1673
|
+
console.error("[AI Commerce] Add to cart failed:", error);
|
|
1674
|
+
button.innerHTML = originalText;
|
|
1675
|
+
button.disabled = false;
|
|
1676
|
+
}
|
|
1677
|
+
});
|
|
1678
|
+
});
|
|
1252
1679
|
const sliders = container.querySelectorAll(".aicommerce-products");
|
|
1253
1680
|
sliders.forEach((slider) => {
|
|
1254
1681
|
let isDown = false;
|