@nuskin/react-search-sdk 1.0.0-trying-again.3 → 1.0.0-trying-again.4
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/README.md +25 -2
- package/dist/index.d.mts +5 -2
- package/dist/index.d.ts +5 -2
- package/dist/index.js +147 -38
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +147 -39
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -3
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { lazy, useState, useEffect, useRef, useMemo, useCallback,
|
|
1
|
+
import { lazy, useState, useEffect, useRef, useMemo, useCallback, Component, Suspense } from 'react';
|
|
2
2
|
import configurationSdk from '@nuskin/configuration-sdk';
|
|
3
3
|
import { SearchModal } from '@nuskin/react-search-components';
|
|
4
|
+
import { createProductClient, ProductProvider, useProductById, ProductCard } from '@nuskin/react-product-sdk';
|
|
5
|
+
import styled from '@emotion/styled';
|
|
4
6
|
import { jsx } from 'react/jsx-runtime';
|
|
5
7
|
|
|
6
8
|
// src/components/CommerceSearch/CommerceSearch.tsx
|
|
@@ -28,7 +30,10 @@ var TEST_ENVIRONMENT_VALUES = {
|
|
|
28
30
|
agent: {
|
|
29
31
|
appKey: "pk_commerce_product_advisor_624aea4305b09240e8c8f41d0f6527b2",
|
|
30
32
|
apiBaseUrl: "https://nui.tst.nuskin.ai/"
|
|
31
|
-
}
|
|
33
|
+
},
|
|
34
|
+
// Open to visitors who are not signed in, so the handoff can be tried where signing in is not
|
|
35
|
+
// possible (for example local development). Sign-in stays required everywhere else.
|
|
36
|
+
allowGuestAgent: true
|
|
32
37
|
};
|
|
33
38
|
function nonEmptyString(value) {
|
|
34
39
|
return typeof value === "string" ? value.trim() : "";
|
|
@@ -45,7 +50,8 @@ function normalizeCommerceSearchConfig(raw, { language } = {}) {
|
|
|
45
50
|
apiBaseUrl,
|
|
46
51
|
...language ? { language } : {}
|
|
47
52
|
}
|
|
48
|
-
} : {}
|
|
53
|
+
} : {},
|
|
54
|
+
...raw?.allowGuestAgent === true ? { allowGuestAgent: true } : {}
|
|
49
55
|
};
|
|
50
56
|
}
|
|
51
57
|
async function fetchCommerceSearchConfig({
|
|
@@ -299,6 +305,16 @@ function resolveCustomerTypeHeaders(getCustomerType) {
|
|
|
299
305
|
const customerType = getCustomerType?.()?.trim();
|
|
300
306
|
return customerType ? { "X-Customer-Type": customerType } : void 0;
|
|
301
307
|
}
|
|
308
|
+
var NO_RESULTS_ERROR_CODE = "SFOSER002";
|
|
309
|
+
async function isNoResultsResponse(response) {
|
|
310
|
+
if (response.status !== 404) return false;
|
|
311
|
+
try {
|
|
312
|
+
const body = await response.json();
|
|
313
|
+
return body?.code === NO_RESULTS_ERROR_CODE;
|
|
314
|
+
} catch {
|
|
315
|
+
return false;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
302
318
|
async function fetchJsonFromCandidates(fetchImpl, requestUrls, requestHeaders = {}) {
|
|
303
319
|
let lastError;
|
|
304
320
|
for (const requestUrl of requestUrls) {
|
|
@@ -309,6 +325,7 @@ async function fetchJsonFromCandidates(fetchImpl, requestUrls, requestHeaders =
|
|
|
309
325
|
headers: { Accept: "application/json", ...requestHeaders }
|
|
310
326
|
});
|
|
311
327
|
if (!response.ok) {
|
|
328
|
+
if (await isNoResultsResponse(response)) return null;
|
|
312
329
|
lastError = new Error(
|
|
313
330
|
`Request failed with status ${response.status}`
|
|
314
331
|
);
|
|
@@ -475,6 +492,19 @@ function toNavigationTarget(path) {
|
|
|
475
492
|
return /^https?:\/\//i.test(path) ? { type: "external", url: path } : { type: "internal", path };
|
|
476
493
|
}
|
|
477
494
|
|
|
495
|
+
// src/utils/productEnvironment.ts
|
|
496
|
+
var PRODUCT_ENVIRONMENTS = ["dev", "test", "prod"];
|
|
497
|
+
function toProductEnvironment(environmentCode) {
|
|
498
|
+
return environmentCode && PRODUCT_ENVIRONMENTS.includes(environmentCode) ? environmentCode : void 0;
|
|
499
|
+
}
|
|
500
|
+
function getProductEnvironment() {
|
|
501
|
+
try {
|
|
502
|
+
return toProductEnvironment(getEnvironmentCode());
|
|
503
|
+
} catch {
|
|
504
|
+
return void 0;
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
|
|
478
508
|
// src/utils/catalogHelpers.ts
|
|
479
509
|
var CART_DISABLED_PRODUCT_STATUSES = /* @__PURE__ */ new Set([
|
|
480
510
|
"discontinued",
|
|
@@ -1004,9 +1034,10 @@ function resolveNuiSearchFlag(env = {}) {
|
|
|
1004
1034
|
}
|
|
1005
1035
|
function isNuiSearchEnabled({
|
|
1006
1036
|
isAuthenticated,
|
|
1007
|
-
flag
|
|
1037
|
+
flag,
|
|
1038
|
+
allowGuests = false
|
|
1008
1039
|
}) {
|
|
1009
|
-
return
|
|
1040
|
+
return flag === true && (isAuthenticated === true || allowGuests);
|
|
1010
1041
|
}
|
|
1011
1042
|
|
|
1012
1043
|
// src/utils/searchRouting.ts
|
|
@@ -1020,15 +1051,69 @@ function decideSearchRoute({
|
|
|
1020
1051
|
if (snapshot.suggestionFetchFailed) return "search";
|
|
1021
1052
|
return snapshot.suggestions.length > 0 ? "search" : "handoff";
|
|
1022
1053
|
}
|
|
1054
|
+
|
|
1055
|
+
// src/utils/cachedProductClient.ts
|
|
1056
|
+
function withProductCache(client) {
|
|
1057
|
+
const lookups = /* @__PURE__ */ new Map();
|
|
1058
|
+
return {
|
|
1059
|
+
getProductById(productId) {
|
|
1060
|
+
let lookup = lookups.get(productId);
|
|
1061
|
+
if (!lookup) {
|
|
1062
|
+
lookup = client.getProductById(productId);
|
|
1063
|
+
lookups.set(productId, lookup);
|
|
1064
|
+
}
|
|
1065
|
+
return lookup;
|
|
1066
|
+
},
|
|
1067
|
+
getProductsByIds: (productIds) => client.getProductsByIds(productIds)
|
|
1068
|
+
};
|
|
1069
|
+
}
|
|
1070
|
+
var AgentProductSlot = styled.div`
|
|
1071
|
+
&& {
|
|
1072
|
+
flex: 0 0 240px;
|
|
1073
|
+
overflow: hidden;
|
|
1074
|
+
width: 240px;
|
|
1075
|
+
}
|
|
1076
|
+
`;
|
|
1077
|
+
var SalesAIChatWidget = lazy(
|
|
1078
|
+
() => Promise.all([
|
|
1079
|
+
import('@nu-skin-enterprises/chat-widget'),
|
|
1080
|
+
import('@nu-skin-enterprises/chat-widget/styles.css')
|
|
1081
|
+
]).then(([mod]) => ({ default: mod.SalesAIChatWidget }))
|
|
1082
|
+
);
|
|
1023
1083
|
var HANDLE_POLL_MS = 50;
|
|
1024
1084
|
var HANDLE_TIMEOUT_MS = 15e3;
|
|
1025
|
-
|
|
1026
|
-
const
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
return {
|
|
1031
|
-
}
|
|
1085
|
+
function AgentProductCard({ sku }) {
|
|
1086
|
+
const { product, isLoading, error } = useProductById(sku);
|
|
1087
|
+
if (!isLoading && (error || !product?.seoInformation?.canonicalURL)) {
|
|
1088
|
+
return null;
|
|
1089
|
+
}
|
|
1090
|
+
return /* @__PURE__ */ jsx(AgentProductSlot, { children: /* @__PURE__ */ jsx(ProductCard, { productId: sku }) });
|
|
1091
|
+
}
|
|
1092
|
+
var renderAgentProduct = (product) => /* @__PURE__ */ jsx(AgentProductCard, { sku: product.sku });
|
|
1093
|
+
function AgentWidget({
|
|
1094
|
+
widgetProps,
|
|
1095
|
+
products
|
|
1096
|
+
}) {
|
|
1097
|
+
const environment = products?.environment;
|
|
1098
|
+
const market = products?.market;
|
|
1099
|
+
const language = products?.language;
|
|
1100
|
+
const client = useMemo(
|
|
1101
|
+
() => environment && market && language ? withProductCache(
|
|
1102
|
+
createProductClient({ environment, market, language })
|
|
1103
|
+
) : void 0,
|
|
1104
|
+
[environment, market, language]
|
|
1105
|
+
);
|
|
1106
|
+
if (!client) {
|
|
1107
|
+
return /* @__PURE__ */ jsx(Suspense, { fallback: null, children: /* @__PURE__ */ jsx(SalesAIChatWidget, { ...widgetProps }) });
|
|
1108
|
+
}
|
|
1109
|
+
return /* @__PURE__ */ jsx(ProductProvider, { client, children: /* @__PURE__ */ jsx(Suspense, { fallback: null, children: /* @__PURE__ */ jsx(
|
|
1110
|
+
SalesAIChatWidget,
|
|
1111
|
+
{
|
|
1112
|
+
renderProduct: renderAgentProduct,
|
|
1113
|
+
...widgetProps
|
|
1114
|
+
}
|
|
1115
|
+
) }) });
|
|
1116
|
+
}
|
|
1032
1117
|
function getSalesAIHandle() {
|
|
1033
1118
|
return window.SalesAI;
|
|
1034
1119
|
}
|
|
@@ -1084,6 +1169,7 @@ function NuiAgentPanel({
|
|
|
1084
1169
|
agent,
|
|
1085
1170
|
query,
|
|
1086
1171
|
handoffContext,
|
|
1172
|
+
products,
|
|
1087
1173
|
onUnavailable
|
|
1088
1174
|
}) {
|
|
1089
1175
|
useHandoff({
|
|
@@ -1092,19 +1178,22 @@ function NuiAgentPanel({
|
|
|
1092
1178
|
agentContext: agent.context,
|
|
1093
1179
|
onUnavailable
|
|
1094
1180
|
});
|
|
1095
|
-
|
|
1096
|
-
|
|
1181
|
+
const widgetProps = {
|
|
1182
|
+
appKey: agent.appKey,
|
|
1183
|
+
apiBaseUrl: agent.apiBaseUrl,
|
|
1184
|
+
theme: agent.theme ?? "nui-light",
|
|
1185
|
+
defaultOpen: true,
|
|
1186
|
+
hideFab: true,
|
|
1187
|
+
placement: "host",
|
|
1188
|
+
...agent.language === void 0 ? {} : { language: agent.language }
|
|
1189
|
+
};
|
|
1190
|
+
return /* @__PURE__ */ jsx(AgentErrorBoundary, { onError: onUnavailable, children: /* @__PURE__ */ jsx(
|
|
1191
|
+
AgentWidget,
|
|
1097
1192
|
{
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
theme: agent.theme ?? "nui-light",
|
|
1101
|
-
defaultOpen: true,
|
|
1102
|
-
hideFab: true,
|
|
1103
|
-
placement: "host",
|
|
1104
|
-
...agent.language === void 0 ? {} : { language: agent.language },
|
|
1105
|
-
...agent.renderProduct === void 0 ? {} : { renderProduct: agent.renderProduct }
|
|
1193
|
+
widgetProps,
|
|
1194
|
+
...products ? { products } : {}
|
|
1106
1195
|
}
|
|
1107
|
-
) })
|
|
1196
|
+
) });
|
|
1108
1197
|
}
|
|
1109
1198
|
var SUBMIT_WAIT_TIMEOUT_MS = 2e3;
|
|
1110
1199
|
function uniqueRecentSearches(queries) {
|
|
@@ -1123,6 +1212,8 @@ function CommerceSearchView({
|
|
|
1123
1212
|
navigate,
|
|
1124
1213
|
isAuthenticated,
|
|
1125
1214
|
agent,
|
|
1215
|
+
allowGuestAgent = false,
|
|
1216
|
+
agentProducts,
|
|
1126
1217
|
logo,
|
|
1127
1218
|
minimumSearchLength = MINIMUM_SEARCH_CHAR_LENGTH,
|
|
1128
1219
|
gtmContext
|
|
@@ -1148,7 +1239,11 @@ function CommerceSearchView({
|
|
|
1148
1239
|
suggestions,
|
|
1149
1240
|
updateQuery
|
|
1150
1241
|
} = search;
|
|
1151
|
-
const enabled = agent !== void 0 && isNuiSearchEnabled({
|
|
1242
|
+
const enabled = agent !== void 0 && isNuiSearchEnabled({
|
|
1243
|
+
isAuthenticated,
|
|
1244
|
+
flag,
|
|
1245
|
+
allowGuests: allowGuestAgent
|
|
1246
|
+
});
|
|
1152
1247
|
const items = getVisibleSuggestions({
|
|
1153
1248
|
didYouMean,
|
|
1154
1249
|
suggestions
|
|
@@ -1318,6 +1413,22 @@ function CommerceSearchView({
|
|
|
1318
1413
|
if (agentQuery !== null)
|
|
1319
1414
|
navigateTo(service.submitProductSearch(agentQuery));
|
|
1320
1415
|
}, [agentQuery, navigateTo, service]);
|
|
1416
|
+
const agentProductsProps = agentProducts ? { products: agentProducts } : {};
|
|
1417
|
+
const agentPanel = handoff === null || agent === void 0 ? void 0 : /* @__PURE__ */ jsx(
|
|
1418
|
+
NuiAgentPanel,
|
|
1419
|
+
{
|
|
1420
|
+
agent,
|
|
1421
|
+
query: handoff.query,
|
|
1422
|
+
handoffContext: {
|
|
1423
|
+
source: "storefront_search",
|
|
1424
|
+
trigger: "zero_results",
|
|
1425
|
+
query: handoff.query,
|
|
1426
|
+
did_you_mean: handoff.didYouMean
|
|
1427
|
+
},
|
|
1428
|
+
...agentProductsProps,
|
|
1429
|
+
onUnavailable: handleAgentUnavailable
|
|
1430
|
+
}
|
|
1431
|
+
);
|
|
1321
1432
|
return /* @__PURE__ */ jsx(
|
|
1322
1433
|
SearchModal,
|
|
1323
1434
|
{
|
|
@@ -1345,20 +1456,7 @@ function CommerceSearchView({
|
|
|
1345
1456
|
onSelect: handleRecentSelect,
|
|
1346
1457
|
onClear: handleClearRecent
|
|
1347
1458
|
},
|
|
1348
|
-
agentPanel
|
|
1349
|
-
NuiAgentPanel,
|
|
1350
|
-
{
|
|
1351
|
-
agent,
|
|
1352
|
-
query: handoff.query,
|
|
1353
|
-
handoffContext: {
|
|
1354
|
-
source: "storefront_search",
|
|
1355
|
-
trigger: "zero_results",
|
|
1356
|
-
query: handoff.query,
|
|
1357
|
-
did_you_mean: handoff.didYouMean
|
|
1358
|
-
},
|
|
1359
|
-
onUnavailable: handleAgentUnavailable
|
|
1360
|
-
}
|
|
1361
|
-
)
|
|
1459
|
+
agentPanel
|
|
1362
1460
|
}
|
|
1363
1461
|
);
|
|
1364
1462
|
}
|
|
@@ -1376,7 +1474,7 @@ function CommerceSearch({
|
|
|
1376
1474
|
useEffect(() => {
|
|
1377
1475
|
if (isOpen) setHasOpened(true);
|
|
1378
1476
|
}, [isOpen]);
|
|
1379
|
-
const { minimumSearchLength, agent } = useCommerceSearchConfig({
|
|
1477
|
+
const { minimumSearchLength, agent, allowGuestAgent } = useCommerceSearchConfig({
|
|
1380
1478
|
country,
|
|
1381
1479
|
language,
|
|
1382
1480
|
enabled: hasOpened
|
|
@@ -1409,6 +1507,14 @@ function CommerceSearch({
|
|
|
1409
1507
|
}),
|
|
1410
1508
|
[country, language, isAuthenticated, accountType, userId]
|
|
1411
1509
|
);
|
|
1510
|
+
const agentProducts = useMemo(() => {
|
|
1511
|
+
const environment = getProductEnvironment();
|
|
1512
|
+
return environment ? {
|
|
1513
|
+
environment,
|
|
1514
|
+
market: country.toUpperCase(),
|
|
1515
|
+
language: language.toLowerCase()
|
|
1516
|
+
} : void 0;
|
|
1517
|
+
}, [country, language]);
|
|
1412
1518
|
return /* @__PURE__ */ jsx(
|
|
1413
1519
|
CommerceSearchView,
|
|
1414
1520
|
{
|
|
@@ -1418,6 +1524,8 @@ function CommerceSearch({
|
|
|
1418
1524
|
navigate: navigateToPath,
|
|
1419
1525
|
isAuthenticated,
|
|
1420
1526
|
...agent ? { agent } : {},
|
|
1527
|
+
...allowGuestAgent ? { allowGuestAgent } : {},
|
|
1528
|
+
...agentProducts ? { agentProducts } : {},
|
|
1421
1529
|
logo,
|
|
1422
1530
|
minimumSearchLength,
|
|
1423
1531
|
gtmContext
|