@gfed-medusa/sf-lib-common 1.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.
Files changed (266) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +38 -0
  3. package/dist/apollo-client-BuznVAE4.js +66 -0
  4. package/dist/apollo-client-BuznVAE4.js.map +1 -0
  5. package/dist/cart-CLJvIUQC.js +103 -0
  6. package/dist/cart-CLJvIUQC.js.map +1 -0
  7. package/dist/cart-D99u8SUJ.js +16 -0
  8. package/dist/cart-D99u8SUJ.js.map +1 -0
  9. package/dist/cart-XQIczSA1.js +42 -0
  10. package/dist/cart-XQIczSA1.js.map +1 -0
  11. package/dist/cart-button-NgoZb9LI.js +12 -0
  12. package/dist/cart-button-NgoZb9LI.js.map +1 -0
  13. package/dist/cart-dropdown-_ZpvhX--.js +195 -0
  14. package/dist/cart-dropdown-_ZpvhX--.js.map +1 -0
  15. package/dist/cart-p3ffQQ5R.js +142 -0
  16. package/dist/cart-p3ffQQ5R.js.map +1 -0
  17. package/dist/categories-BCbIwAcV.js +16 -0
  18. package/dist/categories-BCbIwAcV.js.map +1 -0
  19. package/dist/collections-Buw8B8l9.js +20 -0
  20. package/dist/collections-Buw8B8l9.js.map +1 -0
  21. package/dist/collections-Dkcq21tC.js +22 -0
  22. package/dist/collections-Dkcq21tC.js.map +1 -0
  23. package/dist/components/breadcrumbs/index.d.ts +22 -0
  24. package/dist/components/breadcrumbs/index.d.ts.map +1 -0
  25. package/dist/components/breadcrumbs/index.js +54 -0
  26. package/dist/components/breadcrumbs/index.js.map +1 -0
  27. package/dist/components/cart-button/index.d.ts +7 -0
  28. package/dist/components/cart-button/index.d.ts.map +1 -0
  29. package/dist/components/cart-button/index.js +18 -0
  30. package/dist/components/cart-dropdown/index.d.ts +12 -0
  31. package/dist/components/cart-dropdown/index.d.ts.map +1 -0
  32. package/dist/components/cart-dropdown/index.js +19 -0
  33. package/dist/components/cart-mismatch-banner/index.d.ts +11 -0
  34. package/dist/components/cart-mismatch-banner/index.d.ts.map +1 -0
  35. package/dist/components/cart-mismatch-banner/index.js +55 -0
  36. package/dist/components/cart-mismatch-banner/index.js.map +1 -0
  37. package/dist/components/country-select/index.d.ts +14 -0
  38. package/dist/components/country-select/index.d.ts.map +1 -0
  39. package/dist/components/country-select/index.js +31 -0
  40. package/dist/components/country-select/index.js.map +1 -0
  41. package/dist/components/delete-button/index.d.ts +15 -0
  42. package/dist/components/delete-button/index.d.ts.map +1 -0
  43. package/dist/components/delete-button/index.js +12 -0
  44. package/dist/components/error-message/index.d.ts +13 -0
  45. package/dist/components/error-message/index.d.ts.map +1 -0
  46. package/dist/components/error-message/index.js +15 -0
  47. package/dist/components/error-message/index.js.map +1 -0
  48. package/dist/components/footer/index.d.ts +7 -0
  49. package/dist/components/footer/index.d.ts.map +1 -0
  50. package/dist/components/footer/index.js +115 -0
  51. package/dist/components/footer/index.js.map +1 -0
  52. package/dist/components/free-shipping-price-nudge/index.d.ts +17 -0
  53. package/dist/components/free-shipping-price-nudge/index.d.ts.map +1 -0
  54. package/dist/components/free-shipping-price-nudge/index.js +182 -0
  55. package/dist/components/free-shipping-price-nudge/index.js.map +1 -0
  56. package/dist/components/interactive-link/index.d.ts +17 -0
  57. package/dist/components/interactive-link/index.d.ts.map +1 -0
  58. package/dist/components/interactive-link/index.js +25 -0
  59. package/dist/components/interactive-link/index.js.map +1 -0
  60. package/dist/components/layout-country-select/index.d.ts +16 -0
  61. package/dist/components/layout-country-select/index.d.ts.map +1 -0
  62. package/dist/components/layout-country-select/index.js +14 -0
  63. package/dist/components/line-item-options/index.d.ts +17 -0
  64. package/dist/components/line-item-options/index.d.ts.map +1 -0
  65. package/dist/components/line-item-options/index.js +3 -0
  66. package/dist/components/line-item-price/index.d.ts +17 -0
  67. package/dist/components/line-item-price/index.d.ts.map +1 -0
  68. package/dist/components/line-item-price/index.js +3 -0
  69. package/dist/components/localized-client-link/index.d.ts +24 -0
  70. package/dist/components/localized-client-link/index.d.ts.map +1 -0
  71. package/dist/components/localized-client-link/index.js +5 -0
  72. package/dist/components/modal/index.d.ts +39 -0
  73. package/dist/components/modal/index.d.ts.map +1 -0
  74. package/dist/components/modal/index.js +4 -0
  75. package/dist/components/nav/index.d.ts +7 -0
  76. package/dist/components/nav/index.d.ts.map +1 -0
  77. package/dist/components/nav/index.js +85 -0
  78. package/dist/components/nav/index.js.map +1 -0
  79. package/dist/components/portable-text/index.d.ts +13 -0
  80. package/dist/components/portable-text/index.d.ts.map +1 -0
  81. package/dist/components/portable-text/index.js +3 -0
  82. package/dist/components/preview-price/index.d.ts +12 -0
  83. package/dist/components/preview-price/index.d.ts.map +1 -0
  84. package/dist/components/preview-price/index.js +3 -0
  85. package/dist/components/product-card/index.d.ts +65 -0
  86. package/dist/components/product-card/index.d.ts.map +1 -0
  87. package/dist/components/product-card/index.js +146 -0
  88. package/dist/components/product-card/index.js.map +1 -0
  89. package/dist/components/product-preview/index.d.ts +15 -0
  90. package/dist/components/product-preview/index.d.ts.map +1 -0
  91. package/dist/components/product-preview/index.js +38 -0
  92. package/dist/components/product-preview/index.js.map +1 -0
  93. package/dist/components/search-modal/index.d.ts +12 -0
  94. package/dist/components/search-modal/index.d.ts.map +1 -0
  95. package/dist/components/search-modal/index.js +12 -0
  96. package/dist/components/side-menu/index.d.ts +12 -0
  97. package/dist/components/side-menu/index.d.ts.map +1 -0
  98. package/dist/components/side-menu/index.js +16 -0
  99. package/dist/components/submit-button/index.d.ts +20 -0
  100. package/dist/components/submit-button/index.d.ts.map +1 -0
  101. package/dist/components/submit-button/index.js +24 -0
  102. package/dist/components/submit-button/index.js.map +1 -0
  103. package/dist/components/thumbnail/index.d.ts +15 -0
  104. package/dist/components/thumbnail/index.d.ts.map +1 -0
  105. package/dist/components/thumbnail/index.js +3 -0
  106. package/dist/cookies-DANAjt8U.js +38 -0
  107. package/dist/cookies-DANAjt8U.js.map +1 -0
  108. package/dist/customer-GZZNI4eh.js +25 -0
  109. package/dist/customer-GZZNI4eh.js.map +1 -0
  110. package/dist/data-types-C_rGnTUp.js +10 -0
  111. package/dist/data-types-C_rGnTUp.js.map +1 -0
  112. package/dist/delete-button-Bfog7z-I.js +28 -0
  113. package/dist/delete-button-Bfog7z-I.js.map +1 -0
  114. package/dist/footer-BqaZhjlE.js +76 -0
  115. package/dist/footer-BqaZhjlE.js.map +1 -0
  116. package/dist/footer-fWFeFSUp.js +16 -0
  117. package/dist/footer-fWFeFSUp.js.map +1 -0
  118. package/dist/get-percentage-diff-CxGe_n9N.js +8 -0
  119. package/dist/get-percentage-diff-CxGe_n9N.js.map +1 -0
  120. package/dist/get-product-price-DxBbPmOZ.js +47 -0
  121. package/dist/get-product-price-DxBbPmOZ.js.map +1 -0
  122. package/dist/graphql-BWZPPI_N.d.ts +1368 -0
  123. package/dist/graphql-BWZPPI_N.d.ts.map +1 -0
  124. package/dist/layout-country-select-DrwpoVMM.js +90 -0
  125. package/dist/layout-country-select-DrwpoVMM.js.map +1 -0
  126. package/dist/lib/config/medusa.d.ts +7 -0
  127. package/dist/lib/config/medusa.d.ts.map +1 -0
  128. package/dist/lib/config/medusa.js +3 -0
  129. package/dist/lib/context/apollo-context.d.ts +10 -0
  130. package/dist/lib/context/apollo-context.d.ts.map +1 -0
  131. package/dist/lib/context/apollo-context.js +18 -0
  132. package/dist/lib/context/apollo-context.js.map +1 -0
  133. package/dist/lib/context/modal-context.d.ts +20 -0
  134. package/dist/lib/context/modal-context.d.ts.map +1 -0
  135. package/dist/lib/context/modal-context.js +5 -0
  136. package/dist/lib/data/cart.d.ts +24 -0
  137. package/dist/lib/data/cart.d.ts.map +1 -0
  138. package/dist/lib/data/cart.js +13 -0
  139. package/dist/lib/data/categories.d.ts +19 -0
  140. package/dist/lib/data/categories.d.ts.map +1 -0
  141. package/dist/lib/data/categories.js +6 -0
  142. package/dist/lib/data/collections.d.ts +14 -0
  143. package/dist/lib/data/collections.d.ts.map +1 -0
  144. package/dist/lib/data/collections.js +8 -0
  145. package/dist/lib/data/cookies.d.ts +15 -0
  146. package/dist/lib/data/cookies.d.ts.map +1 -0
  147. package/dist/lib/data/cookies.js +3 -0
  148. package/dist/lib/data/customer.d.ts +7 -0
  149. package/dist/lib/data/customer.d.ts.map +1 -0
  150. package/dist/lib/data/customer.js +8 -0
  151. package/dist/lib/data/footer.d.ts +75 -0
  152. package/dist/lib/data/footer.d.ts.map +1 -0
  153. package/dist/lib/data/footer.js +5 -0
  154. package/dist/lib/data/regions.d.ts +8 -0
  155. package/dist/lib/data/regions.d.ts.map +1 -0
  156. package/dist/lib/data/regions.js +5 -0
  157. package/dist/lib/data/search.d.ts +9 -0
  158. package/dist/lib/data/search.d.ts.map +1 -0
  159. package/dist/lib/data/search.js +8 -0
  160. package/dist/lib/gql/apollo-client.d.ts +18 -0
  161. package/dist/lib/gql/apollo-client.d.ts.map +1 -0
  162. package/dist/lib/gql/apollo-client.js +3 -0
  163. package/dist/lib/gql/fragments/cart.d.ts +14 -0
  164. package/dist/lib/gql/fragments/cart.d.ts.map +1 -0
  165. package/dist/lib/gql/fragments/cart.js +4 -0
  166. package/dist/lib/gql/fragments/product.d.ts +13 -0
  167. package/dist/lib/gql/fragments/product.d.ts.map +1 -0
  168. package/dist/lib/gql/fragments/product.js +3 -0
  169. package/dist/lib/gql/mutations/cart.d.ts +9 -0
  170. package/dist/lib/gql/mutations/cart.d.ts.map +1 -0
  171. package/dist/lib/gql/mutations/cart.js +5 -0
  172. package/dist/lib/gql/mutations/customer.d.ts +1 -0
  173. package/dist/lib/gql/mutations/customer.js +1 -0
  174. package/dist/lib/gql/queries/cart.d.ts +7 -0
  175. package/dist/lib/gql/queries/cart.d.ts.map +1 -0
  176. package/dist/lib/gql/queries/cart.js +5 -0
  177. package/dist/lib/gql/queries/collections.d.ts +7 -0
  178. package/dist/lib/gql/queries/collections.d.ts.map +1 -0
  179. package/dist/lib/gql/queries/collections.js +4 -0
  180. package/dist/lib/gql/queries/footer.d.ts +7 -0
  181. package/dist/lib/gql/queries/footer.d.ts.map +1 -0
  182. package/dist/lib/gql/queries/footer.js +3 -0
  183. package/dist/lib/gql/queries/product.d.ts +8 -0
  184. package/dist/lib/gql/queries/product.d.ts.map +1 -0
  185. package/dist/lib/gql/queries/product.js +4 -0
  186. package/dist/lib/hooks/use-apollo.d.ts +7 -0
  187. package/dist/lib/hooks/use-apollo.d.ts.map +1 -0
  188. package/dist/lib/hooks/use-apollo.js +4 -0
  189. package/dist/lib/hooks/use-search.d.ts +22 -0
  190. package/dist/lib/hooks/use-search.d.ts.map +1 -0
  191. package/dist/lib/hooks/use-search.js +9 -0
  192. package/dist/lib/hooks/use-toggle-state.d.ts +2 -0
  193. package/dist/lib/hooks/use-toggle-state.js +43 -0
  194. package/dist/lib/hooks/use-toggle-state.js.map +1 -0
  195. package/dist/lib/utils/data-types.d.ts +7 -0
  196. package/dist/lib/utils/data-types.d.ts.map +1 -0
  197. package/dist/lib/utils/data-types.js +3 -0
  198. package/dist/lib/utils/env.d.ts +5 -0
  199. package/dist/lib/utils/env.d.ts.map +1 -0
  200. package/dist/lib/utils/env.js +8 -0
  201. package/dist/lib/utils/env.js.map +1 -0
  202. package/dist/lib/utils/get-percentage-diff.d.ts +5 -0
  203. package/dist/lib/utils/get-percentage-diff.d.ts.map +1 -0
  204. package/dist/lib/utils/get-percentage-diff.js +3 -0
  205. package/dist/lib/utils/get-product-price.d.ts +42 -0
  206. package/dist/lib/utils/get-product-price.d.ts.map +1 -0
  207. package/dist/lib/utils/get-product-price.js +3 -0
  208. package/dist/lib/utils/medusa-error.d.ts +5 -0
  209. package/dist/lib/utils/medusa-error.d.ts.map +1 -0
  210. package/dist/lib/utils/medusa-error.js +3 -0
  211. package/dist/lib/utils/money.d.ts +18 -0
  212. package/dist/lib/utils/money.d.ts.map +1 -0
  213. package/dist/lib/utils/money.js +3 -0
  214. package/dist/lib/utils/normalize-functions.d.ts +8 -0
  215. package/dist/lib/utils/normalize-functions.d.ts.map +1 -0
  216. package/dist/lib/utils/normalize-functions.js +3 -0
  217. package/dist/line-item-options-B3rbud31.js +16 -0
  218. package/dist/line-item-options-B3rbud31.js.map +1 -0
  219. package/dist/line-item-price-BBlC_T8m.js +47 -0
  220. package/dist/line-item-price-BBlC_T8m.js.map +1 -0
  221. package/dist/localized-client-link-C3mE37Ub.js +22 -0
  222. package/dist/localized-client-link-C3mE37Ub.js.map +1 -0
  223. package/dist/medusa-C1jfAM1B.js +12 -0
  224. package/dist/medusa-C1jfAM1B.js.map +1 -0
  225. package/dist/medusa-error-Cf_eEPhR.js +17 -0
  226. package/dist/medusa-error-Cf_eEPhR.js.map +1 -0
  227. package/dist/modal-C-crvjtF.js +102 -0
  228. package/dist/modal-C-crvjtF.js.map +1 -0
  229. package/dist/modal-context-D-ugwFUM.js +20 -0
  230. package/dist/modal-context-D-ugwFUM.js.map +1 -0
  231. package/dist/money-BrwiFQUW.js +15 -0
  232. package/dist/money-BrwiFQUW.js.map +1 -0
  233. package/dist/normalize-functions-BIuKc_-k.js +15 -0
  234. package/dist/normalize-functions-BIuKc_-k.js.map +1 -0
  235. package/dist/portable-text-DSWXgovn.js +330 -0
  236. package/dist/portable-text-DSWXgovn.js.map +1 -0
  237. package/dist/preview-price-D_GqXrT4.js +20 -0
  238. package/dist/preview-price-D_GqXrT4.js.map +1 -0
  239. package/dist/prices-IWR3xm6o.d.ts +20 -0
  240. package/dist/prices-IWR3xm6o.d.ts.map +1 -0
  241. package/dist/product-Cgtch-vz.js +90 -0
  242. package/dist/product-Cgtch-vz.js.map +1 -0
  243. package/dist/product-DMWvgZkb.js +47 -0
  244. package/dist/product-DMWvgZkb.js.map +1 -0
  245. package/dist/regions-CF6DH579.js +34 -0
  246. package/dist/regions-CF6DH579.js.map +1 -0
  247. package/dist/search-CKhI5RO4.js +21 -0
  248. package/dist/search-CKhI5RO4.js.map +1 -0
  249. package/dist/search-modal-D1tgUDXQ.js +137 -0
  250. package/dist/search-modal-D1tgUDXQ.js.map +1 -0
  251. package/dist/side-menu-ByDXpZJO.js +97 -0
  252. package/dist/side-menu-ByDXpZJO.js.map +1 -0
  253. package/dist/thumbnail-CXIliWAD.js +44 -0
  254. package/dist/thumbnail-CXIliWAD.js.map +1 -0
  255. package/dist/types/graphql.d.ts +2 -0
  256. package/dist/types/graphql.js +14516 -0
  257. package/dist/types/graphql.js.map +1 -0
  258. package/dist/types/prices.d.ts +2 -0
  259. package/dist/types/prices.js +1 -0
  260. package/dist/use-apollo-q4uz05i-.js +11 -0
  261. package/dist/use-apollo-q4uz05i-.js.map +1 -0
  262. package/dist/use-search-BTEnFlC0.js +67 -0
  263. package/dist/use-search-BTEnFlC0.js.map +1 -0
  264. package/dist/use-toggle-state-zIAKMNfR.d.ts +23 -0
  265. package/dist/use-toggle-state-zIAKMNfR.d.ts.map +1 -0
  266. package/package.json +94 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 goodfrontend
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,38 @@
1
+ # GFED Medusa Storefront Common Library
2
+
3
+ This is the common library for the GFED Medusa Storefront stack. It contains shared components, utilities, types, and other resources.
4
+
5
+ ## Installation
6
+
7
+ Install the package from npm:
8
+
9
+ ```bash
10
+ pnpm add @gfed-medusa/sf-lib-common
11
+ ```
12
+
13
+ For monorepo or local development, you can use the workspace directive to ensure installation of the latest version locally:
14
+
15
+ ```json
16
+ {
17
+ "dependencies": {
18
+ "@gfed-medusa/sf-lib-common": "workspace:*"
19
+ }
20
+ }
21
+ ```
22
+
23
+ ## Usage
24
+
25
+ Import components and other resources into your application:
26
+
27
+ ```tsx
28
+ import { Breadcrumbs } from '@gfed-medusa/sf-lib-common/components/breadcrumbs';
29
+ import { useToggleState } from '@gfed-medusa/sf-lib-common/lib/hooks/use-toggle-state';
30
+ ```
31
+
32
+ ## Codegen
33
+
34
+ To generate GraphQL types, ensure that `BFF_URL` is defined in your `.env` file and then run:
35
+
36
+ ```bash
37
+ pnpm codegen
38
+ ```
@@ -0,0 +1,66 @@
1
+ import { ApolloClient, ApolloLink, HttpLink, InMemoryCache } from "@apollo/client";
2
+
3
+ //#region src/lib/gql/apollo-client.ts
4
+ const isServer = () => typeof window === "undefined";
5
+ const httpLink = new HttpLink({
6
+ uri: isServer() ? `${process.env.NEXT_PUBLIC_BASE_URL}/api/graphql` : "/api/graphql",
7
+ credentials: "include"
8
+ });
9
+ const apolloClient = new ApolloClient({
10
+ link: httpLink,
11
+ cache: new InMemoryCache({}),
12
+ defaultOptions: { watchQuery: { notifyOnNetworkStatusChange: true } }
13
+ });
14
+ /**
15
+ * When requests are sent from the server, cookies need to be manually attached.
16
+ *
17
+ * @param cookieHeader Cookies string to forward
18
+ * @returns Server-side Apollo client
19
+ */
20
+ function createServerApolloClient(cookieHeader) {
21
+ return new ApolloClient({
22
+ link: new ApolloLink((operation, forward) => {
23
+ if (cookieHeader) operation.setContext(({ headers = {} }) => ({ headers: {
24
+ ...headers,
25
+ Cookie: cookieHeader
26
+ } }));
27
+ return forward(operation);
28
+ }).concat(httpLink),
29
+ cache: new InMemoryCache({}),
30
+ defaultOptions: { watchQuery: { notifyOnNetworkStatusChange: true } }
31
+ });
32
+ }
33
+ function initializeApollo(req = null) {
34
+ if (isServer()) {
35
+ const cookieHeader = req?.headers.cookie;
36
+ return createServerApolloClient(cookieHeader);
37
+ }
38
+ return apolloClient;
39
+ }
40
+ async function graphqlFetch(options, apolloClientOverride) {
41
+ try {
42
+ const { data } = await (apolloClientOverride || apolloClient).query({
43
+ ...options,
44
+ fetchPolicy: "network-only"
45
+ });
46
+ return data;
47
+ } catch (error) {
48
+ throw new Error(error.message || "GraphQL error");
49
+ }
50
+ }
51
+ async function graphqlMutation(options, apolloClientOverride) {
52
+ try {
53
+ const { data } = await (apolloClientOverride || apolloClient).mutate({
54
+ ...options,
55
+ fetchPolicy: "network-only"
56
+ });
57
+ return data;
58
+ } catch (error) {
59
+ throw new Error(error.message || "GraphQL error");
60
+ }
61
+ }
62
+ var apollo_client_default = apolloClient;
63
+
64
+ //#endregion
65
+ export { initializeApollo as a, graphqlMutation as i, createServerApolloClient as n, graphqlFetch as r, apollo_client_default as t };
66
+ //# sourceMappingURL=apollo-client-BuznVAE4.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apollo-client-BuznVAE4.js","names":["error: any"],"sources":["../src/lib/gql/apollo-client.ts"],"sourcesContent":["import { IncomingMessage } from 'http';\n\nimport { ApolloLink } from '@apollo/client';\nimport {\n ApolloClient,\n HttpLink,\n InMemoryCache,\n OperationVariables,\n} from '@apollo/client';\n\nconst isServer = () => typeof window === 'undefined';\n\nconst httpLink = new HttpLink({\n uri: isServer()\n ? `${process.env.NEXT_PUBLIC_BASE_URL}/api/graphql`\n : '/api/graphql',\n credentials: 'include',\n});\n\nconst apolloClient = new ApolloClient({\n link: httpLink,\n cache: new InMemoryCache({}),\n defaultOptions: {\n watchQuery: {\n notifyOnNetworkStatusChange: true,\n },\n },\n});\n\n/**\n * When requests are sent from the server, cookies need to be manually attached.\n *\n * @param cookieHeader Cookies string to forward\n * @returns Server-side Apollo client\n */\nexport function createServerApolloClient(cookieHeader?: string) {\n const authLink = new ApolloLink((operation, forward) => {\n if (cookieHeader) {\n operation.setContext(({ headers = {} }) => ({\n headers: {\n ...headers,\n Cookie: cookieHeader,\n },\n }));\n }\n return forward(operation);\n });\n\n return new ApolloClient({\n link: authLink.concat(httpLink),\n cache: new InMemoryCache({}),\n defaultOptions: {\n watchQuery: {\n notifyOnNetworkStatusChange: true,\n },\n },\n });\n}\n\nexport function initializeApollo(req: IncomingMessage | null = null) {\n if (isServer()) {\n const cookieHeader = req?.headers.cookie;\n return createServerApolloClient(cookieHeader);\n }\n\n return apolloClient;\n}\n\nexport async function graphqlFetch<\n TResult,\n TVariables extends OperationVariables,\n>(\n options: ApolloClient.QueryOptions<TResult, TVariables>,\n apolloClientOverride?: ApolloClient\n): Promise<TResult | undefined> {\n try {\n const client = apolloClientOverride || apolloClient;\n\n const { data } = await client.query<TResult, TVariables>({\n ...options,\n fetchPolicy: 'network-only',\n });\n\n return data;\n } catch (error: any) {\n // TODO - Better error handling\n throw new Error(error.message || 'GraphQL error');\n }\n}\n\nexport async function graphqlMutation<\n TResult,\n TVariables extends OperationVariables,\n>(\n options: ApolloClient.MutateOptions<TResult, TVariables>,\n apolloClientOverride?: ApolloClient\n): Promise<TResult | undefined> {\n try {\n const client = apolloClientOverride || apolloClient;\n\n const { data } = await client.mutate<TResult, TVariables>({\n ...options,\n fetchPolicy: 'network-only',\n });\n\n return data;\n } catch (error: any) {\n // TODO - Better error handling\n throw new Error(error.message || 'GraphQL error');\n }\n}\nexport default apolloClient;\n"],"mappings":";;;AAUA,MAAM,iBAAiB,OAAO,WAAW;AAEzC,MAAM,WAAW,IAAI,SAAS;CAC5B,KAAK,UAAU,GACX,GAAG,QAAQ,IAAI,qBAAqB,gBACpC;CACJ,aAAa;CACd,CAAC;AAEF,MAAM,eAAe,IAAI,aAAa;CACpC,MAAM;CACN,OAAO,IAAI,cAAc,EAAE,CAAC;CAC5B,gBAAgB,EACd,YAAY,EACV,6BAA6B,MAC9B,EACF;CACF,CAAC;;;;;;;AAQF,SAAgB,yBAAyB,cAAuB;AAa9D,QAAO,IAAI,aAAa;EACtB,MAbe,IAAI,YAAY,WAAW,YAAY;AACtD,OAAI,aACF,WAAU,YAAY,EAAE,UAAU,EAAE,QAAQ,EAC1C,SAAS;IACP,GAAG;IACH,QAAQ;IACT,EACF,EAAE;AAEL,UAAO,QAAQ,UAAU;IACzB,CAGe,OAAO,SAAS;EAC/B,OAAO,IAAI,cAAc,EAAE,CAAC;EAC5B,gBAAgB,EACd,YAAY,EACV,6BAA6B,MAC9B,EACF;EACF,CAAC;;AAGJ,SAAgB,iBAAiB,MAA8B,MAAM;AACnE,KAAI,UAAU,EAAE;EACd,MAAM,eAAe,KAAK,QAAQ;AAClC,SAAO,yBAAyB,aAAa;;AAG/C,QAAO;;AAGT,eAAsB,aAIpB,SACA,sBAC8B;AAC9B,KAAI;EAGF,MAAM,EAAE,SAAS,OAFF,wBAAwB,cAET,MAA2B;GACvD,GAAG;GACH,aAAa;GACd,CAAC;AAEF,SAAO;UACAA,OAAY;AAEnB,QAAM,IAAI,MAAM,MAAM,WAAW,gBAAgB;;;AAIrD,eAAsB,gBAIpB,SACA,sBAC8B;AAC9B,KAAI;EAGF,MAAM,EAAE,SAAS,OAFF,wBAAwB,cAET,OAA4B;GACxD,GAAG;GACH,aAAa;GACd,CAAC;AAEF,SAAO;UACAA,OAAY;AAEnB,QAAM,IAAI,MAAM,MAAM,WAAW,gBAAgB;;;AAGrD,4BAAe"}
@@ -0,0 +1,103 @@
1
+ import { t as sdk } from "./medusa-C1jfAM1B.js";
2
+ import { i as graphqlMutation, r as graphqlFetch } from "./apollo-client-BuznVAE4.js";
3
+ import { r as UPDATE_CART_MUTATION, t as DELETE_LINE_ITEM_MUTATION } from "./cart-XQIczSA1.js";
4
+ import { t as GET_CART_QUERY } from "./cart-D99u8SUJ.js";
5
+ import { t as medusaError } from "./medusa-error-Cf_eEPhR.js";
6
+ import { i as getCartId, n as getCacheOptions, r as getCacheTag, t as getAuthHeaders } from "./cookies-DANAjt8U.js";
7
+ import { t as getRegion } from "./regions-CF6DH579.js";
8
+ import { redirect } from "next/navigation";
9
+ import { revalidateTag } from "next/cache";
10
+
11
+ //#region src/lib/data/cart.ts
12
+ /**
13
+ * Retrieves a cart by its ID. If no ID is provided, it will use the cart ID from the cookies.
14
+ * @param cartId - optional - The ID of the cart to retrieve.
15
+ * @returns The cart object if found, or null if not found.
16
+ */
17
+ const retrieveCart = async (cartId) => {
18
+ const id = cartId || await getCartId();
19
+ if (!id) return null;
20
+ try {
21
+ return (await graphqlFetch({
22
+ query: GET_CART_QUERY,
23
+ variables: { id }
24
+ }))?.cart ?? null;
25
+ } catch (error) {
26
+ console.error("Failed to fetch cart:", error);
27
+ return null;
28
+ }
29
+ };
30
+ const updateCart = async (data) => {
31
+ const cartId = await getCartId();
32
+ if (!cartId) throw new Error("No existing cart found, please create one before updating");
33
+ try {
34
+ const cart = (await graphqlMutation({
35
+ mutation: UPDATE_CART_MUTATION,
36
+ variables: {
37
+ id: cartId,
38
+ data
39
+ }
40
+ }))?.updateCart ?? null;
41
+ if (cart) {
42
+ revalidateTag(await getCacheTag("carts"));
43
+ revalidateTag(await getCacheTag("fulfillment"));
44
+ }
45
+ return cart;
46
+ } catch (err) {
47
+ medusaError(err);
48
+ }
49
+ };
50
+ const deleteLineItem = async (lineId) => {
51
+ if (!lineId) throw new Error("Missing lineItem ID when deleting line item");
52
+ const cartId = await getCartId();
53
+ if (!cartId) throw new Error("Missing cart ID when deleting line item");
54
+ try {
55
+ const deletedLineItem = (await graphqlMutation({
56
+ mutation: DELETE_LINE_ITEM_MUTATION,
57
+ variables: {
58
+ cartId,
59
+ lineItemId: lineId
60
+ }
61
+ }))?.deleteLineItem ?? null;
62
+ if (deletedLineItem) {
63
+ revalidateTag(await getCacheTag("carts"));
64
+ revalidateTag(await getCacheTag("fulfillment"));
65
+ }
66
+ return deletedLineItem;
67
+ } catch (error) {
68
+ console.error("GraphQL deleteLineItem error:", error.message);
69
+ throw error;
70
+ }
71
+ };
72
+ /**
73
+ * Updates the countrycode param and revalidates the regions cache
74
+ * @param regionId
75
+ * @param countryCode
76
+ */
77
+ async function updateRegion(countryCode, currentPath) {
78
+ const cartId = await getCartId();
79
+ const region = await getRegion(countryCode);
80
+ if (!region) throw new Error(`Region not found for country code: ${countryCode}`);
81
+ if (cartId) {
82
+ await updateCart({ regionId: region.id });
83
+ revalidateTag(await getCacheTag("carts"));
84
+ }
85
+ revalidateTag(await getCacheTag("regions"));
86
+ revalidateTag(await getCacheTag("products"));
87
+ redirect(`/${countryCode}${currentPath}`);
88
+ }
89
+ async function listCartOptions() {
90
+ const cartId = await getCartId();
91
+ const headers = { ...await getAuthHeaders() };
92
+ const next = { ...await getCacheOptions("shippingOptions") };
93
+ return await sdk.client.fetch("/store/shipping-options", {
94
+ query: { cart_id: cartId },
95
+ next,
96
+ headers,
97
+ cache: "force-cache"
98
+ });
99
+ }
100
+
101
+ //#endregion
102
+ export { updateRegion as i, listCartOptions as n, retrieveCart as r, deleteLineItem as t };
103
+ //# sourceMappingURL=cart-CLJvIUQC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cart-CLJvIUQC.js","names":["error: any"],"sources":["../src/lib/data/cart.ts"],"sourcesContent":["'use server';\n\nimport { revalidateTag } from 'next/cache';\nimport { redirect } from 'next/navigation';\n\nimport { HttpTypes } from '@medusajs/types';\n\nimport { sdk } from '@/lib/config/medusa';\nimport { graphqlFetch, graphqlMutation } from '@/lib/gql/apollo-client';\nimport {\n DELETE_LINE_ITEM_MUTATION,\n UPDATE_CART_MUTATION,\n} from '@/lib/gql/mutations/cart';\nimport { GET_CART_QUERY } from '@/lib/gql/queries/cart';\nimport { medusaError } from '@/lib/utils/medusa-error';\nimport {\n Cart,\n DeleteLineItemMutation,\n DeleteLineItemMutationVariables,\n GetCartQuery,\n GetCartQueryVariables,\n UpdateCartMutation,\n UpdateCartMutationVariables,\n} from '@/types/graphql';\n\nimport {\n getAuthHeaders,\n getCacheOptions,\n getCacheTag,\n getCartId,\n} from './cookies';\nimport { getRegion } from './regions';\n\n/**\n * Retrieves a cart by its ID. If no ID is provided, it will use the cart ID from the cookies.\n * @param cartId - optional - The ID of the cart to retrieve.\n * @returns The cart object if found, or null if not found.\n */\nexport const retrieveCart = async (cartId?: string): Promise<Cart | null> => {\n const id = cartId || (await getCartId());\n if (!id) {\n return null;\n }\n\n try {\n const data = await graphqlFetch<GetCartQuery, GetCartQueryVariables>({\n query: GET_CART_QUERY,\n variables: { id },\n });\n\n return data?.cart ?? null;\n } catch (error) {\n console.error('Failed to fetch cart:', error);\n return null;\n }\n};\n\nconst updateCart = async (\n data: UpdateCartMutationVariables['data']\n): Promise<UpdateCartMutation['updateCart'] | null> => {\n const cartId = await getCartId();\n\n if (!cartId) {\n throw new Error(\n 'No existing cart found, please create one before updating'\n );\n }\n\n try {\n const result = await graphqlMutation<\n UpdateCartMutation,\n UpdateCartMutationVariables\n >({\n mutation: UPDATE_CART_MUTATION,\n variables: {\n id: cartId,\n data,\n },\n });\n\n const cart = result?.updateCart ?? null;\n\n if (cart) {\n const cartCacheTag = await getCacheTag('carts');\n revalidateTag(cartCacheTag);\n\n const fulfillmentCacheTag = await getCacheTag('fulfillment');\n revalidateTag(fulfillmentCacheTag);\n }\n\n return cart;\n } catch (err) {\n medusaError(err);\n }\n};\n\nexport const deleteLineItem = async (\n lineId: string\n): Promise<DeleteLineItemMutation['deleteLineItem'] | null> => {\n if (!lineId) {\n throw new Error('Missing lineItem ID when deleting line item');\n }\n\n const cartId = await getCartId();\n\n if (!cartId) {\n throw new Error('Missing cart ID when deleting line item');\n }\n\n try {\n const result = await graphqlMutation<\n DeleteLineItemMutation,\n DeleteLineItemMutationVariables\n >({\n mutation: DELETE_LINE_ITEM_MUTATION,\n variables: {\n cartId,\n lineItemId: lineId,\n },\n });\n\n const deletedLineItem = result?.deleteLineItem ?? null;\n\n if (deletedLineItem) {\n const cartCacheTag = await getCacheTag('carts');\n revalidateTag(cartCacheTag);\n\n const fulfillmentCacheTag = await getCacheTag('fulfillment');\n revalidateTag(fulfillmentCacheTag);\n }\n\n return deletedLineItem;\n } catch (error: any) {\n console.error('GraphQL deleteLineItem error:', error.message);\n throw error;\n }\n};\n\n/**\n * Updates the countrycode param and revalidates the regions cache\n * @param regionId\n * @param countryCode\n */\nexport async function updateRegion(countryCode: string, currentPath: string) {\n const cartId = await getCartId();\n const region = await getRegion(countryCode);\n\n if (!region) {\n throw new Error(`Region not found for country code: ${countryCode}`);\n }\n\n if (cartId) {\n await updateCart({ regionId: region.id });\n const cartCacheTag = await getCacheTag('carts');\n revalidateTag(cartCacheTag);\n }\n\n const regionCacheTag = await getCacheTag('regions');\n revalidateTag(regionCacheTag);\n\n const productsCacheTag = await getCacheTag('products');\n revalidateTag(productsCacheTag);\n\n redirect(`/${countryCode}${currentPath}`);\n}\n\nexport async function listCartOptions() {\n const cartId = await getCartId();\n const headers = {\n ...(await getAuthHeaders()),\n };\n const next = {\n ...(await getCacheOptions('shippingOptions')),\n };\n\n return await sdk.client.fetch<{\n shipping_options: HttpTypes.StoreCartShippingOption[];\n }>('/store/shipping-options', {\n query: { cart_id: cartId },\n next,\n headers,\n cache: 'force-cache',\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAsCA,MAAa,eAAe,OAAO,WAA0C;CAC3E,MAAM,KAAK,UAAW,MAAM,WAAW;AACvC,KAAI,CAAC,GACH,QAAO;AAGT,KAAI;AAMF,UALa,MAAM,aAAkD;GACnE,OAAO;GACP,WAAW,EAAE,IAAI;GAClB,CAAC,GAEW,QAAQ;UACd,OAAO;AACd,UAAQ,MAAM,yBAAyB,MAAM;AAC7C,SAAO;;;AAIX,MAAM,aAAa,OACjB,SACqD;CACrD,MAAM,SAAS,MAAM,WAAW;AAEhC,KAAI,CAAC,OACH,OAAM,IAAI,MACR,4DACD;AAGH,KAAI;EAYF,MAAM,QAXS,MAAM,gBAGnB;GACA,UAAU;GACV,WAAW;IACT,IAAI;IACJ;IACD;GACF,CAAC,GAEmB,cAAc;AAEnC,MAAI,MAAM;AAER,iBADqB,MAAM,YAAY,QAAQ,CACpB;AAG3B,iBAD4B,MAAM,YAAY,cAAc,CAC1B;;AAGpC,SAAO;UACA,KAAK;AACZ,cAAY,IAAI;;;AAIpB,MAAa,iBAAiB,OAC5B,WAC6D;AAC7D,KAAI,CAAC,OACH,OAAM,IAAI,MAAM,8CAA8C;CAGhE,MAAM,SAAS,MAAM,WAAW;AAEhC,KAAI,CAAC,OACH,OAAM,IAAI,MAAM,0CAA0C;AAG5D,KAAI;EAYF,MAAM,mBAXS,MAAM,gBAGnB;GACA,UAAU;GACV,WAAW;IACT;IACA,YAAY;IACb;GACF,CAAC,GAE8B,kBAAkB;AAElD,MAAI,iBAAiB;AAEnB,iBADqB,MAAM,YAAY,QAAQ,CACpB;AAG3B,iBAD4B,MAAM,YAAY,cAAc,CAC1B;;AAGpC,SAAO;UACAA,OAAY;AACnB,UAAQ,MAAM,iCAAiC,MAAM,QAAQ;AAC7D,QAAM;;;;;;;;AASV,eAAsB,aAAa,aAAqB,aAAqB;CAC3E,MAAM,SAAS,MAAM,WAAW;CAChC,MAAM,SAAS,MAAM,UAAU,YAAY;AAE3C,KAAI,CAAC,OACH,OAAM,IAAI,MAAM,sCAAsC,cAAc;AAGtE,KAAI,QAAQ;AACV,QAAM,WAAW,EAAE,UAAU,OAAO,IAAI,CAAC;AAEzC,gBADqB,MAAM,YAAY,QAAQ,CACpB;;AAI7B,eADuB,MAAM,YAAY,UAAU,CACtB;AAG7B,eADyB,MAAM,YAAY,WAAW,CACvB;AAE/B,UAAS,IAAI,cAAc,cAAc;;AAG3C,eAAsB,kBAAkB;CACtC,MAAM,SAAS,MAAM,WAAW;CAChC,MAAM,UAAU,EACd,GAAI,MAAM,gBAAgB,EAC3B;CACD,MAAM,OAAO,EACX,GAAI,MAAM,gBAAgB,kBAAkB,EAC7C;AAED,QAAO,MAAM,IAAI,OAAO,MAErB,2BAA2B;EAC5B,OAAO,EAAE,SAAS,QAAQ;EAC1B;EACA;EACA,OAAO;EACR,CAAC"}
@@ -0,0 +1,16 @@
1
+ import { n as CART_FRAGMENT } from "./cart-p3ffQQ5R.js";
2
+ import { gql } from "@apollo/client";
3
+
4
+ //#region src/lib/gql/queries/cart.ts
5
+ const GET_CART_QUERY = gql`
6
+ query GetCart($id: ID!) {
7
+ cart(id: $id) {
8
+ ...CartFields
9
+ }
10
+ }
11
+ ${CART_FRAGMENT}
12
+ `;
13
+
14
+ //#endregion
15
+ export { GET_CART_QUERY as t };
16
+ //# sourceMappingURL=cart-D99u8SUJ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cart-D99u8SUJ.js","names":[],"sources":["../src/lib/gql/queries/cart.ts"],"sourcesContent":["import { gql } from '@apollo/client';\n\nimport { CART_FRAGMENT } from '../fragments/cart';\n\nexport const GET_CART_QUERY = gql`\n query GetCart($id: ID!) {\n cart(id: $id) {\n ...CartFields\n }\n }\n ${CART_FRAGMENT}\n`;\n"],"mappings":";;;;AAIA,MAAa,iBAAiB,GAAG;;;;;;IAM7B,cAAc"}
@@ -0,0 +1,42 @@
1
+ import { n as CART_FRAGMENT, t as ADDRESS_FRAGMENT } from "./cart-p3ffQQ5R.js";
2
+ import { gql } from "@apollo/client";
3
+
4
+ //#region src/lib/gql/mutations/cart.ts
5
+ const UPDATE_CART_MUTATION = gql`
6
+ mutation UpdateCart($id: ID!, $data: UpdateCartInput!) {
7
+ updateCart(id: $id, data: $data) {
8
+ ...CartFields
9
+ regionId
10
+ currencyCode
11
+ shippingAddress {
12
+ ...AddressFields
13
+ }
14
+ billingAddress {
15
+ ...AddressFields
16
+ }
17
+ }
18
+ }
19
+ ${CART_FRAGMENT}
20
+ ${ADDRESS_FRAGMENT}
21
+ `;
22
+ const DELETE_LINE_ITEM_MUTATION = gql`
23
+ mutation DeleteLineItem($cartId: ID!, $lineItemId: ID!) {
24
+ deleteLineItem(cartId: $cartId, lineItemId: $lineItemId) {
25
+ id
26
+ object
27
+ deleted
28
+ }
29
+ }
30
+ `;
31
+ const TRANSFER_CART_MUTATION = gql`
32
+ mutation TransferCart($cartId: ID!) {
33
+ transferCart(cartId: $cartId) {
34
+ ...CartFields
35
+ }
36
+ }
37
+ ${CART_FRAGMENT}
38
+ `;
39
+
40
+ //#endregion
41
+ export { TRANSFER_CART_MUTATION as n, UPDATE_CART_MUTATION as r, DELETE_LINE_ITEM_MUTATION as t };
42
+ //# sourceMappingURL=cart-XQIczSA1.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cart-XQIczSA1.js","names":[],"sources":["../src/lib/gql/mutations/cart.ts"],"sourcesContent":["import { gql } from '@apollo/client';\n\nimport { ADDRESS_FRAGMENT, CART_FRAGMENT } from '../fragments/cart';\n\nexport const UPDATE_CART_MUTATION = gql`\n mutation UpdateCart($id: ID!, $data: UpdateCartInput!) {\n updateCart(id: $id, data: $data) {\n ...CartFields\n regionId\n currencyCode\n shippingAddress {\n ...AddressFields\n }\n billingAddress {\n ...AddressFields\n }\n }\n }\n ${CART_FRAGMENT}\n ${ADDRESS_FRAGMENT}\n`;\n\nexport const DELETE_LINE_ITEM_MUTATION = gql`\n mutation DeleteLineItem($cartId: ID!, $lineItemId: ID!) {\n deleteLineItem(cartId: $cartId, lineItemId: $lineItemId) {\n id\n object\n deleted\n }\n }\n`;\n\nexport const TRANSFER_CART_MUTATION = gql`\n mutation TransferCart($cartId: ID!) {\n transferCart(cartId: $cartId) {\n ...CartFields\n }\n }\n ${CART_FRAGMENT}\n`;\n"],"mappings":";;;;AAIA,MAAa,uBAAuB,GAAG;;;;;;;;;;;;;;IAcnC,cAAc;IACd,iBAAiB;;AAGrB,MAAa,4BAA4B,GAAG;;;;;;;;;AAU5C,MAAa,yBAAyB,GAAG;;;;;;IAMrC,cAAc"}
@@ -0,0 +1,12 @@
1
+ import { r as retrieveCart } from "./cart-CLJvIUQC.js";
2
+ import { t as CartDropdown } from "./cart-dropdown-_ZpvhX--.js";
3
+ import { jsx } from "react/jsx-runtime";
4
+
5
+ //#region src/components/cart-button/index.tsx
6
+ async function CartButton() {
7
+ return /* @__PURE__ */ jsx(CartDropdown, { cart: await retrieveCart().catch(() => null) });
8
+ }
9
+
10
+ //#endregion
11
+ export { CartButton as t };
12
+ //# sourceMappingURL=cart-button-NgoZb9LI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cart-button-NgoZb9LI.js","names":[],"sources":["../src/components/cart-button/index.tsx"],"sourcesContent":["import { retrieveCart } from '@/lib/data/cart';\n\nimport { CartDropdown } from '../cart-dropdown';\n\nasync function CartButton() {\n const cart = await retrieveCart().catch(() => null);\n\n return <CartDropdown cart={cart} />;\n}\n\nexport { CartButton };\n"],"mappings":";;;;;AAIA,eAAe,aAAa;AAG1B,QAAO,oBAAC,gBAAa,MAFR,MAAM,cAAc,CAAC,YAAY,KAAK,GAEhB"}
@@ -0,0 +1,195 @@
1
+ import { t as convertToLocale } from "./money-BrwiFQUW.js";
2
+ import { t as DeleteButton } from "./delete-button-Bfog7z-I.js";
3
+ import { t as LineItemOptions } from "./line-item-options-B3rbud31.js";
4
+ import { t as LineItemPrice } from "./line-item-price-BBlC_T8m.js";
5
+ import { t as LocalizedClientLink } from "./localized-client-link-C3mE37Ub.js";
6
+ import { t as Thumbnail } from "./thumbnail-CXIliWAD.js";
7
+ import { Fragment, useEffect, useRef, useState } from "react";
8
+ import { usePathname } from "next/navigation";
9
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
10
+ import { Popover, PopoverButton, PopoverPanel, Transition } from "@headlessui/react";
11
+ import { Button } from "@medusajs/ui";
12
+
13
+ //#region src/components/cart-dropdown/index.tsx
14
+ const CartDropdown = ({ cart: cartState }) => {
15
+ const [activeTimer, setActiveTimer] = useState(void 0);
16
+ const [cartDropdownOpen, setCartDropdownOpen] = useState(false);
17
+ const open = () => setCartDropdownOpen(true);
18
+ const close = () => setCartDropdownOpen(false);
19
+ const totalItems = cartState?.items?.reduce((acc, item) => {
20
+ return acc + item.quantity;
21
+ }, 0) || 0;
22
+ const subtotal = cartState?.subtotal ?? 0;
23
+ const itemRef = useRef(totalItems || 0);
24
+ const timedOpen = () => {
25
+ open();
26
+ setActiveTimer(setTimeout(close, 5e3));
27
+ };
28
+ const openAndCancel = () => {
29
+ if (activeTimer) clearTimeout(activeTimer);
30
+ open();
31
+ };
32
+ useEffect(() => {
33
+ return () => {
34
+ if (activeTimer) clearTimeout(activeTimer);
35
+ };
36
+ }, [activeTimer]);
37
+ const pathname = usePathname();
38
+ useEffect(() => {
39
+ if (itemRef.current !== totalItems && !pathname.includes("/cart")) timedOpen();
40
+ }, [totalItems, itemRef.current]);
41
+ return /* @__PURE__ */ jsx("div", {
42
+ className: "z-50 h-full",
43
+ onMouseEnter: openAndCancel,
44
+ onMouseLeave: close,
45
+ children: /* @__PURE__ */ jsxs(Popover, {
46
+ className: "relative h-full",
47
+ children: [/* @__PURE__ */ jsx(PopoverButton, {
48
+ className: "h-full",
49
+ children: /* @__PURE__ */ jsx(LocalizedClientLink, {
50
+ className: "hover:text-ui-fg-base",
51
+ href: "/cart",
52
+ "data-testid": "nav-cart-link",
53
+ children: `Cart (${totalItems})`
54
+ })
55
+ }), /* @__PURE__ */ jsx(Transition, {
56
+ show: cartDropdownOpen,
57
+ as: Fragment,
58
+ enter: "transition ease-out duration-200",
59
+ enterFrom: "opacity-0 translate-y-1",
60
+ enterTo: "opacity-100 translate-y-0",
61
+ leave: "transition ease-in duration-150",
62
+ leaveFrom: "opacity-100 translate-y-0",
63
+ leaveTo: "opacity-0 translate-y-1",
64
+ children: /* @__PURE__ */ jsxs(PopoverPanel, {
65
+ static: true,
66
+ className: "text-ui-fg-base small:block absolute top-[calc(100%+1px)] right-0 hidden w-[420px] border-x border-b border-gray-200 bg-white",
67
+ "data-testid": "nav-cart-dropdown",
68
+ children: [/* @__PURE__ */ jsx("div", {
69
+ className: "flex items-center justify-center p-4",
70
+ children: /* @__PURE__ */ jsx("h3", {
71
+ className: "text-large-semi",
72
+ children: "Cart"
73
+ })
74
+ }), cartState && cartState.items?.length ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("div", {
75
+ className: "no-scrollbar grid max-h-[402px] grid-cols-1 gap-y-8 overflow-y-scroll p-px px-4",
76
+ children: cartState.items.sort((a, b) => {
77
+ return (a.createdAt ?? "") > (b.createdAt ?? "") ? -1 : 1;
78
+ }).map((item) => /* @__PURE__ */ jsxs("div", {
79
+ className: "grid grid-cols-[122px_1fr] gap-x-4",
80
+ "data-testid": "cart-item",
81
+ children: [/* @__PURE__ */ jsx(LocalizedClientLink, {
82
+ href: `/products/${item.productHandle}`,
83
+ className: "w-24",
84
+ children: /* @__PURE__ */ jsx(Thumbnail, {
85
+ thumbnail: item.thumbnail,
86
+ images: item.variant?.product?.images,
87
+ size: "square"
88
+ })
89
+ }), /* @__PURE__ */ jsxs("div", {
90
+ className: "flex flex-1 flex-col justify-between",
91
+ children: [/* @__PURE__ */ jsx("div", {
92
+ className: "flex flex-1 flex-col",
93
+ children: /* @__PURE__ */ jsxs("div", {
94
+ className: "flex items-start justify-between",
95
+ children: [/* @__PURE__ */ jsxs("div", {
96
+ className: "mr-4 flex w-[180px] flex-col overflow-ellipsis whitespace-nowrap",
97
+ children: [
98
+ /* @__PURE__ */ jsx("h3", {
99
+ className: "text-base-regular overflow-hidden text-ellipsis",
100
+ children: /* @__PURE__ */ jsx(LocalizedClientLink, {
101
+ href: `/products/${item.productHandle}`,
102
+ "data-testid": "product-link",
103
+ children: item.title
104
+ })
105
+ }),
106
+ /* @__PURE__ */ jsx(LineItemOptions, {
107
+ variant: item.variant,
108
+ "data-testid": "cart-item-variant",
109
+ "data-value": item.variant
110
+ }),
111
+ /* @__PURE__ */ jsxs("span", {
112
+ "data-testid": "cart-item-quantity",
113
+ "data-value": item.quantity,
114
+ children: ["Quantity: ", item.quantity]
115
+ })
116
+ ]
117
+ }), /* @__PURE__ */ jsx("div", {
118
+ className: "flex justify-end",
119
+ children: /* @__PURE__ */ jsx(LineItemPrice, {
120
+ item,
121
+ style: "tight",
122
+ currencyCode: cartState.currencyCode
123
+ })
124
+ })]
125
+ })
126
+ }), /* @__PURE__ */ jsx(DeleteButton, {
127
+ id: item.id,
128
+ className: "mt-1",
129
+ "data-testid": "cart-item-remove-button",
130
+ children: "Remove"
131
+ })]
132
+ })]
133
+ }, item.id))
134
+ }), /* @__PURE__ */ jsxs("div", {
135
+ className: "text-small-regular flex flex-col gap-y-4 p-4",
136
+ children: [/* @__PURE__ */ jsxs("div", {
137
+ className: "flex items-center justify-between",
138
+ children: [/* @__PURE__ */ jsxs("span", {
139
+ className: "text-ui-fg-base font-semibold",
140
+ children: [
141
+ "Subtotal",
142
+ " ",
143
+ /* @__PURE__ */ jsx("span", {
144
+ className: "font-normal",
145
+ children: "(excl. taxes)"
146
+ })
147
+ ]
148
+ }), /* @__PURE__ */ jsx("span", {
149
+ className: "text-large-semi",
150
+ "data-testid": "cart-subtotal",
151
+ "data-value": subtotal,
152
+ children: convertToLocale({
153
+ amount: subtotal,
154
+ currency_code: cartState.currencyCode
155
+ })
156
+ })]
157
+ }), /* @__PURE__ */ jsx(LocalizedClientLink, {
158
+ href: "/cart",
159
+ passHref: true,
160
+ children: /* @__PURE__ */ jsx(Button, {
161
+ className: "w-full",
162
+ size: "large",
163
+ "data-testid": "go-to-cart-button",
164
+ children: "Go to cart"
165
+ })
166
+ })]
167
+ })] }) : /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs("div", {
168
+ className: "flex flex-col items-center justify-center gap-y-4 py-16",
169
+ children: [
170
+ /* @__PURE__ */ jsx("div", {
171
+ className: "text-small-regular flex h-6 w-6 items-center justify-center rounded-full bg-gray-900 text-white",
172
+ children: /* @__PURE__ */ jsx("span", { children: "0" })
173
+ }),
174
+ /* @__PURE__ */ jsx("span", { children: "Your shopping bag is empty." }),
175
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(LocalizedClientLink, {
176
+ href: "/store",
177
+ children: /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", {
178
+ className: "sr-only",
179
+ children: "Go to all products page"
180
+ }), /* @__PURE__ */ jsx(Button, {
181
+ onClick: close,
182
+ children: "Explore products"
183
+ })] })
184
+ }) })
185
+ ]
186
+ }) })]
187
+ })
188
+ })]
189
+ })
190
+ });
191
+ };
192
+
193
+ //#endregion
194
+ export { CartDropdown as t };
195
+ //# sourceMappingURL=cart-dropdown-_ZpvhX--.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cart-dropdown-_ZpvhX--.js","names":[],"sources":["../src/components/cart-dropdown/index.tsx"],"sourcesContent":["'use client';\n\nimport { Fragment, useEffect, useRef, useState } from 'react';\n\nimport { usePathname } from 'next/navigation';\n\nimport {\n Popover,\n PopoverButton,\n PopoverPanel,\n Transition,\n} from '@headlessui/react';\nimport { Button } from '@medusajs/ui';\n\nimport { convertToLocale } from '@/lib/utils/money';\nimport { Cart } from '@/types/graphql';\n\nimport { DeleteButton } from '../delete-button';\nimport { LineItemOptions } from '../line-item-options';\nimport { LineItemPrice } from '../line-item-price';\nimport { LocalizedClientLink } from '../localized-client-link';\nimport { Thumbnail } from '../thumbnail';\n\nconst CartDropdown = ({ cart: cartState }: { cart?: Cart | null }) => {\n const [activeTimer, setActiveTimer] = useState<NodeJS.Timeout | undefined>(\n undefined\n );\n const [cartDropdownOpen, setCartDropdownOpen] = useState(false);\n\n const open = () => setCartDropdownOpen(true);\n const close = () => setCartDropdownOpen(false);\n\n const totalItems =\n cartState?.items?.reduce((acc, item) => {\n return acc + item.quantity;\n }, 0) || 0;\n\n const subtotal = cartState?.subtotal ?? 0;\n const itemRef = useRef<number>(totalItems || 0);\n\n const timedOpen = () => {\n open();\n\n const timer = setTimeout(close, 5000);\n\n setActiveTimer(timer);\n };\n\n const openAndCancel = () => {\n if (activeTimer) {\n clearTimeout(activeTimer);\n }\n\n open();\n };\n\n // Clean up the timer when the component unmounts\n useEffect(() => {\n return () => {\n if (activeTimer) {\n clearTimeout(activeTimer);\n }\n };\n }, [activeTimer]);\n\n const pathname = usePathname();\n\n // open cart dropdown when modifying the cart items, but only if we're not on the cart page\n useEffect(() => {\n if (itemRef.current !== totalItems && !pathname.includes('/cart')) {\n timedOpen();\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [totalItems, itemRef.current]);\n\n return (\n <div\n className=\"z-50 h-full\"\n onMouseEnter={openAndCancel}\n onMouseLeave={close}\n >\n <Popover className=\"relative h-full\">\n <PopoverButton className=\"h-full\">\n <LocalizedClientLink\n className=\"hover:text-ui-fg-base\"\n href=\"/cart\"\n data-testid=\"nav-cart-link\"\n >{`Cart (${totalItems})`}</LocalizedClientLink>\n </PopoverButton>\n <Transition\n show={cartDropdownOpen}\n as={Fragment}\n enter=\"transition ease-out duration-200\"\n enterFrom=\"opacity-0 translate-y-1\"\n enterTo=\"opacity-100 translate-y-0\"\n leave=\"transition ease-in duration-150\"\n leaveFrom=\"opacity-100 translate-y-0\"\n leaveTo=\"opacity-0 translate-y-1\"\n >\n <PopoverPanel\n static\n className=\"text-ui-fg-base small:block absolute top-[calc(100%+1px)] right-0 hidden w-[420px] border-x border-b border-gray-200 bg-white\"\n data-testid=\"nav-cart-dropdown\"\n >\n <div className=\"flex items-center justify-center p-4\">\n <h3 className=\"text-large-semi\">Cart</h3>\n </div>\n {cartState && cartState.items?.length ? (\n <>\n <div className=\"no-scrollbar grid max-h-[402px] grid-cols-1 gap-y-8 overflow-y-scroll p-px px-4\">\n {cartState.items\n .sort((a, b) => {\n return (a.createdAt ?? '') > (b.createdAt ?? '') ? -1 : 1;\n })\n .map((item) => (\n <div\n className=\"grid grid-cols-[122px_1fr] gap-x-4\"\n key={item.id}\n data-testid=\"cart-item\"\n >\n <LocalizedClientLink\n href={`/products/${item.productHandle}`}\n className=\"w-24\"\n >\n <Thumbnail\n thumbnail={item.thumbnail}\n images={item.variant?.product?.images}\n size=\"square\"\n />\n </LocalizedClientLink>\n <div className=\"flex flex-1 flex-col justify-between\">\n <div className=\"flex flex-1 flex-col\">\n <div className=\"flex items-start justify-between\">\n <div className=\"mr-4 flex w-[180px] flex-col overflow-ellipsis whitespace-nowrap\">\n <h3 className=\"text-base-regular overflow-hidden text-ellipsis\">\n <LocalizedClientLink\n href={`/products/${item.productHandle}`}\n data-testid=\"product-link\"\n >\n {item.title}\n </LocalizedClientLink>\n </h3>\n <LineItemOptions\n variant={item.variant}\n data-testid=\"cart-item-variant\"\n data-value={item.variant}\n />\n <span\n data-testid=\"cart-item-quantity\"\n data-value={item.quantity}\n >\n Quantity: {item.quantity}\n </span>\n </div>\n <div className=\"flex justify-end\">\n <LineItemPrice\n item={item}\n style=\"tight\"\n currencyCode={cartState.currencyCode}\n />\n </div>\n </div>\n </div>\n <DeleteButton\n id={item.id}\n className=\"mt-1\"\n data-testid=\"cart-item-remove-button\"\n >\n Remove\n </DeleteButton>\n </div>\n </div>\n ))}\n </div>\n <div className=\"text-small-regular flex flex-col gap-y-4 p-4\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-ui-fg-base font-semibold\">\n Subtotal{' '}\n <span className=\"font-normal\">(excl. taxes)</span>\n </span>\n <span\n className=\"text-large-semi\"\n data-testid=\"cart-subtotal\"\n data-value={subtotal}\n >\n {convertToLocale({\n amount: subtotal,\n currency_code: cartState.currencyCode,\n })}\n </span>\n </div>\n <LocalizedClientLink href=\"/cart\" passHref>\n <Button\n className=\"w-full\"\n size=\"large\"\n data-testid=\"go-to-cart-button\"\n >\n Go to cart\n </Button>\n </LocalizedClientLink>\n </div>\n </>\n ) : (\n <div>\n <div className=\"flex flex-col items-center justify-center gap-y-4 py-16\">\n <div className=\"text-small-regular flex h-6 w-6 items-center justify-center rounded-full bg-gray-900 text-white\">\n <span>0</span>\n </div>\n <span>Your shopping bag is empty.</span>\n <div>\n <LocalizedClientLink href=\"/store\">\n <>\n <span className=\"sr-only\">Go to all products page</span>\n <Button onClick={close}>Explore products</Button>\n </>\n </LocalizedClientLink>\n </div>\n </div>\n </div>\n )}\n </PopoverPanel>\n </Transition>\n </Popover>\n </div>\n );\n};\n\nexport { CartDropdown };\n"],"mappings":";;;;;;;;;;;;;AAuBA,MAAM,gBAAgB,EAAE,MAAM,gBAAwC;CACpE,MAAM,CAAC,aAAa,kBAAkB,SACpC,OACD;CACD,MAAM,CAAC,kBAAkB,uBAAuB,SAAS,MAAM;CAE/D,MAAM,aAAa,oBAAoB,KAAK;CAC5C,MAAM,cAAc,oBAAoB,MAAM;CAE9C,MAAM,aACJ,WAAW,OAAO,QAAQ,KAAK,SAAS;AACtC,SAAO,MAAM,KAAK;IACjB,EAAE,IAAI;CAEX,MAAM,WAAW,WAAW,YAAY;CACxC,MAAM,UAAU,OAAe,cAAc,EAAE;CAE/C,MAAM,kBAAkB;AACtB,QAAM;AAIN,iBAFc,WAAW,OAAO,IAAK,CAEhB;;CAGvB,MAAM,sBAAsB;AAC1B,MAAI,YACF,cAAa,YAAY;AAG3B,QAAM;;AAIR,iBAAgB;AACd,eAAa;AACX,OAAI,YACF,cAAa,YAAY;;IAG5B,CAAC,YAAY,CAAC;CAEjB,MAAM,WAAW,aAAa;AAG9B,iBAAgB;AACd,MAAI,QAAQ,YAAY,cAAc,CAAC,SAAS,SAAS,QAAQ,CAC/D,YAAW;IAGZ,CAAC,YAAY,QAAQ,QAAQ,CAAC;AAEjC,QACE,oBAAC;EACC,WAAU;EACV,cAAc;EACd,cAAc;YAEd,qBAAC;GAAQ,WAAU;cACjB,oBAAC;IAAc,WAAU;cACvB,oBAAC;KACC,WAAU;KACV,MAAK;KACL,eAAY;eACZ,SAAS,WAAW;MAAyB;KACjC,EAChB,oBAAC;IACC,MAAM;IACN,IAAI;IACJ,OAAM;IACN,WAAU;IACV,SAAQ;IACR,OAAM;IACN,WAAU;IACV,SAAQ;cAER,qBAAC;KACC;KACA,WAAU;KACV,eAAY;gBAEZ,oBAAC;MAAI,WAAU;gBACb,oBAAC;OAAG,WAAU;iBAAkB;QAAS;OACrC,EACL,aAAa,UAAU,OAAO,SAC7B,8CACE,oBAAC;MAAI,WAAU;gBACZ,UAAU,MACR,MAAM,GAAG,MAAM;AACd,eAAQ,EAAE,aAAa,OAAO,EAAE,aAAa,MAAM,KAAK;QACxD,CACD,KAAK,SACJ,qBAAC;OACC,WAAU;OAEV,eAAY;kBAEZ,oBAAC;QACC,MAAM,aAAa,KAAK;QACxB,WAAU;kBAEV,oBAAC;SACC,WAAW,KAAK;SAChB,QAAQ,KAAK,SAAS,SAAS;SAC/B,MAAK;UACL;SACkB,EACtB,qBAAC;QAAI,WAAU;mBACb,oBAAC;SAAI,WAAU;mBACb,qBAAC;UAAI,WAAU;qBACb,qBAAC;WAAI,WAAU;;YACb,oBAAC;aAAG,WAAU;uBACZ,oBAAC;cACC,MAAM,aAAa,KAAK;cACxB,eAAY;wBAEX,KAAK;eACc;cACnB;YACL,oBAAC;aACC,SAAS,KAAK;aACd,eAAY;aACZ,cAAY,KAAK;cACjB;YACF,qBAAC;aACC,eAAY;aACZ,cAAY,KAAK;wBAClB,cACY,KAAK;cACX;;YACH,EACN,oBAAC;WAAI,WAAU;qBACb,oBAAC;YACO;YACN,OAAM;YACN,cAAc,UAAU;aACxB;YACE;WACF;UACF,EACN,oBAAC;SACC,IAAI,KAAK;SACT,WAAU;SACV,eAAY;mBACb;UAEc;SACX;SArDD,KAAK,GAsDN,CACN;OACA,EACN,qBAAC;MAAI,WAAU;iBACb,qBAAC;OAAI,WAAU;kBACb,qBAAC;QAAK,WAAU;;SAAgC;SACrC;SACT,oBAAC;UAAK,WAAU;oBAAc;WAAoB;;SAC7C,EACP,oBAAC;QACC,WAAU;QACV,eAAY;QACZ,cAAY;kBAEX,gBAAgB;SACf,QAAQ;SACR,eAAe,UAAU;SAC1B,CAAC;SACG;QACH,EACN,oBAAC;OAAoB,MAAK;OAAQ;iBAChC,oBAAC;QACC,WAAU;QACV,MAAK;QACL,eAAY;kBACb;SAEQ;QACW;OAClB,IACL,GAEH,oBAAC,mBACC,qBAAC;MAAI,WAAU;;OACb,oBAAC;QAAI,WAAU;kBACb,oBAAC,oBAAK,MAAQ;SACV;OACN,oBAAC,oBAAK,gCAAkC;OACxC,oBAAC,mBACC,oBAAC;QAAoB,MAAK;kBACxB,8CACE,oBAAC;SAAK,WAAU;mBAAU;UAA8B,EACxD,oBAAC;SAAO,SAAS;mBAAO;UAAyB,IAChD;SACiB,GAClB;;OACF,GACF;MAEK;KACJ;IACL;GACN"}