@propeller-commerce/propeller-v2-react-ui 0.8.0 → 0.10.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/CHANGELOG.md +27 -0
- package/dist/index.cjs +92 -32
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -5
- package/dist/index.d.ts +9 -5
- package/dist/index.js +93 -33
- package/dist/index.js.map +1 -1
- package/dist/pure.cjs +4 -4
- package/dist/pure.cjs.map +1 -1
- package/dist/pure.d.cts +2 -2
- package/dist/pure.d.ts +2 -2
- package/dist/pure.js +4 -4
- package/dist/pure.js.map +1 -1
- package/package.json +3 -3
package/dist/index.d.cts
CHANGED
|
@@ -3,7 +3,7 @@ import { Services, ShopMode, UserMode, PriceComponentProps, StockComponentProps,
|
|
|
3
3
|
export * from '@propeller-commerce/propeller-v2-core-ui';
|
|
4
4
|
import * as React$1 from 'react';
|
|
5
5
|
import React__default, { ReactNode, ComponentType } from 'react';
|
|
6
|
-
import { GraphQLClient, Contact, Customer, Cart, CartMainItem, Product, Cluster, AddressType, Gender, YesNo, Address, TransformationsInput, MediaImageProductSearchInput, CartProcessResponse, Crossupsell, CartUpdateAddressInput, CartUpdateInput, CartAddressType, ClusterConfig, Company, CompanyVariables, PurchaseAuthorizationConfigCreateInput, PurchaseAuthorizationConfigUpdateInput, FavoriteList, DateSearchInput, DecimalSearchInput, OrderSortInput, OrderType, OrderSearchFields, Order, ProductTextFilterInput, AttributeFilter, ProductsResponse, Category, SparePart, ProductSortField, SortOrder, SparePartsResponse, SparePartsMachine, CrossupsellType, AttributeResult, RegisterContactInput as RegisterContactInput$1, PurchaseAuthorizationConfig, CartChildItemInput, CartAddress, WarehouseAddress, OrderAddress, CartBaseItem, CartCarrier, CartPaymethod, ClusterOption, ProductInventory, OrderItem, ProductPrice, Bundle, PaginatedMediaDocumentResponse, PaginatedMediaVideoResponse } from '@propeller-commerce/propeller-sdk-v2';
|
|
6
|
+
import { GraphQLClient, Contact, Customer, Cart, CartMainItem, Product, Cluster, AddressType, Gender, YesNo, Address, MagicTokenCreateInput, MagicToken, TransformationsInput, MediaImageProductSearchInput, CartProcessResponse, Crossupsell, CartUpdateAddressInput, CartUpdateInput, CartAddressType, ClusterConfig, Company, CompanyVariables, PurchaseAuthorizationConfigCreateInput, PurchaseAuthorizationConfigUpdateInput, FavoriteList, DateSearchInput, DecimalSearchInput, OrderSortInput, OrderType, OrderSearchFields, Order, ProductTextFilterInput, AttributeFilter, ProductsResponse, Category, SparePart, ProductSortField, SortOrder, SparePartsResponse, SparePartsMachine, CrossupsellType, AttributeResult, RegisterContactInput as RegisterContactInput$1, PurchaseAuthorizationConfig, CartChildItemInput, CartAddress, WarehouseAddress, OrderAddress, CartBaseItem, CartCarrier, CartPaymethod, ClusterOption, ProductInventory, OrderItem, ProductPrice, Bundle, PaginatedMediaDocumentResponse, PaginatedMediaVideoResponse } from '@propeller-commerce/propeller-sdk-v2';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Tier 1 — application-wide infrastructure. Bound by `<PropellerDepsProvider>`
|
|
@@ -499,6 +499,10 @@ interface UseAuthReturn {
|
|
|
499
499
|
error: string | null;
|
|
500
500
|
/** Authenticates by email/password; pass `onLoginSubmit` to fully override the SDK login. */
|
|
501
501
|
login: (email: string, password: string, onLoginSubmit?: (email: string, password: string) => Promise<Contact | Customer>) => Promise<Result<AuthSuccess, string>>;
|
|
502
|
+
/** Passwordless login: exchanges a backend-issued magic token for a session (then loads the viewer). */
|
|
503
|
+
magicLogin: (token: string) => Promise<Result<AuthSuccess, string>>;
|
|
504
|
+
/** Issues a magic token for a contact/customer (authenticated); its `id` is embedded in a magic-login link. */
|
|
505
|
+
createMagicToken: (input: MagicTokenCreateInput) => Promise<Result<MagicToken, string>>;
|
|
502
506
|
/** Registers a B2B contact (and optionally a company + addresses); `autoLogin` keeps the session. */
|
|
503
507
|
registerContact: (input: RegisterContactInput, preferredLanguage?: string, autoLogin?: boolean) => Promise<Result<AuthSuccess, string>>;
|
|
504
508
|
/** Registers a B2C customer (and optionally addresses); `autoLogin` keeps the session. */
|
|
@@ -737,8 +741,8 @@ declare function useCheckout(options: UseCheckoutOptions): UseCheckoutReturn;
|
|
|
737
741
|
|
|
738
742
|
/** A cluster-config setting resolved against the current product set and selections. */
|
|
739
743
|
interface ConfiguredSetting {
|
|
740
|
-
/** Setting id from the cluster config. */
|
|
741
|
-
id:
|
|
744
|
+
/** Setting id (uuid) from the cluster config. */
|
|
745
|
+
id: string;
|
|
742
746
|
/** Raw attribute name this setting selects on. */
|
|
743
747
|
name: string;
|
|
744
748
|
/** Display widget hint (e.g. dropdown, swatch). */
|
|
@@ -3535,12 +3539,12 @@ declare function CategoryDescription(props: CategoryDescriptionProps): React$1.J
|
|
|
3535
3539
|
interface CategoryShortDescriptionProps {
|
|
3536
3540
|
/**
|
|
3537
3541
|
* Language code used to resolve the correct localised short description
|
|
3538
|
-
* from `category.
|
|
3542
|
+
* from `category.shortDescriptions`.
|
|
3539
3543
|
*/
|
|
3540
3544
|
language: string;
|
|
3541
3545
|
/**
|
|
3542
3546
|
* Propeller Category object.
|
|
3543
|
-
* The component reads `category.
|
|
3547
|
+
* The component reads `category.shortDescriptions` (an array of LocalizedString)
|
|
3544
3548
|
* and renders the matching language entry as HTML.
|
|
3545
3549
|
*/
|
|
3546
3550
|
category?: Category;
|
package/dist/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { Services, ShopMode, UserMode, PriceComponentProps, StockComponentProps,
|
|
|
3
3
|
export * from '@propeller-commerce/propeller-v2-core-ui';
|
|
4
4
|
import * as React$1 from 'react';
|
|
5
5
|
import React__default, { ReactNode, ComponentType } from 'react';
|
|
6
|
-
import { GraphQLClient, Contact, Customer, Cart, CartMainItem, Product, Cluster, AddressType, Gender, YesNo, Address, TransformationsInput, MediaImageProductSearchInput, CartProcessResponse, Crossupsell, CartUpdateAddressInput, CartUpdateInput, CartAddressType, ClusterConfig, Company, CompanyVariables, PurchaseAuthorizationConfigCreateInput, PurchaseAuthorizationConfigUpdateInput, FavoriteList, DateSearchInput, DecimalSearchInput, OrderSortInput, OrderType, OrderSearchFields, Order, ProductTextFilterInput, AttributeFilter, ProductsResponse, Category, SparePart, ProductSortField, SortOrder, SparePartsResponse, SparePartsMachine, CrossupsellType, AttributeResult, RegisterContactInput as RegisterContactInput$1, PurchaseAuthorizationConfig, CartChildItemInput, CartAddress, WarehouseAddress, OrderAddress, CartBaseItem, CartCarrier, CartPaymethod, ClusterOption, ProductInventory, OrderItem, ProductPrice, Bundle, PaginatedMediaDocumentResponse, PaginatedMediaVideoResponse } from '@propeller-commerce/propeller-sdk-v2';
|
|
6
|
+
import { GraphQLClient, Contact, Customer, Cart, CartMainItem, Product, Cluster, AddressType, Gender, YesNo, Address, MagicTokenCreateInput, MagicToken, TransformationsInput, MediaImageProductSearchInput, CartProcessResponse, Crossupsell, CartUpdateAddressInput, CartUpdateInput, CartAddressType, ClusterConfig, Company, CompanyVariables, PurchaseAuthorizationConfigCreateInput, PurchaseAuthorizationConfigUpdateInput, FavoriteList, DateSearchInput, DecimalSearchInput, OrderSortInput, OrderType, OrderSearchFields, Order, ProductTextFilterInput, AttributeFilter, ProductsResponse, Category, SparePart, ProductSortField, SortOrder, SparePartsResponse, SparePartsMachine, CrossupsellType, AttributeResult, RegisterContactInput as RegisterContactInput$1, PurchaseAuthorizationConfig, CartChildItemInput, CartAddress, WarehouseAddress, OrderAddress, CartBaseItem, CartCarrier, CartPaymethod, ClusterOption, ProductInventory, OrderItem, ProductPrice, Bundle, PaginatedMediaDocumentResponse, PaginatedMediaVideoResponse } from '@propeller-commerce/propeller-sdk-v2';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Tier 1 — application-wide infrastructure. Bound by `<PropellerDepsProvider>`
|
|
@@ -499,6 +499,10 @@ interface UseAuthReturn {
|
|
|
499
499
|
error: string | null;
|
|
500
500
|
/** Authenticates by email/password; pass `onLoginSubmit` to fully override the SDK login. */
|
|
501
501
|
login: (email: string, password: string, onLoginSubmit?: (email: string, password: string) => Promise<Contact | Customer>) => Promise<Result<AuthSuccess, string>>;
|
|
502
|
+
/** Passwordless login: exchanges a backend-issued magic token for a session (then loads the viewer). */
|
|
503
|
+
magicLogin: (token: string) => Promise<Result<AuthSuccess, string>>;
|
|
504
|
+
/** Issues a magic token for a contact/customer (authenticated); its `id` is embedded in a magic-login link. */
|
|
505
|
+
createMagicToken: (input: MagicTokenCreateInput) => Promise<Result<MagicToken, string>>;
|
|
502
506
|
/** Registers a B2B contact (and optionally a company + addresses); `autoLogin` keeps the session. */
|
|
503
507
|
registerContact: (input: RegisterContactInput, preferredLanguage?: string, autoLogin?: boolean) => Promise<Result<AuthSuccess, string>>;
|
|
504
508
|
/** Registers a B2C customer (and optionally addresses); `autoLogin` keeps the session. */
|
|
@@ -737,8 +741,8 @@ declare function useCheckout(options: UseCheckoutOptions): UseCheckoutReturn;
|
|
|
737
741
|
|
|
738
742
|
/** A cluster-config setting resolved against the current product set and selections. */
|
|
739
743
|
interface ConfiguredSetting {
|
|
740
|
-
/** Setting id from the cluster config. */
|
|
741
|
-
id:
|
|
744
|
+
/** Setting id (uuid) from the cluster config. */
|
|
745
|
+
id: string;
|
|
742
746
|
/** Raw attribute name this setting selects on. */
|
|
743
747
|
name: string;
|
|
744
748
|
/** Display widget hint (e.g. dropdown, swatch). */
|
|
@@ -3535,12 +3539,12 @@ declare function CategoryDescription(props: CategoryDescriptionProps): React$1.J
|
|
|
3535
3539
|
interface CategoryShortDescriptionProps {
|
|
3536
3540
|
/**
|
|
3537
3541
|
* Language code used to resolve the correct localised short description
|
|
3538
|
-
* from `category.
|
|
3542
|
+
* from `category.shortDescriptions`.
|
|
3539
3543
|
*/
|
|
3540
3544
|
language: string;
|
|
3541
3545
|
/**
|
|
3542
3546
|
* Propeller Category object.
|
|
3543
|
-
* The component reads `category.
|
|
3547
|
+
* The component reads `category.shortDescriptions` (an array of LocalizedString)
|
|
3544
3548
|
* and renders the matching language entry as HTML.
|
|
3545
3549
|
*/
|
|
3546
3550
|
category?: Category;
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ export * from '@propeller-commerce/propeller-v2-core-ui';
|
|
|
4
4
|
import * as React6 from 'react';
|
|
5
5
|
import { createContext, useState, useRef, useMemo, useCallback, useContext, useEffect } from 'react';
|
|
6
6
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
7
|
-
import { ProductStatus, ProductSortField, SortOrder, PurchaseRole, CrossupsellType, CartStatus, CartAddressType, Gender, YesNo, AddressType, PaymentStatuses, OrderSearchFields, OrderItemClass, ProductSearchableField, machineService, AttributeType, OrderSortField, OrderType, OrderDiscountType, BundleCondition } from '@propeller-commerce/propeller-sdk-v2';
|
|
7
|
+
import { ProductStatus, ProductSortField, SortOrder, PurchaseRole, CrossupsellType, CartStatus, CartAddressType, Gender, YesNo, AddressType, MagicTokenService, PaymentStatuses, OrderSearchFields, OrderItemClass, ProductSearchableField, machineService, AttributeType, OrderSortField, OrderType, OrderDiscountType, BundleCondition } from '@propeller-commerce/propeller-sdk-v2';
|
|
8
8
|
import { User } from 'lucide-react';
|
|
9
9
|
|
|
10
10
|
// src/index.ts
|
|
@@ -287,6 +287,66 @@ function useAuth(options) {
|
|
|
287
287
|
setLoading(false);
|
|
288
288
|
}
|
|
289
289
|
}, [graphqlClient, language, onAuthHeaderUpdate, configuration]);
|
|
290
|
+
const magicLogin = useCallback(async (token) => {
|
|
291
|
+
setLoading(true);
|
|
292
|
+
setError(null);
|
|
293
|
+
try {
|
|
294
|
+
const loginResult = await new MagicTokenService(graphqlClient).magicTokenLogin(token);
|
|
295
|
+
const session = loginResult?.session;
|
|
296
|
+
const accessToken = session?.accessToken;
|
|
297
|
+
const refreshToken = session?.refreshToken;
|
|
298
|
+
const expiresAt = session?.expirationTime;
|
|
299
|
+
if (accessToken) {
|
|
300
|
+
const cfg = graphqlClient.getConfig();
|
|
301
|
+
graphqlClient.updateConfig({
|
|
302
|
+
headers: { ...cfg.headers, Authorization: `Bearer ${accessToken}` }
|
|
303
|
+
});
|
|
304
|
+
onAuthHeaderUpdate?.(accessToken);
|
|
305
|
+
}
|
|
306
|
+
const userService = createServices(graphqlClient).user;
|
|
307
|
+
const viewerInput = {
|
|
308
|
+
...configuration?.contactTrackAttributes?.length && {
|
|
309
|
+
contactAttributesInput: { attributeDescription: { names: configuration.contactTrackAttributes } }
|
|
310
|
+
},
|
|
311
|
+
...configuration?.customerTrackAttributes?.length && {
|
|
312
|
+
customerAttributesInput: { attributeDescription: { names: configuration.customerTrackAttributes } }
|
|
313
|
+
},
|
|
314
|
+
...configuration?.companyTrackAttributes?.length && {
|
|
315
|
+
companyAttributesInput: { attributeDescription: { names: configuration.companyTrackAttributes } }
|
|
316
|
+
},
|
|
317
|
+
// See isViewerSearchInput — an empty array `[]` is truthy but 400s the viewer.
|
|
318
|
+
...isViewerSearchInput(configuration?.contactPAConfigInput) && {
|
|
319
|
+
contactPAConfigInput: configuration.contactPAConfigInput
|
|
320
|
+
},
|
|
321
|
+
...isViewerSearchInput(configuration?.contactCompaniesSearchInput) && {
|
|
322
|
+
contactCompaniesSearchInput: configuration.contactCompaniesSearchInput
|
|
323
|
+
}
|
|
324
|
+
};
|
|
325
|
+
const viewer = await userService.getViewer(viewerInput);
|
|
326
|
+
const user = viewer;
|
|
327
|
+
return ok({ user, accessToken, refreshToken, expiresAt });
|
|
328
|
+
} catch (e) {
|
|
329
|
+
const msg = e instanceof Error ? e.message : "Magic-token login failed";
|
|
330
|
+
setError(msg);
|
|
331
|
+
return err(msg);
|
|
332
|
+
} finally {
|
|
333
|
+
setLoading(false);
|
|
334
|
+
}
|
|
335
|
+
}, [graphqlClient, onAuthHeaderUpdate, configuration]);
|
|
336
|
+
const createMagicToken = useCallback(async (input) => {
|
|
337
|
+
setLoading(true);
|
|
338
|
+
setError(null);
|
|
339
|
+
try {
|
|
340
|
+
const token = await new MagicTokenService(graphqlClient).createMagicToken(input);
|
|
341
|
+
return ok(token);
|
|
342
|
+
} catch (e) {
|
|
343
|
+
const msg = e instanceof Error ? e.message : "Failed to create magic token";
|
|
344
|
+
setError(msg);
|
|
345
|
+
return err(msg);
|
|
346
|
+
} finally {
|
|
347
|
+
setLoading(false);
|
|
348
|
+
}
|
|
349
|
+
}, [graphqlClient]);
|
|
290
350
|
const registerContact = useCallback(async (input, preferredLanguage = language, autoLogin = true) => {
|
|
291
351
|
setLoading(true);
|
|
292
352
|
setError(null);
|
|
@@ -533,7 +593,7 @@ function useAuth(options) {
|
|
|
533
593
|
setLoading(false);
|
|
534
594
|
}
|
|
535
595
|
}, [graphqlClient]);
|
|
536
|
-
return { loading, error, login, registerContact, registerCustomer, forgotPassword };
|
|
596
|
+
return { loading, error, login, magicLogin, createMagicToken, registerContact, registerCustomer, forgotPassword };
|
|
537
597
|
}
|
|
538
598
|
async function initCart(config) {
|
|
539
599
|
const {
|
|
@@ -1107,7 +1167,7 @@ function useClusterConfigurator(options) {
|
|
|
1107
1167
|
const previousSelections = {};
|
|
1108
1168
|
for (let i = 0; i < settingIndex; i++) {
|
|
1109
1169
|
const prev = sortedSettings[i];
|
|
1110
|
-
if (selections[prev.
|
|
1170
|
+
if (selections[prev.attributeName]) previousSelections[prev.attributeName] = selections[prev.attributeName];
|
|
1111
1171
|
}
|
|
1112
1172
|
const matching = filterProductsBySelections(products, previousSelections);
|
|
1113
1173
|
return collectAttributeValues(matching, attributeName);
|
|
@@ -1116,43 +1176,43 @@ function useClusterConfigurator(options) {
|
|
|
1116
1176
|
const sortedSettings = getSortedSettings();
|
|
1117
1177
|
const sel = selectedAttributes;
|
|
1118
1178
|
return sortedSettings.map((setting, index) => {
|
|
1119
|
-
const availableValues = getAvailableValuesForIndexWithSelections(setting.
|
|
1120
|
-
const selectedValue = sel[setting.
|
|
1121
|
-
const isPreviousMissing = index > 0 && sortedSettings.slice(0, index).some((prev) => !sel[prev.
|
|
1179
|
+
const availableValues = getAvailableValuesForIndexWithSelections(setting.attributeName, index, sel);
|
|
1180
|
+
const selectedValue = sel[setting.attributeName] || "";
|
|
1181
|
+
const isPreviousMissing = index > 0 && sortedSettings.slice(0, index).some((prev) => !sel[prev.attributeName]);
|
|
1122
1182
|
const isDisabled = availableValues.length === 0 || isPreviousMissing;
|
|
1123
|
-
let displayName = setting.
|
|
1183
|
+
let displayName = setting.attributeName;
|
|
1124
1184
|
let attributeType;
|
|
1125
1185
|
for (const product of products) {
|
|
1126
1186
|
const items = product.attributes?.items;
|
|
1127
1187
|
if (!items) continue;
|
|
1128
|
-
const match = items.find((a) => attributeNameMatches(a, setting.
|
|
1188
|
+
const match = items.find((a) => attributeNameMatches(a, setting.attributeName));
|
|
1129
1189
|
if (!match) continue;
|
|
1130
|
-
displayName = getAttributeDisplayName(match, language) || setting.
|
|
1190
|
+
displayName = getAttributeDisplayName(match, language) || setting.attributeName;
|
|
1131
1191
|
attributeType = match.attributeDescription?.type ?? void 0;
|
|
1132
1192
|
break;
|
|
1133
1193
|
}
|
|
1134
|
-
return { id: setting.
|
|
1194
|
+
return { id: setting.uuid, name: setting.attributeName, displayType: setting.displayType, attributeType, priority: setting.priority, displayName, availableValues, selectedValue, disabled: isDisabled };
|
|
1135
1195
|
});
|
|
1136
1196
|
}, [products, config, selectedAttributes, language]);
|
|
1137
1197
|
const handleAttributeSelect = useCallback(
|
|
1138
1198
|
(settingName, value) => {
|
|
1139
1199
|
const sortedSettings = getSortedSettings();
|
|
1140
|
-
const changedIndex = sortedSettings.findIndex((s) => s.
|
|
1200
|
+
const changedIndex = sortedSettings.findIndex((s) => s.attributeName === settingName);
|
|
1141
1201
|
if (changedIndex < 0) return;
|
|
1142
1202
|
const newSelections = { ...selectedAttributes };
|
|
1143
1203
|
newSelections[settingName] = value;
|
|
1144
|
-
for (let i = changedIndex + 1; i < sortedSettings.length; i++) delete newSelections[sortedSettings[i].
|
|
1204
|
+
for (let i = changedIndex + 1; i < sortedSettings.length; i++) delete newSelections[sortedSettings[i].attributeName];
|
|
1145
1205
|
for (let i = changedIndex + 1; i < sortedSettings.length; i++) {
|
|
1146
1206
|
const next = sortedSettings[i];
|
|
1147
|
-
const available = getAvailableValuesForIndexWithSelections(next.
|
|
1207
|
+
const available = getAvailableValuesForIndexWithSelections(next.attributeName, i, newSelections);
|
|
1148
1208
|
if (available.length > 0) {
|
|
1149
|
-
newSelections[next.
|
|
1209
|
+
newSelections[next.attributeName] = available[0];
|
|
1150
1210
|
} else {
|
|
1151
1211
|
break;
|
|
1152
1212
|
}
|
|
1153
1213
|
}
|
|
1154
1214
|
setSelectedAttributes(newSelections);
|
|
1155
|
-
const allSelected = sortedSettings.every((s) => !!newSelections[s.
|
|
1215
|
+
const allSelected = sortedSettings.every((s) => !!newSelections[s.attributeName]);
|
|
1156
1216
|
if (allSelected) {
|
|
1157
1217
|
const matching = filterProductsBySelections(products, newSelections);
|
|
1158
1218
|
if (matching.length > 0 && onConfigurationChange) onConfigurationChange(matching[0]);
|
|
@@ -1168,15 +1228,15 @@ function useClusterConfigurator(options) {
|
|
|
1168
1228
|
if (!attrItems) return;
|
|
1169
1229
|
const initial = {};
|
|
1170
1230
|
for (const setting of sortedSettings) {
|
|
1171
|
-
const match = attrItems.find((a) => attributeNameMatches(a, setting.
|
|
1231
|
+
const match = attrItems.find((a) => attributeNameMatches(a, setting.attributeName));
|
|
1172
1232
|
if (match) {
|
|
1173
1233
|
const values = extractAttributeValues(match);
|
|
1174
|
-
if (values.length) initial[setting.
|
|
1234
|
+
if (values.length) initial[setting.attributeName] = values[0];
|
|
1175
1235
|
}
|
|
1176
1236
|
}
|
|
1177
1237
|
if (!Object.keys(initial).length) return;
|
|
1178
1238
|
setSelectedAttributes(initial);
|
|
1179
|
-
const allSelected = sortedSettings.every((s) => !!initial[s.
|
|
1239
|
+
const allSelected = sortedSettings.every((s) => !!initial[s.attributeName]);
|
|
1180
1240
|
if (allSelected && onConfigurationChange) {
|
|
1181
1241
|
const matching = filterProductsBySelections(products, initial);
|
|
1182
1242
|
if (matching.length > 0) onConfigurationChange(matching[0]);
|
|
@@ -1512,15 +1572,15 @@ function buildCategoriesQuery(depth) {
|
|
|
1512
1572
|
categories {
|
|
1513
1573
|
categoryId
|
|
1514
1574
|
hidden
|
|
1515
|
-
|
|
1516
|
-
|
|
1575
|
+
names(language: $language) { value language }
|
|
1576
|
+
slugs(language: $language) { value }
|
|
1517
1577
|
${buildCategoriesQuery(depth - 1)}
|
|
1518
1578
|
}
|
|
1519
1579
|
`;
|
|
1520
1580
|
}
|
|
1521
1581
|
function mapCategory(raw, language) {
|
|
1522
|
-
const nameEntry = raw.
|
|
1523
|
-
const slugEntry = raw.
|
|
1582
|
+
const nameEntry = raw.names?.find((n) => n.language === language) ?? raw.names?.[0];
|
|
1583
|
+
const slugEntry = raw.slugs?.[0];
|
|
1524
1584
|
return {
|
|
1525
1585
|
categoryId: raw.categoryId,
|
|
1526
1586
|
name: nameEntry?.value ?? "",
|
|
@@ -1600,8 +1660,8 @@ function useMenu(options) {
|
|
|
1600
1660
|
category(categoryId: $categoryId) {
|
|
1601
1661
|
categoryId
|
|
1602
1662
|
hidden
|
|
1603
|
-
|
|
1604
|
-
|
|
1663
|
+
names(language: $language) { value language }
|
|
1664
|
+
slugs(language: $language) { value }
|
|
1605
1665
|
${buildCategoriesQuery(depth)}
|
|
1606
1666
|
}
|
|
1607
1667
|
}
|
|
@@ -2060,7 +2120,7 @@ function useProductInfo(options) {
|
|
|
2060
2120
|
const service = createServices(graphqlClient).cluster;
|
|
2061
2121
|
const clusterConfig = await service.getClusterConfig(clusterId);
|
|
2062
2122
|
const attributeNames = (clusterConfig?.config?.settings ?? []).map(
|
|
2063
|
-
(setting) => setting.
|
|
2123
|
+
(setting) => setting.attributeName
|
|
2064
2124
|
);
|
|
2065
2125
|
const variables = {
|
|
2066
2126
|
clusterId,
|
|
@@ -6155,8 +6215,8 @@ function Breadcrumbs(props) {
|
|
|
6155
6215
|
}
|
|
6156
6216
|
const displayItems = props.showCurrent === false && items.length > 0 ? items.slice(0, items.length - 1) : items;
|
|
6157
6217
|
function getCategoryName(cat) {
|
|
6158
|
-
const match = cat.
|
|
6159
|
-
return match?.value || cat.
|
|
6218
|
+
const match = cat.names?.find((n) => n.language === lang);
|
|
6219
|
+
return match?.value || cat.names?.[0]?.value || "";
|
|
6160
6220
|
}
|
|
6161
6221
|
function getCategoryUrl(cat, index) {
|
|
6162
6222
|
if (props.getUrl) return props.getUrl(cat, index);
|
|
@@ -6164,7 +6224,7 @@ function Breadcrumbs(props) {
|
|
|
6164
6224
|
if (urls && typeof urls.getCategoryUrl === "function") {
|
|
6165
6225
|
return urls.getCategoryUrl(cat, props.language);
|
|
6166
6226
|
}
|
|
6167
|
-
const slug = cat.
|
|
6227
|
+
const slug = cat.slugs?.find((s) => s.language === lang)?.value || cat.slugs?.[0]?.value || "";
|
|
6168
6228
|
return `/category/${cat.categoryId}/${slug}`;
|
|
6169
6229
|
}
|
|
6170
6230
|
function isCurrentItem(index) {
|
|
@@ -7854,7 +7914,7 @@ function CartSummary(rawProps) {
|
|
|
7854
7914
|
var CartSummary_default = CartSummary;
|
|
7855
7915
|
function CategoryDescription(props) {
|
|
7856
7916
|
const [expanded, setExpanded] = useState(false);
|
|
7857
|
-
const match = props.category?.
|
|
7917
|
+
const match = props.category?.descriptions?.find(
|
|
7858
7918
|
(d) => d.language === props.language
|
|
7859
7919
|
);
|
|
7860
7920
|
const html = match?.value || "";
|
|
@@ -7895,7 +7955,7 @@ function CategoryDescription(props) {
|
|
|
7895
7955
|
}
|
|
7896
7956
|
var CategoryDescription_default = CategoryDescription;
|
|
7897
7957
|
function CategoryShortDescription(props) {
|
|
7898
|
-
const match = props.category?.
|
|
7958
|
+
const match = props.category?.shortDescriptions?.find(
|
|
7899
7959
|
(d) => d.language === props.language
|
|
7900
7960
|
);
|
|
7901
7961
|
const html = match?.value || "";
|
|
@@ -12788,7 +12848,7 @@ function Menu(rawProps) {
|
|
|
12788
12848
|
const lang = props.language || "NL";
|
|
12789
12849
|
const category = {
|
|
12790
12850
|
categoryId: cat.categoryId,
|
|
12791
|
-
|
|
12851
|
+
slugs: [{ value: cat.slug, language: lang }]
|
|
12792
12852
|
};
|
|
12793
12853
|
if (props.getUrl) return props.getUrl(category);
|
|
12794
12854
|
return props.configuration.urls.getCategoryUrl(category, lang);
|
|
@@ -12802,8 +12862,8 @@ function Menu(rawProps) {
|
|
|
12802
12862
|
const lang = props.language || "NL";
|
|
12803
12863
|
props.onMenuItemClick({
|
|
12804
12864
|
categoryId: cat.categoryId,
|
|
12805
|
-
|
|
12806
|
-
|
|
12865
|
+
names: [{ value: cat.name, language: lang }],
|
|
12866
|
+
slugs: [{ value: cat.slug, language: lang }]
|
|
12807
12867
|
});
|
|
12808
12868
|
}
|
|
12809
12869
|
}
|