@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.
package/dist/index.js CHANGED
@@ -142,6 +142,81 @@ var CODE_AMOUNT_KEY = "_sku_code_money";
142
142
  var SCRIPT_CODE_AMOUNT_KEY = "_code_money";
143
143
  var MAIN_PRODUCT_CODE = ["WS24", "WSTD", "WS7D", "WSCP", "WSPE", "WSPD"];
144
144
 
145
+ // src/hooks/cart/utils/normalize-add-to-cart-lines.ts
146
+ function normalizeAddToCartLines(lines) {
147
+ return lines.filter((line) => line.variant?.id).map((line, index) => {
148
+ const variant = line.variant;
149
+ const product = variant.product;
150
+ const quantity = line.quantity || 1;
151
+ const price = variant.finalPrice?.amount ? Number(variant.finalPrice.amount) : variant.compareAtPrice?.amount ? Number(variant.compareAtPrice.amount) : variant.price?.amount ? Number(variant.price.amount) : 0;
152
+ const subtotalAmount = price * quantity;
153
+ const totalAmount = subtotalAmount;
154
+ return {
155
+ id: `temp-line-${index}-${variant.id}`,
156
+ // Temporary ID for pre-cart lines
157
+ name: product?.title || variant.title || "",
158
+ quantity,
159
+ variantId: variant.id,
160
+ productId: product?.id || variant.id.split("/").slice(0, -2).join("/"),
161
+ totalAmount,
162
+ subtotalAmount,
163
+ discountAllocations: [],
164
+ customAttributes: line.attributes || [],
165
+ variant: {
166
+ id: variant.id,
167
+ price,
168
+ listPrice: variant.compareAtPrice?.amount ? Number(variant.compareAtPrice.amount) : 0,
169
+ sku: variant.sku || "",
170
+ name: variant.title || "",
171
+ image: variant.image ? {
172
+ url: variant.image.url,
173
+ altText: variant.image.altText || void 0
174
+ } : void 0,
175
+ requiresShipping: false,
176
+ // Default value, not available in NormalizedProductVariant
177
+ availableForSale: variant.availableForSale ?? true,
178
+ quantityAvailable: variant.quantityAvailable ?? 0,
179
+ currentlyNotInStock: false,
180
+ // Default value, will be updated when added to cart
181
+ weight: variant.weight,
182
+ metafields: variant.metafields
183
+ },
184
+ product,
185
+ path: product?.handle ? `/products/${product.handle}` : "",
186
+ discounts: [],
187
+ options: variant.selectedOptions?.map((opt) => ({
188
+ name: opt.name,
189
+ value: opt.value
190
+ }))
191
+ };
192
+ });
193
+ }
194
+ function createMockCartFromLines(lines, existingCart) {
195
+ const normalizedLines = normalizeAddToCartLines(lines);
196
+ const subtotalPrice = normalizedLines.reduce((sum, line) => sum + line.subtotalAmount, 0);
197
+ const totalPrice = normalizedLines.reduce((sum, line) => sum + line.totalAmount, 0);
198
+ return {
199
+ id: existingCart?.id || "temp-cart-id",
200
+ customerId: existingCart?.customerId,
201
+ email: existingCart?.email,
202
+ createdAt: existingCart?.createdAt || (/* @__PURE__ */ new Date()).toISOString(),
203
+ currency: existingCart?.currency || { code: "USD" },
204
+ taxesIncluded: existingCart?.taxesIncluded,
205
+ lineItems: normalizedLines,
206
+ totalLineItemsDiscount: 0,
207
+ orderDiscounts: 0,
208
+ lineItemsSubtotalPrice: subtotalPrice,
209
+ subtotalPrice,
210
+ totalPrice,
211
+ totalTaxAmount: 0,
212
+ discountCodes: existingCart?.discountCodes || [],
213
+ discountAllocations: [],
214
+ url: existingCart?.url || "",
215
+ ready: true,
216
+ customAttributes: existingCart?.customAttributes
217
+ };
218
+ }
219
+
145
220
  // src/hooks/cart/utils/index.ts
146
221
  var getQuery = () => {
147
222
  const url = typeof window !== "undefined" ? window.location.search : "";
@@ -181,25 +256,25 @@ var getMatchedMainProductSubTotal = (cartData, variant_list, main_product) => {
181
256
  return acc + (main_product?.spend_money_type === 1 /* ORIGIN_PRICE */ ? Number(line.subtotalAmount) || 0 : Number(line.totalAmount) || 0);
182
257
  }, 0) || 0;
183
258
  };
184
- var getDiscountEnvAttributeValue = (attributes = []) => {
185
- const attr = attributes.find((attr2) => attr2.key === CUSTOMER_ATTRIBUTE_KEY);
186
- return safeParseJson(attr?.value ?? "") ?? {};
187
- };
188
- var isAttributesEqual = (attrs1 = [], attrs2 = []) => {
189
- if (attrs1.length !== attrs2.length) return false;
190
- const sorted1 = [...attrs1].sort((a, b) => a.key.localeCompare(b.key));
191
- const sorted2 = [...attrs2].sort((a, b) => a.key.localeCompare(b.key));
192
- return sorted1.every(
193
- (attr, i) => attr.key === sorted2[i]?.key && attr.value === sorted2[i]?.value
194
- );
195
- };
196
- var safeParseJson = (str) => {
259
+ var safeParse = (str) => {
197
260
  try {
198
261
  return JSON.parse(str);
199
262
  } catch (err) {
200
263
  return {};
201
264
  }
202
265
  };
266
+ var getDiscountEnvAttributeValue = (attributes = []) => {
267
+ const attr = attributes.find((attr2) => attr2.key === CUSTOMER_ATTRIBUTE_KEY);
268
+ return safeParse(attr?.value ?? "") ?? {};
269
+ };
270
+ var checkAttributesUpdateNeeded = (oldAttributes, newAttributes, customAttributesNeedRemove) => {
271
+ return oldAttributes.some((attr) => {
272
+ const newAttr = newAttributes.find((newAttr2) => newAttr2.key === attr.key);
273
+ return newAttr ? newAttr.value !== attr.value : true;
274
+ }) || newAttributes.some((attr) => !oldAttributes.some((oldAttr) => oldAttr.key === attr.key)) || customAttributesNeedRemove.some(
275
+ (removeAttr) => oldAttributes.some((oldAttr) => oldAttr.key === removeAttr.key)
276
+ );
277
+ };
203
278
  var containsAll = (source, requiredItems = []) => {
204
279
  if (!requiredItems?.length) return true;
205
280
  const sourceSet = new Set(source);
@@ -366,12 +441,18 @@ var formatFunctionAutoFreeGift = ({
366
441
  };
367
442
  return result;
368
443
  };
369
- var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer) => {
444
+ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer, lines) => {
370
445
  const tags = react.useMemo(() => customer?.tags || [], [customer?.tags]);
371
446
  const isCustomerLoading = react.useMemo(() => !customer ? true : false, [customer]);
372
447
  const dealsType = "";
373
448
  const { client, locale } = useShopify();
374
449
  const giftProductsCache = react.useRef(null);
450
+ const effectiveCart = react.useMemo(() => {
451
+ if (lines && lines.length > 0) {
452
+ return createMockCartFromLines(lines, cart);
453
+ }
454
+ return cart;
455
+ }, [lines, cart]);
375
456
  const { activeCampaign, subtotal } = react.useMemo(() => {
376
457
  for (const campaign of autoFreeGiftConfig) {
377
458
  const { rule_conditions = [], rule_result } = campaign;
@@ -379,7 +460,7 @@ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer) => {
379
460
  const isPreCheckPassed = preCheck(rule_conditions, tags, []);
380
461
  if (isPreCheckPassed && spend_get_reward) {
381
462
  const matchedSubtotal = getMatchedMainProductSubTotal(
382
- cart,
463
+ effectiveCart,
383
464
  spend_get_reward.main_product?.variant_list?.map((v) => v.variant_id) || [],
384
465
  {
385
466
  spend_money_type: spend_get_reward.main_product?.spend_money_type || 1,
@@ -393,13 +474,13 @@ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer) => {
393
474
  }
394
475
  }
395
476
  return { activeCampaign: null, subtotal: 0 };
396
- }, [autoFreeGiftConfig, cart, tags, dealsType]);
477
+ }, [autoFreeGiftConfig, effectiveCart, tags, dealsType]);
397
478
  const { qualifyingGift, nextTierGoal } = react.useMemo(() => {
398
479
  if (!activeCampaign || !activeCampaign.rule_result?.spend_get_reward?.gift_product) {
399
480
  return { qualifyingGift: null, nextTierGoal: null };
400
481
  }
401
482
  const giftTiers = activeCampaign.rule_result.spend_get_reward.gift_product;
402
- const qualifyingTier = [...giftTiers].reverse().find((tier) => subtotal >= Number(tier.spend_sum_money));
483
+ const qualifyingTier = [...giftTiers].sort((a, b) => Number(b.spend_sum_money) - Number(a.spend_sum_money)).find((tier) => subtotal >= Number(tier.spend_sum_money));
403
484
  const nextGoal = giftTiers.find((tier) => subtotal < Number(tier.spend_sum_money));
404
485
  if (!qualifyingTier) {
405
486
  return { qualifyingGift: null, nextTierGoal: nextGoal || null };
@@ -476,18 +557,33 @@ var useScriptAutoFreeGift = ({
476
557
  campaign,
477
558
  _giveaway,
478
559
  cart,
479
- locale: providedLocale
560
+ locale: providedLocale,
561
+ lines
480
562
  }) => {
481
563
  const { client, locale: contextLocale } = useShopify();
482
564
  const locale = providedLocale || contextLocale;
483
565
  const [points_subscribe, set_points_subscribe] = react.useState(false);
484
566
  const giftProductsCache = react.useRef(null);
567
+ const effectiveCart = react.useMemo(() => {
568
+ if (lines && lines.length > 0) {
569
+ return createMockCartFromLines(lines, cart);
570
+ }
571
+ return cart;
572
+ }, [lines, cart]);
485
573
  react.useEffect(() => {
486
574
  if (locale === "au") {
487
575
  const isPointsSubscribe = Cookies5__default.default.get("points_subscribe");
488
576
  set_points_subscribe(!!isPointsSubscribe);
489
577
  }
490
578
  }, [locale]);
579
+ const isActivityAvailable = react.useMemo(() => {
580
+ if (!campaign) return false;
581
+ const query = getQuery();
582
+ const utmCampaign = Cookies5__default.default.get("utm_campaign") || query?.utm_campaign;
583
+ if (campaign.activityAvailableQuery && !utmCampaign?.includes(campaign.activityAvailableQuery))
584
+ return false;
585
+ return true;
586
+ }, [campaign]);
491
587
  const [upgrade_multiple, upgrade_value] = react.useMemo(() => {
492
588
  let upgrade_multiple2 = 1;
493
589
  let upgrade_value2 = 0;
@@ -495,17 +591,17 @@ var useScriptAutoFreeGift = ({
495
591
  upgrade_multiple2 = 1.2;
496
592
  upgrade_value2 = 40;
497
593
  }
498
- cart?.lineItems?.forEach(({ customAttributes }) => {
594
+ effectiveCart?.lineItems?.forEach(({ customAttributes }) => {
499
595
  customAttributes?.forEach(({ key, value }) => {
500
596
  if (key === "_amount_upgrade_multiple") upgrade_multiple2 = Number(value) || 1;
501
597
  if (key === "_amount_upgrade_value") upgrade_value2 = Number(value) || 0;
502
598
  });
503
599
  });
504
600
  return [upgrade_multiple2, upgrade_value2];
505
- }, [cart?.lineItems, points_subscribe]);
601
+ }, [effectiveCart?.lineItems, points_subscribe]);
506
602
  const breakpoints = react.useMemo(() => {
507
- if (!campaign) return [];
508
- return (campaign.breakpoints || []).map((item) => ({
603
+ if (!isActivityAvailable) return [];
604
+ return (campaign?.breakpoints || []).map((item) => ({
509
605
  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),
510
606
  giveawayProducts: item.giveawayProducts || []
511
607
  }));
@@ -529,25 +625,26 @@ var useScriptAutoFreeGift = ({
529
625
  return true;
530
626
  }, [giftHandles]);
531
627
  const involvedLines = react.useMemo(() => {
532
- if (!campaign) return [];
533
- return (cart?.lineItems || []).filter((line) => {
628
+ if (!isActivityAvailable) return [];
629
+ return (effectiveCart?.lineItems || []).filter((line) => {
534
630
  const isNotGift = line?.totalAmount && Number(line.totalAmount) > 0 && line.customAttributes?.every(
535
631
  (item) => item.key !== _giveaway
536
632
  );
537
633
  const hasCampaignTag = line.product?.tags?.some(
538
- (tag) => campaign.includeTags?.includes(tag.trim()) && line.variant?.availableForSale
634
+ (tag) => campaign?.includeTags?.includes(tag.trim()) && line.variant?.availableForSale
539
635
  );
540
636
  return isNotGift && hasCampaignTag;
541
637
  });
542
- }, [cart?.lineItems, campaign, _giveaway]);
638
+ }, [effectiveCart?.lineItems, isActivityAvailable, _giveaway]);
543
639
  const involvedSubTotal = react.useMemo(() => {
544
- if (!campaign) return new Decimal2__default.default(0);
640
+ if (!isActivityAvailable) return new Decimal2__default.default(0);
545
641
  return involvedLines.reduce((prev, item) => {
546
- const amount = campaign.useTotalAmount ? item.totalAmount : item.subtotalAmount;
642
+ const amount = campaign?.useTotalAmount ? item.totalAmount : item.subtotalAmount;
547
643
  return new Decimal2__default.default(prev).plus(new Decimal2__default.default(amount || 0));
548
644
  }, new Decimal2__default.default(0));
549
- }, [involvedLines, campaign]);
645
+ }, [involvedLines, isActivityAvailable]);
550
646
  const [freeGiftLevel, nextFreeGiftLevel] = react.useMemo(() => {
647
+ if (!isActivityAvailable) return [null, null];
551
648
  const sortedLevels = [...breakpoints].sort(
552
649
  (a, b) => Number(b.breakpoint) - Number(a.breakpoint)
553
650
  );
@@ -667,8 +764,6 @@ function useAddCartLines(options) {
667
764
  );
668
765
  return useSWRMutation__default.default("add-cart-lines", addLines, options);
669
766
  }
670
-
671
- // src/tracking/ga.ts
672
767
  var gaTrack = (data) => {
673
768
  if (typeof window === "undefined") {
674
769
  return;
@@ -686,18 +781,19 @@ var gaTrack = (data) => {
686
781
  };
687
782
  var trackAddToCartGA = ({
688
783
  lineItems = [],
689
- gtmParams = {},
690
- brand
784
+ gtmParams = {}
691
785
  }) => {
692
786
  if (!lineItems.length || !lineItems[0]?.variant) {
693
787
  return;
694
788
  }
695
789
  const { variant } = lineItems[0];
696
- const currencyCode = variant?.price?.currencyCode;
697
- const totalPrice = lineItems.reduce((sum, item) => {
698
- const price = parseFloat(item.variant?.price?.amount || "0");
699
- return sum + price;
700
- }, 0);
790
+ const currencyCode = variant.product?.price?.currencyCode;
791
+ const totalPrice = lineItems?.reduce(
792
+ (prev, { variant: variant2 }) => prev.plus(
793
+ variant2?.finalPrice?.amount ?? variant2?.compareAtPrice?.amount ?? variant2?.price?.amount ?? 0
794
+ ),
795
+ new Decimal2__default.default(0)
796
+ ).toNumber();
701
797
  gaTrack({
702
798
  event: "ga4Event",
703
799
  event_name: "add_to_cart",
@@ -708,11 +804,11 @@ var trackAddToCartGA = ({
708
804
  position: gtmParams?.position || "",
709
805
  items: lineItems.map(({ variant: variant2, quantity }) => ({
710
806
  item_id: variant2?.sku,
711
- item_name: variant2?.product?.title || variant2?.product?.name,
712
- item_brand: brand || gtmParams?.brand || "",
807
+ item_name: variant2?.product?.title || variant2?.product?.title,
808
+ item_brand: gtmParams?.brand || "",
713
809
  item_category: variant2?.product?.productType || "",
714
- item_variant: variant2?.title || variant2?.name,
715
- price: variant2?.finalPrice?.amount ?? variant2?.price?.amount,
810
+ item_variant: variant2?.title || variant2?.title,
811
+ price: variant2?.compareAtPrice?.amount ?? variant2?.price?.amount,
716
812
  quantity: quantity || 1
717
813
  })),
718
814
  ...gtmParams?.ga4Params
@@ -722,13 +818,17 @@ var trackAddToCartGA = ({
722
818
  var trackBeginCheckoutGA = ({
723
819
  lineItems = [],
724
820
  currencyCode,
725
- totalPrice,
726
- gtmParams = {},
727
- brand
821
+ gtmParams = {}
728
822
  }) => {
729
823
  if (!lineItems.length) {
730
824
  return;
731
825
  }
826
+ const totalPrice = lineItems?.reduce(
827
+ (prev, { variant }) => prev.plus(
828
+ variant?.finalPrice?.amount ?? variant?.compareAtPrice?.amount ?? variant?.price?.amount ?? 0
829
+ ),
830
+ new Decimal2__default.default(0)
831
+ ).toNumber();
732
832
  gaTrack({
733
833
  event: "ga4Event",
734
834
  event_name: "begin_checkout",
@@ -740,10 +840,10 @@ var trackBeginCheckoutGA = ({
740
840
  items: lineItems.map((item) => ({
741
841
  item_id: item.variant?.sku,
742
842
  item_name: item.variant?.product?.title,
743
- item_brand: brand || gtmParams?.brand || "",
843
+ item_brand: gtmParams?.brand || "",
744
844
  item_category: item.variant?.product?.productType,
745
845
  item_variant: item.variant?.title,
746
- price: item.finalPrice?.amount || item.variant?.price?.amount,
846
+ price: item.variant?.compareAtPrice?.amount ?? item.variant?.price?.amount,
747
847
  quantity: item.quantity || 1
748
848
  })),
749
849
  ...gtmParams?.ga4Params
@@ -752,19 +852,19 @@ var trackBeginCheckoutGA = ({
752
852
  };
753
853
  var trackBuyNowGA = ({
754
854
  lineItems = [],
755
- gtmParams = {},
756
- brand
855
+ gtmParams = {}
757
856
  }) => {
758
857
  if (!lineItems.length || !lineItems[0]?.variant) {
759
858
  return;
760
859
  }
761
860
  const { variant } = lineItems[0];
762
861
  const currencyCode = variant.price?.currencyCode;
763
- const totalPrice = lineItems.reduce((sum, item) => {
764
- const price = parseFloat(item.finalPrice?.amount || item.variant?.price?.amount || "0");
765
- const quantity = item.quantity || 1;
766
- return sum + price * quantity;
767
- }, 0);
862
+ const totalPrice = lineItems?.reduce(
863
+ (prev, { variant: variant2 }) => prev.plus(
864
+ variant2?.finalPrice?.amount ?? variant2?.compareAtPrice?.amount ?? (variant2?.price?.amount || 0)
865
+ ),
866
+ new Decimal2__default.default(0)
867
+ ).toNumber();
768
868
  gaTrack({
769
869
  event: "ga4Event",
770
870
  event_name: "begin_checkout",
@@ -776,10 +876,10 @@ var trackBuyNowGA = ({
776
876
  items: lineItems.map((item) => ({
777
877
  item_id: item.variant?.sku,
778
878
  item_name: item.variant?.product?.title || item.variant?.title,
779
- item_brand: item.variant?.product?.vendor || brand || gtmParams?.brand || "",
879
+ item_brand: gtmParams?.brand || "",
780
880
  item_category: item.variant?.product?.productType || "",
781
881
  item_variant: item.variant?.title,
782
- price: item.finalPrice?.amount || item.variant?.price?.amount,
882
+ price: item.variant?.compareAtPrice?.amount ?? item.variant?.price?.amount,
783
883
  quantity: item.quantity || 1
784
884
  })),
785
885
  ...gtmParams?.ga4Params
@@ -793,10 +893,10 @@ var trackAddToCartFBQ = ({ lineItems = [] }) => {
793
893
  return;
794
894
  }
795
895
  if (lineItems.length && lineItems[0]?.variant) {
796
- const { variant, quantity, finalPrice } = lineItems[0];
896
+ const { variant, quantity } = lineItems[0];
797
897
  try {
798
898
  window.fbq("track", "AddToCart", {
799
- value: finalPrice?.amount || variant?.price?.amount,
899
+ value: variant?.compareAtPrice?.amount ?? (variant?.price?.amount || variant?.price || 0),
800
900
  num_items: quantity,
801
901
  currency: variant?.price?.currencyCode,
802
902
  content_name: variant?.product?.title,
@@ -883,9 +983,9 @@ function useRemoveCartCodes(options) {
883
983
  }
884
984
 
885
985
  // src/hooks/cart/use-add-to-cart.ts
886
- function useAddToCart({ withTrack = true, brand } = {}, swrOptions) {
887
- const { client, locale, cartCookieAdapter, userAdapter } = useShopify();
888
- const { mutateCart, cart, metafieldIdentifiers } = useCartContext();
986
+ function useAddToCart({ withTrack = true } = {}, swrOptions) {
987
+ const { client, config, locale, cartCookieAdapter, userAdapter } = useShopify();
988
+ const { cart } = useCartContext();
889
989
  const { trigger: applyCartCodes } = useApplyCartCodes();
890
990
  const { trigger: removeInvalidCodes } = useRemoveCartCodes();
891
991
  const { trigger: addCartLines2 } = useAddCartLines();
@@ -907,7 +1007,8 @@ function useAddToCart({ withTrack = true, brand } = {}, swrOptions) {
907
1007
  const lines = lineItems.map((item) => ({
908
1008
  merchandiseId: item.variant?.id || "",
909
1009
  quantity: item.quantity || 1,
910
- attributes: item.attributes
1010
+ attributes: item.attributes,
1011
+ sellingPlanId: item.sellingPlanId
911
1012
  })).filter((item) => item.merchandiseId && item.quantity);
912
1013
  if (lines.length === 0) {
913
1014
  return;
@@ -921,6 +1022,7 @@ function useAddToCart({ withTrack = true, brand } = {}, swrOptions) {
921
1022
  if (!resultCart) {
922
1023
  return void 0;
923
1024
  }
1025
+ console.log("npm addCartLines resultCart", resultCart);
924
1026
  if (resultCart.discountCodes && resultCart.discountCodes.length > 0) {
925
1027
  const unapplicableCodes = resultCart.discountCodes.filter((item) => !item.applicable).map((item) => item.code);
926
1028
  if (unapplicableCodes.length > 0) {
@@ -942,34 +1044,16 @@ function useAddToCart({ withTrack = true, brand } = {}, swrOptions) {
942
1044
  discountCodes
943
1045
  });
944
1046
  }
945
- if (withTrack && resultCart.lineItems) {
946
- const trackingLineItems = resultCart.lineItems.map((line) => ({
947
- variant: {
948
- id: line.variant.id,
949
- sku: line.variant.sku || "",
950
- title: line.variant.name,
951
- price: {
952
- amount: String(line.variant.price),
953
- currencyCode: resultCart.currency.code
954
- },
955
- product: line.product ? {
956
- title: line.product.title || line.name,
957
- productType: line.product.productType,
958
- vendor: line.product.vendor
959
- } : void 0
960
- },
961
- quantity: line.quantity
962
- }));
1047
+ if (withTrack) {
963
1048
  trackAddToCartGA({
964
- lineItems: trackingLineItems,
965
- gtmParams: { ...gtmParams, brand },
966
- brand
1049
+ lineItems,
1050
+ gtmParams: { ...gtmParams, brand: config.getBrand() }
967
1051
  });
968
- trackAddToCartFBQ({ lineItems: trackingLineItems });
1052
+ trackAddToCartFBQ({ lineItems });
969
1053
  }
970
1054
  return resultCart;
971
1055
  },
972
- [client, locale, cartCookieAdapter, userAdapter, cart, withTrack, brand]
1056
+ [client, locale, cartCookieAdapter, userAdapter, cart, withTrack]
973
1057
  );
974
1058
  return useSWRMutation__default.default("add-to-cart", addToCart, swrOptions);
975
1059
  }
@@ -1050,8 +1134,8 @@ function useUpdateCartAttributes(mutate, metafieldIdentifiers, options) {
1050
1134
  );
1051
1135
  return useSWRMutation__default.default("update-cart-attributes", updateAttributes, options);
1052
1136
  }
1053
- function useBuyNow({ withTrack = true, brand } = {}, swrOptions) {
1054
- const { client, locale, cartCookieAdapter, userAdapter } = useShopify();
1137
+ function useBuyNow({ withTrack = true } = {}, swrOptions) {
1138
+ const { client, config, locale, cartCookieAdapter, userAdapter } = useShopify();
1055
1139
  const isLoggedIn = userAdapter?.isLoggedIn || false;
1056
1140
  const buyNow = react.useCallback(
1057
1141
  async (_key, { arg }) => {
@@ -1069,9 +1153,10 @@ function useBuyNow({ withTrack = true, brand } = {}, swrOptions) {
1069
1153
  return;
1070
1154
  }
1071
1155
  const lines = lineItems.map((item) => ({
1072
- merchandiseId: item.variant?.id || item.variantId || "",
1156
+ merchandiseId: item.variant?.id || "",
1073
1157
  quantity: item.quantity || 1,
1074
- attributes: item.attributes
1158
+ attributes: item.attributes,
1159
+ sellingPlanId: item.sellingPlanId
1075
1160
  })).filter((item) => item.merchandiseId && item.quantity);
1076
1161
  if (lines.length === 0) {
1077
1162
  return;
@@ -1088,27 +1173,9 @@ function useBuyNow({ withTrack = true, brand } = {}, swrOptions) {
1088
1173
  throw new Error("Failed to create cart for buy now");
1089
1174
  }
1090
1175
  if (withTrack && resultCart.lineItems) {
1091
- const trackingLineItems = resultCart.lineItems.map((line) => ({
1092
- variant: {
1093
- id: line.variantId,
1094
- sku: line.variant.sku || "",
1095
- title: line.variant.name,
1096
- price: {
1097
- amount: String(line.variant.price),
1098
- currencyCode: resultCart.currency.code
1099
- },
1100
- product: line.product ? {
1101
- title: line.product.title || line.name,
1102
- productType: line.product.productType,
1103
- vendor: line.product.vendor
1104
- } : void 0
1105
- },
1106
- quantity: line.quantity
1107
- }));
1108
1176
  trackBuyNowGA({
1109
- lineItems: trackingLineItems,
1110
- gtmParams: { ...gtmParams, brand },
1111
- brand
1177
+ lineItems,
1178
+ gtmParams: { ...gtmParams, brand: config.getBrand() }
1112
1179
  });
1113
1180
  if (fbqTrackConfig) {
1114
1181
  trackBuyNowFBQ({ trackConfig: fbqTrackConfig });
@@ -1125,10 +1192,64 @@ function useBuyNow({ withTrack = true, brand } = {}, swrOptions) {
1125
1192
  }
1126
1193
  return resultCart;
1127
1194
  },
1128
- [client, locale, isLoggedIn, cartCookieAdapter, withTrack, brand]
1195
+ [client, locale, isLoggedIn, cartCookieAdapter, withTrack]
1129
1196
  );
1130
1197
  return useSWRMutation__default.default("buy-now", buyNow, swrOptions);
1131
1198
  }
1199
+ function useCalcGiftsFromLines({
1200
+ lines,
1201
+ customer,
1202
+ scriptGiveawayKey = CUSTOMER_SCRIPT_GIFT_KEY
1203
+ }) {
1204
+ const { locale } = useShopify();
1205
+ const { cart, autoFreeGiftConfig, gradientGiftsConfig } = useCartContext();
1206
+ const functionGift = useCalcAutoFreeGift(cart, autoFreeGiftConfig || [], customer, lines);
1207
+ const scriptGift = useScriptAutoFreeGift({
1208
+ campaign: gradientGiftsConfig || null,
1209
+ _giveaway: scriptGiveawayKey,
1210
+ cart,
1211
+ locale,
1212
+ lines
1213
+ });
1214
+ const allGiftLines = react.useMemo(() => {
1215
+ const functionGiftLines = functionGift.qualifyingGift?.itemsToAdd || [];
1216
+ const scriptGiftLines = scriptGift.freeGiftLevel ? scriptGift.freeGiftLevel.giveawayProducts.map((product) => {
1217
+ const giftProduct = scriptGift.giftProductsResult?.find(
1218
+ (p) => p.handle === product.handle
1219
+ );
1220
+ const variant = giftProduct?.variants?.[0];
1221
+ return {
1222
+ variant: {
1223
+ id: variant?.id || "",
1224
+ handle: product.handle,
1225
+ sku: product.sku
1226
+ },
1227
+ quantity: 1,
1228
+ attributes: [
1229
+ {
1230
+ key: scriptGiveawayKey,
1231
+ value: "true"
1232
+ }
1233
+ ]
1234
+ };
1235
+ }).filter((item) => item.variant.id) : [];
1236
+ return [...functionGiftLines, ...scriptGiftLines];
1237
+ }, [
1238
+ functionGift.qualifyingGift,
1239
+ scriptGift.freeGiftLevel,
1240
+ scriptGift.giftProductsResult,
1241
+ scriptGiveawayKey
1242
+ ]);
1243
+ const hasGifts = react.useMemo(() => {
1244
+ return allGiftLines.length > 0;
1245
+ }, [allGiftLines]);
1246
+ return {
1247
+ functionGift,
1248
+ scriptGift,
1249
+ allGiftLines,
1250
+ hasGifts
1251
+ };
1252
+ }
1132
1253
 
1133
1254
  // src/hooks/cart/types/order-discount.ts
1134
1255
  var OrderDiscountType = /* @__PURE__ */ ((OrderDiscountType2) => {
@@ -1278,8 +1399,6 @@ var useCartAttributes = ({
1278
1399
  memberSetting,
1279
1400
  cart
1280
1401
  });
1281
- console.log("memberSetting", memberSetting);
1282
- console.log("hasPlusMember", hasPlusMember);
1283
1402
  react.useEffect(() => {
1284
1403
  setCurrentUrl(window.location.href);
1285
1404
  }, []);
@@ -1328,15 +1447,19 @@ var useCartAttributes = ({
1328
1447
  ];
1329
1448
  }, [profile?.memberType, profile?.token, userType, hasPlusMember]);
1330
1449
  const functionAttributes = react.useMemo(() => {
1331
- return [
1332
- cart?.discountCodes && {
1450
+ const hasFunctionEnvAttribute = cart?.lineItems.some(
1451
+ (item) => item.customAttributes?.some((attr) => attr.key === CUSTOMER_ATTRIBUTE_KEY)
1452
+ );
1453
+ const discountCodes = cart?.discountCodes.map((item) => item.code).filter((code) => code) || [];
1454
+ return hasFunctionEnvAttribute ? [
1455
+ {
1333
1456
  key: "_discounts_function_env",
1334
1457
  value: JSON.stringify({
1335
- discount_code: cart?.discountCodes.map((item) => item.code),
1458
+ discount_code: discountCodes,
1336
1459
  user_tags: customer?.tags || []
1337
1460
  })
1338
1461
  }
1339
- ];
1462
+ ] : [];
1340
1463
  }, [cart]);
1341
1464
  const presellAttributes = react.useMemo(() => {
1342
1465
  return [
@@ -2513,6 +2636,69 @@ var usePlusMemberDeliveryCodes = ({
2513
2636
  [deliveryData]
2514
2637
  );
2515
2638
  };
2639
+ function useUpdateCartDeliveryOptions(mutate, metafieldIdentifiers, options) {
2640
+ const { client, locale, cartCookieAdapter } = useShopify();
2641
+ const updateDeliveryOptions = react.useCallback(
2642
+ async (_key, { arg }) => {
2643
+ const updatedCart = await shopifySdk.updateCartDeliveryOptions(client, {
2644
+ ...arg,
2645
+ metafieldIdentifiers,
2646
+ cookieAdapter: cartCookieAdapter
2647
+ });
2648
+ console.log("useUpdateCartDeliveryOptions updatedCart", updatedCart);
2649
+ if (updatedCart) {
2650
+ mutate(updatedCart);
2651
+ }
2652
+ return updatedCart;
2653
+ },
2654
+ [client, locale, cartCookieAdapter, mutate]
2655
+ );
2656
+ return useSWRMutation__default.default("update-cart-delivery-options", updateDeliveryOptions, options);
2657
+ }
2658
+
2659
+ // src/hooks/member/plus/use-update-plus-member-delivery-options.ts
2660
+ var useUpdatePlusMemberDeliveryOptions = ({
2661
+ options
2662
+ }) => {
2663
+ const { cart, mutateCart: mutate, metafieldIdentifiers } = useCartContext();
2664
+ const { trigger: updateCartDeliveryOptions2, isMutating } = useUpdateCartDeliveryOptions(
2665
+ mutate,
2666
+ metafieldIdentifiers
2667
+ );
2668
+ const handler = react.useCallback(
2669
+ async (_, { arg }) => {
2670
+ const { deliveryData } = arg;
2671
+ const firstDeliveryGroup = cart?.deliveryGroups?.[0];
2672
+ const deliveryGroupId = firstDeliveryGroup?.id;
2673
+ const selectedOptionCode = deliveryData?.deliveryCustomData?.selected_delivery_option?.code;
2674
+ if (!deliveryGroupId || !selectedOptionCode || selectedOptionCode === firstDeliveryGroup?.selectedDeliveryOption?.code) {
2675
+ return null;
2676
+ }
2677
+ const deliveryGroup = cart?.deliveryGroups?.find((group) => group?.id === deliveryGroupId);
2678
+ const matchedOption = deliveryGroup?.deliveryOptions?.find(
2679
+ (option) => option?.code === selectedOptionCode
2680
+ );
2681
+ if (!matchedOption?.handle) {
2682
+ return null;
2683
+ }
2684
+ const deliveryOptions = [
2685
+ {
2686
+ deliveryGroupId,
2687
+ deliveryOptionHandle: matchedOption.handle
2688
+ }
2689
+ ];
2690
+ const updatedCart = await updateCartDeliveryOptions2({
2691
+ selectedDeliveryOptions: deliveryOptions
2692
+ });
2693
+ if (updatedCart && mutate) {
2694
+ mutate(updatedCart);
2695
+ }
2696
+ return updatedCart;
2697
+ },
2698
+ [cart, updateCartDeliveryOptions2, mutate]
2699
+ );
2700
+ return useSWRMutation__default.default("update-cart-delivery-options", handler, options);
2701
+ };
2516
2702
  var usePlusMemberItemCustomAttributes = ({
2517
2703
  deliveryData
2518
2704
  }) => {
@@ -2599,15 +2785,14 @@ var usePlusMemberCheckoutCustomAttributes = ({
2599
2785
  }, [deliveryCustomData, product, profile, userType, variant, isShowShippingBenefits]);
2600
2786
  };
2601
2787
  function useAutoRemovePlusMemberInCart({
2602
- metafields,
2603
- isMonthlyPlus,
2604
- isAnnualPlus
2788
+ cart,
2789
+ profile,
2790
+ memberSetting
2605
2791
  }) {
2606
- const { plus_monthly_product, plus_annual_product } = metafields || {};
2607
- const { cart } = useCartContext();
2792
+ const { plus_monthly_product, plus_annual_product } = memberSetting || {};
2608
2793
  const { trigger: removeCartLines2 } = useRemoveCartLines();
2609
2794
  react.useEffect(() => {
2610
- if (!cart) return;
2795
+ if (!cart || !plus_monthly_product || !plus_annual_product) return;
2611
2796
  const removePlusProduct = async (productType) => {
2612
2797
  if (!productType) return;
2613
2798
  const product = cart.lineItems?.find(
@@ -2619,26 +2804,53 @@ function useAutoRemovePlusMemberInCart({
2619
2804
  });
2620
2805
  }
2621
2806
  };
2622
- if (isMonthlyPlus) {
2807
+ if (profile?.isMonthlyPlus) {
2623
2808
  removePlusProduct(plus_monthly_product);
2624
2809
  }
2625
- if (isAnnualPlus) {
2810
+ if (profile?.isAnnualPlus) {
2626
2811
  removePlusProduct(plus_annual_product);
2627
2812
  }
2813
+ }, [cart, plus_annual_product, plus_monthly_product, profile, removeCartLines2]);
2814
+ }
2815
+ function useAddPlusMemberProductsToCart({
2816
+ cart,
2817
+ profile
2818
+ }) {
2819
+ const { selectedPlusMemberMode, selectedPlusMemberProduct, plusMemberMetafields } = usePlusMemberContext();
2820
+ const { hasMonthlyPlus, hasAnnualPlus } = useHasPlusMemberInCart({
2821
+ memberSetting: plusMemberMetafields,
2822
+ cart
2823
+ });
2824
+ const plusMemberProduct = react.useMemo(() => {
2825
+ if (!selectedPlusMemberProduct || selectedPlusMemberMode === "free" /* FREE */) {
2826
+ return void 0;
2827
+ }
2828
+ if (selectedPlusMemberMode === "monthly" /* MONTHLY */ && hasMonthlyPlus) {
2829
+ return void 0;
2830
+ }
2831
+ if (selectedPlusMemberMode === "annual" /* ANNUAL */ && hasAnnualPlus) {
2832
+ return void 0;
2833
+ }
2834
+ if (profile?.isMonthlyPlus && selectedPlusMemberMode === "monthly" /* MONTHLY */) {
2835
+ return void 0;
2836
+ }
2837
+ if (!profile?.isAnnualPlus && selectedPlusMemberMode === "annual" /* ANNUAL */) {
2838
+ return void 0;
2839
+ }
2840
+ return selectedPlusMemberProduct;
2628
2841
  }, [
2629
- cart,
2630
- plus_annual_product,
2631
- plus_monthly_product,
2632
- isAnnualPlus,
2633
- isMonthlyPlus,
2634
- removeCartLines2
2842
+ selectedPlusMemberMode,
2843
+ selectedPlusMemberProduct?.variant,
2844
+ selectedPlusMemberProduct?.product,
2845
+ hasMonthlyPlus,
2846
+ hasAnnualPlus
2635
2847
  ]);
2848
+ return plusMemberProduct;
2636
2849
  }
2637
2850
  var PlusMemberProvider = ({
2638
2851
  variant,
2639
2852
  product,
2640
- shopCommon,
2641
- metafields,
2853
+ memberSetting,
2642
2854
  initialSelectedPlusMemberMode = "free",
2643
2855
  profile,
2644
2856
  locale,
@@ -2658,14 +2870,14 @@ var PlusMemberProvider = ({
2658
2870
  const [deleteMarginBottom, setDeleteMarginBottom] = react.useState(false);
2659
2871
  const shippingMethodsContext = useShippingMethods({
2660
2872
  variant,
2661
- plusMemberMetafields: metafields,
2873
+ plusMemberMetafields: memberSetting,
2662
2874
  selectedPlusMemberMode});
2663
2875
  const plusMemberHandles = react.useMemo(() => {
2664
2876
  return [
2665
- metafields?.plus_monthly_product?.handle,
2666
- metafields?.plus_annual_product?.handle
2877
+ memberSetting?.plus_monthly_product?.handle,
2878
+ memberSetting?.plus_annual_product?.handle
2667
2879
  ].filter(Boolean);
2668
- }, [metafields]);
2880
+ }, [memberSetting]);
2669
2881
  const { data: plusMemberProducts = [] } = useProductsByHandles({
2670
2882
  handles: plusMemberHandles
2671
2883
  });
@@ -2673,25 +2885,24 @@ var PlusMemberProvider = ({
2673
2885
  if (selectedPlusMemberMode === "free" /* FREE */) {
2674
2886
  return null;
2675
2887
  }
2676
- const handle = selectedPlusMemberMode === "monthly" /* MONTHLY */ ? metafields?.plus_monthly_product?.handle : metafields?.plus_annual_product?.handle;
2677
- const sku = selectedPlusMemberMode === "monthly" /* MONTHLY */ ? metafields?.plus_monthly_product?.sku : metafields?.plus_annual_product?.sku;
2888
+ const handle = selectedPlusMemberMode === "monthly" /* MONTHLY */ ? memberSetting?.plus_monthly_product?.handle : memberSetting?.plus_annual_product?.handle;
2889
+ const sku = selectedPlusMemberMode === "monthly" /* MONTHLY */ ? memberSetting?.plus_monthly_product?.sku : memberSetting?.plus_annual_product?.sku;
2678
2890
  const product2 = plusMemberProducts?.find((p) => p.handle === handle);
2679
2891
  const variant2 = product2?.variants?.find((v) => v.sku === sku);
2680
2892
  return product2 && variant2 ? { product: product2, variant: variant2 } : null;
2681
- }, [plusMemberProducts, metafields, selectedPlusMemberMode]);
2893
+ }, [plusMemberProducts, memberSetting, selectedPlusMemberMode]);
2682
2894
  return /* @__PURE__ */ jsxRuntime.jsx(
2683
2895
  PlusMemberContext.Provider,
2684
2896
  {
2685
2897
  value: {
2686
2898
  variant,
2687
- shopCommon,
2688
2899
  zipCode,
2689
2900
  setZipCode,
2690
2901
  allowNextDayDelivery,
2691
2902
  setAllowNextDayDelivery,
2692
2903
  allowThirdDayDelivery,
2693
2904
  setAllowThirdDayDelivery,
2694
- plusMemberMetafields: metafields,
2905
+ plusMemberMetafields: memberSetting,
2695
2906
  selectedPlusMemberMode,
2696
2907
  setSelectedPlusMemberMode,
2697
2908
  showAreaCheckModal,
@@ -2910,6 +3121,9 @@ function CartProvider({
2910
3121
  }) {
2911
3122
  const { client, cartCookieAdapter } = useShopify();
2912
3123
  const [customAttributes, setCustomAttributes] = react.useState([]);
3124
+ const [customAttributesNeedDelete, setCustomAttributesNeedDelete] = react.useState(
3125
+ []
3126
+ );
2913
3127
  const [isCodeChanging, setIsCodeChanging] = react.useState(false);
2914
3128
  const [loadingState, setLoadingState] = react.useState({
2915
3129
  editLineQuantityLoading: false,
@@ -2940,7 +3154,11 @@ function CartProvider({
2940
3154
  ahooks.useRequest(
2941
3155
  () => {
2942
3156
  const newAttributes = [...attributes, ...customAttributes];
2943
- const needUpdate = cart && !isAttributesEqual(cart.customAttributes, newAttributes);
3157
+ const needUpdate = cart && !checkAttributesUpdateNeeded(
3158
+ cart.customAttributes,
3159
+ newAttributes,
3160
+ customAttributesNeedDelete
3161
+ );
2944
3162
  if (needUpdate) {
2945
3163
  return updateAttributes({ attributes: newAttributes });
2946
3164
  } else {
@@ -2961,11 +3179,12 @@ function CartProvider({
2961
3179
  isCartLoading: isCartLoading || isCodeChanging,
2962
3180
  setLoadingState
2963
3181
  });
2964
- const removeCustomAttributes = react.useCallback((attributes2) => {
2965
- setCustomAttributes(
2966
- (prev) => prev.filter((attr) => !attributes2.some((a) => a.key === attr.key))
2967
- );
2968
- }, []);
3182
+ const removeCustomAttributes = react.useCallback(
3183
+ (attributes2) => {
3184
+ setCustomAttributesNeedDelete(attributes2);
3185
+ },
3186
+ [setCustomAttributesNeedDelete]
3187
+ );
2969
3188
  const addCustomAttributes = react.useCallback(
2970
3189
  (attributes2) => {
2971
3190
  const sameAttributes = attributes2.filter(
@@ -3052,6 +3271,7 @@ function CartProvider({
3052
3271
  isCodeChanging,
3053
3272
  setIsCodeChanging,
3054
3273
  autoFreeGiftConfig,
3274
+ gradientGiftsConfig,
3055
3275
  setLoadingState,
3056
3276
  loadingState,
3057
3277
  // function满赠
@@ -3075,6 +3295,7 @@ function CartProvider({
3075
3295
  locale,
3076
3296
  isCodeChanging,
3077
3297
  autoFreeGiftConfig,
3298
+ gradientGiftsConfig,
3078
3299
  loadingState,
3079
3300
  // function满赠
3080
3301
  functionAutoFreeGift,
@@ -3147,7 +3368,9 @@ exports.atobID = atobID;
3147
3368
  exports.browserCartCookieAdapter = browserCartCookieAdapter;
3148
3369
  exports.browserCookieAdapter = browserCookieAdapter;
3149
3370
  exports.btoaID = btoaID;
3371
+ exports.checkAttributesUpdateNeeded = checkAttributesUpdateNeeded;
3150
3372
  exports.clearGeoLocationCache = clearGeoLocationCache;
3373
+ exports.createMockCartFromLines = createMockCartFromLines;
3151
3374
  exports.currencyCodeMapping = currencyCodeMapping;
3152
3375
  exports.defaultSWRMutationConfiguration = defaultSWRMutationConfiguration;
3153
3376
  exports.formatFunctionAutoFreeGift = formatFunctionAutoFreeGift;
@@ -3158,15 +3381,16 @@ exports.getDiscountEnvAttributeValue = getDiscountEnvAttributeValue;
3158
3381
  exports.getMatchedMainProductSubTotal = getMatchedMainProductSubTotal;
3159
3382
  exports.getQuery = getQuery;
3160
3383
  exports.getReferralAttributes = getReferralAttributes;
3161
- exports.isAttributesEqual = isAttributesEqual;
3384
+ exports.normalizeAddToCartLines = normalizeAddToCartLines;
3162
3385
  exports.preCheck = preCheck;
3163
- exports.safeParseJson = safeParseJson;
3386
+ exports.safeParse = safeParse;
3164
3387
  exports.trackAddToCartFBQ = trackAddToCartFBQ;
3165
3388
  exports.trackAddToCartGA = trackAddToCartGA;
3166
3389
  exports.trackBeginCheckoutGA = trackBeginCheckoutGA;
3167
3390
  exports.trackBuyNowFBQ = trackBuyNowFBQ;
3168
3391
  exports.trackBuyNowGA = trackBuyNowGA;
3169
3392
  exports.useAddCartLines = useAddCartLines;
3393
+ exports.useAddPlusMemberProductsToCart = useAddPlusMemberProductsToCart;
3170
3394
  exports.useAddToCart = useAddToCart;
3171
3395
  exports.useAllBlogs = useAllBlogs;
3172
3396
  exports.useAllCollections = useAllCollections;
@@ -3179,6 +3403,7 @@ exports.useAutoRemovePlusMemberInCart = useAutoRemovePlusMemberInCart;
3179
3403
  exports.useBlog = useBlog;
3180
3404
  exports.useBuyNow = useBuyNow;
3181
3405
  exports.useCalcAutoFreeGift = useCalcAutoFreeGift;
3406
+ exports.useCalcGiftsFromLines = useCalcGiftsFromLines;
3182
3407
  exports.useCalcOrderDiscount = useCalcOrderDiscount;
3183
3408
  exports.useCartAttributes = useCartAttributes;
3184
3409
  exports.useCartContext = useCartContext;
@@ -3213,6 +3438,7 @@ exports.useSite = useSite;
3213
3438
  exports.useUpdateCartAttributes = useUpdateCartAttributes;
3214
3439
  exports.useUpdateCartLines = useUpdateCartLines;
3215
3440
  exports.useUpdateLineCodeAmountAttributes = useUpdateLineCodeAmountAttributes;
3441
+ exports.useUpdatePlusMemberDeliveryOptions = useUpdatePlusMemberDeliveryOptions;
3216
3442
  exports.useUpdateVariantQuery = useUpdateVariantQuery;
3217
3443
  exports.useVariant = useVariant;
3218
3444
  exports.useVariantMedia = useVariantMedia;