@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.
@@ -71,6 +71,81 @@ var CODE_AMOUNT_KEY = "_sku_code_money";
71
71
  var SCRIPT_CODE_AMOUNT_KEY = "_code_money";
72
72
  var MAIN_PRODUCT_CODE = ["WS24", "WSTD", "WS7D", "WSCP", "WSPE", "WSPD"];
73
73
 
74
+ // src/hooks/cart/utils/normalize-add-to-cart-lines.ts
75
+ function normalizeAddToCartLines(lines) {
76
+ return lines.filter((line) => line.variant?.id).map((line, index) => {
77
+ const variant = line.variant;
78
+ const product = variant.product;
79
+ const quantity = line.quantity || 1;
80
+ const price = variant.finalPrice?.amount ? Number(variant.finalPrice.amount) : variant.compareAtPrice?.amount ? Number(variant.compareAtPrice.amount) : variant.price?.amount ? Number(variant.price.amount) : 0;
81
+ const subtotalAmount = price * quantity;
82
+ const totalAmount = subtotalAmount;
83
+ return {
84
+ id: `temp-line-${index}-${variant.id}`,
85
+ // Temporary ID for pre-cart lines
86
+ name: product?.title || variant.title || "",
87
+ quantity,
88
+ variantId: variant.id,
89
+ productId: product?.id || variant.id.split("/").slice(0, -2).join("/"),
90
+ totalAmount,
91
+ subtotalAmount,
92
+ discountAllocations: [],
93
+ customAttributes: line.attributes || [],
94
+ variant: {
95
+ id: variant.id,
96
+ price,
97
+ listPrice: variant.compareAtPrice?.amount ? Number(variant.compareAtPrice.amount) : 0,
98
+ sku: variant.sku || "",
99
+ name: variant.title || "",
100
+ image: variant.image ? {
101
+ url: variant.image.url,
102
+ altText: variant.image.altText || void 0
103
+ } : void 0,
104
+ requiresShipping: false,
105
+ // Default value, not available in NormalizedProductVariant
106
+ availableForSale: variant.availableForSale ?? true,
107
+ quantityAvailable: variant.quantityAvailable ?? 0,
108
+ currentlyNotInStock: false,
109
+ // Default value, will be updated when added to cart
110
+ weight: variant.weight,
111
+ metafields: variant.metafields
112
+ },
113
+ product,
114
+ path: product?.handle ? `/products/${product.handle}` : "",
115
+ discounts: [],
116
+ options: variant.selectedOptions?.map((opt) => ({
117
+ name: opt.name,
118
+ value: opt.value
119
+ }))
120
+ };
121
+ });
122
+ }
123
+ function createMockCartFromLines(lines, existingCart) {
124
+ const normalizedLines = normalizeAddToCartLines(lines);
125
+ const subtotalPrice = normalizedLines.reduce((sum, line) => sum + line.subtotalAmount, 0);
126
+ const totalPrice = normalizedLines.reduce((sum, line) => sum + line.totalAmount, 0);
127
+ return {
128
+ id: existingCart?.id || "temp-cart-id",
129
+ customerId: existingCart?.customerId,
130
+ email: existingCart?.email,
131
+ createdAt: existingCart?.createdAt || (/* @__PURE__ */ new Date()).toISOString(),
132
+ currency: existingCart?.currency || { code: "USD" },
133
+ taxesIncluded: existingCart?.taxesIncluded,
134
+ lineItems: normalizedLines,
135
+ totalLineItemsDiscount: 0,
136
+ orderDiscounts: 0,
137
+ lineItemsSubtotalPrice: subtotalPrice,
138
+ subtotalPrice,
139
+ totalPrice,
140
+ totalTaxAmount: 0,
141
+ discountCodes: existingCart?.discountCodes || [],
142
+ discountAllocations: [],
143
+ url: existingCart?.url || "",
144
+ ready: true,
145
+ customAttributes: existingCart?.customAttributes
146
+ };
147
+ }
148
+
74
149
  // src/hooks/cart/utils/index.ts
75
150
  var getQuery = () => {
76
151
  const url = typeof window !== "undefined" ? window.location.search : "";
@@ -110,25 +185,25 @@ var getMatchedMainProductSubTotal = (cartData, variant_list, main_product) => {
110
185
  return acc + (main_product?.spend_money_type === 1 /* ORIGIN_PRICE */ ? Number(line.subtotalAmount) || 0 : Number(line.totalAmount) || 0);
111
186
  }, 0) || 0;
112
187
  };
113
- var getDiscountEnvAttributeValue = (attributes = []) => {
114
- const attr = attributes.find((attr2) => attr2.key === CUSTOMER_ATTRIBUTE_KEY);
115
- return safeParseJson(attr?.value ?? "") ?? {};
116
- };
117
- var isAttributesEqual = (attrs1 = [], attrs2 = []) => {
118
- if (attrs1.length !== attrs2.length) return false;
119
- const sorted1 = [...attrs1].sort((a, b) => a.key.localeCompare(b.key));
120
- const sorted2 = [...attrs2].sort((a, b) => a.key.localeCompare(b.key));
121
- return sorted1.every(
122
- (attr, i) => attr.key === sorted2[i]?.key && attr.value === sorted2[i]?.value
123
- );
124
- };
125
- var safeParseJson = (str) => {
188
+ var safeParse = (str) => {
126
189
  try {
127
190
  return JSON.parse(str);
128
191
  } catch (err) {
129
192
  return {};
130
193
  }
131
194
  };
195
+ var getDiscountEnvAttributeValue = (attributes = []) => {
196
+ const attr = attributes.find((attr2) => attr2.key === CUSTOMER_ATTRIBUTE_KEY);
197
+ return safeParse(attr?.value ?? "") ?? {};
198
+ };
199
+ var checkAttributesUpdateNeeded = (oldAttributes, newAttributes, customAttributesNeedRemove) => {
200
+ return oldAttributes.some((attr) => {
201
+ const newAttr = newAttributes.find((newAttr2) => newAttr2.key === attr.key);
202
+ return newAttr ? newAttr.value !== attr.value : true;
203
+ }) || newAttributes.some((attr) => !oldAttributes.some((oldAttr) => oldAttr.key === attr.key)) || customAttributesNeedRemove.some(
204
+ (removeAttr) => oldAttributes.some((oldAttr) => oldAttr.key === removeAttr.key)
205
+ );
206
+ };
132
207
  var containsAll = (source, requiredItems = []) => {
133
208
  if (!requiredItems?.length) return true;
134
209
  const sourceSet = new Set(source);
@@ -295,12 +370,18 @@ var formatFunctionAutoFreeGift = ({
295
370
  };
296
371
  return result;
297
372
  };
298
- var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer) => {
373
+ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer, lines) => {
299
374
  const tags = react.useMemo(() => customer?.tags || [], [customer?.tags]);
300
375
  const isCustomerLoading = react.useMemo(() => !customer ? true : false, [customer]);
301
376
  const dealsType = "";
302
377
  const { client, locale } = useShopify();
303
378
  const giftProductsCache = react.useRef(null);
379
+ const effectiveCart = react.useMemo(() => {
380
+ if (lines && lines.length > 0) {
381
+ return createMockCartFromLines(lines, cart);
382
+ }
383
+ return cart;
384
+ }, [lines, cart]);
304
385
  const { activeCampaign, subtotal } = react.useMemo(() => {
305
386
  for (const campaign of autoFreeGiftConfig) {
306
387
  const { rule_conditions = [], rule_result } = campaign;
@@ -308,7 +389,7 @@ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer) => {
308
389
  const isPreCheckPassed = preCheck(rule_conditions, tags, []);
309
390
  if (isPreCheckPassed && spend_get_reward) {
310
391
  const matchedSubtotal = getMatchedMainProductSubTotal(
311
- cart,
392
+ effectiveCart,
312
393
  spend_get_reward.main_product?.variant_list?.map((v) => v.variant_id) || [],
313
394
  {
314
395
  spend_money_type: spend_get_reward.main_product?.spend_money_type || 1,
@@ -322,13 +403,13 @@ var useCalcAutoFreeGift = (cart, autoFreeGiftConfig, customer) => {
322
403
  }
323
404
  }
324
405
  return { activeCampaign: null, subtotal: 0 };
325
- }, [autoFreeGiftConfig, cart, tags, dealsType]);
406
+ }, [autoFreeGiftConfig, effectiveCart, tags, dealsType]);
326
407
  const { qualifyingGift, nextTierGoal } = react.useMemo(() => {
327
408
  if (!activeCampaign || !activeCampaign.rule_result?.spend_get_reward?.gift_product) {
328
409
  return { qualifyingGift: null, nextTierGoal: null };
329
410
  }
330
411
  const giftTiers = activeCampaign.rule_result.spend_get_reward.gift_product;
331
- const qualifyingTier = [...giftTiers].reverse().find((tier) => subtotal >= Number(tier.spend_sum_money));
412
+ const qualifyingTier = [...giftTiers].sort((a, b) => Number(b.spend_sum_money) - Number(a.spend_sum_money)).find((tier) => subtotal >= Number(tier.spend_sum_money));
332
413
  const nextGoal = giftTiers.find((tier) => subtotal < Number(tier.spend_sum_money));
333
414
  if (!qualifyingTier) {
334
415
  return { qualifyingGift: null, nextTierGoal: nextGoal || null };
@@ -405,18 +486,33 @@ var useScriptAutoFreeGift = ({
405
486
  campaign,
406
487
  _giveaway,
407
488
  cart,
408
- locale: providedLocale
489
+ locale: providedLocale,
490
+ lines
409
491
  }) => {
410
492
  const { client, locale: contextLocale } = useShopify();
411
493
  const locale = providedLocale || contextLocale;
412
494
  const [points_subscribe, set_points_subscribe] = react.useState(false);
413
495
  const giftProductsCache = react.useRef(null);
496
+ const effectiveCart = react.useMemo(() => {
497
+ if (lines && lines.length > 0) {
498
+ return createMockCartFromLines(lines, cart);
499
+ }
500
+ return cart;
501
+ }, [lines, cart]);
414
502
  react.useEffect(() => {
415
503
  if (locale === "au") {
416
504
  const isPointsSubscribe = Cookies5__default.default.get("points_subscribe");
417
505
  set_points_subscribe(!!isPointsSubscribe);
418
506
  }
419
507
  }, [locale]);
508
+ const isActivityAvailable = react.useMemo(() => {
509
+ if (!campaign) return false;
510
+ const query = getQuery();
511
+ const utmCampaign = Cookies5__default.default.get("utm_campaign") || query?.utm_campaign;
512
+ if (campaign.activityAvailableQuery && !utmCampaign?.includes(campaign.activityAvailableQuery))
513
+ return false;
514
+ return true;
515
+ }, [campaign]);
420
516
  const [upgrade_multiple, upgrade_value] = react.useMemo(() => {
421
517
  let upgrade_multiple2 = 1;
422
518
  let upgrade_value2 = 0;
@@ -424,17 +520,17 @@ var useScriptAutoFreeGift = ({
424
520
  upgrade_multiple2 = 1.2;
425
521
  upgrade_value2 = 40;
426
522
  }
427
- cart?.lineItems?.forEach(({ customAttributes }) => {
523
+ effectiveCart?.lineItems?.forEach(({ customAttributes }) => {
428
524
  customAttributes?.forEach(({ key, value }) => {
429
525
  if (key === "_amount_upgrade_multiple") upgrade_multiple2 = Number(value) || 1;
430
526
  if (key === "_amount_upgrade_value") upgrade_value2 = Number(value) || 0;
431
527
  });
432
528
  });
433
529
  return [upgrade_multiple2, upgrade_value2];
434
- }, [cart?.lineItems, points_subscribe]);
530
+ }, [effectiveCart?.lineItems, points_subscribe]);
435
531
  const breakpoints = react.useMemo(() => {
436
- if (!campaign) return [];
437
- return (campaign.breakpoints || []).map((item) => ({
532
+ if (!isActivityAvailable) return [];
533
+ return (campaign?.breakpoints || []).map((item) => ({
438
534
  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),
439
535
  giveawayProducts: item.giveawayProducts || []
440
536
  }));
@@ -458,25 +554,26 @@ var useScriptAutoFreeGift = ({
458
554
  return true;
459
555
  }, [giftHandles]);
460
556
  const involvedLines = react.useMemo(() => {
461
- if (!campaign) return [];
462
- return (cart?.lineItems || []).filter((line) => {
557
+ if (!isActivityAvailable) return [];
558
+ return (effectiveCart?.lineItems || []).filter((line) => {
463
559
  const isNotGift = line?.totalAmount && Number(line.totalAmount) > 0 && line.customAttributes?.every(
464
560
  (item) => item.key !== _giveaway
465
561
  );
466
562
  const hasCampaignTag = line.product?.tags?.some(
467
- (tag) => campaign.includeTags?.includes(tag.trim()) && line.variant?.availableForSale
563
+ (tag) => campaign?.includeTags?.includes(tag.trim()) && line.variant?.availableForSale
468
564
  );
469
565
  return isNotGift && hasCampaignTag;
470
566
  });
471
- }, [cart?.lineItems, campaign, _giveaway]);
567
+ }, [effectiveCart?.lineItems, isActivityAvailable, _giveaway]);
472
568
  const involvedSubTotal = react.useMemo(() => {
473
- if (!campaign) return new Decimal2__default.default(0);
569
+ if (!isActivityAvailable) return new Decimal2__default.default(0);
474
570
  return involvedLines.reduce((prev, item) => {
475
- const amount = campaign.useTotalAmount ? item.totalAmount : item.subtotalAmount;
571
+ const amount = campaign?.useTotalAmount ? item.totalAmount : item.subtotalAmount;
476
572
  return new Decimal2__default.default(prev).plus(new Decimal2__default.default(amount || 0));
477
573
  }, new Decimal2__default.default(0));
478
- }, [involvedLines, campaign]);
574
+ }, [involvedLines, isActivityAvailable]);
479
575
  const [freeGiftLevel, nextFreeGiftLevel] = react.useMemo(() => {
576
+ if (!isActivityAvailable) return [null, null];
480
577
  const sortedLevels = [...breakpoints].sort(
481
578
  (a, b) => Number(b.breakpoint) - Number(a.breakpoint)
482
579
  );
@@ -606,8 +703,6 @@ function useAddCartLines(options) {
606
703
  );
607
704
  return useSWRMutation__default.default("add-cart-lines", addLines, options);
608
705
  }
609
-
610
- // src/tracking/ga.ts
611
706
  var gaTrack = (data) => {
612
707
  if (typeof window === "undefined") {
613
708
  return;
@@ -625,18 +720,19 @@ var gaTrack = (data) => {
625
720
  };
626
721
  var trackAddToCartGA = ({
627
722
  lineItems = [],
628
- gtmParams = {},
629
- brand
723
+ gtmParams = {}
630
724
  }) => {
631
725
  if (!lineItems.length || !lineItems[0]?.variant) {
632
726
  return;
633
727
  }
634
728
  const { variant } = lineItems[0];
635
- const currencyCode = variant?.price?.currencyCode;
636
- const totalPrice = lineItems.reduce((sum, item) => {
637
- const price = parseFloat(item.variant?.price?.amount || "0");
638
- return sum + price;
639
- }, 0);
729
+ const currencyCode = variant.product?.price?.currencyCode;
730
+ const totalPrice = lineItems?.reduce(
731
+ (prev, { variant: variant2 }) => prev.plus(
732
+ variant2?.finalPrice?.amount ?? variant2?.compareAtPrice?.amount ?? variant2?.price?.amount ?? 0
733
+ ),
734
+ new Decimal2__default.default(0)
735
+ ).toNumber();
640
736
  gaTrack({
641
737
  event: "ga4Event",
642
738
  event_name: "add_to_cart",
@@ -647,11 +743,11 @@ var trackAddToCartGA = ({
647
743
  position: gtmParams?.position || "",
648
744
  items: lineItems.map(({ variant: variant2, quantity }) => ({
649
745
  item_id: variant2?.sku,
650
- item_name: variant2?.product?.title || variant2?.product?.name,
651
- item_brand: brand || gtmParams?.brand || "",
746
+ item_name: variant2?.product?.title || variant2?.product?.title,
747
+ item_brand: gtmParams?.brand || "",
652
748
  item_category: variant2?.product?.productType || "",
653
- item_variant: variant2?.title || variant2?.name,
654
- price: variant2?.finalPrice?.amount ?? variant2?.price?.amount,
749
+ item_variant: variant2?.title || variant2?.title,
750
+ price: variant2?.compareAtPrice?.amount ?? variant2?.price?.amount,
655
751
  quantity: quantity || 1
656
752
  })),
657
753
  ...gtmParams?.ga4Params
@@ -660,19 +756,19 @@ var trackAddToCartGA = ({
660
756
  };
661
757
  var trackBuyNowGA = ({
662
758
  lineItems = [],
663
- gtmParams = {},
664
- brand
759
+ gtmParams = {}
665
760
  }) => {
666
761
  if (!lineItems.length || !lineItems[0]?.variant) {
667
762
  return;
668
763
  }
669
764
  const { variant } = lineItems[0];
670
765
  const currencyCode = variant.price?.currencyCode;
671
- const totalPrice = lineItems.reduce((sum, item) => {
672
- const price = parseFloat(item.finalPrice?.amount || item.variant?.price?.amount || "0");
673
- const quantity = item.quantity || 1;
674
- return sum + price * quantity;
675
- }, 0);
766
+ const totalPrice = lineItems?.reduce(
767
+ (prev, { variant: variant2 }) => prev.plus(
768
+ variant2?.finalPrice?.amount ?? variant2?.compareAtPrice?.amount ?? (variant2?.price?.amount || 0)
769
+ ),
770
+ new Decimal2__default.default(0)
771
+ ).toNumber();
676
772
  gaTrack({
677
773
  event: "ga4Event",
678
774
  event_name: "begin_checkout",
@@ -684,10 +780,10 @@ var trackBuyNowGA = ({
684
780
  items: lineItems.map((item) => ({
685
781
  item_id: item.variant?.sku,
686
782
  item_name: item.variant?.product?.title || item.variant?.title,
687
- item_brand: item.variant?.product?.vendor || brand || gtmParams?.brand || "",
783
+ item_brand: gtmParams?.brand || "",
688
784
  item_category: item.variant?.product?.productType || "",
689
785
  item_variant: item.variant?.title,
690
- price: item.finalPrice?.amount || item.variant?.price?.amount,
786
+ price: item.variant?.compareAtPrice?.amount ?? item.variant?.price?.amount,
691
787
  quantity: item.quantity || 1
692
788
  })),
693
789
  ...gtmParams?.ga4Params
@@ -701,10 +797,10 @@ var trackAddToCartFBQ = ({ lineItems = [] }) => {
701
797
  return;
702
798
  }
703
799
  if (lineItems.length && lineItems[0]?.variant) {
704
- const { variant, quantity, finalPrice } = lineItems[0];
800
+ const { variant, quantity } = lineItems[0];
705
801
  try {
706
802
  window.fbq("track", "AddToCart", {
707
- value: finalPrice?.amount || variant?.price?.amount,
803
+ value: variant?.compareAtPrice?.amount ?? (variant?.price?.amount || variant?.price || 0),
708
804
  num_items: quantity,
709
805
  currency: variant?.price?.currencyCode,
710
806
  content_name: variant?.product?.title,
@@ -791,9 +887,9 @@ function useRemoveCartCodes(options) {
791
887
  }
792
888
 
793
889
  // src/hooks/cart/use-add-to-cart.ts
794
- function useAddToCart({ withTrack = true, brand } = {}, swrOptions) {
795
- const { client, locale, cartCookieAdapter, userAdapter } = useShopify();
796
- const { mutateCart, cart, metafieldIdentifiers } = useCartContext();
890
+ function useAddToCart({ withTrack = true } = {}, swrOptions) {
891
+ const { client, config, locale, cartCookieAdapter, userAdapter } = useShopify();
892
+ const { cart } = useCartContext();
797
893
  const { trigger: applyCartCodes } = useApplyCartCodes();
798
894
  const { trigger: removeInvalidCodes } = useRemoveCartCodes();
799
895
  const { trigger: addCartLines2 } = useAddCartLines();
@@ -815,7 +911,8 @@ function useAddToCart({ withTrack = true, brand } = {}, swrOptions) {
815
911
  const lines = lineItems.map((item) => ({
816
912
  merchandiseId: item.variant?.id || "",
817
913
  quantity: item.quantity || 1,
818
- attributes: item.attributes
914
+ attributes: item.attributes,
915
+ sellingPlanId: item.sellingPlanId
819
916
  })).filter((item) => item.merchandiseId && item.quantity);
820
917
  if (lines.length === 0) {
821
918
  return;
@@ -829,6 +926,7 @@ function useAddToCart({ withTrack = true, brand } = {}, swrOptions) {
829
926
  if (!resultCart) {
830
927
  return void 0;
831
928
  }
929
+ console.log("npm addCartLines resultCart", resultCart);
832
930
  if (resultCart.discountCodes && resultCart.discountCodes.length > 0) {
833
931
  const unapplicableCodes = resultCart.discountCodes.filter((item) => !item.applicable).map((item) => item.code);
834
932
  if (unapplicableCodes.length > 0) {
@@ -850,34 +948,16 @@ function useAddToCart({ withTrack = true, brand } = {}, swrOptions) {
850
948
  discountCodes
851
949
  });
852
950
  }
853
- if (withTrack && resultCart.lineItems) {
854
- const trackingLineItems = resultCart.lineItems.map((line) => ({
855
- variant: {
856
- id: line.variant.id,
857
- sku: line.variant.sku || "",
858
- title: line.variant.name,
859
- price: {
860
- amount: String(line.variant.price),
861
- currencyCode: resultCart.currency.code
862
- },
863
- product: line.product ? {
864
- title: line.product.title || line.name,
865
- productType: line.product.productType,
866
- vendor: line.product.vendor
867
- } : void 0
868
- },
869
- quantity: line.quantity
870
- }));
951
+ if (withTrack) {
871
952
  trackAddToCartGA({
872
- lineItems: trackingLineItems,
873
- gtmParams: { ...gtmParams, brand },
874
- brand
953
+ lineItems,
954
+ gtmParams: { ...gtmParams, brand: config.getBrand() }
875
955
  });
876
- trackAddToCartFBQ({ lineItems: trackingLineItems });
956
+ trackAddToCartFBQ({ lineItems });
877
957
  }
878
958
  return resultCart;
879
959
  },
880
- [client, locale, cartCookieAdapter, userAdapter, cart, withTrack, brand]
960
+ [client, locale, cartCookieAdapter, userAdapter, cart, withTrack]
881
961
  );
882
962
  return useSWRMutation__default.default("add-to-cart", addToCart, swrOptions);
883
963
  }
@@ -958,8 +1038,8 @@ function useUpdateCartAttributes(mutate, metafieldIdentifiers, options) {
958
1038
  );
959
1039
  return useSWRMutation__default.default("update-cart-attributes", updateAttributes, options);
960
1040
  }
961
- function useBuyNow({ withTrack = true, brand } = {}, swrOptions) {
962
- const { client, locale, cartCookieAdapter, userAdapter } = useShopify();
1041
+ function useBuyNow({ withTrack = true } = {}, swrOptions) {
1042
+ const { client, config, locale, cartCookieAdapter, userAdapter } = useShopify();
963
1043
  const isLoggedIn = userAdapter?.isLoggedIn || false;
964
1044
  const buyNow = react.useCallback(
965
1045
  async (_key, { arg }) => {
@@ -977,9 +1057,10 @@ function useBuyNow({ withTrack = true, brand } = {}, swrOptions) {
977
1057
  return;
978
1058
  }
979
1059
  const lines = lineItems.map((item) => ({
980
- merchandiseId: item.variant?.id || item.variantId || "",
1060
+ merchandiseId: item.variant?.id || "",
981
1061
  quantity: item.quantity || 1,
982
- attributes: item.attributes
1062
+ attributes: item.attributes,
1063
+ sellingPlanId: item.sellingPlanId
983
1064
  })).filter((item) => item.merchandiseId && item.quantity);
984
1065
  if (lines.length === 0) {
985
1066
  return;
@@ -996,27 +1077,9 @@ function useBuyNow({ withTrack = true, brand } = {}, swrOptions) {
996
1077
  throw new Error("Failed to create cart for buy now");
997
1078
  }
998
1079
  if (withTrack && resultCart.lineItems) {
999
- const trackingLineItems = resultCart.lineItems.map((line) => ({
1000
- variant: {
1001
- id: line.variantId,
1002
- sku: line.variant.sku || "",
1003
- title: line.variant.name,
1004
- price: {
1005
- amount: String(line.variant.price),
1006
- currencyCode: resultCart.currency.code
1007
- },
1008
- product: line.product ? {
1009
- title: line.product.title || line.name,
1010
- productType: line.product.productType,
1011
- vendor: line.product.vendor
1012
- } : void 0
1013
- },
1014
- quantity: line.quantity
1015
- }));
1016
1080
  trackBuyNowGA({
1017
- lineItems: trackingLineItems,
1018
- gtmParams: { ...gtmParams, brand },
1019
- brand
1081
+ lineItems,
1082
+ gtmParams: { ...gtmParams, brand: config.getBrand() }
1020
1083
  });
1021
1084
  if (fbqTrackConfig) {
1022
1085
  trackBuyNowFBQ({ trackConfig: fbqTrackConfig });
@@ -1033,10 +1096,64 @@ function useBuyNow({ withTrack = true, brand } = {}, swrOptions) {
1033
1096
  }
1034
1097
  return resultCart;
1035
1098
  },
1036
- [client, locale, isLoggedIn, cartCookieAdapter, withTrack, brand]
1099
+ [client, locale, isLoggedIn, cartCookieAdapter, withTrack]
1037
1100
  );
1038
1101
  return useSWRMutation__default.default("buy-now", buyNow, swrOptions);
1039
1102
  }
1103
+ function useCalcGiftsFromLines({
1104
+ lines,
1105
+ customer,
1106
+ scriptGiveawayKey = CUSTOMER_SCRIPT_GIFT_KEY
1107
+ }) {
1108
+ const { locale } = useShopify();
1109
+ const { cart, autoFreeGiftConfig, gradientGiftsConfig } = useCartContext();
1110
+ const functionGift = useCalcAutoFreeGift(cart, autoFreeGiftConfig || [], customer, lines);
1111
+ const scriptGift = useScriptAutoFreeGift({
1112
+ campaign: gradientGiftsConfig || null,
1113
+ _giveaway: scriptGiveawayKey,
1114
+ cart,
1115
+ locale,
1116
+ lines
1117
+ });
1118
+ const allGiftLines = react.useMemo(() => {
1119
+ const functionGiftLines = functionGift.qualifyingGift?.itemsToAdd || [];
1120
+ const scriptGiftLines = scriptGift.freeGiftLevel ? scriptGift.freeGiftLevel.giveawayProducts.map((product) => {
1121
+ const giftProduct = scriptGift.giftProductsResult?.find(
1122
+ (p) => p.handle === product.handle
1123
+ );
1124
+ const variant = giftProduct?.variants?.[0];
1125
+ return {
1126
+ variant: {
1127
+ id: variant?.id || "",
1128
+ handle: product.handle,
1129
+ sku: product.sku
1130
+ },
1131
+ quantity: 1,
1132
+ attributes: [
1133
+ {
1134
+ key: scriptGiveawayKey,
1135
+ value: "true"
1136
+ }
1137
+ ]
1138
+ };
1139
+ }).filter((item) => item.variant.id) : [];
1140
+ return [...functionGiftLines, ...scriptGiftLines];
1141
+ }, [
1142
+ functionGift.qualifyingGift,
1143
+ scriptGift.freeGiftLevel,
1144
+ scriptGift.giftProductsResult,
1145
+ scriptGiveawayKey
1146
+ ]);
1147
+ const hasGifts = react.useMemo(() => {
1148
+ return allGiftLines.length > 0;
1149
+ }, [allGiftLines]);
1150
+ return {
1151
+ functionGift,
1152
+ scriptGift,
1153
+ allGiftLines,
1154
+ hasGifts
1155
+ };
1156
+ }
1040
1157
 
1041
1158
  // src/hooks/cart/types/order-discount.ts
1042
1159
  var OrderDiscountType = /* @__PURE__ */ ((OrderDiscountType2) => {
@@ -1186,8 +1303,6 @@ var useCartAttributes = ({
1186
1303
  memberSetting,
1187
1304
  cart
1188
1305
  });
1189
- console.log("memberSetting", memberSetting);
1190
- console.log("hasPlusMember", hasPlusMember);
1191
1306
  react.useEffect(() => {
1192
1307
  setCurrentUrl(window.location.href);
1193
1308
  }, []);
@@ -1236,15 +1351,19 @@ var useCartAttributes = ({
1236
1351
  ];
1237
1352
  }, [profile?.memberType, profile?.token, userType, hasPlusMember]);
1238
1353
  const functionAttributes = react.useMemo(() => {
1239
- return [
1240
- cart?.discountCodes && {
1354
+ const hasFunctionEnvAttribute = cart?.lineItems.some(
1355
+ (item) => item.customAttributes?.some((attr) => attr.key === CUSTOMER_ATTRIBUTE_KEY)
1356
+ );
1357
+ const discountCodes = cart?.discountCodes.map((item) => item.code).filter((code) => code) || [];
1358
+ return hasFunctionEnvAttribute ? [
1359
+ {
1241
1360
  key: "_discounts_function_env",
1242
1361
  value: JSON.stringify({
1243
- discount_code: cart?.discountCodes.map((item) => item.code),
1362
+ discount_code: discountCodes,
1244
1363
  user_tags: customer?.tags || []
1245
1364
  })
1246
1365
  }
1247
- ];
1366
+ ] : [];
1248
1367
  }, [cart]);
1249
1368
  const presellAttributes = react.useMemo(() => {
1250
1369
  return [
@@ -2421,6 +2540,69 @@ var usePlusMemberDeliveryCodes = ({
2421
2540
  [deliveryData]
2422
2541
  );
2423
2542
  };
2543
+ function useUpdateCartDeliveryOptions(mutate, metafieldIdentifiers, options) {
2544
+ const { client, locale, cartCookieAdapter } = useShopify();
2545
+ const updateDeliveryOptions = react.useCallback(
2546
+ async (_key, { arg }) => {
2547
+ const updatedCart = await shopifySdk.updateCartDeliveryOptions(client, {
2548
+ ...arg,
2549
+ metafieldIdentifiers,
2550
+ cookieAdapter: cartCookieAdapter
2551
+ });
2552
+ console.log("useUpdateCartDeliveryOptions updatedCart", updatedCart);
2553
+ if (updatedCart) {
2554
+ mutate(updatedCart);
2555
+ }
2556
+ return updatedCart;
2557
+ },
2558
+ [client, locale, cartCookieAdapter, mutate]
2559
+ );
2560
+ return useSWRMutation__default.default("update-cart-delivery-options", updateDeliveryOptions, options);
2561
+ }
2562
+
2563
+ // src/hooks/member/plus/use-update-plus-member-delivery-options.ts
2564
+ var useUpdatePlusMemberDeliveryOptions = ({
2565
+ options
2566
+ }) => {
2567
+ const { cart, mutateCart: mutate, metafieldIdentifiers } = useCartContext();
2568
+ const { trigger: updateCartDeliveryOptions2, isMutating } = useUpdateCartDeliveryOptions(
2569
+ mutate,
2570
+ metafieldIdentifiers
2571
+ );
2572
+ const handler = react.useCallback(
2573
+ async (_, { arg }) => {
2574
+ const { deliveryData } = arg;
2575
+ const firstDeliveryGroup = cart?.deliveryGroups?.[0];
2576
+ const deliveryGroupId = firstDeliveryGroup?.id;
2577
+ const selectedOptionCode = deliveryData?.deliveryCustomData?.selected_delivery_option?.code;
2578
+ if (!deliveryGroupId || !selectedOptionCode || selectedOptionCode === firstDeliveryGroup?.selectedDeliveryOption?.code) {
2579
+ return null;
2580
+ }
2581
+ const deliveryGroup = cart?.deliveryGroups?.find((group) => group?.id === deliveryGroupId);
2582
+ const matchedOption = deliveryGroup?.deliveryOptions?.find(
2583
+ (option) => option?.code === selectedOptionCode
2584
+ );
2585
+ if (!matchedOption?.handle) {
2586
+ return null;
2587
+ }
2588
+ const deliveryOptions = [
2589
+ {
2590
+ deliveryGroupId,
2591
+ deliveryOptionHandle: matchedOption.handle
2592
+ }
2593
+ ];
2594
+ const updatedCart = await updateCartDeliveryOptions2({
2595
+ selectedDeliveryOptions: deliveryOptions
2596
+ });
2597
+ if (updatedCart && mutate) {
2598
+ mutate(updatedCart);
2599
+ }
2600
+ return updatedCart;
2601
+ },
2602
+ [cart, updateCartDeliveryOptions2, mutate]
2603
+ );
2604
+ return useSWRMutation__default.default("update-cart-delivery-options", handler, options);
2605
+ };
2424
2606
  var usePlusMemberItemCustomAttributes = ({
2425
2607
  deliveryData
2426
2608
  }) => {
@@ -2507,15 +2689,14 @@ var usePlusMemberCheckoutCustomAttributes = ({
2507
2689
  }, [deliveryCustomData, product, profile, userType, variant, isShowShippingBenefits]);
2508
2690
  };
2509
2691
  function useAutoRemovePlusMemberInCart({
2510
- metafields,
2511
- isMonthlyPlus,
2512
- isAnnualPlus
2692
+ cart,
2693
+ profile,
2694
+ memberSetting
2513
2695
  }) {
2514
- const { plus_monthly_product, plus_annual_product } = metafields || {};
2515
- const { cart } = useCartContext();
2696
+ const { plus_monthly_product, plus_annual_product } = memberSetting || {};
2516
2697
  const { trigger: removeCartLines2 } = useRemoveCartLines();
2517
2698
  react.useEffect(() => {
2518
- if (!cart) return;
2699
+ if (!cart || !plus_monthly_product || !plus_annual_product) return;
2519
2700
  const removePlusProduct = async (productType) => {
2520
2701
  if (!productType) return;
2521
2702
  const product = cart.lineItems?.find(
@@ -2527,26 +2708,53 @@ function useAutoRemovePlusMemberInCart({
2527
2708
  });
2528
2709
  }
2529
2710
  };
2530
- if (isMonthlyPlus) {
2711
+ if (profile?.isMonthlyPlus) {
2531
2712
  removePlusProduct(plus_monthly_product);
2532
2713
  }
2533
- if (isAnnualPlus) {
2714
+ if (profile?.isAnnualPlus) {
2534
2715
  removePlusProduct(plus_annual_product);
2535
2716
  }
2717
+ }, [cart, plus_annual_product, plus_monthly_product, profile, removeCartLines2]);
2718
+ }
2719
+ function useAddPlusMemberProductsToCart({
2720
+ cart,
2721
+ profile
2722
+ }) {
2723
+ const { selectedPlusMemberMode, selectedPlusMemberProduct, plusMemberMetafields } = usePlusMemberContext();
2724
+ const { hasMonthlyPlus, hasAnnualPlus } = useHasPlusMemberInCart({
2725
+ memberSetting: plusMemberMetafields,
2726
+ cart
2727
+ });
2728
+ const plusMemberProduct = react.useMemo(() => {
2729
+ if (!selectedPlusMemberProduct || selectedPlusMemberMode === "free" /* FREE */) {
2730
+ return void 0;
2731
+ }
2732
+ if (selectedPlusMemberMode === "monthly" /* MONTHLY */ && hasMonthlyPlus) {
2733
+ return void 0;
2734
+ }
2735
+ if (selectedPlusMemberMode === "annual" /* ANNUAL */ && hasAnnualPlus) {
2736
+ return void 0;
2737
+ }
2738
+ if (profile?.isMonthlyPlus && selectedPlusMemberMode === "monthly" /* MONTHLY */) {
2739
+ return void 0;
2740
+ }
2741
+ if (!profile?.isAnnualPlus && selectedPlusMemberMode === "annual" /* ANNUAL */) {
2742
+ return void 0;
2743
+ }
2744
+ return selectedPlusMemberProduct;
2536
2745
  }, [
2537
- cart,
2538
- plus_annual_product,
2539
- plus_monthly_product,
2540
- isAnnualPlus,
2541
- isMonthlyPlus,
2542
- removeCartLines2
2746
+ selectedPlusMemberMode,
2747
+ selectedPlusMemberProduct?.variant,
2748
+ selectedPlusMemberProduct?.product,
2749
+ hasMonthlyPlus,
2750
+ hasAnnualPlus
2543
2751
  ]);
2752
+ return plusMemberProduct;
2544
2753
  }
2545
2754
  var PlusMemberProvider = ({
2546
2755
  variant,
2547
2756
  product,
2548
- shopCommon,
2549
- metafields,
2757
+ memberSetting,
2550
2758
  initialSelectedPlusMemberMode = "free",
2551
2759
  profile,
2552
2760
  locale,
@@ -2566,14 +2774,14 @@ var PlusMemberProvider = ({
2566
2774
  const [deleteMarginBottom, setDeleteMarginBottom] = react.useState(false);
2567
2775
  const shippingMethodsContext = useShippingMethods({
2568
2776
  variant,
2569
- plusMemberMetafields: metafields,
2777
+ plusMemberMetafields: memberSetting,
2570
2778
  selectedPlusMemberMode});
2571
2779
  const plusMemberHandles = react.useMemo(() => {
2572
2780
  return [
2573
- metafields?.plus_monthly_product?.handle,
2574
- metafields?.plus_annual_product?.handle
2781
+ memberSetting?.plus_monthly_product?.handle,
2782
+ memberSetting?.plus_annual_product?.handle
2575
2783
  ].filter(Boolean);
2576
- }, [metafields]);
2784
+ }, [memberSetting]);
2577
2785
  const { data: plusMemberProducts = [] } = useProductsByHandles({
2578
2786
  handles: plusMemberHandles
2579
2787
  });
@@ -2581,25 +2789,24 @@ var PlusMemberProvider = ({
2581
2789
  if (selectedPlusMemberMode === "free" /* FREE */) {
2582
2790
  return null;
2583
2791
  }
2584
- const handle = selectedPlusMemberMode === "monthly" /* MONTHLY */ ? metafields?.plus_monthly_product?.handle : metafields?.plus_annual_product?.handle;
2585
- const sku = selectedPlusMemberMode === "monthly" /* MONTHLY */ ? metafields?.plus_monthly_product?.sku : metafields?.plus_annual_product?.sku;
2792
+ const handle = selectedPlusMemberMode === "monthly" /* MONTHLY */ ? memberSetting?.plus_monthly_product?.handle : memberSetting?.plus_annual_product?.handle;
2793
+ const sku = selectedPlusMemberMode === "monthly" /* MONTHLY */ ? memberSetting?.plus_monthly_product?.sku : memberSetting?.plus_annual_product?.sku;
2586
2794
  const product2 = plusMemberProducts?.find((p) => p.handle === handle);
2587
2795
  const variant2 = product2?.variants?.find((v) => v.sku === sku);
2588
2796
  return product2 && variant2 ? { product: product2, variant: variant2 } : null;
2589
- }, [plusMemberProducts, metafields, selectedPlusMemberMode]);
2797
+ }, [plusMemberProducts, memberSetting, selectedPlusMemberMode]);
2590
2798
  return /* @__PURE__ */ jsxRuntime.jsx(
2591
2799
  PlusMemberContext.Provider,
2592
2800
  {
2593
2801
  value: {
2594
2802
  variant,
2595
- shopCommon,
2596
2803
  zipCode,
2597
2804
  setZipCode,
2598
2805
  allowNextDayDelivery,
2599
2806
  setAllowNextDayDelivery,
2600
2807
  allowThirdDayDelivery,
2601
2808
  setAllowThirdDayDelivery,
2602
- plusMemberMetafields: metafields,
2809
+ plusMemberMetafields: memberSetting,
2603
2810
  selectedPlusMemberMode,
2604
2811
  setSelectedPlusMemberMode,
2605
2812
  showAreaCheckModal,
@@ -2825,7 +3032,9 @@ exports.ShippingMethodMode = ShippingMethodMode;
2825
3032
  exports.SpendMoneyType = SpendMoneyType;
2826
3033
  exports.atobID = atobID;
2827
3034
  exports.btoaID = btoaID;
3035
+ exports.checkAttributesUpdateNeeded = checkAttributesUpdateNeeded;
2828
3036
  exports.clearGeoLocationCache = clearGeoLocationCache;
3037
+ exports.createMockCartFromLines = createMockCartFromLines;
2829
3038
  exports.currencyCodeMapping = currencyCodeMapping;
2830
3039
  exports.defaultSWRMutationConfiguration = defaultSWRMutationConfiguration;
2831
3040
  exports.formatFunctionAutoFreeGift = formatFunctionAutoFreeGift;
@@ -2835,10 +3044,11 @@ exports.getDiscountEnvAttributeValue = getDiscountEnvAttributeValue;
2835
3044
  exports.getMatchedMainProductSubTotal = getMatchedMainProductSubTotal;
2836
3045
  exports.getQuery = getQuery;
2837
3046
  exports.getReferralAttributes = getReferralAttributes;
2838
- exports.isAttributesEqual = isAttributesEqual;
3047
+ exports.normalizeAddToCartLines = normalizeAddToCartLines;
2839
3048
  exports.preCheck = preCheck;
2840
- exports.safeParseJson = safeParseJson;
3049
+ exports.safeParse = safeParse;
2841
3050
  exports.useAddCartLines = useAddCartLines;
3051
+ exports.useAddPlusMemberProductsToCart = useAddPlusMemberProductsToCart;
2842
3052
  exports.useAddToCart = useAddToCart;
2843
3053
  exports.useAllBlogs = useAllBlogs;
2844
3054
  exports.useAllCollections = useAllCollections;
@@ -2851,6 +3061,7 @@ exports.useAutoRemovePlusMemberInCart = useAutoRemovePlusMemberInCart;
2851
3061
  exports.useBlog = useBlog;
2852
3062
  exports.useBuyNow = useBuyNow;
2853
3063
  exports.useCalcAutoFreeGift = useCalcAutoFreeGift;
3064
+ exports.useCalcGiftsFromLines = useCalcGiftsFromLines;
2854
3065
  exports.useCalcOrderDiscount = useCalcOrderDiscount;
2855
3066
  exports.useCartAttributes = useCartAttributes;
2856
3067
  exports.useCartItemQuantityLimit = useCartItemQuantityLimit;
@@ -2883,6 +3094,7 @@ exports.useSite = useSite;
2883
3094
  exports.useUpdateCartAttributes = useUpdateCartAttributes;
2884
3095
  exports.useUpdateCartLines = useUpdateCartLines;
2885
3096
  exports.useUpdateLineCodeAmountAttributes = useUpdateLineCodeAmountAttributes;
3097
+ exports.useUpdatePlusMemberDeliveryOptions = useUpdatePlusMemberDeliveryOptions;
2886
3098
  exports.useUpdateVariantQuery = useUpdateVariantQuery;
2887
3099
  exports.useVariant = useVariant;
2888
3100
  exports.useVariantMedia = useVariantMedia;