@yassirbenmoussa/aicommerce-sdk 1.7.0 → 1.9.0
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 +431 -63
- package/dist/index.cjs +523 -42
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +20 -2
- package/dist/index.d.ts +20 -2
- package/dist/index.min.js.map +1 -1
- package/dist/index.mjs +523 -42
- package/dist/index.mjs.map +1 -1
- package/dist/widget.min.js +423 -55
- package/dist/widget.min.js.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -900,6 +900,301 @@ function createWidgetStyles(config) {
|
|
|
900
900
|
.aicommerce-messages::-webkit-scrollbar-thumb:hover {
|
|
901
901
|
background: var(--aic-text-secondary);
|
|
902
902
|
}
|
|
903
|
+
|
|
904
|
+
/* ============================================
|
|
905
|
+
Embedded Mode Styles - ChatGPT Style
|
|
906
|
+
============================================ */
|
|
907
|
+
|
|
908
|
+
/* Embedded container - fit content with max height */
|
|
909
|
+
#aicommerce-widget.aicommerce-embedded {
|
|
910
|
+
position: relative;
|
|
911
|
+
bottom: auto;
|
|
912
|
+
left: auto;
|
|
913
|
+
right: auto;
|
|
914
|
+
width: 100%;
|
|
915
|
+
height: auto;
|
|
916
|
+
max-height: var(--aic-max-height, 600px);
|
|
917
|
+
display: flex;
|
|
918
|
+
flex-direction: column;
|
|
919
|
+
background: transparent;
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
/* Embedded mode: hide launcher button */
|
|
923
|
+
.aicommerce-embedded .aicommerce-launcher {
|
|
924
|
+
display: none !important;
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
/* Embedded mode: hide the header completely */
|
|
928
|
+
.aicommerce-embedded .aicommerce-header {
|
|
929
|
+
display: none !important;
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
/* Embedded mode: hide close button */
|
|
933
|
+
.aicommerce-embedded .aicommerce-close {
|
|
934
|
+
display: none !important;
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
/* Embedded mode: chat fills container with transparent background */
|
|
938
|
+
.aicommerce-embedded .aicommerce-chat {
|
|
939
|
+
position: relative;
|
|
940
|
+
width: 100%;
|
|
941
|
+
height: auto;
|
|
942
|
+
max-width: 100%;
|
|
943
|
+
border-radius: 0;
|
|
944
|
+
background: transparent;
|
|
945
|
+
box-shadow: none;
|
|
946
|
+
transform: none !important;
|
|
947
|
+
opacity: 1 !important;
|
|
948
|
+
pointer-events: auto !important;
|
|
949
|
+
display: flex;
|
|
950
|
+
flex-direction: column;
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
/* Embedded mode: no open/close animations */
|
|
954
|
+
.aicommerce-embedded .aicommerce-chat.aicommerce-closed {
|
|
955
|
+
opacity: 1 !important;
|
|
956
|
+
transform: none !important;
|
|
957
|
+
pointer-events: auto !important;
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
/* Embedded mode: messages area - messages start from bottom, grow upward */
|
|
961
|
+
.aicommerce-embedded .aicommerce-messages {
|
|
962
|
+
display: flex;
|
|
963
|
+
flex-direction: column;
|
|
964
|
+
justify-content: flex-end;
|
|
965
|
+
overflow-y: auto;
|
|
966
|
+
max-height: calc(var(--aic-max-height, 600px) - 100px);
|
|
967
|
+
padding: 16px;
|
|
968
|
+
max-width: 700px;
|
|
969
|
+
margin: 0 auto;
|
|
970
|
+
width: 100%;
|
|
971
|
+
background: transparent;
|
|
972
|
+
gap: 12px;
|
|
973
|
+
scrollbar-width: thin;
|
|
974
|
+
scrollbar-color: var(--aic-border) transparent;
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
/* Embedded mode: custom scrollbar for webkit browsers */
|
|
978
|
+
.aicommerce-embedded .aicommerce-messages::-webkit-scrollbar {
|
|
979
|
+
width: 6px;
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
.aicommerce-embedded .aicommerce-messages::-webkit-scrollbar-track {
|
|
983
|
+
background: transparent;
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
.aicommerce-embedded .aicommerce-messages::-webkit-scrollbar-thumb {
|
|
987
|
+
background-color: var(--aic-border);
|
|
988
|
+
border-radius: 3px;
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
.aicommerce-embedded .aicommerce-messages::-webkit-scrollbar-thumb:hover {
|
|
992
|
+
background-color: var(--aic-text-secondary);
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
/* Embedded mode: messages have different styling */
|
|
996
|
+
.aicommerce-embedded .aicommerce-message {
|
|
997
|
+
max-width: 100%;
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
.aicommerce-embedded .aicommerce-message-content {
|
|
1001
|
+
background: var(--aic-bg);
|
|
1002
|
+
border: 1px solid var(--aic-border);
|
|
1003
|
+
border-radius: 12px;
|
|
1004
|
+
padding: 12px 16px;
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
.aicommerce-embedded .aicommerce-user .aicommerce-message-content {
|
|
1008
|
+
background: var(--aic-primary);
|
|
1009
|
+
color: white;
|
|
1010
|
+
border-color: var(--aic-primary);
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
/* Embedded mode: input container wrapper - always at bottom */
|
|
1014
|
+
.aicommerce-embedded .aicommerce-input-wrapper {
|
|
1015
|
+
width: 100%;
|
|
1016
|
+
display: flex;
|
|
1017
|
+
flex-direction: column;
|
|
1018
|
+
align-items: center;
|
|
1019
|
+
padding: 16px;
|
|
1020
|
+
flex-shrink: 0;
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
/* Embedded mode: input container styled like ChatGPT */
|
|
1024
|
+
.aicommerce-embedded .aicommerce-input-container {
|
|
1025
|
+
width: 100%;
|
|
1026
|
+
max-width: 700px;
|
|
1027
|
+
background: var(--aic-bg);
|
|
1028
|
+
border: 1px solid var(--aic-border);
|
|
1029
|
+
border-radius: 24px;
|
|
1030
|
+
padding: 8px 12px;
|
|
1031
|
+
display: flex;
|
|
1032
|
+
align-items: flex-end;
|
|
1033
|
+
gap: 8px;
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
/* Embedded mode: textarea field styling - auto-grow */
|
|
1037
|
+
.aicommerce-embedded .aicommerce-input {
|
|
1038
|
+
flex: 1;
|
|
1039
|
+
min-width: 0;
|
|
1040
|
+
border: none;
|
|
1041
|
+
background: transparent;
|
|
1042
|
+
padding: 8px 4px;
|
|
1043
|
+
font-size: 16px;
|
|
1044
|
+
font-family: inherit;
|
|
1045
|
+
color: var(--aic-text);
|
|
1046
|
+
outline: none;
|
|
1047
|
+
resize: none;
|
|
1048
|
+
min-height: 24px;
|
|
1049
|
+
max-height: 150px;
|
|
1050
|
+
line-height: 1.5;
|
|
1051
|
+
overflow-y: auto;
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
.aicommerce-embedded .aicommerce-input::placeholder {
|
|
1055
|
+
color: var(--aic-text-secondary);
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
/* Embedded mode: buttons styling - smaller, no overflow */
|
|
1059
|
+
.aicommerce-embedded .aicommerce-mic,
|
|
1060
|
+
.aicommerce-embedded .aicommerce-send {
|
|
1061
|
+
flex-shrink: 0;
|
|
1062
|
+
width: 36px;
|
|
1063
|
+
height: 36px;
|
|
1064
|
+
min-width: 36px;
|
|
1065
|
+
border-radius: 50%;
|
|
1066
|
+
background: var(--aic-primary);
|
|
1067
|
+
color: white;
|
|
1068
|
+
border: none;
|
|
1069
|
+
display: flex;
|
|
1070
|
+
align-items: center;
|
|
1071
|
+
justify-content: center;
|
|
1072
|
+
cursor: pointer;
|
|
1073
|
+
transition: all 0.2s ease;
|
|
1074
|
+
}
|
|
1075
|
+
|
|
1076
|
+
.aicommerce-embedded .aicommerce-mic:hover,
|
|
1077
|
+
.aicommerce-embedded .aicommerce-send:hover {
|
|
1078
|
+
opacity: 0.9;
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
.aicommerce-embedded .aicommerce-mic {
|
|
1082
|
+
background: transparent;
|
|
1083
|
+
color: var(--aic-text-secondary);
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
.aicommerce-embedded .aicommerce-mic:hover {
|
|
1087
|
+
background: rgba(0, 0, 0, 0.05);
|
|
1088
|
+
color: var(--aic-text);
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1091
|
+
/* Embedded mode: product cards styling */
|
|
1092
|
+
.aicommerce-embedded .aicommerce-products {
|
|
1093
|
+
display: flex;
|
|
1094
|
+
flex-wrap: wrap;
|
|
1095
|
+
gap: 12px;
|
|
1096
|
+
margin-top: 12px;
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
.aicommerce-embedded .aicommerce-product-card {
|
|
1100
|
+
background: var(--aic-bg);
|
|
1101
|
+
border: 1px solid var(--aic-border);
|
|
1102
|
+
border-radius: 12px;
|
|
1103
|
+
max-width: 180px;
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
/* Embedded mode: typing indicator */
|
|
1107
|
+
.aicommerce-embedded .aicommerce-typing {
|
|
1108
|
+
background: var(--aic-bg);
|
|
1109
|
+
border: 1px solid var(--aic-border);
|
|
1110
|
+
border-radius: 12px;
|
|
1111
|
+
padding: 12px 16px;
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
/* Embedded mode responsive - mobile fixes */
|
|
1115
|
+
@media (max-width: 640px) {
|
|
1116
|
+
.aicommerce-embedded .aicommerce-input-container {
|
|
1117
|
+
padding: 6px 10px;
|
|
1118
|
+
gap: 6px;
|
|
1119
|
+
border-radius: 20px;
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
.aicommerce-embedded .aicommerce-mic,
|
|
1123
|
+
.aicommerce-embedded .aicommerce-send {
|
|
1124
|
+
width: 32px;
|
|
1125
|
+
height: 32px;
|
|
1126
|
+
min-width: 32px;
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
.aicommerce-embedded .aicommerce-mic svg,
|
|
1130
|
+
.aicommerce-embedded .aicommerce-send svg {
|
|
1131
|
+
width: 16px;
|
|
1132
|
+
height: 16px;
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
.aicommerce-embedded .aicommerce-input {
|
|
1136
|
+
font-size: 16px;
|
|
1137
|
+
padding: 6px 4px;
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
.aicommerce-embedded .aicommerce-messages {
|
|
1141
|
+
padding: 12px;
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1144
|
+
.aicommerce-embedded .aicommerce-input-wrapper {
|
|
1145
|
+
padding: 12px;
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1149
|
+
/* ============================================
|
|
1150
|
+
Add to Cart Button Styles
|
|
1151
|
+
============================================ */
|
|
1152
|
+
|
|
1153
|
+
.aicommerce-add-to-cart {
|
|
1154
|
+
width: 100%;
|
|
1155
|
+
padding: 8px 12px;
|
|
1156
|
+
background: var(--aic-primary);
|
|
1157
|
+
color: white;
|
|
1158
|
+
border: none;
|
|
1159
|
+
border-radius: 6px;
|
|
1160
|
+
font-size: 12px;
|
|
1161
|
+
font-weight: 500;
|
|
1162
|
+
cursor: pointer;
|
|
1163
|
+
margin-top: 8px;
|
|
1164
|
+
transition: all 0.2s;
|
|
1165
|
+
display: flex;
|
|
1166
|
+
align-items: center;
|
|
1167
|
+
justify-content: center;
|
|
1168
|
+
gap: 6px;
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1171
|
+
.aicommerce-add-to-cart:hover {
|
|
1172
|
+
opacity: 0.9;
|
|
1173
|
+
transform: translateY(-1px);
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1176
|
+
.aicommerce-add-to-cart:active {
|
|
1177
|
+
transform: translateY(0);
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1180
|
+
.aicommerce-add-to-cart:disabled {
|
|
1181
|
+
opacity: 0.7;
|
|
1182
|
+
cursor: not-allowed;
|
|
1183
|
+
transform: none;
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
.aicommerce-add-to-cart svg {
|
|
1187
|
+
flex-shrink: 0;
|
|
1188
|
+
}
|
|
1189
|
+
|
|
1190
|
+
/* Spinner animation for loading state */
|
|
1191
|
+
@keyframes aicommerce-spin {
|
|
1192
|
+
to { transform: rotate(360deg); }
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1195
|
+
.aicommerce-spinner {
|
|
1196
|
+
animation: aicommerce-spin 1s linear infinite;
|
|
1197
|
+
}
|
|
903
1198
|
`;
|
|
904
1199
|
}
|
|
905
1200
|
function injectStyles(css) {
|
|
@@ -970,10 +1265,16 @@ function createWidget(config) {
|
|
|
970
1265
|
}
|
|
971
1266
|
async function initialize() {
|
|
972
1267
|
state.storeConfig = await fetchStoreConfig();
|
|
1268
|
+
const displayMode = config.displayMode || "widget";
|
|
1269
|
+
const isEmbedded = displayMode === "embedded";
|
|
973
1270
|
resolvedConfig = {
|
|
974
1271
|
apiKey: config.apiKey,
|
|
975
1272
|
storeId: config.storeId,
|
|
976
1273
|
baseUrl: config.baseUrl || detectBaseUrl(),
|
|
1274
|
+
displayMode,
|
|
1275
|
+
container: config.container,
|
|
1276
|
+
maxHeight: config.maxHeight || "600px",
|
|
1277
|
+
placeholder: config.placeholder || "Ask me anything about our products...",
|
|
977
1278
|
position: config.position || "bottom-right",
|
|
978
1279
|
theme: config.theme || "auto",
|
|
979
1280
|
primaryColor: config.primaryColor || state.storeConfig?.primaryColor || "#6366f1",
|
|
@@ -982,35 +1283,120 @@ function createWidget(config) {
|
|
|
982
1283
|
zIndex: config.zIndex || 9999,
|
|
983
1284
|
buttonText: config.buttonText || "\u{1F4AC}",
|
|
984
1285
|
hideLauncher: config.hideLauncher || false,
|
|
1286
|
+
addToCartText: config.addToCartText,
|
|
985
1287
|
onOpen: config.onOpen,
|
|
986
1288
|
onClose: config.onClose,
|
|
987
1289
|
onProductClick: config.onProductClick,
|
|
1290
|
+
onAddToCart: config.onAddToCart,
|
|
988
1291
|
onMessage: config.onMessage
|
|
989
1292
|
};
|
|
990
1293
|
const styles = createWidgetStyles(resolvedConfig);
|
|
991
1294
|
styleElement = injectStyles(styles);
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
1295
|
+
if (isEmbedded) {
|
|
1296
|
+
let targetContainer = null;
|
|
1297
|
+
if (typeof config.container === "string") {
|
|
1298
|
+
targetContainer = document.querySelector(config.container);
|
|
1299
|
+
} else if (config.container instanceof HTMLElement) {
|
|
1300
|
+
targetContainer = config.container;
|
|
1301
|
+
}
|
|
1302
|
+
if (!targetContainer) {
|
|
1303
|
+
console.error("[AI Commerce] Embedded mode requires a valid container element or selector");
|
|
1304
|
+
return;
|
|
1305
|
+
}
|
|
1306
|
+
container = document.createElement("div");
|
|
1307
|
+
container.id = "aicommerce-widget";
|
|
1308
|
+
container.className = `aicommerce-widget aicommerce-embedded aicommerce-theme-${resolvedConfig.theme}`;
|
|
1309
|
+
container.style.setProperty("--aic-max-height", resolvedConfig.maxHeight);
|
|
1310
|
+
targetContainer.appendChild(container);
|
|
1311
|
+
state.isOpen = true;
|
|
1312
|
+
} else {
|
|
1313
|
+
container = document.createElement("div");
|
|
1314
|
+
container.id = "aicommerce-widget";
|
|
1315
|
+
container.className = `aicommerce-widget aicommerce-${resolvedConfig.position} aicommerce-theme-${resolvedConfig.theme}`;
|
|
1316
|
+
document.body.appendChild(container);
|
|
1317
|
+
}
|
|
996
1318
|
render();
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1319
|
+
if (!isEmbedded) {
|
|
1320
|
+
state.messages.push({
|
|
1321
|
+
role: "assistant",
|
|
1322
|
+
content: resolvedConfig.welcomeMessage
|
|
1323
|
+
});
|
|
1324
|
+
}
|
|
1001
1325
|
state.isLoading = false;
|
|
1002
1326
|
render();
|
|
1003
1327
|
}
|
|
1328
|
+
async function addToShopifyCart(variantId, quantity = 1) {
|
|
1329
|
+
const response = await fetch("/cart/add.js", {
|
|
1330
|
+
method: "POST",
|
|
1331
|
+
headers: {
|
|
1332
|
+
"Content-Type": "application/json"
|
|
1333
|
+
},
|
|
1334
|
+
body: JSON.stringify({
|
|
1335
|
+
id: variantId,
|
|
1336
|
+
quantity
|
|
1337
|
+
})
|
|
1338
|
+
});
|
|
1339
|
+
if (!response.ok) {
|
|
1340
|
+
throw new Error("Failed to add to cart");
|
|
1341
|
+
}
|
|
1342
|
+
document.dispatchEvent(new CustomEvent("cart:refresh"));
|
|
1343
|
+
}
|
|
1004
1344
|
function render() {
|
|
1005
1345
|
if (!container) return;
|
|
1346
|
+
const isEmbedded = resolvedConfig.displayMode === "embedded";
|
|
1347
|
+
const hasUserMessages = state.messages.some((m) => m.role === "user");
|
|
1348
|
+
if (isEmbedded) {
|
|
1349
|
+
container.classList.remove("aicommerce-no-messages", "aicommerce-has-messages");
|
|
1350
|
+
container.classList.add(hasUserMessages ? "aicommerce-has-messages" : "aicommerce-no-messages");
|
|
1351
|
+
}
|
|
1352
|
+
const placeholder = resolvedConfig.placeholder || "Ask me anything about our products...";
|
|
1353
|
+
const inputContainerHtml = `
|
|
1354
|
+
<div class="aicommerce-input-container">
|
|
1355
|
+
${isEmbedded ? `
|
|
1356
|
+
<textarea
|
|
1357
|
+
class="aicommerce-input"
|
|
1358
|
+
placeholder="${placeholder}"
|
|
1359
|
+
rows="1"
|
|
1360
|
+
${state.isLoading || state.isRecording ? "disabled" : ""}
|
|
1361
|
+
></textarea>
|
|
1362
|
+
` : `
|
|
1363
|
+
<input
|
|
1364
|
+
type="text"
|
|
1365
|
+
class="aicommerce-input"
|
|
1366
|
+
placeholder="${placeholder}"
|
|
1367
|
+
${state.isLoading || state.isRecording ? "disabled" : ""}
|
|
1368
|
+
/>
|
|
1369
|
+
`}
|
|
1370
|
+
<button class="aicommerce-mic ${state.isRecording ? "aicommerce-recording" : ""}" ${state.isLoading ? "disabled" : ""} aria-label="${state.isRecording ? "Stop recording" : "Voice input"}">
|
|
1371
|
+
${state.isRecording ? `
|
|
1372
|
+
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
|
|
1373
|
+
<rect x="6" y="6" width="12" height="12" rx="2"/>
|
|
1374
|
+
</svg>
|
|
1375
|
+
` : `
|
|
1376
|
+
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
1377
|
+
<path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"/>
|
|
1378
|
+
<path d="M19 10v2a7 7 0 0 1-14 0v-2"/>
|
|
1379
|
+
<line x1="12" y1="19" x2="12" y2="23"/>
|
|
1380
|
+
<line x1="8" y1="23" x2="16" y2="23"/>
|
|
1381
|
+
</svg>
|
|
1382
|
+
`}
|
|
1383
|
+
</button>
|
|
1384
|
+
<button class="aicommerce-send" ${state.isLoading || state.isRecording ? "disabled" : ""} aria-label="Send message">
|
|
1385
|
+
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
1386
|
+
<path d="M22 2L11 13M22 2L15 22L11 13M22 2L2 9L11 13"/>
|
|
1387
|
+
</svg>
|
|
1388
|
+
</button>
|
|
1389
|
+
</div>
|
|
1390
|
+
`;
|
|
1006
1391
|
const html = `
|
|
1007
|
-
${!resolvedConfig.hideLauncher ? `
|
|
1392
|
+
${!isEmbedded && !resolvedConfig.hideLauncher ? `
|
|
1008
1393
|
<button class="aicommerce-launcher ${state.isOpen ? "aicommerce-hidden" : ""}" aria-label="Open chat">
|
|
1009
1394
|
<span class="aicommerce-launcher-icon">${resolvedConfig.buttonText}</span>
|
|
1010
1395
|
</button>
|
|
1011
1396
|
` : ""}
|
|
1012
1397
|
|
|
1013
1398
|
<div class="aicommerce-chat ${state.isOpen ? "aicommerce-open" : "aicommerce-closed"}">
|
|
1399
|
+
${!isEmbedded ? `
|
|
1014
1400
|
<div class="aicommerce-header">
|
|
1015
1401
|
<div class="aicommerce-header-info">
|
|
1016
1402
|
<div class="aicommerce-avatar">
|
|
@@ -1023,7 +1409,9 @@ function createWidget(config) {
|
|
|
1023
1409
|
</div>
|
|
1024
1410
|
<button class="aicommerce-close" aria-label="Close chat">\u2715</button>
|
|
1025
1411
|
</div>
|
|
1412
|
+
` : ""}
|
|
1026
1413
|
|
|
1414
|
+
${isEmbedded && hasUserMessages ? `
|
|
1027
1415
|
<div class="aicommerce-messages">
|
|
1028
1416
|
${state.messages.map((msg, index) => {
|
|
1029
1417
|
const isRtl = isArabic(msg.content);
|
|
@@ -1062,34 +1450,61 @@ function createWidget(config) {
|
|
|
1062
1450
|
</div>
|
|
1063
1451
|
` : ""}
|
|
1064
1452
|
</div>
|
|
1453
|
+
` : ""}
|
|
1065
1454
|
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1455
|
+
${!isEmbedded ? `
|
|
1456
|
+
<div class="aicommerce-messages">
|
|
1457
|
+
${state.messages.map((msg, index) => {
|
|
1458
|
+
const isRtl = isArabic(msg.content);
|
|
1459
|
+
const isUser = msg.role === "user";
|
|
1460
|
+
return `
|
|
1461
|
+
<div class="aicommerce-message aicommerce-${msg.role}">
|
|
1462
|
+
<div class="aicommerce-message-content ${isRtl ? "aicommerce-rtl" : "aicommerce-ltr"}">
|
|
1463
|
+
${msg.audioUrl ? renderAudioPlayer(msg, index, isUser) : escapeHtml(msg.content)}
|
|
1464
|
+
</div>
|
|
1465
|
+
${msg.products && msg.products.length > 0 ? `
|
|
1466
|
+
<div class="aicommerce-products">
|
|
1467
|
+
${msg.products.map((product) => `
|
|
1468
|
+
<div class="aicommerce-product-card" data-product-id="${product.id}" data-variant-id="${product.variantId || ""}">
|
|
1469
|
+
${product.image || product.imageUrl ? `
|
|
1470
|
+
<img src="${product.image || product.imageUrl}" alt="${escapeHtml(product.name)}" class="aicommerce-product-image" />
|
|
1471
|
+
` : `
|
|
1472
|
+
<div class="aicommerce-product-placeholder">\u{1F4E6}</div>
|
|
1473
|
+
`}
|
|
1474
|
+
<div class="aicommerce-product-info">
|
|
1475
|
+
<span class="aicommerce-product-name" title="${escapeHtml(product.name)}">${escapeHtml(product.name)}</span>
|
|
1476
|
+
${product.description ? `<p class="aicommerce-product-desc">${escapeHtml(product.description)}</p>` : ""}
|
|
1477
|
+
<span class="aicommerce-product-price">${formatPrice(product.price, product.currency)}</span>
|
|
1478
|
+
<button class="aicommerce-add-to-cart" data-product-id="${product.id}">
|
|
1479
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
1480
|
+
<circle cx="9" cy="21" r="1"/><circle cx="20" cy="21" r="1"/>
|
|
1481
|
+
<path d="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6"/>
|
|
1482
|
+
</svg>
|
|
1483
|
+
${resolvedConfig.addToCartText || "Add to Cart"}
|
|
1484
|
+
</button>
|
|
1485
|
+
</div>
|
|
1486
|
+
</div>
|
|
1487
|
+
`).join("")}
|
|
1488
|
+
</div>
|
|
1489
|
+
` : ""}
|
|
1490
|
+
</div>
|
|
1491
|
+
`;
|
|
1492
|
+
}).join("")}
|
|
1493
|
+
${state.isLoading ? `
|
|
1494
|
+
<div class="aicommerce-message aicommerce-assistant">
|
|
1495
|
+
<div class="aicommerce-typing">
|
|
1496
|
+
<span></span><span></span><span></span>
|
|
1497
|
+
</div>
|
|
1498
|
+
</div>
|
|
1499
|
+
` : ""}
|
|
1500
|
+
</div>
|
|
1501
|
+
` : ""}
|
|
1502
|
+
|
|
1503
|
+
${isEmbedded ? `
|
|
1504
|
+
<div class="aicommerce-input-wrapper">
|
|
1505
|
+
${inputContainerHtml}
|
|
1092
1506
|
</div>
|
|
1507
|
+
` : inputContainerHtml}
|
|
1093
1508
|
</div>
|
|
1094
1509
|
`;
|
|
1095
1510
|
container.innerHTML = html;
|
|
@@ -1133,18 +1548,40 @@ function createWidget(config) {
|
|
|
1133
1548
|
const inputEl = container.querySelector(".aicommerce-input");
|
|
1134
1549
|
const sendEl = container.querySelector(".aicommerce-send");
|
|
1135
1550
|
if (inputEl) {
|
|
1136
|
-
inputEl.addEventListener("
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1551
|
+
inputEl.addEventListener("keydown", (e) => {
|
|
1552
|
+
const keyEvent = e;
|
|
1553
|
+
if (keyEvent.key === "Enter") {
|
|
1554
|
+
const isTextarea = inputEl instanceof HTMLTextAreaElement;
|
|
1555
|
+
if (isTextarea && keyEvent.shiftKey) {
|
|
1556
|
+
return;
|
|
1557
|
+
}
|
|
1558
|
+
e.preventDefault();
|
|
1559
|
+
const value = inputEl.value.trim();
|
|
1560
|
+
if (value) {
|
|
1561
|
+
handleSend(value);
|
|
1562
|
+
inputEl.value = "";
|
|
1563
|
+
if (isTextarea) {
|
|
1564
|
+
inputEl.style.height = "auto";
|
|
1565
|
+
}
|
|
1566
|
+
}
|
|
1140
1567
|
}
|
|
1141
1568
|
});
|
|
1569
|
+
if (inputEl instanceof HTMLTextAreaElement) {
|
|
1570
|
+
inputEl.addEventListener("input", () => {
|
|
1571
|
+
inputEl.style.height = "auto";
|
|
1572
|
+
inputEl.style.height = Math.min(inputEl.scrollHeight, 150) + "px";
|
|
1573
|
+
});
|
|
1574
|
+
}
|
|
1142
1575
|
}
|
|
1143
1576
|
if (sendEl && inputEl) {
|
|
1144
1577
|
sendEl.addEventListener("click", () => {
|
|
1145
|
-
|
|
1146
|
-
|
|
1578
|
+
const value = inputEl.value.trim();
|
|
1579
|
+
if (value) {
|
|
1580
|
+
handleSend(value);
|
|
1147
1581
|
inputEl.value = "";
|
|
1582
|
+
if (inputEl instanceof HTMLTextAreaElement) {
|
|
1583
|
+
inputEl.style.height = "auto";
|
|
1584
|
+
}
|
|
1148
1585
|
}
|
|
1149
1586
|
});
|
|
1150
1587
|
}
|
|
@@ -1154,7 +1591,8 @@ function createWidget(config) {
|
|
|
1154
1591
|
}
|
|
1155
1592
|
const productCards = container.querySelectorAll(".aicommerce-product-card");
|
|
1156
1593
|
productCards.forEach((card) => {
|
|
1157
|
-
card.addEventListener("click", () => {
|
|
1594
|
+
card.addEventListener("click", (e) => {
|
|
1595
|
+
if (e.target.closest(".aicommerce-add-to-cart")) return;
|
|
1158
1596
|
const productId = card.getAttribute("data-product-id");
|
|
1159
1597
|
const product = state.messages.flatMap((m) => m.products || []).find((p) => p.id === productId);
|
|
1160
1598
|
if (product) {
|
|
@@ -1166,6 +1604,49 @@ function createWidget(config) {
|
|
|
1166
1604
|
}
|
|
1167
1605
|
});
|
|
1168
1606
|
});
|
|
1607
|
+
const addToCartBtns = container.querySelectorAll(".aicommerce-add-to-cart");
|
|
1608
|
+
addToCartBtns.forEach((btn) => {
|
|
1609
|
+
btn.addEventListener("click", async (e) => {
|
|
1610
|
+
e.stopPropagation();
|
|
1611
|
+
const button = btn;
|
|
1612
|
+
const productCard = button.closest(".aicommerce-product-card");
|
|
1613
|
+
const productId = productCard?.getAttribute("data-product-id");
|
|
1614
|
+
const variantId = productCard?.getAttribute("data-variant-id");
|
|
1615
|
+
const product = state.messages.flatMap((m) => m.products || []).find((p) => p.id === productId);
|
|
1616
|
+
if (!product) return;
|
|
1617
|
+
const originalText = button.innerHTML;
|
|
1618
|
+
button.disabled = true;
|
|
1619
|
+
button.innerHTML = `
|
|
1620
|
+
<svg class="aicommerce-spinner" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
1621
|
+
<circle cx="12" cy="12" r="10" stroke-dasharray="32" stroke-dashoffset="32"/>
|
|
1622
|
+
</svg>
|
|
1623
|
+
Adding...
|
|
1624
|
+
`;
|
|
1625
|
+
try {
|
|
1626
|
+
if (resolvedConfig.onAddToCart) {
|
|
1627
|
+
await resolvedConfig.onAddToCart(product);
|
|
1628
|
+
} else if (variantId && window.Shopify) {
|
|
1629
|
+
await addToShopifyCart(variantId);
|
|
1630
|
+
} else if (product.url) {
|
|
1631
|
+
window.open(product.url, "_blank", "noopener,noreferrer");
|
|
1632
|
+
}
|
|
1633
|
+
button.innerHTML = `
|
|
1634
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
1635
|
+
<polyline points="20 6 9 17 4 12"/>
|
|
1636
|
+
</svg>
|
|
1637
|
+
Added!
|
|
1638
|
+
`;
|
|
1639
|
+
setTimeout(() => {
|
|
1640
|
+
button.innerHTML = originalText;
|
|
1641
|
+
button.disabled = false;
|
|
1642
|
+
}, 2e3);
|
|
1643
|
+
} catch (error) {
|
|
1644
|
+
console.error("[AI Commerce] Add to cart failed:", error);
|
|
1645
|
+
button.innerHTML = originalText;
|
|
1646
|
+
button.disabled = false;
|
|
1647
|
+
}
|
|
1648
|
+
});
|
|
1649
|
+
});
|
|
1169
1650
|
const sliders = container.querySelectorAll(".aicommerce-products");
|
|
1170
1651
|
sliders.forEach((slider) => {
|
|
1171
1652
|
let isDown = false;
|