medusa-ui-common 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +93 -0
- package/src/common/components/breadcrumb/index.tsx +43 -0
- package/src/common/components/cart-totals/index.tsx +562 -0
- package/src/common/components/checkbox/index.tsx +98 -0
- package/src/common/components/delete-button/index.tsx +158 -0
- package/src/common/components/discount-code/index.tsx +220 -0
- package/src/common/components/divider/index.tsx +9 -0
- package/src/common/components/error-message/index.tsx +13 -0
- package/src/common/components/filter-checkbox-group/index.tsx +134 -0
- package/src/common/components/filter-radio-group/index.tsx +62 -0
- package/src/common/components/input/index.tsx +79 -0
- package/src/common/components/interactive-link/index.tsx +33 -0
- package/src/common/components/line-item-options/index.tsx +26 -0
- package/src/common/components/line-item-price/index.tsx +64 -0
- package/src/common/components/line-item-unit-price/index.tsx +64 -0
- package/src/common/components/localized-client-link/index.tsx +32 -0
- package/src/common/components/login-popup/index.tsx +78 -0
- package/src/common/components/modal/index.tsx +123 -0
- package/src/common/components/native-select/index.tsx +75 -0
- package/src/common/components/obfuscated-email/index.tsx +30 -0
- package/src/common/components/processing-overlay/index.tsx +83 -0
- package/src/common/components/radio/index.tsx +27 -0
- package/src/common/components/side-panel/index.tsx +65 -0
- package/src/common/components/submit-button/index.tsx +32 -0
- package/src/common/icons/arrow-left.tsx +36 -0
- package/src/common/icons/back.tsx +37 -0
- package/src/common/icons/bancontact.tsx +26 -0
- package/src/common/icons/chevron-down.tsx +30 -0
- package/src/common/icons/delivered.tsx +29 -0
- package/src/common/icons/envelope.tsx +27 -0
- package/src/common/icons/eye-off.tsx +37 -0
- package/src/common/icons/eye.tsx +37 -0
- package/src/common/icons/fast-delivery.tsx +65 -0
- package/src/common/icons/ideal.tsx +26 -0
- package/src/common/icons/lock.tsx +31 -0
- package/src/common/icons/map-pin.tsx +37 -0
- package/src/common/icons/medusa.tsx +27 -0
- package/src/common/icons/menu.tsx +45 -0
- package/src/common/icons/nextjs.tsx +27 -0
- package/src/common/icons/package.tsx +44 -0
- package/src/common/icons/paypal.tsx +30 -0
- package/src/common/icons/phone.tsx +30 -0
- package/src/common/icons/placeholder-image.tsx +44 -0
- package/src/common/icons/refresh.tsx +51 -0
- package/src/common/icons/spinner.tsx +37 -0
- package/src/common/icons/trash.tsx +51 -0
- package/src/common/icons/user.tsx +37 -0
- package/src/common/icons/x.tsx +37 -0
- package/src/constants/payments.tsx +31 -0
- package/src/context/modal-context.tsx +37 -0
- package/src/context/wishlist-context.tsx +83 -0
- package/src/index.ts +16 -0
- package/src/skeletons/components/skeleton-button/index.tsx +5 -0
- package/src/skeletons/components/skeleton-card-details/index.tsx +10 -0
- package/src/skeletons/components/skeleton-cart-item/index.tsx +35 -0
- package/src/skeletons/components/skeleton-cart-totals/index.tsx +30 -0
- package/src/skeletons/components/skeleton-code-form/index.tsx +13 -0
- package/src/skeletons/components/skeleton-line-item/index.tsx +35 -0
- package/src/skeletons/components/skeleton-order-confirmed-header/index.tsx +14 -0
- package/src/skeletons/components/skeleton-order-information/index.tsx +36 -0
- package/src/skeletons/components/skeleton-order-items/index.tsx +43 -0
- package/src/skeletons/components/skeleton-order-summary/index.tsx +15 -0
- package/src/skeletons/components/skeleton-product-preview/index.tsx +15 -0
- package/src/skeletons/templates/skeleton-cart-page/index.tsx +65 -0
- package/src/skeletons/templates/skeleton-order-confirmed/index.tsx +21 -0
- package/src/skeletons/templates/skeleton-product-grid/index.tsx +23 -0
- package/src/skeletons/templates/skeleton-related-products/index.tsx +25 -0
- package/src/types/global.ts +24 -0
- package/src/types/icon.ts +6 -0
- package/src/util/checkout-dom.ts +65 -0
- package/src/util/compare-addresses.ts +28 -0
- package/src/util/env.ts +3 -0
- package/src/util/get-percentage-diff.ts +6 -0
- package/src/util/get-product-price.ts +79 -0
- package/src/util/isEmpty.ts +11 -0
- package/src/util/money.ts +26 -0
- package/src/util/product.ts +86 -0
- package/src/util/repeat.ts +5 -0
- package/src/util/returns.ts +72 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import React from "react"
|
|
2
|
+
|
|
3
|
+
import { IconProps } from "types/icon"
|
|
4
|
+
|
|
5
|
+
const Package: React.FC<IconProps> = ({
|
|
6
|
+
size = "20",
|
|
7
|
+
color = "currentColor",
|
|
8
|
+
...attributes
|
|
9
|
+
}) => {
|
|
10
|
+
return (
|
|
11
|
+
<svg
|
|
12
|
+
width={size}
|
|
13
|
+
height={size}
|
|
14
|
+
viewBox="0 0 20 20"
|
|
15
|
+
fill="none"
|
|
16
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
17
|
+
{...attributes}
|
|
18
|
+
>
|
|
19
|
+
<path
|
|
20
|
+
d="M13.3634 8.02695L6.73047 4.21271"
|
|
21
|
+
stroke={color}
|
|
22
|
+
strokeWidth="1.5"
|
|
23
|
+
strokeLinecap="round"
|
|
24
|
+
strokeLinejoin="round"
|
|
25
|
+
/>
|
|
26
|
+
<path
|
|
27
|
+
d="M16.724 12.9577V6.98101C16.7237 6.71899 16.6546 6.46164 16.5234 6.23479C16.3923 6.00794 16.2038 5.81956 15.9769 5.68855L10.7473 2.70018C10.5201 2.56904 10.2625 2.5 10.0002 2.5C9.7379 2.5 9.48024 2.56904 9.25309 2.70018L4.02346 5.68855C3.79654 5.81956 3.60806 6.00794 3.47693 6.23479C3.3458 6.46164 3.27664 6.71899 3.27637 6.98101V12.9577C3.27664 13.2198 3.3458 13.4771 3.47693 13.704C3.60806 13.9308 3.79654 14.1192 4.02346 14.2502L9.25309 17.2386C9.48024 17.3697 9.7379 17.4388 10.0002 17.4388C10.2625 17.4388 10.5201 17.3697 10.7473 17.2386L15.9769 14.2502C16.2038 14.1192 16.3923 13.9308 16.5234 13.704C16.6546 13.4771 16.7237 13.2198 16.724 12.9577Z"
|
|
28
|
+
stroke={color}
|
|
29
|
+
strokeWidth="1.5"
|
|
30
|
+
strokeLinecap="round"
|
|
31
|
+
strokeLinejoin="round"
|
|
32
|
+
/>
|
|
33
|
+
<path
|
|
34
|
+
d="M3.47852 6.20404L10.0006 9.97685L16.5227 6.20404"
|
|
35
|
+
stroke={color}
|
|
36
|
+
strokeWidth="1.5"
|
|
37
|
+
strokeLinecap="round"
|
|
38
|
+
strokeLinejoin="round"
|
|
39
|
+
/>
|
|
40
|
+
</svg>
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export default Package
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
const PayPal = () => {
|
|
2
|
+
return (
|
|
3
|
+
<svg
|
|
4
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
5
|
+
height="20"
|
|
6
|
+
width="20"
|
|
7
|
+
viewBox="0 0 26 25"
|
|
8
|
+
id="paypalIcon"
|
|
9
|
+
>
|
|
10
|
+
<path
|
|
11
|
+
fill="none"
|
|
12
|
+
stroke="#303c42"
|
|
13
|
+
strokeWidth="2"
|
|
14
|
+
strokeLinecap="round"
|
|
15
|
+
strokeLinejoin="round"
|
|
16
|
+
d="M6.9 20.5H2c-.6 0-.5-.1-.5-.5s2.9-18 3-18.5.5-1 1-1h10c2.8 0 5 2.2 5 5h0c0 4.4-3.6 8-8 8H7.9"
|
|
17
|
+
></path>
|
|
18
|
+
<path
|
|
19
|
+
fill="none"
|
|
20
|
+
stroke="#303c42"
|
|
21
|
+
strokeWidth="2"
|
|
22
|
+
strokeLinecap="round"
|
|
23
|
+
strokeLinejoin="round"
|
|
24
|
+
d="M7 23.5c-.3 0-.5-.2-.5-.5 0 0 0 0 0 0 0-.3 2.4-16 2.5-16.5s.3-1 1-1h7.5c2.8 0 5 2.2 5 5h0c0 3.9-3.1 7-7 7h-2l-1 6H7z"
|
|
25
|
+
></path>
|
|
26
|
+
</svg>
|
|
27
|
+
)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export default PayPal
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React from "react"
|
|
2
|
+
|
|
3
|
+
import { IconProps } from "types/icon"
|
|
4
|
+
|
|
5
|
+
const Phone: React.FC<IconProps> = ({
|
|
6
|
+
size = "20",
|
|
7
|
+
color = "currentColor",
|
|
8
|
+
...props
|
|
9
|
+
}) => {
|
|
10
|
+
return (
|
|
11
|
+
<svg
|
|
12
|
+
width={size}
|
|
13
|
+
height={size}
|
|
14
|
+
viewBox="0 0 24 24"
|
|
15
|
+
fill="none"
|
|
16
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
17
|
+
{...props}
|
|
18
|
+
>
|
|
19
|
+
<path
|
|
20
|
+
d="M22 16.92V19.92C22.0011 20.1985 21.944 20.4741 21.8325 20.7294C21.721 20.9846 21.5573 21.2137 21.3521 21.4019C21.1469 21.5901 20.9045 21.7335 20.6407 21.8228C20.3769 21.9122 20.0974 21.9456 19.82 21.92C16.742 21.5855 13.787 20.5341 11.19 18.85C8.77381 17.2995 6.72053 15.2462 5.17 12.83C3.47997 10.2215 2.42752 7.25414 2.09 4.16C2.0645 3.88295 2.09756 3.60368 2.18696 3.34005C2.27636 3.07641 2.4199 2.83416 2.60783 2.62886C2.79576 2.42356 3.02396 2.25965 3.27814 2.14725C3.53232 2.03485 3.80665 1.97645 4.084 1.976H7.084C7.57354 1.97193 8.04753 2.15286 8.4116 2.48261C8.77567 2.81236 9.00412 3.26871 9.051 3.76C9.13825 4.71714 9.37181 5.65868 9.746 6.56C9.88603 6.89241 9.92882 7.25624 9.86901 7.61053C9.80919 7.96482 9.64939 8.29524 9.408 8.56L8.138 9.83C9.57461 12.3555 11.6645 14.4454 14.19 15.88L15.46 14.61C15.7248 14.3686 16.0552 14.2088 16.4095 14.149C16.7638 14.0892 17.1276 14.132 17.46 14.272C18.3613 14.6462 19.3029 14.8797 20.26 14.967C20.756 15.0145 21.2159 15.247 21.5469 15.6175C21.8778 15.988 22.0567 16.4716 22.049 16.971L22 16.92Z"
|
|
21
|
+
stroke={color}
|
|
22
|
+
strokeWidth="2"
|
|
23
|
+
strokeLinecap="round"
|
|
24
|
+
strokeLinejoin="round"
|
|
25
|
+
/>
|
|
26
|
+
</svg>
|
|
27
|
+
)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export default Phone
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import React from "react"
|
|
2
|
+
|
|
3
|
+
import { IconProps } from "types/icon"
|
|
4
|
+
|
|
5
|
+
const PlaceholderImage: React.FC<IconProps> = ({
|
|
6
|
+
size = "20",
|
|
7
|
+
color = "currentColor",
|
|
8
|
+
...attributes
|
|
9
|
+
}) => {
|
|
10
|
+
return (
|
|
11
|
+
<svg
|
|
12
|
+
width={size}
|
|
13
|
+
height={size}
|
|
14
|
+
viewBox="0 0 20 20"
|
|
15
|
+
fill="none"
|
|
16
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
17
|
+
{...attributes}
|
|
18
|
+
>
|
|
19
|
+
<path
|
|
20
|
+
d="M15.3141 3.16699H4.68453C3.84588 3.16699 3.16602 3.84685 3.16602 4.6855V15.3151C3.16602 16.1537 3.84588 16.8336 4.68453 16.8336H15.3141C16.1527 16.8336 16.8326 16.1537 16.8326 15.3151V4.6855C16.8326 3.84685 16.1527 3.16699 15.3141 3.16699Z"
|
|
21
|
+
stroke={color}
|
|
22
|
+
strokeWidth="1.53749"
|
|
23
|
+
strokeLinecap="round"
|
|
24
|
+
strokeLinejoin="round"
|
|
25
|
+
/>
|
|
26
|
+
<path
|
|
27
|
+
d="M7.91699 9.16699C8.60735 9.16699 9.16699 8.60735 9.16699 7.91699C9.16699 7.22664 8.60735 6.66699 7.91699 6.66699C7.22664 6.66699 6.66699 7.22664 6.66699 7.91699C6.66699 8.60735 7.22664 9.16699 7.91699 9.16699Z"
|
|
28
|
+
stroke={color}
|
|
29
|
+
strokeWidth="1.5"
|
|
30
|
+
strokeLinecap="round"
|
|
31
|
+
strokeLinejoin="round"
|
|
32
|
+
/>
|
|
33
|
+
<path
|
|
34
|
+
d="M16.6667 12.5756L13.0208 9.1665L5 16.6665"
|
|
35
|
+
stroke={color}
|
|
36
|
+
strokeWidth="1.5"
|
|
37
|
+
strokeLinecap="round"
|
|
38
|
+
strokeLinejoin="round"
|
|
39
|
+
/>
|
|
40
|
+
</svg>
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export default PlaceholderImage
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import React from "react"
|
|
2
|
+
|
|
3
|
+
import { IconProps } from "types/icon"
|
|
4
|
+
|
|
5
|
+
const Refresh: React.FC<IconProps> = ({
|
|
6
|
+
size = "16",
|
|
7
|
+
color = "currentColor",
|
|
8
|
+
...attributes
|
|
9
|
+
}) => {
|
|
10
|
+
return (
|
|
11
|
+
<svg
|
|
12
|
+
width={size}
|
|
13
|
+
height={size}
|
|
14
|
+
viewBox="0 0 24 24"
|
|
15
|
+
fill="none"
|
|
16
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
17
|
+
{...attributes}
|
|
18
|
+
>
|
|
19
|
+
<path
|
|
20
|
+
d="M19.8007 3.33301V8.53308H14.6006"
|
|
21
|
+
stroke={color}
|
|
22
|
+
strokeWidth="1.5"
|
|
23
|
+
strokeLinecap="round"
|
|
24
|
+
strokeLinejoin="round"
|
|
25
|
+
/>
|
|
26
|
+
<path
|
|
27
|
+
d="M4.2002 12C4.20157 10.4949 4.63839 9.02228 5.45797 7.75984C6.27755 6.4974 7.44488 5.49905 8.81917 4.8852C10.1935 4.27135 11.716 4.06823 13.2031 4.30034C14.6903 4.53244 16.0785 5.18986 17.2004 6.19329L19.8004 8.53332"
|
|
28
|
+
stroke={color}
|
|
29
|
+
strokeWidth="1.5"
|
|
30
|
+
strokeLinecap="round"
|
|
31
|
+
strokeLinejoin="round"
|
|
32
|
+
/>
|
|
33
|
+
<path
|
|
34
|
+
d="M4.2002 20.6669V15.4668H9.40027"
|
|
35
|
+
stroke={color}
|
|
36
|
+
strokeWidth="1.5"
|
|
37
|
+
strokeLinecap="round"
|
|
38
|
+
strokeLinejoin="round"
|
|
39
|
+
/>
|
|
40
|
+
<path
|
|
41
|
+
d="M19.8004 12C19.799 13.5051 19.3622 14.9778 18.5426 16.2402C17.7231 17.5026 16.5557 18.501 15.1814 19.1148C13.8072 19.7287 12.2846 19.9318 10.7975 19.6997C9.31033 19.4676 7.9221 18.8102 6.80023 17.8067L4.2002 15.4667"
|
|
42
|
+
stroke={color}
|
|
43
|
+
strokeWidth="1.5"
|
|
44
|
+
strokeLinecap="round"
|
|
45
|
+
strokeLinejoin="round"
|
|
46
|
+
/>
|
|
47
|
+
</svg>
|
|
48
|
+
)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export default Refresh
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import React from "react"
|
|
2
|
+
|
|
3
|
+
import { IconProps } from "types/icon"
|
|
4
|
+
|
|
5
|
+
const Spinner: React.FC<IconProps> = ({
|
|
6
|
+
size = "16",
|
|
7
|
+
color = "currentColor",
|
|
8
|
+
...attributes
|
|
9
|
+
}) => {
|
|
10
|
+
return (
|
|
11
|
+
<svg
|
|
12
|
+
className="animate-spin"
|
|
13
|
+
width={size}
|
|
14
|
+
height={size}
|
|
15
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
16
|
+
fill="none"
|
|
17
|
+
viewBox="0 0 24 24"
|
|
18
|
+
{...attributes}
|
|
19
|
+
>
|
|
20
|
+
<circle
|
|
21
|
+
className="opacity-25"
|
|
22
|
+
cx="12"
|
|
23
|
+
cy="12"
|
|
24
|
+
r="10"
|
|
25
|
+
stroke={color}
|
|
26
|
+
strokeWidth="4"
|
|
27
|
+
></circle>
|
|
28
|
+
<path
|
|
29
|
+
className="opacity-75"
|
|
30
|
+
fill={color}
|
|
31
|
+
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
|
32
|
+
></path>
|
|
33
|
+
</svg>
|
|
34
|
+
)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export default Spinner
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import React from "react"
|
|
2
|
+
|
|
3
|
+
import { IconProps } from "types/icon"
|
|
4
|
+
|
|
5
|
+
const Trash: React.FC<IconProps> = ({
|
|
6
|
+
size = "16",
|
|
7
|
+
color = "currentColor",
|
|
8
|
+
...attributes
|
|
9
|
+
}) => {
|
|
10
|
+
return (
|
|
11
|
+
<svg
|
|
12
|
+
width={size}
|
|
13
|
+
height={size}
|
|
14
|
+
viewBox="0 0 20 20"
|
|
15
|
+
fill="none"
|
|
16
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
17
|
+
{...attributes}
|
|
18
|
+
>
|
|
19
|
+
<path
|
|
20
|
+
d="M3.33301 5.49054H4.81449H16.6663"
|
|
21
|
+
stroke={color}
|
|
22
|
+
strokeWidth="1.5"
|
|
23
|
+
strokeLinecap="round"
|
|
24
|
+
strokeLinejoin="round"
|
|
25
|
+
/>
|
|
26
|
+
<path
|
|
27
|
+
d="M7.14286 5.5V4C7.14286 3.60218 7.29337 3.22064 7.56128 2.93934C7.82919 2.65804 8.19255 2.5 8.57143 2.5H11.4286C11.8075 2.5 12.1708 2.65804 12.4387 2.93934C12.7066 3.22064 12.8571 3.60218 12.8571 4V5.5M15 5.5V16C15 16.3978 14.8495 16.7794 14.5816 17.0607C14.3137 17.342 13.9503 17.5 13.5714 17.5H6.42857C6.04969 17.5 5.68633 17.342 5.41842 17.0607C5.15051 16.7794 5 16.3978 5 16V5.5H15Z"
|
|
28
|
+
stroke={color}
|
|
29
|
+
strokeWidth="1.5"
|
|
30
|
+
strokeLinecap="round"
|
|
31
|
+
strokeLinejoin="round"
|
|
32
|
+
/>
|
|
33
|
+
<path
|
|
34
|
+
d="M8.33203 9.23724V13.4039"
|
|
35
|
+
stroke={color}
|
|
36
|
+
strokeWidth="1.5"
|
|
37
|
+
strokeLinecap="round"
|
|
38
|
+
strokeLinejoin="round"
|
|
39
|
+
/>
|
|
40
|
+
<path
|
|
41
|
+
d="M11.666 9.23724V13.4039"
|
|
42
|
+
stroke={color}
|
|
43
|
+
strokeWidth="1.5"
|
|
44
|
+
strokeLinecap="round"
|
|
45
|
+
strokeLinejoin="round"
|
|
46
|
+
/>
|
|
47
|
+
</svg>
|
|
48
|
+
)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export default Trash
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import React from "react"
|
|
2
|
+
|
|
3
|
+
import { IconProps } from "types/icon"
|
|
4
|
+
|
|
5
|
+
const User: React.FC<IconProps> = ({
|
|
6
|
+
size = "16",
|
|
7
|
+
color = "currentColor",
|
|
8
|
+
...attributes
|
|
9
|
+
}) => {
|
|
10
|
+
return (
|
|
11
|
+
<svg
|
|
12
|
+
width={size}
|
|
13
|
+
height={size}
|
|
14
|
+
viewBox="0 0 20 20"
|
|
15
|
+
fill="none"
|
|
16
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
17
|
+
{...attributes}
|
|
18
|
+
>
|
|
19
|
+
<path
|
|
20
|
+
d="M16.6663 18V16.3333C16.6663 15.4493 16.3152 14.6014 15.69 13.9763C15.0649 13.3512 14.2171 13 13.333 13H6.66634C5.78229 13 4.93444 13.3512 4.30932 13.9763C3.6842 14.6014 3.33301 15.4493 3.33301 16.3333V18"
|
|
21
|
+
stroke={color}
|
|
22
|
+
strokeWidth="1.5"
|
|
23
|
+
strokeLinecap="round"
|
|
24
|
+
strokeLinejoin="round"
|
|
25
|
+
/>
|
|
26
|
+
<path
|
|
27
|
+
d="M10.0003 9.66667C11.8413 9.66667 13.3337 8.17428 13.3337 6.33333C13.3337 4.49238 11.8413 3 10.0003 3C8.15938 3 6.66699 4.49238 6.66699 6.33333C6.66699 8.17428 8.15938 9.66667 10.0003 9.66667Z"
|
|
28
|
+
stroke={color}
|
|
29
|
+
strokeWidth="1.5"
|
|
30
|
+
strokeLinecap="round"
|
|
31
|
+
strokeLinejoin="round"
|
|
32
|
+
/>
|
|
33
|
+
</svg>
|
|
34
|
+
)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export default User
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import React from "react"
|
|
2
|
+
|
|
3
|
+
import { IconProps } from "types/icon"
|
|
4
|
+
|
|
5
|
+
const X: React.FC<IconProps> = ({
|
|
6
|
+
size = "20",
|
|
7
|
+
color = "currentColor",
|
|
8
|
+
...attributes
|
|
9
|
+
}) => {
|
|
10
|
+
return (
|
|
11
|
+
<svg
|
|
12
|
+
width={size}
|
|
13
|
+
height={size}
|
|
14
|
+
viewBox="0 0 20 20"
|
|
15
|
+
fill="none"
|
|
16
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
17
|
+
{...attributes}
|
|
18
|
+
>
|
|
19
|
+
<path
|
|
20
|
+
d="M15 5L5 15"
|
|
21
|
+
stroke={color}
|
|
22
|
+
strokeWidth="1.5"
|
|
23
|
+
strokeLinecap="round"
|
|
24
|
+
strokeLinejoin="round"
|
|
25
|
+
/>
|
|
26
|
+
<path
|
|
27
|
+
d="M5 5L15 15"
|
|
28
|
+
stroke={color}
|
|
29
|
+
strokeWidth="1.5"
|
|
30
|
+
strokeLinecap="round"
|
|
31
|
+
strokeLinejoin="round"
|
|
32
|
+
/>
|
|
33
|
+
</svg>
|
|
34
|
+
)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export default X
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { CreditCard } from "@medusajs/icons";
|
|
3
|
+
import Ideal from "medusa-ui-common/common/icons/ideal";
|
|
4
|
+
import Bancontact from "medusa-ui-common/common/icons/bancontact";
|
|
5
|
+
import PayPal from "medusa-ui-common/common/icons/paypal";
|
|
6
|
+
|
|
7
|
+
export const paymentInfoMap: Record<string, { title: string; icon: React.JSX.Element }> = {
|
|
8
|
+
pp_stripe_stripe: { title: "Credit card", icon: <CreditCard /> },
|
|
9
|
+
"pp_medusa-payments_default": { title: "Credit card", icon: <CreditCard /> },
|
|
10
|
+
"pp_stripe-ideal_stripe": { title: "iDeal", icon: <Ideal /> },
|
|
11
|
+
"pp_stripe-bancontact_stripe": { title: "Bancontact", icon: <Bancontact /> },
|
|
12
|
+
pp_paypal_paypal: { title: "PayPal", icon: <PayPal /> },
|
|
13
|
+
pp_system_default: { title: "Cash on Delivery (Cash/UPI)", icon: <CreditCard /> },
|
|
14
|
+
razorpay: { title: "Razorpay", icon: <CreditCard /> },
|
|
15
|
+
pp_razorpay_razorpay: { title: "Razorpay", icon: <CreditCard /> },
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const isStripeLike = (providerId?: string) =>
|
|
19
|
+
providerId?.startsWith("pp_stripe_") || providerId?.startsWith("pp_medusa-");
|
|
20
|
+
|
|
21
|
+
export const isPaypal = (providerId?: string) => providerId?.startsWith("pp_paypal");
|
|
22
|
+
|
|
23
|
+
export const isManual = (providerId?: string) => providerId?.startsWith("pp_system_default");
|
|
24
|
+
|
|
25
|
+
export const isRazorpay = (providerId?: string) =>
|
|
26
|
+
providerId?.startsWith("razorpay") || providerId?.startsWith("pp_razorpay");
|
|
27
|
+
|
|
28
|
+
export const noDivisionCurrencies = [
|
|
29
|
+
"krw", "jpy", "vnd", "clp", "pyg", "xaf", "xof", "bif", "djf", "gnf", "kmf", "mga", "rwf",
|
|
30
|
+
"xpf", "htg", "vuv", "xag", "xdr", "xau",
|
|
31
|
+
];
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import React, { createContext, useContext, useState } from "react"
|
|
4
|
+
|
|
5
|
+
interface ModalContextType {
|
|
6
|
+
isModalOpen: boolean
|
|
7
|
+
setIsModalOpen: (isOpen: boolean) => void
|
|
8
|
+
close: () => void
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const ModalContext = createContext<ModalContextType | undefined>(undefined)
|
|
12
|
+
|
|
13
|
+
export const ModalProvider: React.FC<{ children: React.ReactNode; close?: () => void }> = ({ children, close: closeProp }) => {
|
|
14
|
+
const [isModalOpen, setIsModalOpen] = useState(false)
|
|
15
|
+
|
|
16
|
+
const close = () => {
|
|
17
|
+
if (closeProp) {
|
|
18
|
+
closeProp()
|
|
19
|
+
} else {
|
|
20
|
+
setIsModalOpen(false)
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<ModalContext.Provider value={{ isModalOpen, setIsModalOpen, close }}>
|
|
26
|
+
{children}
|
|
27
|
+
</ModalContext.Provider>
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export const useModal = () => {
|
|
32
|
+
const context = useContext(ModalContext)
|
|
33
|
+
if (context === undefined) {
|
|
34
|
+
throw new Error("useModal must be used within a ModalProvider")
|
|
35
|
+
}
|
|
36
|
+
return context
|
|
37
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import React, { createContext, useContext, useState, useEffect, useCallback } from "react"
|
|
4
|
+
import { getWishlistProductIds, addToWishlist as addToWishlistApi, removeFromWishlist as removeFromWishlistApi } from "medusa-wishlist-logic/server"
|
|
5
|
+
import { trackAddToWishlist } from "medusa-storefront-analytics"
|
|
6
|
+
|
|
7
|
+
interface WishlistContextType {
|
|
8
|
+
wishlistIds: string[]
|
|
9
|
+
count: number
|
|
10
|
+
isWishlisted: (productId: string) => boolean
|
|
11
|
+
toggleWishlist: (productId: string) => Promise<{ success: boolean; error?: string }>
|
|
12
|
+
refreshWishlist: () => Promise<void>
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const WishlistContext = createContext<WishlistContextType | undefined>(undefined)
|
|
16
|
+
|
|
17
|
+
export const WishlistProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
|
18
|
+
const [wishlistIds, setWishlistIds] = useState<string[]>([])
|
|
19
|
+
|
|
20
|
+
const refreshWishlist = useCallback(async () => {
|
|
21
|
+
try {
|
|
22
|
+
const ids = await getWishlistProductIds()
|
|
23
|
+
setWishlistIds(ids)
|
|
24
|
+
} catch (error) {
|
|
25
|
+
// Error silently ignored for production
|
|
26
|
+
}
|
|
27
|
+
}, [])
|
|
28
|
+
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
refreshWishlist()
|
|
31
|
+
}, [refreshWishlist])
|
|
32
|
+
|
|
33
|
+
const isWishlisted = useCallback((productId: string) => {
|
|
34
|
+
return wishlistIds.includes(productId)
|
|
35
|
+
}, [wishlistIds])
|
|
36
|
+
|
|
37
|
+
const toggleWishlist = async (productId: string) => {
|
|
38
|
+
const currentlyWishlisted = isWishlisted(productId)
|
|
39
|
+
|
|
40
|
+
try {
|
|
41
|
+
if (currentlyWishlisted) {
|
|
42
|
+
const result = await removeFromWishlistApi(productId)
|
|
43
|
+
if (result.success) {
|
|
44
|
+
setWishlistIds(prev => prev.filter(id => id !== productId))
|
|
45
|
+
return { success: true }
|
|
46
|
+
}
|
|
47
|
+
return { success: false, error: result.error }
|
|
48
|
+
} else {
|
|
49
|
+
const result = await addToWishlistApi(productId)
|
|
50
|
+
if (result.success) {
|
|
51
|
+
setWishlistIds(prev => [...prev, productId])
|
|
52
|
+
trackAddToWishlist({ content_ids: [productId] })
|
|
53
|
+
return { success: true }
|
|
54
|
+
}
|
|
55
|
+
return { success: false, error: result.error }
|
|
56
|
+
}
|
|
57
|
+
} catch (error: any) {
|
|
58
|
+
return { success: false, error: error.message || "An error occurred" }
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return (
|
|
63
|
+
<WishlistContext.Provider
|
|
64
|
+
value={{
|
|
65
|
+
wishlistIds,
|
|
66
|
+
count: wishlistIds.length,
|
|
67
|
+
isWishlisted,
|
|
68
|
+
toggleWishlist,
|
|
69
|
+
refreshWishlist,
|
|
70
|
+
}}
|
|
71
|
+
>
|
|
72
|
+
{children}
|
|
73
|
+
</WishlistContext.Provider>
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export const useWishlist = () => {
|
|
78
|
+
const context = useContext(WishlistContext)
|
|
79
|
+
if (context === undefined) {
|
|
80
|
+
throw new Error("useWishlist must be used within a WishlistProvider")
|
|
81
|
+
}
|
|
82
|
+
return context
|
|
83
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** Shared contexts */
|
|
2
|
+
export { ModalProvider, useModal } from "./context/modal-context";
|
|
3
|
+
export { WishlistProvider, useWishlist } from "./context/wishlist-context";
|
|
4
|
+
|
|
5
|
+
/** Utilities */
|
|
6
|
+
export { getBaseURL } from "./util/env";
|
|
7
|
+
export { getProductPrice, getPricesForVariant } from "./util/get-product-price";
|
|
8
|
+
export { convertToLocale } from "./util/money";
|
|
9
|
+
export {
|
|
10
|
+
paymentInfoMap,
|
|
11
|
+
isStripeLike,
|
|
12
|
+
isPaypal,
|
|
13
|
+
isManual,
|
|
14
|
+
isRazorpay,
|
|
15
|
+
noDivisionCurrencies,
|
|
16
|
+
} from "./constants/payments";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
const SkeletonCardDetails = () => {
|
|
2
|
+
return (
|
|
3
|
+
<div className="flex flex-col gap-1 my-4 transition-all duration-150 ease-in-out">
|
|
4
|
+
<div className="h-4 bg-ui-bg-component-pressed rounded-md w-1/4 animate-pulse mb-1"></div>
|
|
5
|
+
<div className="pt-3 pb-1 block w-full h-11 px-4 mt-0 bg-ui-bg-field border rounded-md appearance-none border-ui-border-base animate-pulse" />
|
|
6
|
+
</div>
|
|
7
|
+
)
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export default SkeletonCardDetails
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Table } from "@medusajs/ui"
|
|
2
|
+
|
|
3
|
+
const SkeletonCartItem = () => {
|
|
4
|
+
return (
|
|
5
|
+
<Table.Row className="w-full m-4">
|
|
6
|
+
<Table.Cell className="!pl-0 p-4 w-24">
|
|
7
|
+
<div className="flex w-24 h-24 p-4 bg-gray-200 rounded-large animate-pulse" />
|
|
8
|
+
</Table.Cell>
|
|
9
|
+
<Table.Cell className="text-left">
|
|
10
|
+
<div className="flex flex-col gap-y-2">
|
|
11
|
+
<div className="w-32 h-4 bg-gray-200 animate-pulse" />
|
|
12
|
+
<div className="w-24 h-4 bg-gray-200 animate-pulse" />
|
|
13
|
+
</div>
|
|
14
|
+
</Table.Cell>
|
|
15
|
+
<Table.Cell>
|
|
16
|
+
<div className="flex gap-2 items-center">
|
|
17
|
+
<div className="w-6 h-8 bg-gray-200 animate-pulse" />
|
|
18
|
+
<div className="w-14 h-10 bg-gray-200 animate-pulse" />
|
|
19
|
+
</div>
|
|
20
|
+
</Table.Cell>
|
|
21
|
+
<Table.Cell>
|
|
22
|
+
<div className="flex gap-2">
|
|
23
|
+
<div className="w-12 h-6 bg-gray-200 animate-pulse" />
|
|
24
|
+
</div>
|
|
25
|
+
</Table.Cell>
|
|
26
|
+
<Table.Cell className="!pr-0 text-right">
|
|
27
|
+
<div className="flex gap-2 justify-end">
|
|
28
|
+
<div className="w-12 h-6 bg-gray-200 animate-pulse" />
|
|
29
|
+
</div>
|
|
30
|
+
</Table.Cell>
|
|
31
|
+
</Table.Row>
|
|
32
|
+
)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export default SkeletonCartItem
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
const SkeletonCartTotals = ({ header = true }) => {
|
|
2
|
+
return (
|
|
3
|
+
<div className="flex flex-col">
|
|
4
|
+
{header && <div className="w-32 h-4 bg-gray-100 mb-4"></div>}
|
|
5
|
+
<div className="flex items-center justify-between">
|
|
6
|
+
<div className="w-32 h-3 bg-gray-100"></div>
|
|
7
|
+
<div className="w-32 h-3 bg-gray-100"></div>
|
|
8
|
+
</div>
|
|
9
|
+
|
|
10
|
+
<div className="flex items-center justify-between my-4">
|
|
11
|
+
<div className="w-24 h-3 bg-gray-100"></div>
|
|
12
|
+
<div className="w-24 h-3 bg-gray-100"></div>
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
<div className="flex items-center justify-between">
|
|
16
|
+
<div className="w-28 h-3 bg-gray-100 "></div>
|
|
17
|
+
<div className="w-20 h-3 bg-gray-100"></div>
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
<div className="w-full border-b border-gray-200 border-dashed my-4"></div>
|
|
21
|
+
|
|
22
|
+
<div className="flex items-center justify-between">
|
|
23
|
+
<div className="w-32 h-6 bg-gray-100 mb-4"></div>
|
|
24
|
+
<div className="w-24 h-6 bg-gray-100 mb-4"></div>
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export default SkeletonCartTotals
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const SkeletonCodeForm = () => {
|
|
2
|
+
return (
|
|
3
|
+
<div className="w-full flex flex-col">
|
|
4
|
+
<div className="bg-gray-100 h-7 w-24 mb-4"></div>
|
|
5
|
+
<div className="grid grid-cols-[1fr_80px] gap-x-2">
|
|
6
|
+
<div className="bg-gray-100 h-12"></div>
|
|
7
|
+
<div className="bg-gray-100 h-12"></div>
|
|
8
|
+
</div>
|
|
9
|
+
</div>
|
|
10
|
+
)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export default SkeletonCodeForm
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Table } from "@medusajs/ui"
|
|
2
|
+
|
|
3
|
+
const SkeletonLineItem = () => {
|
|
4
|
+
return (
|
|
5
|
+
<Table.Row className="w-full m-4">
|
|
6
|
+
<Table.Cell className="p-4 w-24">
|
|
7
|
+
<div className="flex w-24 h-24 p-4 bg-gray-200 animate-pulse" />
|
|
8
|
+
</Table.Cell>
|
|
9
|
+
<Table.Cell className="text-left">
|
|
10
|
+
<div className="flex flex-col gap-y-2">
|
|
11
|
+
<div className="w-32 h-4 bg-gray-200 animate-pulse" />
|
|
12
|
+
<div className="w-24 h-4 bg-gray-200 animate-pulse" />
|
|
13
|
+
</div>
|
|
14
|
+
</Table.Cell>
|
|
15
|
+
<Table.Cell>
|
|
16
|
+
<div className="flex gap-2 items-center">
|
|
17
|
+
<div className="w-6 h-8 bg-gray-200 animate-pulse" />
|
|
18
|
+
<div className="w-14 h-10 bg-gray-200 animate-pulse" />
|
|
19
|
+
</div>
|
|
20
|
+
</Table.Cell>
|
|
21
|
+
<Table.Cell>
|
|
22
|
+
<div className="flex gap-2">
|
|
23
|
+
<div className="w-12 h-6 bg-gray-200 animate-pulse" />
|
|
24
|
+
</div>
|
|
25
|
+
</Table.Cell>
|
|
26
|
+
<Table.Cell>
|
|
27
|
+
<div className="flex gap-2 justify-end">
|
|
28
|
+
<div className="w-12 h-6 bg-gray-200 animate-pulse" />
|
|
29
|
+
</div>
|
|
30
|
+
</Table.Cell>
|
|
31
|
+
</Table.Row>
|
|
32
|
+
)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export default SkeletonLineItem
|