@ecomiq/storefront 2.1.3 → 3.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 (317) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +150 -123
  3. package/dist/account-Dx4e3syi.js +258 -0
  4. package/dist/account-forms-AVk71ko7.js +39 -0
  5. package/dist/account-forms.d.ts +13 -0
  6. package/dist/account.d.ts +240 -0
  7. package/dist/address-defaults-BqjRhS82.js +14 -0
  8. package/dist/address-defaults.d.ts +11 -0
  9. package/dist/analytics/analytics-CG1Qagwl.js +148 -0
  10. package/dist/analytics/analytics.d.ts +1 -0
  11. package/dist/analytics/config-DJr-GRhs.js +62 -0
  12. package/dist/analytics/config.d.ts +22 -0
  13. package/dist/analytics/consent-B13rBpBs.js +57 -0
  14. package/dist/analytics/consent-banner-9QvRRy8v.js +239 -0
  15. package/dist/analytics/consent-banner.d.ts +20 -0
  16. package/dist/analytics/cookies-pLozllyB.js +100 -0
  17. package/dist/analytics/cookies.d.ts +6 -0
  18. package/dist/analytics/destinations-iECrlLIr.js +144 -0
  19. package/dist/analytics/events-Dt81tIp1.js +102 -0
  20. package/dist/analytics/events.d.ts +51 -0
  21. package/dist/analytics/tracker-p4yaoOyk.js +51 -0
  22. package/dist/api-cache-DsuIn5hX.js +159 -0
  23. package/dist/bank-accounts-DlEczQQ5.js +81 -0
  24. package/dist/bank-accounts.d.ts +4 -0
  25. package/dist/captcha-DAqaIx8m.js +117 -0
  26. package/dist/captcha.d.ts +34 -0
  27. package/dist/cart-D7DxZ2lD.js +30 -0
  28. package/dist/cart-actions-Bsub_FFG.js +116 -0
  29. package/dist/cart-actions.d.ts +15 -0
  30. package/dist/cart-drawer-B7PPsR69.js +22 -0
  31. package/dist/cart-drawer.d.ts +9 -0
  32. package/dist/cart-form-y9P1r_EX.js +81 -0
  33. package/dist/cart-form.d.ts +24 -0
  34. package/dist/cart-summary-ur2VWKr-.js +89 -0
  35. package/dist/cart-summary.d.ts +31 -0
  36. package/dist/cart.d.ts +4 -0
  37. package/dist/catalog-7gJ-l5hW.js +67 -0
  38. package/dist/catalog-hooks-B7ZP4wYY.js +312 -0
  39. package/dist/catalog-hooks.d.ts +111 -0
  40. package/dist/catalog.d.ts +5 -0
  41. package/dist/checkout-DVWSXANi.js +474 -0
  42. package/dist/checkout-form-CbOIdENC.js +131 -0
  43. package/dist/checkout-form.d.ts +20 -0
  44. package/dist/checkout.d.ts +86 -0
  45. package/dist/complaint-book-BvwLvfx0.js +117 -0
  46. package/dist/complaint-book.d.ts +62 -0
  47. package/dist/culqi-authentication-BGr20vAJ.js +204 -0
  48. package/dist/culqi-authentication.d.ts +15 -0
  49. package/dist/culqi-checkout-CTXpKgp_.js +55 -0
  50. package/dist/culqi-three-ds-HP3mfrvV.js +33 -0
  51. package/dist/culqi-three-ds.d.ts +29 -0
  52. package/dist/customer-avatar-CJXSDroK.js +12 -0
  53. package/dist/customer-avatar.d.ts +5 -0
  54. package/dist/customer-cookies-DHOgFAMV.js +45 -0
  55. package/dist/customer-csrf-C1oDX-Py.js +17 -0
  56. package/dist/customer-csrf.d.ts +3 -0
  57. package/dist/customer-document-fields-C1K-_DAD.js +70 -0
  58. package/dist/customer-document-fields.d.ts +9 -0
  59. package/dist/customer-login-form-C7AC6vXd.js +144 -0
  60. package/dist/customer-login-form.d.ts +17 -0
  61. package/dist/customer-registration-form-BEm_NEfP.js +93 -0
  62. package/dist/customer-registration-form.d.ts +8 -0
  63. package/dist/document-url-CGsAl5Tf.js +9 -0
  64. package/dist/documents-T1mzc_j8.js +38 -0
  65. package/dist/documents.d.ts +16 -0
  66. package/dist/entries/account.d.ts +11 -0
  67. package/dist/entries/account.js +10 -0
  68. package/dist/entries/analytics.d.ts +6 -0
  69. package/dist/entries/analytics.js +5 -0
  70. package/dist/entries/cart.d.ts +8 -0
  71. package/dist/entries/cart.js +7 -0
  72. package/dist/entries/checkout.d.ts +12 -0
  73. package/dist/entries/checkout.js +11 -0
  74. package/dist/entries/order.d.ts +11 -0
  75. package/dist/entries/order.js +11 -0
  76. package/dist/favicon-YpyhVJ9H.js +28 -0
  77. package/dist/favicon.d.ts +4 -0
  78. package/dist/form-BtQcbXlJ.js +18 -0
  79. package/dist/form-contracts-BNpHaTGJ.js +166 -0
  80. package/dist/form-contracts.d.ts +42 -0
  81. package/dist/form.d.ts +3 -0
  82. package/dist/hidden-CCWtOWKR.js +3 -0
  83. package/dist/hidden.d.ts +4 -0
  84. package/dist/index.d.ts +50 -0
  85. package/dist/index.js +50 -0
  86. package/dist/invoice-fields-BG0HjL6T.js +103 -0
  87. package/dist/invoice-fields.d.ts +39 -0
  88. package/dist/links-kFxBZfdb.js +96 -0
  89. package/dist/links.d.ts +21 -0
  90. package/dist/mercadopago-checkout-DC7RXa8k.js +27 -0
  91. package/dist/mercadopago-dialog-UTQev0MG.js +180 -0
  92. package/dist/mercadopago-dialog.d.ts +21 -0
  93. package/dist/money-DtGOtDri.js +32 -0
  94. package/dist/money.d.ts +1 -0
  95. package/dist/optimistic-cart-BveVOHuh.js +53 -0
  96. package/dist/optimistic-cart.d.ts +16 -0
  97. package/dist/order-display-DTt5WBbc.js +112 -0
  98. package/dist/order-display.d.ts +20 -0
  99. package/dist/order-draft-DxV1Uhm3.js +38 -0
  100. package/dist/order-draft.d.ts +16 -0
  101. package/dist/order-pages-Dm6l5m0m.js +38 -0
  102. package/dist/order-pages.d.ts +12 -0
  103. package/dist/order-payment-continuation-D_d5PGA4.js +212 -0
  104. package/dist/order-payment-continuation.d.ts +10 -0
  105. package/dist/order-payment-in-review-x4gdLFHZ.js +65 -0
  106. package/dist/order-payment-in-review.d.ts +5 -0
  107. package/dist/order-status-BJXLJwxq.js +162 -0
  108. package/dist/order-status.d.ts +89 -0
  109. package/dist/order-view-9IlBg5AF.js +62 -0
  110. package/dist/order-view.d.ts +12 -0
  111. package/dist/page-action-Ctkf4xC6.js +7 -0
  112. package/dist/page-seo-a5FJl8x5.js +262 -0
  113. package/dist/page-seo.d.ts +34 -0
  114. package/dist/pages-Ca_Gt6mq.js +150 -0
  115. package/dist/pages.d.ts +45 -0
  116. package/dist/payment-dialog-frame-B-Q_xQ94.js +57 -0
  117. package/dist/payment-logo-BoPaGJc_.js +46 -0
  118. package/dist/payment-logo-svgs-By9lDTLK.js +20 -0
  119. package/dist/payment-logo.d.ts +11 -0
  120. package/dist/payment-logos-BYvdwYyJ.js +23 -0
  121. package/dist/payment-methods-B8ocTgFZ.js +73 -0
  122. package/dist/payment-methods.d.ts +58 -0
  123. package/dist/payment-return-5cjypwIw.js +7 -0
  124. package/dist/place-CmW4hBWY.js +13 -0
  125. package/dist/place.d.ts +4 -0
  126. package/dist/preview-BiIBif3C.js +427 -0
  127. package/dist/preview-address-Cf0sJ-9p.js +21 -0
  128. package/dist/preview-cart-Dg2CVktS.js +376 -0
  129. package/dist/product-preview-BspMAecJ.js +51 -0
  130. package/dist/product-preview.d.ts +5 -0
  131. package/dist/product-variants-BNDHvs1y.js +46 -0
  132. package/dist/product-variants.d.ts +12 -0
  133. package/dist/public-pages-XtwlaLwt.js +194 -0
  134. package/dist/public-pages.d.ts +67 -0
  135. package/dist/registration-CpDcv8ql.js +91 -0
  136. package/dist/registration.d.ts +12 -0
  137. package/dist/request-security-CRsRMgwj.js +76 -0
  138. package/dist/rich-text-M-Ju8RL4.js +9 -0
  139. package/dist/rich-text.d.ts +5 -0
  140. package/dist/route-text-DcJw2SsK.js +9 -0
  141. package/dist/route-text.d.ts +4 -0
  142. package/dist/section-preview-CmsMl3yu.js +83 -0
  143. package/dist/section-preview.d.ts +12 -0
  144. package/dist/sections/account-addresses.d.ts +18 -0
  145. package/dist/sections/account-addresses.js +375 -0
  146. package/dist/sections/account-order.d.ts +12 -0
  147. package/dist/sections/account-order.js +592 -0
  148. package/dist/sections/account-orders.d.ts +8 -0
  149. package/dist/sections/account-orders.js +359 -0
  150. package/dist/sections/account-profile.d.ts +16 -0
  151. package/dist/sections/account-profile.js +123 -0
  152. package/dist/sections/checkout.d.ts +24 -0
  153. package/dist/sections/checkout.js +963 -0
  154. package/dist/sections/complaint-book.d.ts +8 -0
  155. package/dist/sections/complaint-book.js +538 -0
  156. package/dist/sections/design-system.d.ts +1 -0
  157. package/dist/sections/design-system.js +310 -0
  158. package/dist/sections/draft-invoice.d.ts +20 -0
  159. package/dist/sections/draft-invoice.js +158 -0
  160. package/dist/sections/order-tracking.d.ts +19 -0
  161. package/dist/sections/order-tracking.js +141 -0
  162. package/dist/sections-CNUMWTF_.js +77 -0
  163. package/dist/sections.d.ts +19 -0
  164. package/dist/seo-GpDRhAAA.js +78 -0
  165. package/dist/session-CKvmFJyg.js +379 -0
  166. package/dist/session.d.ts +24 -0
  167. package/dist/settings-B0NO2A6Y.js +78 -0
  168. package/dist/settings.d.ts +51 -0
  169. package/dist/source-marker-DhqSkW7n.js +4 -0
  170. package/dist/sources-B-3JFJfb.js +46 -0
  171. package/dist/sources.d.ts +7 -0
  172. package/dist/store-8Q-_LFrQ.js +152 -0
  173. package/dist/store-contact--hY6CoFb.js +19 -0
  174. package/dist/store-contact.d.ts +6 -0
  175. package/dist/store.d.ts +17 -0
  176. package/dist/storefront-language-DrMjVbmk.js +29 -0
  177. package/dist/storefront-language.d.ts +14 -0
  178. package/dist/storefront-text-D25ae1qf.js +11 -0
  179. package/dist/storefront-text-en-ljjjSS4q.js +1030 -0
  180. package/dist/storefront-text-pt-BtHaJLcp.js +1030 -0
  181. package/dist/storefront-text.d.ts +4 -0
  182. package/dist/stripe-dialog-Ev9s3Z62.js +396 -0
  183. package/dist/stripe-dialog.d.ts +30 -0
  184. package/dist/telemetry-HuZXWBPi.js +114 -0
  185. package/dist/telemetry.d.ts +10 -0
  186. package/dist/templates-CAqoNyTW.js +40 -0
  187. package/dist/templates.d.ts +15 -0
  188. package/dist/urls-CpGQPxvf.js +71 -0
  189. package/dist/urls.d.ts +18 -0
  190. package/dist/use-checkout-CZcxXJXi.js +42 -0
  191. package/dist/use-checkout-payment-9R-zacrJ.js +80 -0
  192. package/dist/use-checkout-payment.d.ts +18 -0
  193. package/dist/use-checkout.d.ts +36 -0
  194. package/dist/use-culqi-checkout-CrjLAipU.js +109 -0
  195. package/dist/use-order-payment-BKIz_IO0.js +45 -0
  196. package/dist/use-order-payment.d.ts +18 -0
  197. package/dist/use-payment-token-CErx-tN-.js +105 -0
  198. package/dist/vite-payment-logos-kziu7wKb.js +27 -0
  199. package/dist/vite-payment-logos.d.ts +24 -0
  200. package/dist/vite-public-assets-DW2fgtVb.js +209 -0
  201. package/dist/vite-public-assets.d.ts +29 -0
  202. package/dist/vite-sections-DTBr0-Kg.js +464 -0
  203. package/dist/vite-sections.d.ts +21 -0
  204. package/dist/vite-theme-ui-BMO-CDi3.js +41 -0
  205. package/dist/vite-theme-ui.d.ts +10 -0
  206. package/dist/vite.d.ts +36 -0
  207. package/dist/vite.js +127 -0
  208. package/dist/voucher-payment-CVFDZ1L8.js +66 -0
  209. package/dist/worker-CNi-gzCu.js +86 -0
  210. package/dist/worker.d.ts +27 -0
  211. package/package.json +100 -81
  212. package/src/sections/account-addresses.tsx +215 -0
  213. package/src/sections/account-order.tsx +424 -0
  214. package/src/sections/account-orders.tsx +259 -0
  215. package/src/sections/account-profile.tsx +70 -0
  216. package/src/sections/checkout.tsx +586 -0
  217. package/src/sections/complaint-book.tsx +325 -0
  218. package/src/sections/design-system.tsx +146 -0
  219. package/src/sections/draft-invoice.tsx +105 -0
  220. package/src/sections/order-tracking.tsx +81 -0
  221. package/src/vite-client.d.ts +4 -0
  222. package/bin/ecomiq.mjs +0 -179
  223. package/public/design-bridge.js +0 -318
  224. package/src/api-proxy.ts +0 -194
  225. package/src/auth/create-storefront-auth.ts +0 -94
  226. package/src/auth/ecomiq-oauth-password-client.ts +0 -26
  227. package/src/auth/ecomiq-oauth-password-constants.ts +0 -24
  228. package/src/auth/ecomiq-oauth-password-plugin.ts +0 -294
  229. package/src/auth/ecomiq-oauth-password-types.ts +0 -24
  230. package/src/auth/ecomiq-storefront-sign-in.ts +0 -44
  231. package/src/auth/env.ts +0 -7
  232. package/src/auth/secure-cookies.ts +0 -23
  233. package/src/auth/storefront-auth-base-url.ts +0 -117
  234. package/src/auth/storefront-auth.ts +0 -7
  235. package/src/cart-session.ts +0 -239
  236. package/src/client.ts +0 -48
  237. package/src/cloud-runtime-client.ts +0 -378
  238. package/src/codegen.mjs +0 -789
  239. package/src/components/account/customer-addresses-panel.tsx +0 -678
  240. package/src/components/account/customer-order-detail-panel.tsx +0 -285
  241. package/src/components/account/customer-orders-panel.tsx +0 -192
  242. package/src/components/account/customer-profile-panel.tsx +0 -379
  243. package/src/components/checkout/cart-sync.ts +0 -143
  244. package/src/components/checkout/checkout-contact-section.tsx +0 -76
  245. package/src/components/checkout/checkout-external-update-banner.tsx +0 -15
  246. package/src/components/checkout/checkout-form-controls.tsx +0 -139
  247. package/src/components/checkout/checkout-line-items.tsx +0 -43
  248. package/src/components/checkout/checkout-order-summary.tsx +0 -165
  249. package/src/components/checkout/checkout-payment-section.tsx +0 -212
  250. package/src/components/checkout/checkout-session-view.tsx +0 -564
  251. package/src/components/checkout/checkout-shipping-address-section.tsx +0 -400
  252. package/src/components/checkout/checkout-shipping-section.tsx +0 -98
  253. package/src/components/checkout/checkout-states.tsx +0 -73
  254. package/src/components/checkout/checkout-step-card.tsx +0 -101
  255. package/src/components/checkout/checkout-steps.ts +0 -111
  256. package/src/components/checkout/form-schema.ts +0 -281
  257. package/src/components/checkout/format.ts +0 -15
  258. package/src/components/checkout/index.ts +0 -5
  259. package/src/components/checkout/map-customer-to-checkout.ts +0 -188
  260. package/src/components/checkout/types.ts +0 -41
  261. package/src/components/checkout/use-checkout-customer-prefill.ts +0 -409
  262. package/src/components/checkout/use-checkout-geo.ts +0 -50
  263. package/src/components/checkout/use-checkout-session.ts +0 -640
  264. package/src/components/hero.tsx +0 -291
  265. package/src/config.d.ts +0 -94
  266. package/src/config.mjs +0 -146
  267. package/src/format-money.ts +0 -31
  268. package/src/health.ts +0 -90
  269. package/src/hooks/index.ts +0 -9
  270. package/src/hooks/recently-viewed.ts +0 -125
  271. package/src/index.ts +0 -354
  272. package/src/link.tsx +0 -2
  273. package/src/pages/account/account-page-skeleton.tsx +0 -69
  274. package/src/pages/account/account-page-view.tsx +0 -270
  275. package/src/pages/account/account-shell.tsx +0 -101
  276. package/src/pages/account/parse-account-route.ts +0 -36
  277. package/src/pages/account.tsx +0 -16
  278. package/src/pages/api.$.ts +0 -20
  279. package/src/pages/api.auth.$.ts +0 -16
  280. package/src/pages/checkout.$checkoutId.tsx +0 -60
  281. package/src/pages/checkout.tsx +0 -31
  282. package/src/pages/pages.$pageSlug.tsx +0 -111
  283. package/src/pages/thank-you.tsx +0 -53
  284. package/src/providers/auth.tsx +0 -96
  285. package/src/providers/cart.tsx +0 -275
  286. package/src/providers/ecomiq.ts +0 -137
  287. package/src/providers/index.ts +0 -26
  288. package/src/proxy-api.ts +0 -20
  289. package/src/public-config.ts +0 -24
  290. package/src/review-submission.ts +0 -89
  291. package/src/runtime/context.ts +0 -2
  292. package/src/runtime/default-layout.tsx +0 -64
  293. package/src/runtime/head.ts +0 -149
  294. package/src/runtime/page.tsx +0 -143
  295. package/src/runtime/postcss-browser-stub.mjs +0 -5
  296. package/src/server-config-store.ts +0 -35
  297. package/src/server.ts +0 -301
  298. package/src/storefront-definition/contract.ts +0 -1
  299. package/src/storefront-definition/data.ts +0 -188
  300. package/src/storefront-definition/index.ts +0 -2
  301. package/src/storefront-definition/renderer.tsx +0 -1481
  302. package/src/storefront-layout.ts +0 -59
  303. package/src/storefront-runtime.ts +0 -173
  304. package/src/styles.css +0 -97
  305. package/src/ui/badge.tsx +0 -32
  306. package/src/ui/button.tsx +0 -31
  307. package/src/ui/card.tsx +0 -31
  308. package/src/ui/carousel.tsx +0 -218
  309. package/src/ui/cn.ts +0 -6
  310. package/src/ui/index.ts +0 -8
  311. package/src/ui/separator.tsx +0 -6
  312. package/src/ui/skeleton.tsx +0 -6
  313. package/src/ui/storefront-error.tsx +0 -49
  314. package/src/utils.ts +0 -36
  315. package/src/vite-inline.mjs +0 -263
  316. package/templates/__root.tsx +0 -83
  317. package/templates/router.tsx +0 -19
@@ -0,0 +1,239 @@
1
+ import { consentPurposes, installConsent, onConsent, onConsentOpen, openConsent } from "./consent-B13rBpBs.js";
2
+ import { Link, useRouteLoaderData } from "react-router";
3
+ import { useEffect, useId, useRef, useState } from "react";
4
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
5
+ // src/analytics/consent-banner.tsx
6
+ const PURPOSES = ["analytics", "marketing"];
7
+ const REJECTED = {
8
+ analytics: false,
9
+ marketing: false
10
+ };
11
+ const ACCEPTED = {
12
+ analytics: true,
13
+ marketing: true
14
+ };
15
+ const COPY = {
16
+ es: {
17
+ label: "Cookies",
18
+ privacy: "Privacidad",
19
+ configure: "Configurar",
20
+ choose: "Elige qué aceptas. Las cookies necesarias para el carrito y tu sesión siempre están activas.",
21
+ accept: "Aceptar",
22
+ reject: "Rechazar",
23
+ save: "Guardar",
24
+ and: " y ",
25
+ others: "otros proveedores",
26
+ uses: {
27
+ analytics: "medir visitas",
28
+ marketing: "mostrarte publicidad"
29
+ },
30
+ options: {
31
+ analytics: {
32
+ name: "Medición",
33
+ use: "para contar visitas y compras"
34
+ },
35
+ marketing: {
36
+ name: "Publicidad",
37
+ use: "para medir campañas y mostrarte anuncios"
38
+ }
39
+ },
40
+ notice: (providers, uses) => `Con tu permiso, usamos cookies de ${providers} para ${uses}. Los datos que recogen pueden tratarse fuera del país, por ejemplo en Estados Unidos. Puedes cambiar tu elección en «Cookies», al pie de la página.`
41
+ },
42
+ en: {
43
+ label: "Cookies",
44
+ privacy: "Privacy",
45
+ configure: "Customize",
46
+ choose: "Choose what you accept. Cookies needed for the cart and your session are always on.",
47
+ accept: "Accept",
48
+ reject: "Reject",
49
+ save: "Save",
50
+ and: " and ",
51
+ others: "other providers",
52
+ uses: {
53
+ analytics: "measure visits",
54
+ marketing: "show you ads"
55
+ },
56
+ options: {
57
+ analytics: {
58
+ name: "Measurement",
59
+ use: "to count visits and purchases"
60
+ },
61
+ marketing: {
62
+ name: "Advertising",
63
+ use: "to measure campaigns and show you ads"
64
+ }
65
+ },
66
+ notice: (providers, uses) => `With your permission, we use cookies from ${providers} to ${uses}. The data they collect may be processed outside your country, for example in the United States. You can change your choice under “Cookies” at the bottom of the page.`
67
+ },
68
+ pt: {
69
+ label: "Cookies",
70
+ privacy: "Privacidade",
71
+ configure: "Configurar",
72
+ choose: "Escolha o que aceita. Os cookies necessários para o carrinho e a sua sessão estão sempre ativos.",
73
+ accept: "Aceitar",
74
+ reject: "Recusar",
75
+ save: "Salvar",
76
+ and: " e ",
77
+ others: "outros fornecedores",
78
+ uses: {
79
+ analytics: "medir visitas",
80
+ marketing: "mostrar publicidade"
81
+ },
82
+ options: {
83
+ analytics: {
84
+ name: "Medição",
85
+ use: "para contar visitas e compras"
86
+ },
87
+ marketing: {
88
+ name: "Publicidade",
89
+ use: "para medir campanhas e mostrar anúncios"
90
+ }
91
+ },
92
+ notice: (providers, uses) => `Com a sua permissão, usamos cookies de ${providers} para ${uses}. Os dados que coletam podem ser tratados fora do país, por exemplo nos Estados Unidos. Você pode mudar sua escolha em “Cookies”, no rodapé da página.`
93
+ }
94
+ };
95
+ function consentCopy(language) {
96
+ return COPY[language.slice(0, 2).toLowerCase()] ?? COPY.es;
97
+ }
98
+ function useAnalyticsConfig() {
99
+ return useRouteLoaderData("root")?.analytics ?? null;
100
+ }
101
+ function providers(config, purpose) {
102
+ const generic = config.googleTagManager !== null || config.scripts !== null;
103
+ return {
104
+ google: purpose === "marketing" ? config.googleTagManager !== null : config.googleAnalytics !== null || config.googleTagManager !== null,
105
+ meta: purpose !== "analytics" && config.metaPixel !== null,
106
+ others: generic
107
+ };
108
+ }
109
+ function providerNames(found, copy) {
110
+ const names = [];
111
+ if (found.google) names.push("Google");
112
+ if (found.meta) names.push("Meta");
113
+ if (found.others) names.push(copy.others);
114
+ const last = names.pop() ?? "";
115
+ if (names.length === 0) return last;
116
+ return `${names.join(", ")}${copy.and}${last}`;
117
+ }
118
+ function ConsentBanner({ className, classNames = {} }) {
119
+ const config = useAnalyticsConfig();
120
+ const version = config?.consentVersion ?? null;
121
+ const id = useId();
122
+ const [open, setOpen] = useState(false);
123
+ const [configuring, setConfiguring] = useState(false);
124
+ const [choice, setChoice] = useState(REJECTED);
125
+ const [focused, setFocused] = useState(0);
126
+ const banner = useRef(null);
127
+ useEffect(() => {
128
+ if (config === null) return;
129
+ setOpen(installConsent(config).get() === null);
130
+ setConfiguring(false);
131
+ const stopChoice = onConsent(() => setOpen(false));
132
+ const stopOpen = onConsentOpen(() => {
133
+ setConfiguring(false);
134
+ setOpen(true);
135
+ setFocused((count) => count + 1);
136
+ });
137
+ return () => {
138
+ stopChoice();
139
+ stopOpen();
140
+ };
141
+ }, [version]);
142
+ useEffect(() => {
143
+ if (focused > 0) banner.current?.focus();
144
+ }, [focused]);
145
+ if (config === null || !open) return null;
146
+ const copy = consentCopy(config.language);
147
+ const offered = consentPurposes(config);
148
+ const purposes = PURPOSES.filter((purpose) => offered[purpose]);
149
+ const choose = (consent) => installConsent(config).set(consent);
150
+ const configure = () => {
151
+ const current = installConsent(config).get();
152
+ setChoice(current === null ? REJECTED : {
153
+ analytics: current.analytics,
154
+ marketing: current.marketing
155
+ });
156
+ setConfiguring(true);
157
+ setFocused((count) => count + 1);
158
+ };
159
+ const privacy = config.privacy === null ? null : /* @__PURE__ */ jsxs(Fragment$1, { children: [" ", /* @__PURE__ */ jsx(Link, {
160
+ to: config.privacy,
161
+ className: classNames.link,
162
+ children: copy.privacy
163
+ })] });
164
+ return /* @__PURE__ */ jsxs("section", {
165
+ ref: banner,
166
+ tabIndex: -1,
167
+ "aria-label": copy.label,
168
+ className,
169
+ children: [configuring ? /* @__PURE__ */ jsxs("div", {
170
+ className: classNames.options,
171
+ children: [/* @__PURE__ */ jsxs("p", {
172
+ className: classNames.text,
173
+ children: [copy.choose, privacy]
174
+ }), purposes.map((purpose) => /* @__PURE__ */ jsxs("p", {
175
+ className: classNames.option,
176
+ children: [/* @__PURE__ */ jsx("input", {
177
+ id: `${id}${purpose}`,
178
+ type: "checkbox",
179
+ checked: choice[purpose],
180
+ onChange: (event) => setChoice({
181
+ ...choice,
182
+ [purpose]: event.currentTarget.checked
183
+ })
184
+ }), /* @__PURE__ */ jsxs("label", {
185
+ htmlFor: `${id}${purpose}`,
186
+ children: [
187
+ /* @__PURE__ */ jsx("strong", { children: copy.options[purpose].name }),
188
+ ": ",
189
+ copy.options[purpose].use,
190
+ " (",
191
+ providerNames(providers(config, purpose), copy),
192
+ ")."
193
+ ]
194
+ })]
195
+ }, purpose))]
196
+ }) : /* @__PURE__ */ jsxs("p", {
197
+ className: classNames.text,
198
+ children: [
199
+ copy.notice(providerNames(providers(config, null), copy), purposes.map((purpose) => copy.uses[purpose]).join(copy.and)),
200
+ privacy,
201
+ purposes.length > 1 ? /* @__PURE__ */ jsxs(Fragment$1, { children: [privacy === null ? " " : " · ", /* @__PURE__ */ jsx("button", {
202
+ type: "button",
203
+ className: classNames.configure ?? classNames.link,
204
+ onClick: configure,
205
+ children: copy.configure
206
+ })] }) : null
207
+ ]
208
+ }), /* @__PURE__ */ jsxs("div", {
209
+ className: classNames.actions,
210
+ children: [/* @__PURE__ */ jsx("button", {
211
+ type: "button",
212
+ className: classNames.reject,
213
+ onClick: () => choose(REJECTED),
214
+ children: copy.reject
215
+ }), configuring ? /* @__PURE__ */ jsx("button", {
216
+ type: "button",
217
+ className: classNames.accept,
218
+ onClick: () => choose(choice),
219
+ children: copy.save
220
+ }) : /* @__PURE__ */ jsx("button", {
221
+ type: "button",
222
+ className: classNames.accept,
223
+ onClick: () => choose(ACCEPTED),
224
+ children: copy.accept
225
+ })]
226
+ })]
227
+ });
228
+ }
229
+ function ConsentLink({ className, children }) {
230
+ const config = useAnalyticsConfig();
231
+ if (config === null) return null;
232
+ return /* @__PURE__ */ jsx("button", {
233
+ type: "button",
234
+ className,
235
+ onClick: openConsent,
236
+ children: children ?? consentCopy(config.language).label
237
+ });
238
+ }
239
+ export { ConsentBanner, ConsentLink };
@@ -0,0 +1,20 @@
1
+ import { ReactNode } from "react";
2
+ export type ConsentBannerProps = {
3
+ className?: string;
4
+ classNames?: {
5
+ text?: string;
6
+ link?: string;
7
+ configure?: string;
8
+ options?: string;
9
+ option?: string;
10
+ actions?: string;
11
+ accept?: string;
12
+ reject?: string;
13
+ };
14
+ };
15
+ export type ConsentLinkProps = {
16
+ className?: string;
17
+ children?: ReactNode;
18
+ };
19
+ export declare function ConsentBanner({ className, classNames }: ConsentBannerProps): import("react").JSX.Element | null;
20
+ export declare function ConsentLink({ className, children }: ConsentLinkProps): import("react").JSX.Element | null;
@@ -0,0 +1,100 @@
1
+ import { cartItem } from "./events-Dt81tIp1.js";
2
+ // src/analytics/cookies.ts
3
+ const CONSENT_COOKIE = "__Host-ecomiq-consent";
4
+ const PURCHASE_COOKIE = "__Host-ecomiq-purchase";
5
+ const CONSENT_MAX_AGE = 31536e3;
6
+ const PURCHASE_MAX_AGE = 600;
7
+ const PURCHASE_ITEMS = 20;
8
+ const PURCHASE_NAME_LENGTH = 60;
9
+ const PURCHASE_COOKIE_BYTES = 3800;
10
+ const CATEGORIES = ["analytics", "marketing"];
11
+ function cookieValue(cookies, name) {
12
+ for (const part of cookies.split(";")) {
13
+ const separator = part.indexOf("=");
14
+ if (separator > 0 && part.slice(0, separator).trim() === name) return part.slice(separator + 1).trim();
15
+ }
16
+ return null;
17
+ }
18
+ function grantedChoice(value) {
19
+ if (value === "none") return {
20
+ analytics: false,
21
+ marketing: false
22
+ };
23
+ const granted = value.split(".");
24
+ if (granted.some((category) => !CATEGORIES.some((known) => known === category))) return null;
25
+ return {
26
+ analytics: granted.includes("analytics"),
27
+ marketing: granted.includes("marketing")
28
+ };
29
+ }
30
+ function readConsent(cookies) {
31
+ const value = cookieValue(cookies ?? "", CONSENT_COOKIE);
32
+ if (value === null) return null;
33
+ const [granted = "", version, date, ...rest] = value.split("|");
34
+ const choice = grantedChoice(granted);
35
+ if (choice === null || rest.length > 0 || !version || !date) return null;
36
+ return {
37
+ ...choice,
38
+ version,
39
+ date
40
+ };
41
+ }
42
+ function consentCookie(consent) {
43
+ const granted = CATEGORIES.filter((category) => consent[category]);
44
+ const choice = granted.length === 0 ? "none" : granted.join(".");
45
+ return `${CONSENT_COOKIE}=${choice}|${consent.version}|${consent.date}; Max-Age=${CONSENT_MAX_AGE}; Path=/; SameSite=Lax; Secure`;
46
+ }
47
+ function purchaseCookie(result) {
48
+ const { cart } = result;
49
+ const items = cart.items.slice(0, PURCHASE_ITEMS).map((item) => ({
50
+ ...cartItem(item),
51
+ item_name: item.title.slice(0, PURCHASE_NAME_LENGTH)
52
+ }));
53
+ const purchase = {
54
+ orderId: result.orderId,
55
+ currency: cart.currencyCode,
56
+ value: cart.totals.total,
57
+ tax: cart.totals.taxTotal,
58
+ shipping: cart.totals.shippingTotal,
59
+ items
60
+ };
61
+ let value = encodeURIComponent(JSON.stringify(purchase));
62
+ while (value.length > PURCHASE_COOKIE_BYTES && purchase.items.length > 0) {
63
+ purchase.items.pop();
64
+ value = encodeURIComponent(JSON.stringify(purchase));
65
+ }
66
+ return `${PURCHASE_COOKIE}=${value}; Max-Age=${PURCHASE_MAX_AGE}; Path=/; SameSite=Lax; Secure`;
67
+ }
68
+ function expiredPurchaseCookie() {
69
+ return `${PURCHASE_COOKIE}=; Max-Age=0; Path=/; SameSite=Lax; Secure`;
70
+ }
71
+ function purchaseItem(value) {
72
+ if (typeof value !== "object" || value === null) return false;
73
+ const item = value;
74
+ return typeof item.item_id === "string" && typeof item.item_name === "string" && typeof item.price === "number";
75
+ }
76
+ function readPurchase(cookies) {
77
+ const value = cookieValue(cookies, PURCHASE_COOKIE);
78
+ if (value === null || value === "") return null;
79
+ try {
80
+ const purchase = JSON.parse(decodeURIComponent(value));
81
+ if (typeof purchase.orderId !== "string" || typeof purchase.currency !== "string") return null;
82
+ if (typeof purchase.value !== "number" || typeof purchase.tax !== "number" || typeof purchase.shipping !== "number") return null;
83
+ if (!Array.isArray(purchase.items) || !purchase.items.every(purchaseItem)) return null;
84
+ return purchase;
85
+ } catch {
86
+ return null;
87
+ }
88
+ }
89
+ const ANALYTICS_COOKIE = /^(_ga|_ga_[A-Za-z0-9]+|_gid|_gat(_.+)?)$/;
90
+ const MARKETING_COOKIE = /^(_fbp|_fbc|_gcl_[a-z]+)$/;
91
+ function revokedCookies(cookies, consent) {
92
+ return cookies.split(";").map((pair) => pair.split("=")[0]?.trim() ?? "").filter((name) => !consent.analytics && ANALYTICS_COOKIE.test(name) || !consent.marketing && MARKETING_COOKIE.test(name));
93
+ }
94
+ function cookieDomains(hostname) {
95
+ const parts = hostname.split(".");
96
+ const domains = [null];
97
+ for (let index = 0; index < parts.length - 1; index += 1) domains.push(`.${parts.slice(index).join(".")}`);
98
+ return domains;
99
+ }
100
+ export { CONSENT_COOKIE, PURCHASE_COOKIE, consentCookie, cookieDomains, expiredPurchaseCookie, purchaseCookie, readConsent, readPurchase, revokedCookies };
@@ -0,0 +1,6 @@
1
+ import "./events.js";
2
+ import "@ecomiq/core";
3
+ export type Consent = {
4
+ analytics: boolean;
5
+ marketing: boolean;
6
+ };
@@ -0,0 +1,144 @@
1
+ // src/analytics/destinations.ts
2
+ const TOOLS = [
3
+ "googleAnalytics",
4
+ "googleTagManager",
5
+ "metaPixel",
6
+ "scripts"
7
+ ];
8
+ const DENIED = {
9
+ ad_storage: "denied",
10
+ ad_user_data: "denied",
11
+ ad_personalization: "denied",
12
+ analytics_storage: "denied"
13
+ };
14
+ const META_EVENTS = {
15
+ page_view: "PageView",
16
+ search: "Search",
17
+ view_item: "ViewContent",
18
+ add_to_cart: "AddToCart",
19
+ begin_checkout: "InitiateCheckout",
20
+ purchase: "Purchase"
21
+ };
22
+ const loaded = /* @__PURE__ */ new Set();
23
+ function grant(value) {
24
+ return value ? "granted" : "denied";
25
+ }
26
+ function googleConsent(consent) {
27
+ return {
28
+ ad_storage: grant(consent.marketing),
29
+ ad_user_data: grant(consent.marketing),
30
+ ad_personalization: grant(consent.marketing),
31
+ analytics_storage: grant(consent.analytics)
32
+ };
33
+ }
34
+ function script(parent, source) {
35
+ const element = document.createElement("script");
36
+ if ("src" in source) {
37
+ element.async = true;
38
+ element.src = source.src;
39
+ } else element.text = source.text;
40
+ parent.appendChild(element);
41
+ }
42
+ function gtag() {
43
+ if (window.gtag) return window.gtag;
44
+ const layer = window.dataLayer ??= [];
45
+ window.gtag = function() {
46
+ layer.push(arguments);
47
+ };
48
+ window.gtag("consent", "default", DENIED);
49
+ return window.gtag;
50
+ }
51
+ function metaPixel() {
52
+ if (window.fbq) return window.fbq;
53
+ const pixel = function(...args) {
54
+ if (pixel.callMethod) pixel.callMethod.apply(pixel, args);
55
+ else pixel.queue.push(args);
56
+ };
57
+ pixel.push = pixel;
58
+ pixel.loaded = true;
59
+ pixel.version = "2.0";
60
+ pixel.queue = [];
61
+ window.fbq = pixel;
62
+ window._fbq = pixel;
63
+ script(document.head, { src: "https://connect.facebook.net/en_US/fbevents.js" });
64
+ return pixel;
65
+ }
66
+ function allowed(tool, consent) {
67
+ if (tool === "googleAnalytics") return consent.analytics;
68
+ if (tool === "metaPixel") return consent.marketing;
69
+ return consent.analytics && consent.marketing;
70
+ }
71
+ function withdraw(consent) {
72
+ if (window.gtag) window.gtag("consent", "update", googleConsent(consent));
73
+ if (loaded.has("metaPixel") && !consent.marketing) metaPixel()("consent", "revoke");
74
+ location.reload();
75
+ }
76
+ function load(settings, consent) {
77
+ if ([...loaded].some((tool) => !allowed(tool, consent))) return withdraw(consent);
78
+ const pending = TOOLS.filter((tool) => settings[tool] !== null && allowed(tool, consent) && !loaded.has(tool));
79
+ if (window.gtag || pending.includes("googleAnalytics") || pending.includes("googleTagManager")) gtag()("consent", "update", googleConsent(consent));
80
+ for (const tool of pending) loaded.add(tool);
81
+ if (settings.googleAnalytics !== null && pending.includes("googleAnalytics")) {
82
+ gtag()("js", /* @__PURE__ */ new Date());
83
+ gtag()("config", settings.googleAnalytics, { send_page_view: false });
84
+ script(document.head, { src: `https://www.googletagmanager.com/gtag/js?id=${encodeURIComponent(settings.googleAnalytics)}` });
85
+ }
86
+ if (settings.googleTagManager !== null && pending.includes("googleTagManager")) {
87
+ (window.dataLayer ??= []).push({
88
+ "gtm.start": Date.now(),
89
+ event: "gtm.js"
90
+ });
91
+ script(document.head, { src: `https://www.googletagmanager.com/gtm.js?id=${encodeURIComponent(settings.googleTagManager)}` });
92
+ }
93
+ if (settings.metaPixel !== null && pending.includes("metaPixel")) metaPixel()("init", settings.metaPixel);
94
+ if (settings.scripts !== null && pending.includes("scripts")) {
95
+ if (settings.scripts.head !== null) script(document.head, { text: settings.scripts.head });
96
+ if (settings.scripts.bodyEnd !== null) script(document.body, { text: settings.scripts.bodyEnd });
97
+ }
98
+ }
99
+ function contents(params, currency) {
100
+ const { items } = params;
101
+ return {
102
+ content_type: "product",
103
+ content_ids: items.map((item) => item.item_id),
104
+ contents: items.map((item) => ({
105
+ id: item.item_id,
106
+ quantity: item.quantity ?? 1,
107
+ item_price: item.price
108
+ })),
109
+ num_items: items.reduce((sum, item) => sum + (item.quantity ?? 1), 0),
110
+ value: params.value,
111
+ currency: params.currency ?? currency
112
+ };
113
+ }
114
+ function sendMeta(event, currency) {
115
+ const name = META_EVENTS[event.name];
116
+ if (name === void 0) return;
117
+ const pixel = metaPixel();
118
+ if (event.name === "page_view") pixel("track", name);
119
+ else if (event.name === "search") pixel("track", name, { search_string: event.params.search_term });
120
+ else if (event.name === "purchase") pixel("track", name, contents(event.params, currency), { eventID: event.params.transaction_id });
121
+ else if ("value" in event.params) pixel("track", name, contents(event.params, currency));
122
+ }
123
+ function send(settings, consent, event) {
124
+ const params = "items" in event.params ? {
125
+ currency: settings.currency,
126
+ ...event.params
127
+ } : event.params;
128
+ if (loaded.has("googleAnalytics") && allowed("googleAnalytics", consent)) gtag()("event", event.name, params);
129
+ if (loaded.has("googleTagManager") && allowed("googleTagManager", consent)) {
130
+ const layer = window.dataLayer ??= [];
131
+ if ("items" in event.params) {
132
+ layer.push({ ecommerce: null });
133
+ layer.push({
134
+ event: event.name,
135
+ ecommerce: params
136
+ });
137
+ } else layer.push({
138
+ event: event.name,
139
+ ...params
140
+ });
141
+ }
142
+ if (loaded.has("metaPixel") && allowed("metaPixel", consent)) sendMeta(event, settings.currency);
143
+ }
144
+ export { load, send };
@@ -0,0 +1,102 @@
1
+ // src/analytics/events.ts
2
+ const LIST_LIMIT = 24;
3
+ const SEARCH_LIST = {
4
+ id: "search",
5
+ name: "Búsqueda"
6
+ };
7
+ const CATALOG_LIST = {
8
+ id: "catalog",
9
+ name: "Catálogo"
10
+ };
11
+ function filled(value) {
12
+ const trimmed = value?.trim() ?? "";
13
+ if (trimmed === "") return void 0;
14
+ return trimmed;
15
+ }
16
+ function itemsValue(items) {
17
+ const total = items.reduce((sum, item) => sum + item.price * (item.quantity ?? 1), 0);
18
+ return Math.round(total * 100) / 100;
19
+ }
20
+ function productItem(product) {
21
+ return {
22
+ item_id: product.id,
23
+ item_name: product.name,
24
+ item_brand: filled(product.brand),
25
+ item_category: filled(product.category),
26
+ price: product.price
27
+ };
28
+ }
29
+ function cartItem(item) {
30
+ return {
31
+ item_id: item.productId ?? item.variantId ?? item.id,
32
+ item_name: item.title,
33
+ item_variant: filled(item.variantLabel),
34
+ price: item.unitPrice,
35
+ quantity: item.quantity
36
+ };
37
+ }
38
+ function listAnalytics(list, products) {
39
+ const items = products.slice(0, LIST_LIMIT).map((product, index) => ({
40
+ ...productItem(product),
41
+ index
42
+ }));
43
+ return { events: [{
44
+ name: "view_item_list",
45
+ params: {
46
+ item_list_id: list.id,
47
+ item_list_name: list.name,
48
+ items
49
+ }
50
+ }] };
51
+ }
52
+ function productAnalytics(product) {
53
+ return { events: [{
54
+ name: "view_item",
55
+ params: {
56
+ value: product.price,
57
+ items: [productItem(product)]
58
+ }
59
+ }] };
60
+ }
61
+ function categoryAnalytics(category, products) {
62
+ return listAnalytics({
63
+ id: category.slug,
64
+ name: category.name
65
+ }, products);
66
+ }
67
+ function collectionAnalytics(collection, products) {
68
+ return listAnalytics({
69
+ id: collection.slug,
70
+ name: collection.name
71
+ }, products);
72
+ }
73
+ function catalogAnalytics(q, products) {
74
+ if (q === "") return listAnalytics(CATALOG_LIST, products);
75
+ const list = listAnalytics(SEARCH_LIST, products);
76
+ return { events: [{
77
+ name: "search",
78
+ params: { search_term: q }
79
+ }, ...list.events] };
80
+ }
81
+ function checkoutAnalytics(cart) {
82
+ const items = cart.items.map(cartItem);
83
+ return {
84
+ events: [{
85
+ name: "begin_checkout",
86
+ params: {
87
+ currency: cart.currencyCode,
88
+ value: itemsValue(items),
89
+ items
90
+ }
91
+ }],
92
+ once: `begin_checkout:${cart.id}`
93
+ };
94
+ }
95
+ function orderAnalytics(order, paid) {
96
+ if (!paid) return { events: [] };
97
+ return {
98
+ events: [],
99
+ paid: order.id
100
+ };
101
+ }
102
+ export { cartItem, catalogAnalytics, categoryAnalytics, checkoutAnalytics, collectionAnalytics, itemsValue, orderAnalytics, productAnalytics };
@@ -0,0 +1,51 @@
1
+ import { CategoryDetail, Collection, CustomerOrderDetail, ProductDetail, ProductSummary, StorefrontCart } from "@ecomiq/core";
2
+ export type AnalyticsItem = {
3
+ item_id: string;
4
+ item_name: string;
5
+ item_variant?: string;
6
+ item_brand?: string;
7
+ item_category?: string;
8
+ price: number;
9
+ quantity?: number;
10
+ index?: number;
11
+ };
12
+ export type CommerceParams = {
13
+ currency?: string;
14
+ value: number;
15
+ items: AnalyticsItem[];
16
+ };
17
+ export type AnalyticsEvent = {
18
+ name: "page_view";
19
+ params: {
20
+ page_location: string;
21
+ page_title: string;
22
+ };
23
+ } | {
24
+ name: "search";
25
+ params: {
26
+ search_term: string;
27
+ };
28
+ } | {
29
+ name: "view_item_list";
30
+ params: {
31
+ item_list_id: string;
32
+ item_list_name: string;
33
+ items: AnalyticsItem[];
34
+ };
35
+ } | {
36
+ name: "view_item" | "add_to_cart" | "remove_from_cart" | "begin_checkout";
37
+ params: CommerceParams;
38
+ } | {
39
+ name: "purchase";
40
+ params: CommerceParams & {
41
+ transaction_id: string;
42
+ tax: number;
43
+ shipping: number;
44
+ };
45
+ };
46
+ export type PageAnalytics = {
47
+ events: AnalyticsEvent[];
48
+ once?: string;
49
+ paid?: string;
50
+ };
51
+ export declare function catalogAnalytics(q: string, products: ProductSummary[]): PageAnalytics;