@anker-in/shopify-react 0.1.1-beta.0 → 0.1.1-beta.10

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.
@@ -4,7 +4,8 @@ import { ShopifyClient, ShopifyConfig, CartCookieAdapter as CartCookieAdapter$1,
4
4
  import { C as CookieAdapter, b as CartCookieAdapter, R as RouterAdapter, U as UserContextAdapter } from '../types-BLMoxbOk.mjs';
5
5
  import * as react_jsx_runtime from 'react/jsx-runtime';
6
6
  import { SWRConfiguration } from 'swr';
7
- import { d as PlusMemberSettingsMetafields } from '../types-CMA6_FML.mjs';
7
+ import { e as PlusMemberSettingsMetafields } from '../types-CUv-lzQk.mjs';
8
+ import 'swr/mutation';
8
9
 
9
10
  interface ShopifyContextValue {
10
11
  client: ShopifyClient;
@@ -95,6 +96,8 @@ interface CartContextValue {
95
96
  giftNeedAddToCartLines: any[];
96
97
  /** Auto free gift config */
97
98
  autoFreeGiftConfig?: any;
99
+ /** Gradient gifts config */
100
+ gradientGiftsConfig?: any;
98
101
  /** Metafield identifiers */
99
102
  metafieldIdentifiers?: {
100
103
  variant: HasMetafieldsIdentifier[];
@@ -4,7 +4,8 @@ import { ShopifyClient, ShopifyConfig, CartCookieAdapter as CartCookieAdapter$1,
4
4
  import { C as CookieAdapter, b as CartCookieAdapter, R as RouterAdapter, U as UserContextAdapter } from '../types-BLMoxbOk.js';
5
5
  import * as react_jsx_runtime from 'react/jsx-runtime';
6
6
  import { SWRConfiguration } from 'swr';
7
- import { d as PlusMemberSettingsMetafields } from '../types-CMA6_FML.js';
7
+ import { e as PlusMemberSettingsMetafields } from '../types-CUv-lzQk.js';
8
+ import 'swr/mutation';
8
9
 
9
10
  interface ShopifyContextValue {
10
11
  client: ShopifyClient;
@@ -95,6 +96,8 @@ interface CartContextValue {
95
96
  giftNeedAddToCartLines: any[];
96
97
  /** Auto free gift config */
97
98
  autoFreeGiftConfig?: any;
99
+ /** Gradient gifts config */
100
+ gradientGiftsConfig?: any;
98
101
  /** Metafield identifiers */
99
102
  metafieldIdentifiers?: {
100
103
  variant: HasMetafieldsIdentifier[];
@@ -104,6 +104,81 @@ var CODE_AMOUNT_KEY = "_sku_code_money";
104
104
  var SCRIPT_CODE_AMOUNT_KEY = "_code_money";
105
105
  var MAIN_PRODUCT_CODE = ["WS24", "WSTD", "WS7D", "WSCP", "WSPE", "WSPD"];
106
106
 
107
+ // src/hooks/cart/utils/normalize-add-to-cart-lines.ts
108
+ function normalizeAddToCartLines(lines) {
109
+ return lines.filter((line) => line.variant?.id).map((line, index) => {
110
+ const variant = line.variant;
111
+ const product = variant.product;
112
+ const quantity = line.quantity || 1;
113
+ const price = variant.finalPrice?.amount ? Number(variant.finalPrice.amount) : variant.compareAtPrice?.amount ? Number(variant.compareAtPrice.amount) : variant.price?.amount ? Number(variant.price.amount) : 0;
114
+ const subtotalAmount = price * quantity;
115
+ const totalAmount = subtotalAmount;
116
+ return {
117
+ id: `temp-line-${index}-${variant.id}`,
118
+ // Temporary ID for pre-cart lines
119
+ name: product?.title || variant.title || "",
120
+ quantity,
121
+ variantId: variant.id,
122
+ productId: product?.id || variant.id.split("/").slice(0, -2).join("/"),
123
+ totalAmount,
124
+ subtotalAmount,
125
+ discountAllocations: [],
126
+ customAttributes: line.attributes || [],
127
+ variant: {
128
+ id: variant.id,
129
+ price,
130
+ listPrice: variant.compareAtPrice?.amount ? Number(variant.compareAtPrice.amount) : 0,
131
+ sku: variant.sku || "",
132
+ name: variant.title || "",
133
+ image: variant.image ? {
134
+ url: variant.image.url,
135
+ altText: variant.image.altText || void 0
136
+ } : void 0,
137
+ requiresShipping: false,
138
+ // Default value, not available in NormalizedProductVariant
139
+ availableForSale: variant.availableForSale ?? true,
140
+ quantityAvailable: variant.quantityAvailable ?? 0,
141
+ currentlyNotInStock: false,
142
+ // Default value, will be updated when added to cart
143
+ weight: variant.weight,
144
+ metafields: variant.metafields
145
+ },
146
+ product,
147
+ path: product?.handle ? `/products/${product.handle}` : "",
148
+ discounts: [],
149
+ options: variant.selectedOptions?.map((opt) => ({
150
+ name: opt.name,
151
+ value: opt.value
152
+ }))
153
+ };
154
+ });
155
+ }
156
+ function createMockCartFromLines(lines, existingCart) {
157
+ const normalizedLines = normalizeAddToCartLines(lines);
158
+ const subtotalPrice = normalizedLines.reduce((sum, line) => sum + line.subtotalAmount, 0);
159
+ const totalPrice = normalizedLines.reduce((sum, line) => sum + line.totalAmount, 0);
160
+ return {
161
+ id: existingCart?.id || "temp-cart-id",
162
+ customerId: existingCart?.customerId,
163
+ email: existingCart?.email,
164
+ createdAt: existingCart?.createdAt || (/* @__PURE__ */ new Date()).toISOString(),
165
+ currency: existingCart?.currency || { code: "USD" },
166
+ taxesIncluded: existingCart?.taxesIncluded,
167
+ lineItems: normalizedLines,
168
+ totalLineItemsDiscount: 0,
169
+ orderDiscounts: 0,
170
+ lineItemsSubtotalPrice: subtotalPrice,
171
+ subtotalPrice,
172
+ totalPrice,
173
+ totalTaxAmount: 0,
174
+ discountCodes: existingCart?.discountCodes || [],
175
+ discountAllocations: [],
176
+ url: existingCart?.url || "",
177
+ ready: true,
178
+ customAttributes: existingCart?.customAttributes
179
+ };
180
+ }
181
+
107
182
  // src/hooks/cart/utils/index.ts
108
183
  var getQuery = () => {
109
184
  const url = typeof window !== "undefined" ? window.location.search : "";
@@ -143,25 +218,25 @@ var getMatchedMainProductSubTotal = (cartData, variant_list, main_product) => {
143
218
  return acc + (main_product?.spend_money_type === 1 /* ORIGIN_PRICE */ ? Number(line.subtotalAmount) || 0 : Number(line.totalAmount) || 0);
144
219
  }, 0) || 0;
145
220
  };
146
- var getDiscountEnvAttributeValue = (attributes = []) => {
147
- const attr = attributes.find((attr2) => attr2.key === CUSTOMER_ATTRIBUTE_KEY);
148
- return safeParseJson(attr?.value ?? "") ?? {};
149
- };
150
- var isAttributesEqual = (attrs1 = [], attrs2 = []) => {
151
- if (attrs1.length !== attrs2.length) return false;
152
- const sorted1 = [...attrs1].sort((a, b) => a.key.localeCompare(b.key));
153
- const sorted2 = [...attrs2].sort((a, b) => a.key.localeCompare(b.key));
154
- return sorted1.every(
155
- (attr, i) => attr.key === sorted2[i]?.key && attr.value === sorted2[i]?.value
156
- );
157
- };
158
- var safeParseJson = (str) => {
221
+ var safeParse = (str) => {
159
222
  try {
160
223
  return JSON.parse(str);
161
224
  } catch (err) {
162
225
  return {};
163
226
  }
164
227
  };
228
+ var getDiscountEnvAttributeValue = (attributes = []) => {
229
+ const attr = attributes.find((attr2) => attr2.key === CUSTOMER_ATTRIBUTE_KEY);
230
+ return safeParse(attr?.value ?? "") ?? {};
231
+ };
232
+ var checkAttributesUpdateNeeded = (oldAttributes, newAttributes, customAttributesNeedRemove) => {
233
+ return oldAttributes.some((attr) => {
234
+ const newAttr = newAttributes.find((newAttr2) => newAttr2.key === attr.key);
235
+ return newAttr ? newAttr.value !== attr.value : true;
236
+ }) || newAttributes.some((attr) => !oldAttributes.some((oldAttr) => oldAttr.key === attr.key)) || customAttributesNeedRemove.some(
237
+ (removeAttr) => oldAttributes.some((oldAttr) => oldAttr.key === removeAttr.key)
238
+ );
239
+ };
165
240
  var containsAll = (source, requiredItems = []) => {
166
241
  if (!requiredItems?.length) return true;
167
242
  const sourceSet = new Set(source);
@@ -328,12 +403,15 @@ var formatFunctionAutoFreeGift = ({
328
403
  };
329
404
  return result;
330
405
  };
331
- var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer) => {
406
+ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer, lines) => {
332
407
  const tags = react.useMemo(() => customer?.tags || [], [customer?.tags]);
333
408
  const isCustomerLoading = react.useMemo(() => !customer ? true : false, [customer]);
334
409
  const dealsType = "";
335
410
  const { client, locale } = useShopify();
336
411
  const giftProductsCache = react.useRef(null);
412
+ const effectiveCart = react.useMemo(() => {
413
+ return cart;
414
+ }, [lines, cart]);
337
415
  const { activeCampaign, subtotal } = react.useMemo(() => {
338
416
  for (const campaign of autoFreeGiftConfig) {
339
417
  const { rule_conditions = [], rule_result } = campaign;
@@ -341,7 +419,7 @@ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer) => {
341
419
  const isPreCheckPassed = preCheck(rule_conditions, tags, []);
342
420
  if (isPreCheckPassed && spend_get_reward) {
343
421
  const matchedSubtotal = getMatchedMainProductSubTotal(
344
- cart,
422
+ effectiveCart,
345
423
  spend_get_reward.main_product?.variant_list?.map((v) => v.variant_id) || [],
346
424
  {
347
425
  spend_money_type: spend_get_reward.main_product?.spend_money_type || 1,
@@ -355,13 +433,13 @@ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer) => {
355
433
  }
356
434
  }
357
435
  return { activeCampaign: null, subtotal: 0 };
358
- }, [autoFreeGiftConfig, cart, tags, dealsType]);
436
+ }, [autoFreeGiftConfig, effectiveCart, tags, dealsType]);
359
437
  const { qualifyingGift, nextTierGoal } = react.useMemo(() => {
360
438
  if (!activeCampaign || !activeCampaign.rule_result?.spend_get_reward?.gift_product) {
361
439
  return { qualifyingGift: null, nextTierGoal: null };
362
440
  }
363
441
  const giftTiers = activeCampaign.rule_result.spend_get_reward.gift_product;
364
- const qualifyingTier = [...giftTiers].reverse().find((tier) => subtotal >= Number(tier.spend_sum_money));
442
+ const qualifyingTier = [...giftTiers].sort((a, b) => Number(b.spend_sum_money) - Number(a.spend_sum_money)).find((tier) => subtotal >= Number(tier.spend_sum_money));
365
443
  const nextGoal = giftTiers.find((tier) => subtotal < Number(tier.spend_sum_money));
366
444
  if (!qualifyingTier) {
367
445
  return { qualifyingGift: null, nextTierGoal: nextGoal || null };
@@ -438,18 +516,33 @@ var useScriptAutoFreeGift = ({
438
516
  campaign,
439
517
  _giveaway,
440
518
  cart,
441
- locale: providedLocale
519
+ locale: providedLocale,
520
+ lines
442
521
  }) => {
443
522
  const { client, locale: contextLocale } = useShopify();
444
523
  const locale = providedLocale || contextLocale;
445
524
  const [points_subscribe, set_points_subscribe] = react.useState(false);
446
525
  const giftProductsCache = react.useRef(null);
526
+ const effectiveCart = react.useMemo(() => {
527
+ if (lines && lines.length > 0) {
528
+ return createMockCartFromLines(lines, cart);
529
+ }
530
+ return cart;
531
+ }, [lines, cart]);
447
532
  react.useEffect(() => {
448
533
  if (locale === "au") {
449
534
  const isPointsSubscribe = Cookies5__default.default.get("points_subscribe");
450
535
  set_points_subscribe(!!isPointsSubscribe);
451
536
  }
452
537
  }, [locale]);
538
+ const isActivityAvailable = react.useMemo(() => {
539
+ if (!campaign) return false;
540
+ const query = getQuery();
541
+ const utmCampaign = Cookies5__default.default.get("utm_campaign") || query?.utm_campaign;
542
+ if (campaign.activityAvailableQuery && !utmCampaign?.includes(campaign.activityAvailableQuery))
543
+ return false;
544
+ return true;
545
+ }, [campaign]);
453
546
  const [upgrade_multiple, upgrade_value] = react.useMemo(() => {
454
547
  let upgrade_multiple2 = 1;
455
548
  let upgrade_value2 = 0;
@@ -457,17 +550,17 @@ var useScriptAutoFreeGift = ({
457
550
  upgrade_multiple2 = 1.2;
458
551
  upgrade_value2 = 40;
459
552
  }
460
- cart?.lineItems?.forEach(({ customAttributes }) => {
553
+ effectiveCart?.lineItems?.forEach(({ customAttributes }) => {
461
554
  customAttributes?.forEach(({ key, value }) => {
462
555
  if (key === "_amount_upgrade_multiple") upgrade_multiple2 = Number(value) || 1;
463
556
  if (key === "_amount_upgrade_value") upgrade_value2 = Number(value) || 0;
464
557
  });
465
558
  });
466
559
  return [upgrade_multiple2, upgrade_value2];
467
- }, [cart?.lineItems, points_subscribe]);
560
+ }, [effectiveCart?.lineItems, points_subscribe]);
468
561
  const breakpoints = react.useMemo(() => {
469
- if (!campaign) return [];
470
- return (campaign.breakpoints || []).map((item) => ({
562
+ if (!isActivityAvailable) return [];
563
+ return (campaign?.breakpoints || []).map((item) => ({
471
564
  breakpoint: new Decimal2__default.default(item.breakpoint).minus(new Decimal2__default.default(upgrade_value)).dividedBy(new Decimal2__default.default(upgrade_multiple)).toFixed(2, Decimal2__default.default.ROUND_DOWN),
472
565
  giveawayProducts: item.giveawayProducts || []
473
566
  }));
@@ -491,25 +584,26 @@ var useScriptAutoFreeGift = ({
491
584
  return true;
492
585
  }, [giftHandles]);
493
586
  const involvedLines = react.useMemo(() => {
494
- if (!campaign) return [];
495
- return (cart?.lineItems || []).filter((line) => {
587
+ if (!isActivityAvailable) return [];
588
+ return (effectiveCart?.lineItems || []).filter((line) => {
496
589
  const isNotGift = line?.totalAmount && Number(line.totalAmount) > 0 && line.customAttributes?.every(
497
590
  (item) => item.key !== _giveaway
498
591
  );
499
592
  const hasCampaignTag = line.product?.tags?.some(
500
- (tag) => campaign.includeTags?.includes(tag.trim()) && line.variant?.availableForSale
593
+ (tag) => campaign?.includeTags?.includes(tag.trim()) && line.variant?.availableForSale
501
594
  );
502
595
  return isNotGift && hasCampaignTag;
503
596
  });
504
- }, [cart?.lineItems, campaign, _giveaway]);
597
+ }, [effectiveCart?.lineItems, isActivityAvailable, _giveaway]);
505
598
  const involvedSubTotal = react.useMemo(() => {
506
- if (!campaign) return new Decimal2__default.default(0);
599
+ if (!isActivityAvailable) return new Decimal2__default.default(0);
507
600
  return involvedLines.reduce((prev, item) => {
508
- const amount = campaign.useTotalAmount ? item.totalAmount : item.subtotalAmount;
601
+ const amount = campaign?.useTotalAmount ? item.totalAmount : item.subtotalAmount;
509
602
  return new Decimal2__default.default(prev).plus(new Decimal2__default.default(amount || 0));
510
603
  }, new Decimal2__default.default(0));
511
- }, [involvedLines, campaign]);
604
+ }, [involvedLines, isActivityAvailable]);
512
605
  const [freeGiftLevel, nextFreeGiftLevel] = react.useMemo(() => {
606
+ if (!isActivityAvailable) return [null, null];
513
607
  const sortedLevels = [...breakpoints].sort(
514
608
  (a, b) => Number(b.breakpoint) - Number(a.breakpoint)
515
609
  );
@@ -648,8 +742,6 @@ var useCartAttributes = ({
648
742
  memberSetting,
649
743
  cart
650
744
  });
651
- console.log("memberSetting", memberSetting);
652
- console.log("hasPlusMember", hasPlusMember);
653
745
  react.useEffect(() => {
654
746
  setCurrentUrl(window.location.href);
655
747
  }, []);
@@ -698,15 +790,19 @@ var useCartAttributes = ({
698
790
  ];
699
791
  }, [profile?.memberType, profile?.token, userType, hasPlusMember]);
700
792
  const functionAttributes = react.useMemo(() => {
701
- return [
702
- cart?.discountCodes && {
793
+ const hasFunctionEnvAttribute = cart?.lineItems.some(
794
+ (item) => item.customAttributes?.some((attr) => attr.key === CUSTOMER_ATTRIBUTE_KEY)
795
+ );
796
+ const discountCodes = cart?.discountCodes.map((item) => item.code).filter((code) => code) || [];
797
+ return hasFunctionEnvAttribute ? [
798
+ {
703
799
  key: "_discounts_function_env",
704
800
  value: JSON.stringify({
705
- discount_code: cart?.discountCodes.map((item) => item.code),
801
+ discount_code: discountCodes,
706
802
  user_tags: customer?.tags || []
707
803
  })
708
804
  }
709
- ];
805
+ ] : [];
710
806
  }, [cart]);
711
807
  const presellAttributes = react.useMemo(() => {
712
808
  return [
@@ -933,6 +1029,9 @@ function CartProvider({
933
1029
  }) {
934
1030
  const { client, cartCookieAdapter } = useShopify();
935
1031
  const [customAttributes, setCustomAttributes] = react.useState([]);
1032
+ const [customAttributesNeedDelete, setCustomAttributesNeedDelete] = react.useState(
1033
+ []
1034
+ );
936
1035
  const [isCodeChanging, setIsCodeChanging] = react.useState(false);
937
1036
  const [loadingState, setLoadingState] = react.useState({
938
1037
  editLineQuantityLoading: false,
@@ -963,7 +1062,11 @@ function CartProvider({
963
1062
  ahooks.useRequest(
964
1063
  () => {
965
1064
  const newAttributes = [...attributes, ...customAttributes];
966
- const needUpdate = cart && !isAttributesEqual(cart.customAttributes, newAttributes);
1065
+ const needUpdate = cart && !checkAttributesUpdateNeeded(
1066
+ cart.customAttributes,
1067
+ newAttributes,
1068
+ customAttributesNeedDelete
1069
+ );
967
1070
  if (needUpdate) {
968
1071
  return updateAttributes({ attributes: newAttributes });
969
1072
  } else {
@@ -984,11 +1087,12 @@ function CartProvider({
984
1087
  isCartLoading: isCartLoading || isCodeChanging,
985
1088
  setLoadingState
986
1089
  });
987
- const removeCustomAttributes = react.useCallback((attributes2) => {
988
- setCustomAttributes(
989
- (prev) => prev.filter((attr) => !attributes2.some((a) => a.key === attr.key))
990
- );
991
- }, []);
1090
+ const removeCustomAttributes = react.useCallback(
1091
+ (attributes2) => {
1092
+ setCustomAttributesNeedDelete(attributes2);
1093
+ },
1094
+ [setCustomAttributesNeedDelete]
1095
+ );
992
1096
  const addCustomAttributes = react.useCallback(
993
1097
  (attributes2) => {
994
1098
  const sameAttributes = attributes2.filter(
@@ -1075,6 +1179,7 @@ function CartProvider({
1075
1179
  isCodeChanging,
1076
1180
  setIsCodeChanging,
1077
1181
  autoFreeGiftConfig,
1182
+ gradientGiftsConfig,
1078
1183
  setLoadingState,
1079
1184
  loadingState,
1080
1185
  // function满赠
@@ -1098,6 +1203,7 @@ function CartProvider({
1098
1203
  locale,
1099
1204
  isCodeChanging,
1100
1205
  autoFreeGiftConfig,
1206
+ gradientGiftsConfig,
1101
1207
  loadingState,
1102
1208
  // function满赠
1103
1209
  functionAutoFreeGift,