@tapcart/mobile-components 0.7.59 → 0.7.60
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/components/hooks/use-mock-cart.d.ts +70 -13
- package/dist/components/hooks/use-mock-cart.d.ts.map +1 -1
- package/dist/components/hooks/use-mock-cart.js +70 -16
- package/dist/components/libs/cart/calculated-cart-values.util.d.ts +16 -0
- package/dist/components/libs/cart/calculated-cart-values.util.d.ts.map +1 -0
- package/dist/components/libs/cart/calculated-cart-values.util.js +144 -0
- package/dist/components/libs/cart/calculated-cart-values.util.test.d.ts +2 -0
- package/dist/components/libs/cart/calculated-cart-values.util.test.d.ts.map +1 -0
- package/dist/components/libs/cart/calculated-cart-values.util.test.js +150 -0
- package/dist/components/libs/cart/calculatedCartValues.util.d.ts +1 -0
- package/dist/components/libs/cart/calculatedCartValues.util.d.ts.map +1 -0
- package/dist/components/libs/cart/calculatedCartValues.util.js +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/lib/cart.util copy.d.ts +1 -0
- package/dist/lib/cart.util copy.d.ts.map +1 -0
- package/dist/lib/cart.util copy.js +1 -0
- package/dist/lib/cart.util.d.ts +16 -0
- package/dist/lib/cart.util.d.ts.map +1 -0
- package/dist/lib/cart.util.js +144 -0
- package/dist/lib/cart.util.test.d.ts +2 -0
- package/dist/lib/cart.util.test.d.ts.map +1 -0
- package/dist/lib/cart.util.test.js +150 -0
- package/package.json +20 -20
- package/dist/components/hooks/use-click-outside.d.ts +0 -6
- package/dist/components/hooks/use-click-outside.d.ts.map +0 -1
- package/dist/components/hooks/use-click-outside.js +0 -15
- package/dist/components/hooks/use-outside-click.d.ts +0 -7
- package/dist/components/hooks/use-outside-click.d.ts.map +0 -1
- package/dist/components/hooks/use-outside-click.js +0 -16
- package/dist/components/hooks/use-tap.d.ts +0 -8
- package/dist/components/hooks/use-tap.d.ts.map +0 -1
- package/dist/components/hooks/use-tap.js +0 -100
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Product } from "app-studio-types";
|
|
1
|
+
import { Money, Product, DiscountApplicationTargetType } from "app-studio-types";
|
|
2
2
|
type UseMockCartParams = {
|
|
3
3
|
apiUrl: string;
|
|
4
4
|
appId: string;
|
|
@@ -15,8 +15,10 @@ export declare const useMockCart: ({ apiUrl, appId, enabled, limit, }: UseMockCa
|
|
|
15
15
|
error: any;
|
|
16
16
|
isLoading: boolean;
|
|
17
17
|
cart: {
|
|
18
|
+
calculatedData: import("../../lib/cart.util").CalculatedData;
|
|
18
19
|
subtotal: number;
|
|
19
20
|
items: {
|
|
21
|
+
id: string;
|
|
20
22
|
discounts: {
|
|
21
23
|
amount: number;
|
|
22
24
|
code: string;
|
|
@@ -39,7 +41,7 @@ export declare const useMockCart: ({ apiUrl, appId, enabled, limit, }: UseMockCa
|
|
|
39
41
|
value: string;
|
|
40
42
|
optionValue: import("app-studio-types").ProductOptionValue;
|
|
41
43
|
}[];
|
|
42
|
-
price:
|
|
44
|
+
price: Money;
|
|
43
45
|
available: boolean;
|
|
44
46
|
image?: import("app-studio-types").Image | undefined;
|
|
45
47
|
createdAt: string;
|
|
@@ -58,16 +60,10 @@ export declare const useMockCart: ({ apiUrl, appId, enabled, limit, }: UseMockCa
|
|
|
58
60
|
};
|
|
59
61
|
};
|
|
60
62
|
sellingPlanAllocation: {
|
|
61
|
-
priceAdjustments: {
|
|
62
|
-
perDeliveryPrice:
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
};
|
|
66
|
-
price: {
|
|
67
|
-
amount: number;
|
|
68
|
-
currencyCode: string;
|
|
69
|
-
};
|
|
70
|
-
};
|
|
63
|
+
priceAdjustments: [{
|
|
64
|
+
perDeliveryPrice: Money;
|
|
65
|
+
price: Money;
|
|
66
|
+
}];
|
|
71
67
|
sellingPlan: {
|
|
72
68
|
id: string;
|
|
73
69
|
name: string;
|
|
@@ -76,12 +72,64 @@ export declare const useMockCart: ({ apiUrl, appId, enabled, limit, }: UseMockCa
|
|
|
76
72
|
} | undefined;
|
|
77
73
|
}[];
|
|
78
74
|
discountAllocations: {
|
|
79
|
-
targetType:
|
|
75
|
+
targetType: DiscountApplicationTargetType;
|
|
80
76
|
discountedAmount: {
|
|
81
77
|
amount: string;
|
|
78
|
+
currencyCode: string;
|
|
82
79
|
};
|
|
83
80
|
code: string;
|
|
84
81
|
}[];
|
|
82
|
+
delivery: {
|
|
83
|
+
addresses: {
|
|
84
|
+
selected: boolean;
|
|
85
|
+
oneTimeUse: boolean;
|
|
86
|
+
id: string;
|
|
87
|
+
address: {
|
|
88
|
+
address1: string;
|
|
89
|
+
city: string;
|
|
90
|
+
countryCode: string;
|
|
91
|
+
};
|
|
92
|
+
}[];
|
|
93
|
+
};
|
|
94
|
+
deliveryGroups: {
|
|
95
|
+
id: string;
|
|
96
|
+
deliveryOptions: {
|
|
97
|
+
code: string;
|
|
98
|
+
handle: string;
|
|
99
|
+
title: string;
|
|
100
|
+
deliveryMethodType: string;
|
|
101
|
+
description: string;
|
|
102
|
+
estimatedCost: {
|
|
103
|
+
amount: string;
|
|
104
|
+
currencyCode: string;
|
|
105
|
+
};
|
|
106
|
+
}[];
|
|
107
|
+
selectedDeliveryOption: {
|
|
108
|
+
code: string;
|
|
109
|
+
handle: string;
|
|
110
|
+
title: string;
|
|
111
|
+
deliveryMethodType: string;
|
|
112
|
+
description: string;
|
|
113
|
+
estimatedCost: {
|
|
114
|
+
amount: string;
|
|
115
|
+
currencyCode: string;
|
|
116
|
+
};
|
|
117
|
+
};
|
|
118
|
+
}[];
|
|
119
|
+
cost: {
|
|
120
|
+
subtotalAmount: {
|
|
121
|
+
amount: string;
|
|
122
|
+
currencyCode: string;
|
|
123
|
+
};
|
|
124
|
+
totalAmount: {
|
|
125
|
+
amount: string;
|
|
126
|
+
currencyCode: string;
|
|
127
|
+
};
|
|
128
|
+
totalTaxAmount: {
|
|
129
|
+
amount: string;
|
|
130
|
+
currencyCode: string;
|
|
131
|
+
};
|
|
132
|
+
};
|
|
85
133
|
attributes: {
|
|
86
134
|
key: string;
|
|
87
135
|
value: string;
|
|
@@ -95,6 +143,15 @@ export declare const useMockCart: ({ apiUrl, appId, enabled, limit, }: UseMockCa
|
|
|
95
143
|
lastCharacters: string;
|
|
96
144
|
amountUsed: {
|
|
97
145
|
amount: string;
|
|
146
|
+
currencyCode: string;
|
|
147
|
+
};
|
|
148
|
+
balance: {
|
|
149
|
+
amount: string;
|
|
150
|
+
currencyCode: string;
|
|
151
|
+
};
|
|
152
|
+
presentmentAmountUsed: {
|
|
153
|
+
amount: string;
|
|
154
|
+
currencyCode: string;
|
|
98
155
|
};
|
|
99
156
|
}[];
|
|
100
157
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-mock-cart.d.ts","sourceRoot":"","sources":["../../../components/hooks/use-mock-cart.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"use-mock-cart.d.ts","sourceRoot":"","sources":["../../../components/hooks/use-mock-cart.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,6BAA6B,EAAE,MAAM,kBAAkB,CAAA;AAsLhF,KAAK,iBAAiB,GAAG;IACvB,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAED,eAAO,MAAM,WAAW,uCAKrB,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sCAzGc,KAAK;2BAChB,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0I3B,CAAA"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
import { getCalculatedCartData } from "../../lib/cart.util";
|
|
2
3
|
import { getIdFromGid } from "../../lib/utils";
|
|
3
4
|
import { useProducts } from "./use-products";
|
|
5
|
+
import { DiscountApplicationTargetType } from "app-studio-types";
|
|
4
6
|
const cartMock = {
|
|
5
7
|
attributes: [{ key: "tapcart_id", value: "123" }],
|
|
6
8
|
currency: "USD",
|
|
@@ -11,8 +13,8 @@ const cartMock = {
|
|
|
11
13
|
subtotal: 0,
|
|
12
14
|
discountAllocations: [
|
|
13
15
|
{
|
|
14
|
-
targetType:
|
|
15
|
-
discountedAmount: { amount: "10.00" },
|
|
16
|
+
targetType: DiscountApplicationTargetType.ShippingLine,
|
|
17
|
+
discountedAmount: { amount: "10.00", currencyCode: "USD" },
|
|
16
18
|
code: "FREE_SHIPPING",
|
|
17
19
|
},
|
|
18
20
|
],
|
|
@@ -20,7 +22,9 @@ const cartMock = {
|
|
|
20
22
|
{
|
|
21
23
|
id: "gid://shopify/GiftCard/1",
|
|
22
24
|
lastCharacters: "1234",
|
|
23
|
-
amountUsed: { amount: "10.00" },
|
|
25
|
+
amountUsed: { amount: "10.00", currencyCode: "USD" },
|
|
26
|
+
balance: { amount: "40.00", currencyCode: "USD" },
|
|
27
|
+
presentmentAmountUsed: { amount: "10.00", currencyCode: "USD" },
|
|
24
28
|
},
|
|
25
29
|
],
|
|
26
30
|
};
|
|
@@ -55,16 +59,18 @@ const transformCart = ({ products, cartOrigin = cartMock, }) => {
|
|
|
55
59
|
}
|
|
56
60
|
const sellingPlanAllocation = i === 0
|
|
57
61
|
? {
|
|
58
|
-
priceAdjustments:
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
+
priceAdjustments: [
|
|
63
|
+
{
|
|
64
|
+
perDeliveryPrice: {
|
|
65
|
+
amount: price,
|
|
66
|
+
currencyCode: "USD",
|
|
67
|
+
},
|
|
68
|
+
price: {
|
|
69
|
+
amount: price,
|
|
70
|
+
currencyCode: "USD",
|
|
71
|
+
},
|
|
62
72
|
},
|
|
63
|
-
|
|
64
|
-
amount: price,
|
|
65
|
-
currencyCode: "USD",
|
|
66
|
-
},
|
|
67
|
-
},
|
|
73
|
+
],
|
|
68
74
|
sellingPlan: {
|
|
69
75
|
id: "gid://shopify/SellingPlan/123",
|
|
70
76
|
name: "Delivery every 30 Days",
|
|
@@ -73,6 +79,7 @@ const transformCart = ({ products, cartOrigin = cartMock, }) => {
|
|
|
73
79
|
}
|
|
74
80
|
: undefined;
|
|
75
81
|
return {
|
|
82
|
+
id: `item-${i}`,
|
|
76
83
|
discounts,
|
|
77
84
|
productId,
|
|
78
85
|
quantity: 1,
|
|
@@ -84,15 +91,62 @@ const transformCart = ({ products, cartOrigin = cartMock, }) => {
|
|
|
84
91
|
};
|
|
85
92
|
});
|
|
86
93
|
const orderLevelDiscount = {
|
|
87
|
-
targetType:
|
|
88
|
-
discountedAmount: {
|
|
94
|
+
targetType: DiscountApplicationTargetType.LineItem,
|
|
95
|
+
discountedAmount: {
|
|
96
|
+
amount: (subtotal / 10).toString(),
|
|
97
|
+
currencyCode: "USD",
|
|
98
|
+
},
|
|
89
99
|
code: "10_OFF_ORDER",
|
|
90
100
|
};
|
|
101
|
+
const delivery = {
|
|
102
|
+
addresses: [
|
|
103
|
+
{
|
|
104
|
+
selected: true,
|
|
105
|
+
oneTimeUse: false,
|
|
106
|
+
id: "mock-delivery-address-id",
|
|
107
|
+
address: {
|
|
108
|
+
address1: "123 Mock St",
|
|
109
|
+
city: "Mock City",
|
|
110
|
+
countryCode: "US",
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
],
|
|
114
|
+
};
|
|
115
|
+
const deliveryGroups = [
|
|
116
|
+
{
|
|
117
|
+
id: "mock-delivery-group-id",
|
|
118
|
+
deliveryOptions: [
|
|
119
|
+
{
|
|
120
|
+
code: "mock-code",
|
|
121
|
+
handle: "mock-handle",
|
|
122
|
+
title: "Mock Delivery Option",
|
|
123
|
+
deliveryMethodType: "standard",
|
|
124
|
+
description: "Mock delivery description",
|
|
125
|
+
estimatedCost: { amount: "5.00", currencyCode: "USD" },
|
|
126
|
+
},
|
|
127
|
+
],
|
|
128
|
+
selectedDeliveryOption: {
|
|
129
|
+
code: "mock-code",
|
|
130
|
+
handle: "mock-handle",
|
|
131
|
+
title: "Mock Delivery Option",
|
|
132
|
+
deliveryMethodType: "standard",
|
|
133
|
+
description: "Mock delivery description",
|
|
134
|
+
estimatedCost: { amount: "5.00", currencyCode: "USD" },
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
];
|
|
138
|
+
const cost = {
|
|
139
|
+
subtotalAmount: { amount: subtotal.toString(), currencyCode: "USD" },
|
|
140
|
+
totalAmount: { amount: (subtotal + 5).toString(), currencyCode: "USD" },
|
|
141
|
+
totalTaxAmount: { amount: "0.00", currencyCode: "USD" },
|
|
142
|
+
};
|
|
91
143
|
return Object.assign(Object.assign({}, cartOrigin), { subtotal,
|
|
92
144
|
items, discountAllocations: [
|
|
93
145
|
...cartOrigin.discountAllocations,
|
|
94
146
|
orderLevelDiscount,
|
|
95
|
-
]
|
|
147
|
+
], delivery,
|
|
148
|
+
deliveryGroups,
|
|
149
|
+
cost });
|
|
96
150
|
};
|
|
97
151
|
export const useMockCart = ({ apiUrl, appId, enabled = true, limit = 1, }) => {
|
|
98
152
|
const { products, error: productsError, isLoading: productsLoading, } = useProducts({
|
|
@@ -116,6 +170,6 @@ export const useMockCart = ({ apiUrl, appId, enabled = true, limit = 1, }) => {
|
|
|
116
170
|
return {
|
|
117
171
|
error: productsError,
|
|
118
172
|
isLoading: productsLoading,
|
|
119
|
-
cart,
|
|
173
|
+
cart: Object.assign(Object.assign({}, cart), { calculatedData: getCalculatedCartData(cart) }),
|
|
120
174
|
};
|
|
121
175
|
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { EnrichedCart, CartCalculatedDiscount, CartCalculatedAppliedGiftCard } from "app-studio-types";
|
|
2
|
+
export declare const isOrderLevelDiscount: (code: string, cart: EnrichedCart) => boolean;
|
|
3
|
+
export declare const isLineItemDiscount: (code: string, cart: EnrichedCart) => boolean;
|
|
4
|
+
export type CalculatedData = {
|
|
5
|
+
orderAndLineItemDiscounts: CartCalculatedDiscount[];
|
|
6
|
+
appliedGiftCards: CartCalculatedAppliedGiftCard[];
|
|
7
|
+
isFreeShipping: boolean;
|
|
8
|
+
discountsTotalAmount: number;
|
|
9
|
+
giftCardsTotalAmount: number;
|
|
10
|
+
salesAmount: number;
|
|
11
|
+
totalCompareAtPrice: number;
|
|
12
|
+
totalDiscountedPrice: number;
|
|
13
|
+
};
|
|
14
|
+
export declare const DEFAULT_CALCULATED_DATA: CalculatedData;
|
|
15
|
+
export declare const getData: (cart: EnrichedCart) => CalculatedData;
|
|
16
|
+
//# sourceMappingURL=calculated-cart-values.util.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"calculated-cart-values.util.d.ts","sourceRoot":"","sources":["../../../../components/libs/cart/calculated-cart-values.util.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,sBAAsB,EACtB,6BAA6B,EAC9B,MAAM,kBAAkB,CAAA;AAuCzB,eAAO,MAAM,oBAAoB,SAAU,MAAM,QAAQ,YAAY,YAGpE,CAAA;AAED,eAAO,MAAM,kBAAkB,SAAU,MAAM,QAAQ,YAAY,YAGlE,CAAA;AAgGD,MAAM,MAAM,cAAc,GAAG;IAC3B,yBAAyB,EAAE,sBAAsB,EAAE,CAAA;IACnD,gBAAgB,EAAE,6BAA6B,EAAE,CAAA;IACjD,cAAc,EAAE,OAAO,CAAA;IACvB,oBAAoB,EAAE,MAAM,CAAA;IAC5B,oBAAoB,EAAE,MAAM,CAAA;IAC5B,WAAW,EAAE,MAAM,CAAA;IACnB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,oBAAoB,EAAE,MAAM,CAAA;CAC7B,CAAA;AAED,eAAO,MAAM,uBAAuB,EAAE,cASrC,CAAA;AAED,eAAO,MAAM,OAAO,SAAU,YAAY,KAAG,cA4B5C,CAAA"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
const getOrderLevelDiscounts = (cart) => {
|
|
2
|
+
var _a;
|
|
3
|
+
const discountMap = (_a = cart.discountAllocations) === null || _a === void 0 ? void 0 : _a.filter((discount) => discount.targetType !== "SHIPPING_LINE").reduce((acc, discount) => {
|
|
4
|
+
var _a;
|
|
5
|
+
const code = (_a = discount.code) !== null && _a !== void 0 ? _a : "unknown";
|
|
6
|
+
if (!acc[code]) {
|
|
7
|
+
acc[code] = 0;
|
|
8
|
+
}
|
|
9
|
+
acc[code] += parseFloat(discount.discountedAmount.amount);
|
|
10
|
+
return acc;
|
|
11
|
+
}, {});
|
|
12
|
+
if (!discountMap)
|
|
13
|
+
return [];
|
|
14
|
+
return Object.entries(discountMap)
|
|
15
|
+
.map(([code, amount]) => ({
|
|
16
|
+
id: code,
|
|
17
|
+
amount,
|
|
18
|
+
name: `Discount - ${code}`,
|
|
19
|
+
type: "ORDER_LEVEL",
|
|
20
|
+
}))
|
|
21
|
+
.filter((discount) => cart.discounts.includes(discount.id));
|
|
22
|
+
};
|
|
23
|
+
const getShippingDiscounts = (cart) => {
|
|
24
|
+
var _a;
|
|
25
|
+
if (!(cart === null || cart === void 0 ? void 0 : cart.discountAllocations))
|
|
26
|
+
return [];
|
|
27
|
+
return (_a = cart.discountAllocations) === null || _a === void 0 ? void 0 : _a.filter((discount) => discount.targetType === "SHIPPING_LINE").map((discount) => ({
|
|
28
|
+
amount: discount.discountedAmount.amount,
|
|
29
|
+
code: discount.code,
|
|
30
|
+
type: discount.targetType,
|
|
31
|
+
}));
|
|
32
|
+
};
|
|
33
|
+
export const isOrderLevelDiscount = (code, cart) => {
|
|
34
|
+
const orderLevelDiscounts = getOrderLevelDiscounts(cart);
|
|
35
|
+
return orderLevelDiscounts.some((discount) => discount.id === code);
|
|
36
|
+
};
|
|
37
|
+
export const isLineItemDiscount = (code, cart) => {
|
|
38
|
+
const lineItemDiscounts = getLineItemDiscounts(cart);
|
|
39
|
+
return lineItemDiscounts.some((discount) => discount.id === code);
|
|
40
|
+
};
|
|
41
|
+
const getAppliedGiftCards = (cart) => {
|
|
42
|
+
var _a;
|
|
43
|
+
return (_a = cart.appliedGiftCards) === null || _a === void 0 ? void 0 : _a.map((giftCard) => ({
|
|
44
|
+
id: giftCard.id,
|
|
45
|
+
amount: +giftCard.amountUsed.amount,
|
|
46
|
+
name: `Gift Card - ${giftCard.lastCharacters}`,
|
|
47
|
+
}));
|
|
48
|
+
};
|
|
49
|
+
const getSalesAmount = (cart) => {
|
|
50
|
+
var _a;
|
|
51
|
+
return (_a = cart.items) === null || _a === void 0 ? void 0 : _a.reduce((acc, item) => {
|
|
52
|
+
var _a, _b, _c, _d;
|
|
53
|
+
const compareAtPrice = +(((_b = (_a = item.variantDetails) === null || _a === void 0 ? void 0 : _a.compareAtPrice) === null || _b === void 0 ? void 0 : _b.amount) || 0);
|
|
54
|
+
const price = +(((_d = (_c = item.variantDetails) === null || _c === void 0 ? void 0 : _c.price) === null || _d === void 0 ? void 0 : _d.amount) || 0);
|
|
55
|
+
const quantity = item.quantity || 1;
|
|
56
|
+
if (compareAtPrice && compareAtPrice > price) {
|
|
57
|
+
return acc + (compareAtPrice - price) * quantity;
|
|
58
|
+
}
|
|
59
|
+
return acc;
|
|
60
|
+
}, 0);
|
|
61
|
+
};
|
|
62
|
+
const getLineItemDiscounts = (cart) => {
|
|
63
|
+
var _a, _b;
|
|
64
|
+
const discountMap = (_a = cart.items) === null || _a === void 0 ? void 0 : _a.reduce((acc, item) => {
|
|
65
|
+
var _a;
|
|
66
|
+
(_a = item === null || item === void 0 ? void 0 : item.discounts) === null || _a === void 0 ? void 0 : _a.forEach((discount) => {
|
|
67
|
+
const code = discount === null || discount === void 0 ? void 0 : discount.code;
|
|
68
|
+
if (!code)
|
|
69
|
+
return;
|
|
70
|
+
if (!acc[code]) {
|
|
71
|
+
acc[code] = { amount: 0, type: discount.type };
|
|
72
|
+
}
|
|
73
|
+
acc[code].amount += discount.amount;
|
|
74
|
+
});
|
|
75
|
+
return acc;
|
|
76
|
+
}, {});
|
|
77
|
+
if (!discountMap)
|
|
78
|
+
return [];
|
|
79
|
+
return (_b = Object.entries(discountMap)) === null || _b === void 0 ? void 0 : _b.map(([code, { amount, type }]) => ({
|
|
80
|
+
id: code,
|
|
81
|
+
name: `Discount - ${code}`,
|
|
82
|
+
amount,
|
|
83
|
+
type,
|
|
84
|
+
})).filter((discount) => cart.discounts.includes(discount.id));
|
|
85
|
+
};
|
|
86
|
+
const getDiscountsTotalAmount = (orderAndLineItemDiscounts) => {
|
|
87
|
+
return orderAndLineItemDiscounts === null || orderAndLineItemDiscounts === void 0 ? void 0 : orderAndLineItemDiscounts.reduce((acc, discount) => acc + +discount.amount, 0);
|
|
88
|
+
};
|
|
89
|
+
const getGiftCardsTotalAmount = (appliedGiftCards) => {
|
|
90
|
+
return appliedGiftCards === null || appliedGiftCards === void 0 ? void 0 : appliedGiftCards.reduce((acc, giftCard) => acc + +giftCard.amount, 0);
|
|
91
|
+
};
|
|
92
|
+
const getTotalCompareAtPrice = (cart) => {
|
|
93
|
+
var _a;
|
|
94
|
+
return (_a = cart.items) === null || _a === void 0 ? void 0 : _a.reduce((acc, item) => {
|
|
95
|
+
var _a, _b, _c, _d;
|
|
96
|
+
const compareAtPrice = ((_b = (_a = item.variantDetails) === null || _a === void 0 ? void 0 : _a.compareAtPrice) === null || _b === void 0 ? void 0 : _b.amount) ||
|
|
97
|
+
((_d = (_c = item.variantDetails) === null || _c === void 0 ? void 0 : _c.price) === null || _d === void 0 ? void 0 : _d.amount);
|
|
98
|
+
const quantity = item.quantity || 1;
|
|
99
|
+
return acc + +(compareAtPrice || 0) * quantity;
|
|
100
|
+
}, 0);
|
|
101
|
+
};
|
|
102
|
+
const getTotalDiscountedPrice = (totalCompareAtPrice, discountsTotalAmount, salesAmount, giftCardsTotalAmount) => {
|
|
103
|
+
const total = (totalCompareAtPrice === undefined || isNaN(totalCompareAtPrice)
|
|
104
|
+
? 0
|
|
105
|
+
: totalCompareAtPrice) -
|
|
106
|
+
(discountsTotalAmount === undefined || isNaN(discountsTotalAmount)
|
|
107
|
+
? 0
|
|
108
|
+
: discountsTotalAmount) -
|
|
109
|
+
(salesAmount === undefined || isNaN(salesAmount) ? 0 : salesAmount) -
|
|
110
|
+
(giftCardsTotalAmount === undefined || isNaN(giftCardsTotalAmount)
|
|
111
|
+
? 0
|
|
112
|
+
: giftCardsTotalAmount);
|
|
113
|
+
return isNaN(total) ? 0 : total;
|
|
114
|
+
};
|
|
115
|
+
export const DEFAULT_CALCULATED_DATA = {
|
|
116
|
+
orderAndLineItemDiscounts: [],
|
|
117
|
+
appliedGiftCards: [],
|
|
118
|
+
isFreeShipping: false,
|
|
119
|
+
discountsTotalAmount: 0,
|
|
120
|
+
salesAmount: 0,
|
|
121
|
+
giftCardsTotalAmount: 0,
|
|
122
|
+
totalCompareAtPrice: 0,
|
|
123
|
+
totalDiscountedPrice: 0,
|
|
124
|
+
};
|
|
125
|
+
export const getData = (cart) => {
|
|
126
|
+
const orderAndLineItemDiscounts = getOrderLevelDiscounts(cart).concat(getLineItemDiscounts(cart));
|
|
127
|
+
const appliedGiftCards = getAppliedGiftCards(cart);
|
|
128
|
+
const isFreeShipping = getShippingDiscounts(cart).length > 0;
|
|
129
|
+
const discountsTotalAmount = getDiscountsTotalAmount(orderAndLineItemDiscounts);
|
|
130
|
+
const giftCardsTotalAmount = getGiftCardsTotalAmount(appliedGiftCards);
|
|
131
|
+
const salesAmount = getSalesAmount(cart);
|
|
132
|
+
const totalCompareAtPrice = getTotalCompareAtPrice(cart);
|
|
133
|
+
const totalDiscountedPrice = getTotalDiscountedPrice(totalCompareAtPrice, discountsTotalAmount, salesAmount, giftCardsTotalAmount);
|
|
134
|
+
return {
|
|
135
|
+
orderAndLineItemDiscounts,
|
|
136
|
+
appliedGiftCards,
|
|
137
|
+
isFreeShipping,
|
|
138
|
+
discountsTotalAmount,
|
|
139
|
+
giftCardsTotalAmount,
|
|
140
|
+
salesAmount,
|
|
141
|
+
totalCompareAtPrice,
|
|
142
|
+
totalDiscountedPrice,
|
|
143
|
+
};
|
|
144
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"calculated-cart-values.util.test.d.ts","sourceRoot":"","sources":["../../../../components/libs/cart/calculated-cart-values.util.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { getData } from "./calculated-cart-values.util";
|
|
2
|
+
import { DiscountApplicationTargetType } from "app-studio-types";
|
|
3
|
+
const baseCartData = {
|
|
4
|
+
id: "cart123",
|
|
5
|
+
subtotal: 100.0,
|
|
6
|
+
currency: "USD",
|
|
7
|
+
discounts: [],
|
|
8
|
+
attributes: [],
|
|
9
|
+
note: "",
|
|
10
|
+
items: [],
|
|
11
|
+
discountAllocations: [],
|
|
12
|
+
appliedGiftCards: [],
|
|
13
|
+
delivery: {
|
|
14
|
+
addresses: [],
|
|
15
|
+
},
|
|
16
|
+
deliveryGroups: [],
|
|
17
|
+
cost: {
|
|
18
|
+
subtotalAmount: { amount: "0", currencyCode: "" },
|
|
19
|
+
totalAmount: { amount: "0", currencyCode: "" },
|
|
20
|
+
totalTaxAmount: { amount: "0", currencyCode: "" },
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
describe("cart-provider.util", () => {
|
|
24
|
+
describe("getData", () => {
|
|
25
|
+
it("should calculate order level discounts correctly", () => {
|
|
26
|
+
const mockCart = Object.assign(Object.assign({}, baseCartData), { discounts: ["DISCOUNT10"], items: [], discountAllocations: [
|
|
27
|
+
{
|
|
28
|
+
targetType: DiscountApplicationTargetType.LineItem,
|
|
29
|
+
discountedAmount: { amount: "10.00", currencyCode: "USD" },
|
|
30
|
+
code: "DISCOUNT10",
|
|
31
|
+
},
|
|
32
|
+
], appliedGiftCards: [], deliveryGroups: [] });
|
|
33
|
+
const result = getData(mockCart);
|
|
34
|
+
expect(result.orderAndLineItemDiscounts).toHaveLength(1);
|
|
35
|
+
expect(result.orderAndLineItemDiscounts[0]).toEqual({
|
|
36
|
+
id: "DISCOUNT10",
|
|
37
|
+
amount: 10,
|
|
38
|
+
name: "Discount - DISCOUNT10",
|
|
39
|
+
type: "ORDER_LEVEL",
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
it("should calculate gift cards correctly", () => {
|
|
43
|
+
const mockCart = Object.assign(Object.assign({}, baseCartData), { discounts: [], items: [], discountAllocations: [], appliedGiftCards: [
|
|
44
|
+
{
|
|
45
|
+
id: "giftcard1",
|
|
46
|
+
amountUsed: { amount: "25.00", currencyCode: "USD" },
|
|
47
|
+
balance: { amount: "75.00", currencyCode: "USD" },
|
|
48
|
+
lastCharacters: "1234",
|
|
49
|
+
presentmentAmountUsed: { amount: "25.00", currencyCode: "USD" },
|
|
50
|
+
},
|
|
51
|
+
], deliveryGroups: [] });
|
|
52
|
+
const result = getData(mockCart);
|
|
53
|
+
expect(result.appliedGiftCards).toHaveLength(1);
|
|
54
|
+
expect(result.appliedGiftCards[0]).toEqual({
|
|
55
|
+
id: "giftcard1",
|
|
56
|
+
amount: 25,
|
|
57
|
+
name: "Gift Card - 1234",
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
it("should calculate sales amount correctly", () => {
|
|
61
|
+
const mockCart = Object.assign(Object.assign({}, baseCartData), { discounts: [], items: [
|
|
62
|
+
{
|
|
63
|
+
id: "line1",
|
|
64
|
+
quantity: 2,
|
|
65
|
+
productId: "prod1",
|
|
66
|
+
variantId: "var1",
|
|
67
|
+
productDetails: {},
|
|
68
|
+
variantDetails: {
|
|
69
|
+
compareAtPrice: { amount: "20.00", currencyCode: "USD" },
|
|
70
|
+
price: { amount: "15.00", currencyCode: "USD" },
|
|
71
|
+
},
|
|
72
|
+
discounts: [],
|
|
73
|
+
cost: { totalAmount: { amount: "30.00", currencyCode: "USD" } },
|
|
74
|
+
},
|
|
75
|
+
], discountAllocations: [], appliedGiftCards: [], deliveryGroups: [] });
|
|
76
|
+
const result = getData(mockCart);
|
|
77
|
+
expect(result.salesAmount).toBe(10); // (20-15) * 2
|
|
78
|
+
});
|
|
79
|
+
it("should detect free shipping", () => {
|
|
80
|
+
const mockCart = Object.assign(Object.assign({}, baseCartData), { discounts: [], items: [], discountAllocations: [
|
|
81
|
+
{
|
|
82
|
+
targetType: DiscountApplicationTargetType.ShippingLine,
|
|
83
|
+
discountedAmount: { amount: "5.00", currencyCode: "USD" },
|
|
84
|
+
code: "FREESHIP",
|
|
85
|
+
},
|
|
86
|
+
], appliedGiftCards: [], deliveryGroups: [] });
|
|
87
|
+
const result = getData(mockCart);
|
|
88
|
+
expect(result.isFreeShipping).toBe(true);
|
|
89
|
+
});
|
|
90
|
+
it("should calculate total discounted price correctly", () => {
|
|
91
|
+
const mockCart = Object.assign(Object.assign({}, baseCartData), { discounts: ["DISCOUNT10"], items: [
|
|
92
|
+
{
|
|
93
|
+
id: "line1",
|
|
94
|
+
quantity: 1,
|
|
95
|
+
productId: "prod1",
|
|
96
|
+
variantId: "var1",
|
|
97
|
+
productDetails: {},
|
|
98
|
+
variantDetails: {
|
|
99
|
+
compareAtPrice: { amount: "100.00", currencyCode: "USD" },
|
|
100
|
+
price: { amount: "80.00", currencyCode: "USD" },
|
|
101
|
+
},
|
|
102
|
+
discounts: [
|
|
103
|
+
{
|
|
104
|
+
amount: 10,
|
|
105
|
+
type: "LINE_ITEM",
|
|
106
|
+
code: "DISCOUNT10",
|
|
107
|
+
},
|
|
108
|
+
],
|
|
109
|
+
cost: { totalAmount: { amount: "80.00", currencyCode: "USD" } },
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
id: "line2",
|
|
113
|
+
quantity: 1,
|
|
114
|
+
productId: "prod2",
|
|
115
|
+
variantId: "var2",
|
|
116
|
+
productDetails: {},
|
|
117
|
+
variantDetails: {
|
|
118
|
+
compareAtPrice: { amount: "100.00", currencyCode: "USD" },
|
|
119
|
+
price: { amount: "80.00", currencyCode: "USD" },
|
|
120
|
+
},
|
|
121
|
+
discounts: [
|
|
122
|
+
{
|
|
123
|
+
amount: 10,
|
|
124
|
+
type: "LINE_ITEM",
|
|
125
|
+
code: "DISCOUNT10",
|
|
126
|
+
},
|
|
127
|
+
],
|
|
128
|
+
cost: { totalAmount: { amount: "80.00", currencyCode: "USD" } },
|
|
129
|
+
},
|
|
130
|
+
], discountAllocations: [
|
|
131
|
+
{
|
|
132
|
+
targetType: DiscountApplicationTargetType.LineItem,
|
|
133
|
+
discountedAmount: { amount: "10.00", currencyCode: "USD" },
|
|
134
|
+
code: "DISCOUNT10",
|
|
135
|
+
},
|
|
136
|
+
], appliedGiftCards: [
|
|
137
|
+
{
|
|
138
|
+
id: "giftcard1",
|
|
139
|
+
amountUsed: { amount: "5.00", currencyCode: "USD" },
|
|
140
|
+
balance: { amount: "95.00", currencyCode: "USD" },
|
|
141
|
+
lastCharacters: "1234",
|
|
142
|
+
presentmentAmountUsed: { amount: "5.00", currencyCode: "USD" },
|
|
143
|
+
},
|
|
144
|
+
], deliveryGroups: [] });
|
|
145
|
+
const result = getData(mockCart);
|
|
146
|
+
// 100 (compare) - 10 (discount) - 20 (sale) - 5 (gift card) = 65
|
|
147
|
+
expect(result.totalDiscountedPrice).toBe(125);
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=calculatedCartValues.util.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"calculatedCartValues.util.d.ts","sourceRoot":"","sources":["../../../../components/libs/cart/calculatedCartValues.util.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { cn, cva, getColor, getBackgroundAndPaddingStyle, getBorderStyle, getBorderSidesStyle, getTextStyle, getVerticalAlignmentStyle, getBackgroundAndSpacingStyle, getIdFromGid, productGidFromId, variantGidFromId, getPaddingStyle, getMarginStyle, getVerticalAlignment, mapFlexToAlignment, formatRelativeTime, stringRatioToInt, getOverlayStyle, throttleFunction, getDestinationHandler, getProductGidsFromIds, createCollectionImageMap, isFavoriteIntegrationEnabled, getSpaceBetween, getGridSpacing, pluralize, getInputPlaceholderTextProps, } from "./lib/utils";
|
|
2
|
+
export * from "./lib/cart.util";
|
|
2
3
|
export * from "./components/contexts/translation-context";
|
|
3
4
|
export * from "./components/hooks/use-collection";
|
|
4
5
|
export * from "./components/hooks/use-infinite-scroll";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,EAAE,EACF,GAAG,EACH,QAAQ,EACR,4BAA4B,EAC5B,cAAc,EACd,mBAAmB,EACnB,YAAY,EACZ,yBAAyB,EACzB,4BAA4B,EAC5B,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,qBAAqB,EACrB,qBAAqB,EACrB,wBAAwB,EACxB,4BAA4B,EAC5B,eAAe,EACf,cAAc,EACd,SAAS,EACT,4BAA4B,GAC7B,MAAM,aAAa,CAAA;AACpB,cAAc,2CAA2C,CAAA;AACzD,cAAc,mCAAmC,CAAA;AACjD,cAAc,wCAAwC,CAAA;AACtD,cAAc,wCAAwC,CAAA;AACtD,cAAc,iCAAiC,CAAA;AAC/C,cAAc,sCAAsC,CAAA;AACpD,cAAc,yCAAyC,CAAA;AACvD,cAAc,oCAAoC,CAAA;AAClD,cAAc,wCAAwC,CAAA;AACtD,cAAc,6BAA6B,CAAA;AAC3C,cAAc,sCAAsC,CAAA;AACpD,cAAc,oDAAoD,CAAA;AAClE,cAAc,kCAAkC,CAAA;AAChD,cAAc,2BAA2B,CAAA;AACzC,cAAc,kCAAkC,CAAA;AAChD,cAAc,8BAA8B,CAAA;AAC5C,cAAc,uBAAuB,CAAA;AACrC,cAAc,wBAAwB,CAAA;AACtC,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AACxC,cAAc,sBAAsB,CAAA;AACpC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,2BAA2B,CAAA;AACzC,cAAc,wBAAwB,CAAA;AACtC,cAAc,0BAA0B,CAAA;AACxC,cAAc,+BAA+B,CAAA;AAC7C,cAAc,0BAA0B,CAAA;AACxC,cAAc,sBAAsB,CAAA;AACpC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,sBAAsB,CAAA;AACpC,cAAc,uBAAuB,CAAA;AACrC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,uBAAuB,CAAA;AACrC,cAAc,sCAAsC,CAAA;AACpD,cAAc,uBAAuB,CAAA;AACrC,cAAc,uBAAuB,CAAA;AACrC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,iCAAiC,CAAA;AAC/C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,2BAA2B,CAAA;AACzC,cAAc,2BAA2B,CAAA;AACzC,cAAc,0BAA0B,CAAA;AACxC,cAAc,wBAAwB,CAAA;AACtC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,8BAA8B,CAAA;AAC5C,cAAc,wBAAwB,CAAA;AACtC,cAAc,sBAAsB,CAAA;AACpC,cAAc,sBAAsB,CAAA;AACpC,cAAc,0BAA0B,CAAA;AACxC,cAAc,uBAAuB,CAAA;AACrC,cAAc,yBAAyB,CAAA;AACvC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,wBAAwB,CAAA;AACtC,cAAc,2BAA2B,CAAA;AACzC,cAAc,uBAAuB,CAAA;AACrC,cAAc,gCAAgC,CAAA;AAC9C,cAAc,0BAA0B,CAAA;AACxC,cAAc,iCAAiC,CAAA;AAC/C,cAAc,sBAAsB,CAAA;AACpC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,kDAAkD,CAAA;AAChE,cAAc,gCAAgC,CAAA;AAC9C,cAAc,oCAAoC,CAAA;AAClD,cAAc,mCAAmC,CAAA;AACjD,cAAc,aAAa,CAAA;AAC3B,cAAc,6CAA6C,CAAA;AAC3D,cAAc,kDAAkD,CAAA;AAChE,cAAc,qBAAqB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,EAAE,EACF,GAAG,EACH,QAAQ,EACR,4BAA4B,EAC5B,cAAc,EACd,mBAAmB,EACnB,YAAY,EACZ,yBAAyB,EACzB,4BAA4B,EAC5B,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,qBAAqB,EACrB,qBAAqB,EACrB,wBAAwB,EACxB,4BAA4B,EAC5B,eAAe,EACf,cAAc,EACd,SAAS,EACT,4BAA4B,GAC7B,MAAM,aAAa,CAAA;AACpB,cAAc,iBAAiB,CAAA;AAC/B,cAAc,2CAA2C,CAAA;AACzD,cAAc,mCAAmC,CAAA;AACjD,cAAc,wCAAwC,CAAA;AACtD,cAAc,wCAAwC,CAAA;AACtD,cAAc,iCAAiC,CAAA;AAC/C,cAAc,sCAAsC,CAAA;AACpD,cAAc,yCAAyC,CAAA;AACvD,cAAc,oCAAoC,CAAA;AAClD,cAAc,wCAAwC,CAAA;AACtD,cAAc,6BAA6B,CAAA;AAC3C,cAAc,sCAAsC,CAAA;AACpD,cAAc,oDAAoD,CAAA;AAClE,cAAc,kCAAkC,CAAA;AAChD,cAAc,2BAA2B,CAAA;AACzC,cAAc,kCAAkC,CAAA;AAChD,cAAc,8BAA8B,CAAA;AAC5C,cAAc,uBAAuB,CAAA;AACrC,cAAc,wBAAwB,CAAA;AACtC,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AACxC,cAAc,sBAAsB,CAAA;AACpC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,2BAA2B,CAAA;AACzC,cAAc,wBAAwB,CAAA;AACtC,cAAc,0BAA0B,CAAA;AACxC,cAAc,+BAA+B,CAAA;AAC7C,cAAc,0BAA0B,CAAA;AACxC,cAAc,sBAAsB,CAAA;AACpC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,sBAAsB,CAAA;AACpC,cAAc,uBAAuB,CAAA;AACrC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,uBAAuB,CAAA;AACrC,cAAc,sCAAsC,CAAA;AACpD,cAAc,uBAAuB,CAAA;AACrC,cAAc,uBAAuB,CAAA;AACrC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,iCAAiC,CAAA;AAC/C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,2BAA2B,CAAA;AACzC,cAAc,2BAA2B,CAAA;AACzC,cAAc,0BAA0B,CAAA;AACxC,cAAc,wBAAwB,CAAA;AACtC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,8BAA8B,CAAA;AAC5C,cAAc,wBAAwB,CAAA;AACtC,cAAc,sBAAsB,CAAA;AACpC,cAAc,sBAAsB,CAAA;AACpC,cAAc,0BAA0B,CAAA;AACxC,cAAc,uBAAuB,CAAA;AACrC,cAAc,yBAAyB,CAAA;AACvC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,wBAAwB,CAAA;AACtC,cAAc,2BAA2B,CAAA;AACzC,cAAc,uBAAuB,CAAA;AACrC,cAAc,gCAAgC,CAAA;AAC9C,cAAc,0BAA0B,CAAA;AACxC,cAAc,iCAAiC,CAAA;AAC/C,cAAc,sBAAsB,CAAA;AACpC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,kDAAkD,CAAA;AAChE,cAAc,gCAAgC,CAAA;AAC9C,cAAc,oCAAoC,CAAA;AAClD,cAAc,mCAAmC,CAAA;AACjD,cAAc,aAAa,CAAA;AAC3B,cAAc,6CAA6C,CAAA;AAC3D,cAAc,kDAAkD,CAAA;AAChE,cAAc,qBAAqB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// component exports
|
|
2
2
|
export { cn, cva, getColor, getBackgroundAndPaddingStyle, getBorderStyle, getBorderSidesStyle, getTextStyle, getVerticalAlignmentStyle, getBackgroundAndSpacingStyle, getIdFromGid, productGidFromId, variantGidFromId, getPaddingStyle, getMarginStyle, getVerticalAlignment, mapFlexToAlignment, formatRelativeTime, stringRatioToInt, getOverlayStyle, throttleFunction, getDestinationHandler, getProductGidsFromIds, createCollectionImageMap, isFavoriteIntegrationEnabled, getSpaceBetween, getGridSpacing, pluralize, getInputPlaceholderTextProps, } from "./lib/utils";
|
|
3
|
+
export * from "./lib/cart.util";
|
|
3
4
|
export * from "./components/contexts/translation-context";
|
|
4
5
|
export * from "./components/hooks/use-collection";
|
|
5
6
|
export * from "./components/hooks/use-infinite-scroll";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=cart.util%20copy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cart.util copy.d.ts","sourceRoot":"","sources":["../../lib/cart.util copy.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { EnrichedCart, CartCalculatedDiscount, CartCalculatedAppliedGiftCard } from "app-studio-types";
|
|
2
|
+
export declare const isOrderLevelDiscount: (code: string, cart: EnrichedCart) => boolean;
|
|
3
|
+
export declare const isLineItemDiscount: (code: string, cart: EnrichedCart) => boolean;
|
|
4
|
+
export type CalculatedData = {
|
|
5
|
+
orderAndLineItemDiscounts: CartCalculatedDiscount[];
|
|
6
|
+
appliedGiftCards: CartCalculatedAppliedGiftCard[];
|
|
7
|
+
isFreeShipping: boolean;
|
|
8
|
+
discountsTotalAmount: number;
|
|
9
|
+
giftCardsTotalAmount: number;
|
|
10
|
+
salesAmount: number;
|
|
11
|
+
totalCompareAtPrice: number;
|
|
12
|
+
totalDiscountedPrice: number;
|
|
13
|
+
};
|
|
14
|
+
export declare const DEFAULT_CALCULATED_DATA: CalculatedData;
|
|
15
|
+
export declare const getCalculatedCartData: (cart: EnrichedCart) => CalculatedData;
|
|
16
|
+
//# sourceMappingURL=cart.util.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cart.util.d.ts","sourceRoot":"","sources":["../../lib/cart.util.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,sBAAsB,EACtB,6BAA6B,EAC9B,MAAM,kBAAkB,CAAA;AAuCzB,eAAO,MAAM,oBAAoB,SAAU,MAAM,QAAQ,YAAY,YAGpE,CAAA;AAED,eAAO,MAAM,kBAAkB,SAAU,MAAM,QAAQ,YAAY,YAGlE,CAAA;AAgGD,MAAM,MAAM,cAAc,GAAG;IAC3B,yBAAyB,EAAE,sBAAsB,EAAE,CAAA;IACnD,gBAAgB,EAAE,6BAA6B,EAAE,CAAA;IACjD,cAAc,EAAE,OAAO,CAAA;IACvB,oBAAoB,EAAE,MAAM,CAAA;IAC5B,oBAAoB,EAAE,MAAM,CAAA;IAC5B,WAAW,EAAE,MAAM,CAAA;IACnB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,oBAAoB,EAAE,MAAM,CAAA;CAC7B,CAAA;AAED,eAAO,MAAM,uBAAuB,EAAE,cASrC,CAAA;AAED,eAAO,MAAM,qBAAqB,SAAU,YAAY,KAAG,cA4B1D,CAAA"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
const getOrderLevelDiscounts = (cart) => {
|
|
2
|
+
var _a;
|
|
3
|
+
const discountMap = (_a = cart.discountAllocations) === null || _a === void 0 ? void 0 : _a.filter((discount) => discount.targetType !== "SHIPPING_LINE").reduce((acc, discount) => {
|
|
4
|
+
var _a;
|
|
5
|
+
const code = (_a = discount.code) !== null && _a !== void 0 ? _a : "unknown";
|
|
6
|
+
if (!acc[code]) {
|
|
7
|
+
acc[code] = 0;
|
|
8
|
+
}
|
|
9
|
+
acc[code] += parseFloat(discount.discountedAmount.amount);
|
|
10
|
+
return acc;
|
|
11
|
+
}, {});
|
|
12
|
+
if (!discountMap)
|
|
13
|
+
return [];
|
|
14
|
+
return Object.entries(discountMap)
|
|
15
|
+
.map(([code, amount]) => ({
|
|
16
|
+
id: code,
|
|
17
|
+
amount,
|
|
18
|
+
name: `Discount - ${code}`,
|
|
19
|
+
type: "ORDER_LEVEL",
|
|
20
|
+
}))
|
|
21
|
+
.filter((discount) => cart.discounts.includes(discount.id));
|
|
22
|
+
};
|
|
23
|
+
const getShippingDiscounts = (cart) => {
|
|
24
|
+
var _a;
|
|
25
|
+
if (!(cart === null || cart === void 0 ? void 0 : cart.discountAllocations))
|
|
26
|
+
return [];
|
|
27
|
+
return (_a = cart.discountAllocations) === null || _a === void 0 ? void 0 : _a.filter((discount) => discount.targetType === "SHIPPING_LINE").map((discount) => ({
|
|
28
|
+
amount: discount.discountedAmount.amount,
|
|
29
|
+
code: discount.code,
|
|
30
|
+
type: discount.targetType,
|
|
31
|
+
}));
|
|
32
|
+
};
|
|
33
|
+
export const isOrderLevelDiscount = (code, cart) => {
|
|
34
|
+
const orderLevelDiscounts = getOrderLevelDiscounts(cart);
|
|
35
|
+
return orderLevelDiscounts.some((discount) => discount.id === code);
|
|
36
|
+
};
|
|
37
|
+
export const isLineItemDiscount = (code, cart) => {
|
|
38
|
+
const lineItemDiscounts = getLineItemDiscounts(cart);
|
|
39
|
+
return lineItemDiscounts.some((discount) => discount.id === code);
|
|
40
|
+
};
|
|
41
|
+
const getAppliedGiftCards = (cart) => {
|
|
42
|
+
var _a;
|
|
43
|
+
return (_a = cart.appliedGiftCards) === null || _a === void 0 ? void 0 : _a.map((giftCard) => ({
|
|
44
|
+
id: giftCard.id,
|
|
45
|
+
amount: +giftCard.amountUsed.amount,
|
|
46
|
+
name: `Gift Card - ${giftCard.lastCharacters}`,
|
|
47
|
+
}));
|
|
48
|
+
};
|
|
49
|
+
const getSalesAmount = (cart) => {
|
|
50
|
+
var _a;
|
|
51
|
+
return (_a = cart.items) === null || _a === void 0 ? void 0 : _a.reduce((acc, item) => {
|
|
52
|
+
var _a, _b, _c, _d;
|
|
53
|
+
const compareAtPrice = +(((_b = (_a = item.variantDetails) === null || _a === void 0 ? void 0 : _a.compareAtPrice) === null || _b === void 0 ? void 0 : _b.amount) || 0);
|
|
54
|
+
const price = +(((_d = (_c = item.variantDetails) === null || _c === void 0 ? void 0 : _c.price) === null || _d === void 0 ? void 0 : _d.amount) || 0);
|
|
55
|
+
const quantity = item.quantity || 1;
|
|
56
|
+
if (compareAtPrice && compareAtPrice > price) {
|
|
57
|
+
return acc + (compareAtPrice - price) * quantity;
|
|
58
|
+
}
|
|
59
|
+
return acc;
|
|
60
|
+
}, 0);
|
|
61
|
+
};
|
|
62
|
+
const getLineItemDiscounts = (cart) => {
|
|
63
|
+
var _a, _b;
|
|
64
|
+
const discountMap = (_a = cart.items) === null || _a === void 0 ? void 0 : _a.reduce((acc, item) => {
|
|
65
|
+
var _a;
|
|
66
|
+
(_a = item === null || item === void 0 ? void 0 : item.discounts) === null || _a === void 0 ? void 0 : _a.forEach((discount) => {
|
|
67
|
+
const code = discount === null || discount === void 0 ? void 0 : discount.code;
|
|
68
|
+
if (!code)
|
|
69
|
+
return;
|
|
70
|
+
if (!acc[code]) {
|
|
71
|
+
acc[code] = { amount: 0, type: discount.type };
|
|
72
|
+
}
|
|
73
|
+
acc[code].amount += discount.amount;
|
|
74
|
+
});
|
|
75
|
+
return acc;
|
|
76
|
+
}, {});
|
|
77
|
+
if (!discountMap)
|
|
78
|
+
return [];
|
|
79
|
+
return (_b = Object.entries(discountMap)) === null || _b === void 0 ? void 0 : _b.map(([code, { amount, type }]) => ({
|
|
80
|
+
id: code,
|
|
81
|
+
name: `Discount - ${code}`,
|
|
82
|
+
amount,
|
|
83
|
+
type,
|
|
84
|
+
})).filter((discount) => cart.discounts.includes(discount.id));
|
|
85
|
+
};
|
|
86
|
+
const getDiscountsTotalAmount = (orderAndLineItemDiscounts) => {
|
|
87
|
+
return orderAndLineItemDiscounts === null || orderAndLineItemDiscounts === void 0 ? void 0 : orderAndLineItemDiscounts.reduce((acc, discount) => acc + +discount.amount, 0);
|
|
88
|
+
};
|
|
89
|
+
const getGiftCardsTotalAmount = (appliedGiftCards) => {
|
|
90
|
+
return appliedGiftCards === null || appliedGiftCards === void 0 ? void 0 : appliedGiftCards.reduce((acc, giftCard) => acc + +giftCard.amount, 0);
|
|
91
|
+
};
|
|
92
|
+
const getTotalCompareAtPrice = (cart) => {
|
|
93
|
+
var _a;
|
|
94
|
+
return (_a = cart.items) === null || _a === void 0 ? void 0 : _a.reduce((acc, item) => {
|
|
95
|
+
var _a, _b, _c, _d;
|
|
96
|
+
const compareAtPrice = ((_b = (_a = item.variantDetails) === null || _a === void 0 ? void 0 : _a.compareAtPrice) === null || _b === void 0 ? void 0 : _b.amount) ||
|
|
97
|
+
((_d = (_c = item.variantDetails) === null || _c === void 0 ? void 0 : _c.price) === null || _d === void 0 ? void 0 : _d.amount);
|
|
98
|
+
const quantity = item.quantity || 1;
|
|
99
|
+
return acc + +(compareAtPrice || 0) * quantity;
|
|
100
|
+
}, 0);
|
|
101
|
+
};
|
|
102
|
+
const getTotalDiscountedPrice = (totalCompareAtPrice, discountsTotalAmount, salesAmount, giftCardsTotalAmount) => {
|
|
103
|
+
const total = (totalCompareAtPrice === undefined || isNaN(totalCompareAtPrice)
|
|
104
|
+
? 0
|
|
105
|
+
: totalCompareAtPrice) -
|
|
106
|
+
(discountsTotalAmount === undefined || isNaN(discountsTotalAmount)
|
|
107
|
+
? 0
|
|
108
|
+
: discountsTotalAmount) -
|
|
109
|
+
(salesAmount === undefined || isNaN(salesAmount) ? 0 : salesAmount) -
|
|
110
|
+
(giftCardsTotalAmount === undefined || isNaN(giftCardsTotalAmount)
|
|
111
|
+
? 0
|
|
112
|
+
: giftCardsTotalAmount);
|
|
113
|
+
return isNaN(total) ? 0 : total;
|
|
114
|
+
};
|
|
115
|
+
export const DEFAULT_CALCULATED_DATA = {
|
|
116
|
+
orderAndLineItemDiscounts: [],
|
|
117
|
+
appliedGiftCards: [],
|
|
118
|
+
isFreeShipping: false,
|
|
119
|
+
discountsTotalAmount: 0,
|
|
120
|
+
salesAmount: 0,
|
|
121
|
+
giftCardsTotalAmount: 0,
|
|
122
|
+
totalCompareAtPrice: 0,
|
|
123
|
+
totalDiscountedPrice: 0,
|
|
124
|
+
};
|
|
125
|
+
export const getCalculatedCartData = (cart) => {
|
|
126
|
+
const orderAndLineItemDiscounts = getOrderLevelDiscounts(cart).concat(getLineItemDiscounts(cart));
|
|
127
|
+
const appliedGiftCards = getAppliedGiftCards(cart);
|
|
128
|
+
const isFreeShipping = getShippingDiscounts(cart).length > 0;
|
|
129
|
+
const discountsTotalAmount = getDiscountsTotalAmount(orderAndLineItemDiscounts);
|
|
130
|
+
const giftCardsTotalAmount = getGiftCardsTotalAmount(appliedGiftCards);
|
|
131
|
+
const salesAmount = getSalesAmount(cart);
|
|
132
|
+
const totalCompareAtPrice = getTotalCompareAtPrice(cart);
|
|
133
|
+
const totalDiscountedPrice = getTotalDiscountedPrice(totalCompareAtPrice, discountsTotalAmount, salesAmount, giftCardsTotalAmount);
|
|
134
|
+
return {
|
|
135
|
+
orderAndLineItemDiscounts,
|
|
136
|
+
appliedGiftCards,
|
|
137
|
+
isFreeShipping,
|
|
138
|
+
discountsTotalAmount,
|
|
139
|
+
giftCardsTotalAmount,
|
|
140
|
+
salesAmount,
|
|
141
|
+
totalCompareAtPrice,
|
|
142
|
+
totalDiscountedPrice,
|
|
143
|
+
};
|
|
144
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cart.util.test.d.ts","sourceRoot":"","sources":["../../lib/cart.util.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { getCalculatedCartData } from "./cart.util";
|
|
2
|
+
import { DiscountApplicationTargetType } from "app-studio-types";
|
|
3
|
+
const baseCartData = {
|
|
4
|
+
id: "cart123",
|
|
5
|
+
subtotal: 100.0,
|
|
6
|
+
currency: "USD",
|
|
7
|
+
discounts: [],
|
|
8
|
+
attributes: [],
|
|
9
|
+
note: "",
|
|
10
|
+
items: [],
|
|
11
|
+
discountAllocations: [],
|
|
12
|
+
appliedGiftCards: [],
|
|
13
|
+
delivery: {
|
|
14
|
+
addresses: [],
|
|
15
|
+
},
|
|
16
|
+
deliveryGroups: [],
|
|
17
|
+
cost: {
|
|
18
|
+
subtotalAmount: { amount: "0", currencyCode: "" },
|
|
19
|
+
totalAmount: { amount: "0", currencyCode: "" },
|
|
20
|
+
totalTaxAmount: { amount: "0", currencyCode: "" },
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
describe("cart-provider.util", () => {
|
|
24
|
+
describe("getData", () => {
|
|
25
|
+
it("should calculate order level discounts correctly", () => {
|
|
26
|
+
const mockCart = Object.assign(Object.assign({}, baseCartData), { discounts: ["DISCOUNT10"], items: [], discountAllocations: [
|
|
27
|
+
{
|
|
28
|
+
targetType: DiscountApplicationTargetType.LineItem,
|
|
29
|
+
discountedAmount: { amount: "10.00", currencyCode: "USD" },
|
|
30
|
+
code: "DISCOUNT10",
|
|
31
|
+
},
|
|
32
|
+
], appliedGiftCards: [], deliveryGroups: [] });
|
|
33
|
+
const result = getCalculatedCartData(mockCart);
|
|
34
|
+
expect(result.orderAndLineItemDiscounts).toHaveLength(1);
|
|
35
|
+
expect(result.orderAndLineItemDiscounts[0]).toEqual({
|
|
36
|
+
id: "DISCOUNT10",
|
|
37
|
+
amount: 10,
|
|
38
|
+
name: "Discount - DISCOUNT10",
|
|
39
|
+
type: "ORDER_LEVEL",
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
it("should calculate gift cards correctly", () => {
|
|
43
|
+
const mockCart = Object.assign(Object.assign({}, baseCartData), { discounts: [], items: [], discountAllocations: [], appliedGiftCards: [
|
|
44
|
+
{
|
|
45
|
+
id: "giftcard1",
|
|
46
|
+
amountUsed: { amount: "25.00", currencyCode: "USD" },
|
|
47
|
+
balance: { amount: "75.00", currencyCode: "USD" },
|
|
48
|
+
lastCharacters: "1234",
|
|
49
|
+
presentmentAmountUsed: { amount: "25.00", currencyCode: "USD" },
|
|
50
|
+
},
|
|
51
|
+
], deliveryGroups: [] });
|
|
52
|
+
const result = getCalculatedCartData(mockCart);
|
|
53
|
+
expect(result.appliedGiftCards).toHaveLength(1);
|
|
54
|
+
expect(result.appliedGiftCards[0]).toEqual({
|
|
55
|
+
id: "giftcard1",
|
|
56
|
+
amount: 25,
|
|
57
|
+
name: "Gift Card - 1234",
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
it("should calculate sales amount correctly", () => {
|
|
61
|
+
const mockCart = Object.assign(Object.assign({}, baseCartData), { discounts: [], items: [
|
|
62
|
+
{
|
|
63
|
+
id: "line1",
|
|
64
|
+
quantity: 2,
|
|
65
|
+
productId: "prod1",
|
|
66
|
+
variantId: "var1",
|
|
67
|
+
productDetails: {},
|
|
68
|
+
variantDetails: {
|
|
69
|
+
compareAtPrice: { amount: "20.00", currencyCode: "USD" },
|
|
70
|
+
price: { amount: "15.00", currencyCode: "USD" },
|
|
71
|
+
},
|
|
72
|
+
discounts: [],
|
|
73
|
+
cost: { totalAmount: { amount: "30.00", currencyCode: "USD" } },
|
|
74
|
+
},
|
|
75
|
+
], discountAllocations: [], appliedGiftCards: [], deliveryGroups: [] });
|
|
76
|
+
const result = getCalculatedCartData(mockCart);
|
|
77
|
+
expect(result.salesAmount).toBe(10); // (20-15) * 2
|
|
78
|
+
});
|
|
79
|
+
it("should detect free shipping", () => {
|
|
80
|
+
const mockCart = Object.assign(Object.assign({}, baseCartData), { discounts: [], items: [], discountAllocations: [
|
|
81
|
+
{
|
|
82
|
+
targetType: DiscountApplicationTargetType.ShippingLine,
|
|
83
|
+
discountedAmount: { amount: "5.00", currencyCode: "USD" },
|
|
84
|
+
code: "FREESHIP",
|
|
85
|
+
},
|
|
86
|
+
], appliedGiftCards: [], deliveryGroups: [] });
|
|
87
|
+
const result = getCalculatedCartData(mockCart);
|
|
88
|
+
expect(result.isFreeShipping).toBe(true);
|
|
89
|
+
});
|
|
90
|
+
it("should calculate total discounted price correctly", () => {
|
|
91
|
+
const mockCart = Object.assign(Object.assign({}, baseCartData), { discounts: ["DISCOUNT10"], items: [
|
|
92
|
+
{
|
|
93
|
+
id: "line1",
|
|
94
|
+
quantity: 1,
|
|
95
|
+
productId: "prod1",
|
|
96
|
+
variantId: "var1",
|
|
97
|
+
productDetails: {},
|
|
98
|
+
variantDetails: {
|
|
99
|
+
compareAtPrice: { amount: "100.00", currencyCode: "USD" },
|
|
100
|
+
price: { amount: "80.00", currencyCode: "USD" },
|
|
101
|
+
},
|
|
102
|
+
discounts: [
|
|
103
|
+
{
|
|
104
|
+
amount: 10,
|
|
105
|
+
type: "LINE_ITEM",
|
|
106
|
+
code: "DISCOUNT10",
|
|
107
|
+
},
|
|
108
|
+
],
|
|
109
|
+
cost: { totalAmount: { amount: "80.00", currencyCode: "USD" } },
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
id: "line2",
|
|
113
|
+
quantity: 1,
|
|
114
|
+
productId: "prod2",
|
|
115
|
+
variantId: "var2",
|
|
116
|
+
productDetails: {},
|
|
117
|
+
variantDetails: {
|
|
118
|
+
compareAtPrice: { amount: "100.00", currencyCode: "USD" },
|
|
119
|
+
price: { amount: "80.00", currencyCode: "USD" },
|
|
120
|
+
},
|
|
121
|
+
discounts: [
|
|
122
|
+
{
|
|
123
|
+
amount: 10,
|
|
124
|
+
type: "LINE_ITEM",
|
|
125
|
+
code: "DISCOUNT10",
|
|
126
|
+
},
|
|
127
|
+
],
|
|
128
|
+
cost: { totalAmount: { amount: "80.00", currencyCode: "USD" } },
|
|
129
|
+
},
|
|
130
|
+
], discountAllocations: [
|
|
131
|
+
{
|
|
132
|
+
targetType: DiscountApplicationTargetType.LineItem,
|
|
133
|
+
discountedAmount: { amount: "10.00", currencyCode: "USD" },
|
|
134
|
+
code: "DISCOUNT10",
|
|
135
|
+
},
|
|
136
|
+
], appliedGiftCards: [
|
|
137
|
+
{
|
|
138
|
+
id: "giftcard1",
|
|
139
|
+
amountUsed: { amount: "5.00", currencyCode: "USD" },
|
|
140
|
+
balance: { amount: "95.00", currencyCode: "USD" },
|
|
141
|
+
lastCharacters: "1234",
|
|
142
|
+
presentmentAmountUsed: { amount: "5.00", currencyCode: "USD" },
|
|
143
|
+
},
|
|
144
|
+
], deliveryGroups: [] });
|
|
145
|
+
const result = getCalculatedCartData(mockCart);
|
|
146
|
+
// 100 (compare) - 10 (discount) - 20 (sale) - 5 (gift card) = 65
|
|
147
|
+
expect(result.totalDiscountedPrice).toBe(125);
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tapcart/mobile-components",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.60",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"style": "dist/styles.css",
|
|
@@ -11,6 +11,20 @@
|
|
|
11
11
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
12
12
|
"author": "Tapcart Inc.",
|
|
13
13
|
"homepage": "https://tapcart.com",
|
|
14
|
+
"scripts": {
|
|
15
|
+
"clean": "rm -rf dist node_modules",
|
|
16
|
+
"lint": "eslint \"**/*.ts*\"",
|
|
17
|
+
"ui:add": "pnpm dlx shadcn-ui@latest add",
|
|
18
|
+
"build:styles": "postcss styles/globals.css -o dist/styles.css",
|
|
19
|
+
"build:ts": "tsc -p tsconfig.json && tsc-alias",
|
|
20
|
+
"build": "pnpm run build:ts && pnpm run build:styles",
|
|
21
|
+
"dev:ts": "tsc -w -p tsconfig.json",
|
|
22
|
+
"dev:styles": "npx tailwindcss -i styles/globals.css -o dist/styles.css --watch",
|
|
23
|
+
"dev": "concurrently \"pnpm run dev:ts\" \"pnpm run dev:styles\"",
|
|
24
|
+
"test": "jest",
|
|
25
|
+
"test:silent": "jest --silent",
|
|
26
|
+
"test:watch": "jest --watch"
|
|
27
|
+
},
|
|
14
28
|
"peerDependencies": {
|
|
15
29
|
"react": "^17.0.2 || ^18.0.0",
|
|
16
30
|
"react-dom": "^17.0.2 || ^18.0.0"
|
|
@@ -23,20 +37,20 @@
|
|
|
23
37
|
"@types/pluralize": "^0.0.33",
|
|
24
38
|
"@types/react": "^18.2.0",
|
|
25
39
|
"@types/react-dom": "^18.2.0",
|
|
40
|
+
"app-studio-types": "workspace:*",
|
|
26
41
|
"autoprefixer": "^10.4.14",
|
|
27
42
|
"chokidar-cli": "^3.0.0",
|
|
28
43
|
"concurrently": "^8.2.2",
|
|
29
44
|
"eslint": "^7.32.0",
|
|
45
|
+
"eslint-config-custom": "workspace:*",
|
|
30
46
|
"jest": "^29.7.0",
|
|
31
47
|
"jest-environment-jsdom": "^29.7.0",
|
|
32
48
|
"postcss": "^8.4.24",
|
|
33
49
|
"tailwindcss": "^3.3.2",
|
|
34
50
|
"ts-jest": "^29.2.5",
|
|
35
51
|
"tsc-alias": "^1.8.10",
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"eslint-config-custom": "0.0.0",
|
|
39
|
-
"tsconfig": "0.0.0"
|
|
52
|
+
"tsconfig": "workspace:*",
|
|
53
|
+
"typescript": "^4.5.2"
|
|
40
54
|
},
|
|
41
55
|
"dependencies": {
|
|
42
56
|
"@radix-ui/react-accordion": "^1.1.2",
|
|
@@ -76,19 +90,5 @@
|
|
|
76
90
|
"tailwind-merge": "^1.13.2",
|
|
77
91
|
"tailwindcss-animate": "^1.0.6",
|
|
78
92
|
"vaul": "0.9.1"
|
|
79
|
-
},
|
|
80
|
-
"scripts": {
|
|
81
|
-
"clean": "rm -rf dist node_modules",
|
|
82
|
-
"lint": "eslint \"**/*.ts*\"",
|
|
83
|
-
"ui:add": "pnpm dlx shadcn-ui@latest add",
|
|
84
|
-
"build:styles": "postcss styles/globals.css -o dist/styles.css",
|
|
85
|
-
"build:ts": "tsc -p tsconfig.json && tsc-alias",
|
|
86
|
-
"build": "pnpm run build:ts && pnpm run build:styles",
|
|
87
|
-
"dev:ts": "tsc -w -p tsconfig.json",
|
|
88
|
-
"dev:styles": "npx tailwindcss -i styles/globals.css -o dist/styles.css --watch",
|
|
89
|
-
"dev": "concurrently \"pnpm run dev:ts\" \"pnpm run dev:styles\"",
|
|
90
|
-
"test": "jest",
|
|
91
|
-
"test:silent": "jest --silent",
|
|
92
|
-
"test:watch": "jest --watch"
|
|
93
93
|
}
|
|
94
|
-
}
|
|
94
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"use-click-outside.d.ts","sourceRoot":"","sources":["../../../components/hooks/use-click-outside.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,wBAAgB,eAAe,CAAC,GAAG,EAAE,KAAK,CAAC,SAAS,CAAC,WAAW,CAAC,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAE,IAAI,CAa5F"}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
"use client"
|
|
2
|
-
import React from "react"
|
|
3
|
-
export function useClickOutside(ref, callback) {
|
|
4
|
-
React.useEffect(() => {
|
|
5
|
-
const handleClickOutside = (event) => {
|
|
6
|
-
if (ref.current && !ref.current.contains(event.target)) {
|
|
7
|
-
callback()
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
|
-
document.addEventListener("mousedown", handleClickOutside)
|
|
11
|
-
return () => {
|
|
12
|
-
document.removeEventListener("mousedown", handleClickOutside)
|
|
13
|
-
}
|
|
14
|
-
}, [ref, callback])
|
|
15
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"use-outside-click.d.ts","sourceRoot":"","sources":["../../../components/hooks/use-outside-click.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,QAAA,MAAM,eAAe,QAAS,MAAM,SAAS,CAAC,WAAW,CAAC,YAAY,MAAM,IAAI,SAa/E,CAAC;AAEF,eAAe,eAAe,CAAC"}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
"use client"
|
|
2
|
-
import React from "react"
|
|
3
|
-
const useClickOutside = (ref, callback) => {
|
|
4
|
-
React.useEffect(() => {
|
|
5
|
-
const handleClickOutside = (event) => {
|
|
6
|
-
if (ref.current && !ref.current.contains(event.target)) {
|
|
7
|
-
callback()
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
|
-
document.addEventListener("mousedown", handleClickOutside)
|
|
11
|
-
return () => {
|
|
12
|
-
document.removeEventListener("mousedown", handleClickOutside)
|
|
13
|
-
}
|
|
14
|
-
}, [ref, callback])
|
|
15
|
-
}
|
|
16
|
-
export default useClickOutside
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"use-tap.d.ts","sourceRoot":"","sources":["../../../components/hooks/use-tap.ts"],"names":[],"mappings":"AACA,OAAO,KAAmD,MAAM,OAAO,CAAA;AAuFvE,QAAA,MAAM,MAAM;6BAuBkC,GAAG,KAAK,IAAI,aACvC,GAAG;;;CAerB,CAAA;AAED,OAAO,EAAE,MAAM,EAAE,CAAA"}
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
"use client"
|
|
2
|
-
import { useState, useEffect, useCallback, useRef } from "react"
|
|
3
|
-
// Shared manager for all instances of the hook
|
|
4
|
-
const tapManager = (() => {
|
|
5
|
-
const elements = new Map()
|
|
6
|
-
let isListening = false
|
|
7
|
-
const startListening = () => {
|
|
8
|
-
if (isListening) return
|
|
9
|
-
const handleTouchStart = (e) => {
|
|
10
|
-
const touch = e.touches[0]
|
|
11
|
-
elements.forEach((data, el) => {
|
|
12
|
-
if (el.contains(touch.target)) {
|
|
13
|
-
data.touchStarted = true
|
|
14
|
-
data.touchMoved = false
|
|
15
|
-
data.startPosition = { x: touch.clientX, y: touch.clientY }
|
|
16
|
-
// Don't set isPressed here, wait to determine if it's a tap or drag
|
|
17
|
-
}
|
|
18
|
-
})
|
|
19
|
-
}
|
|
20
|
-
const handleTouchMove = (e) => {
|
|
21
|
-
const touch = e.touches[0]
|
|
22
|
-
elements.forEach((data, el) => {
|
|
23
|
-
if (data.touchStarted) {
|
|
24
|
-
const deltaX = Math.abs(touch.clientX - data.startPosition.x)
|
|
25
|
-
const deltaY = Math.abs(touch.clientY - data.startPosition.y)
|
|
26
|
-
if (deltaX > data.tapThreshold || deltaY > data.tapThreshold) {
|
|
27
|
-
data.touchMoved = true
|
|
28
|
-
data.setIsPressed(false)
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
})
|
|
32
|
-
}
|
|
33
|
-
const handleTouchEnd = () => {
|
|
34
|
-
elements.forEach((data) => {
|
|
35
|
-
if (data.touchStarted) {
|
|
36
|
-
data.touchStarted = false
|
|
37
|
-
if (!data.touchMoved) {
|
|
38
|
-
// It's a tap, set isPressed briefly
|
|
39
|
-
data.setIsPressed(true)
|
|
40
|
-
setTimeout(() => data.setIsPressed(false), 100)
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
})
|
|
44
|
-
}
|
|
45
|
-
document.addEventListener("touchstart", (e) => handleTouchStart(e), {
|
|
46
|
-
passive: true,
|
|
47
|
-
})
|
|
48
|
-
document.addEventListener("touchmove", (e) => handleTouchMove(e), {
|
|
49
|
-
passive: true,
|
|
50
|
-
})
|
|
51
|
-
document.addEventListener("touchend", () => handleTouchEnd(), {
|
|
52
|
-
passive: true,
|
|
53
|
-
})
|
|
54
|
-
isListening = true
|
|
55
|
-
}
|
|
56
|
-
return {
|
|
57
|
-
register: (el, data) => {
|
|
58
|
-
elements.set(el, data)
|
|
59
|
-
startListening()
|
|
60
|
-
},
|
|
61
|
-
unregister: (el) => {
|
|
62
|
-
elements.delete(el)
|
|
63
|
-
},
|
|
64
|
-
elements,
|
|
65
|
-
}
|
|
66
|
-
})()
|
|
67
|
-
const useTap = (tapThreshold = 10) => {
|
|
68
|
-
const [isPressed, setIsPressed] = useState(false)
|
|
69
|
-
const elementRef = useRef(null)
|
|
70
|
-
useEffect(() => {
|
|
71
|
-
const element = elementRef.current
|
|
72
|
-
if (!element) return
|
|
73
|
-
const data = {
|
|
74
|
-
touchStarted: false,
|
|
75
|
-
touchMoved: false,
|
|
76
|
-
startPosition: { x: 0, y: 0 },
|
|
77
|
-
setIsPressed,
|
|
78
|
-
tapThreshold,
|
|
79
|
-
}
|
|
80
|
-
tapManager.register(element, data)
|
|
81
|
-
return () => {
|
|
82
|
-
tapManager.unregister(element)
|
|
83
|
-
}
|
|
84
|
-
}, [tapThreshold])
|
|
85
|
-
const onTap = useCallback((handler) => {
|
|
86
|
-
return (event) => {
|
|
87
|
-
const data = tapManager.elements.get(elementRef.current)
|
|
88
|
-
if (!data) return
|
|
89
|
-
if (event.type === "touchend" && !data.touchMoved) {
|
|
90
|
-
handler(event)
|
|
91
|
-
} else if (event.type === "click" && !data.touchStarted) {
|
|
92
|
-
handler(event)
|
|
93
|
-
setIsPressed(true)
|
|
94
|
-
setTimeout(() => setIsPressed(false), 100)
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}, [])
|
|
98
|
-
return { onTap, isPressed, ref: elementRef }
|
|
99
|
-
}
|
|
100
|
-
export { useTap }
|