@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,376 @@
1
+ import { previewAddress } from "./preview-address-Cf0sJ-9p.js";
2
+ // src/preview-cart.ts
3
+ const PREVIEW_CART_TOKEN = "ecomiq-editor-preview-cart";
4
+ const BUYER = {
5
+ email: "ana.torres@example.com",
6
+ firstName: "Ana",
7
+ lastName: "Torres",
8
+ phone: "000000000",
9
+ identificationCountryCode: null,
10
+ identificationType: null,
11
+ identificationNumber: null,
12
+ entityTaxId: null,
13
+ entityName: null,
14
+ invoiceType: "ticket"
15
+ };
16
+ const RATES = [
17
+ {
18
+ shippingMethodId: "preview-regular",
19
+ name: "Envío regular",
20
+ displayName: "Envío regular",
21
+ target: "automatic",
22
+ price: 12,
23
+ description: "Llega en 3 a 5 días",
24
+ estimatedDeliveryDays: 4,
25
+ rateId: "preview-regular"
26
+ },
27
+ {
28
+ shippingMethodId: "preview-express",
29
+ name: "Envío express",
30
+ displayName: "Envío express",
31
+ target: "automatic",
32
+ price: 25,
33
+ description: "Llega mañana",
34
+ estimatedDeliveryDays: 1,
35
+ rateId: "preview-express"
36
+ },
37
+ {
38
+ shippingMethodId: "preview-pickup",
39
+ name: "Retiro en tienda",
40
+ displayName: "Retiro en tienda",
41
+ target: "pickupPoint",
42
+ price: 0,
43
+ description: "Listo en 24 horas",
44
+ estimatedDeliveryDays: 1,
45
+ rateId: "preview-pickup"
46
+ }
47
+ ];
48
+ const SAMPLE_METHODS = [{
49
+ code: "card",
50
+ name: "Tarjeta de crédito o débito",
51
+ description: null,
52
+ kind: "card",
53
+ isActive: true,
54
+ isDefault: true,
55
+ isManual: false,
56
+ sortOrder: 0,
57
+ providerId: null,
58
+ checkoutMode: null,
59
+ brands: ["visa", "mastercard"],
60
+ bankAccounts: [],
61
+ publicConfiguration: {}
62
+ }, {
63
+ code: "transfer",
64
+ name: "Transferencia bancaria",
65
+ description: "Te enviamos los datos al confirmar",
66
+ kind: "offline",
67
+ isActive: true,
68
+ isDefault: false,
69
+ isManual: true,
70
+ sortOrder: 1,
71
+ providerId: null,
72
+ checkoutMode: null,
73
+ brands: [],
74
+ bankAccounts: [],
75
+ publicConfiguration: {}
76
+ }];
77
+ const state = {
78
+ items: null,
79
+ codes: [],
80
+ rate: "preview-regular",
81
+ method: null,
82
+ buyer: BUYER,
83
+ address: null
84
+ };
85
+ const variants = /* @__PURE__ */ new Map();
86
+ function line(id, product, quantity) {
87
+ return {
88
+ id,
89
+ productId: product.id,
90
+ title: product.name,
91
+ variantLabel: null,
92
+ productHandle: product.slug,
93
+ productUrl: product.url,
94
+ thumbnail: product.imageUrl || null,
95
+ quantity,
96
+ variantId: null,
97
+ variantSku: null,
98
+ unitPrice: product.price,
99
+ compareAtUnitPrice: product.compareAtPrice,
100
+ bundleItems: [],
101
+ requiresShipping: true,
102
+ sellerId: null,
103
+ sellerName: null,
104
+ orderBumpId: null
105
+ };
106
+ }
107
+ function rememberProduct(product) {
108
+ for (const variant of product.variants) {
109
+ if (variant.id === null) continue;
110
+ const label = variant.options.map((option) => option.value).join(" / ");
111
+ variants.set(variant.id, {
112
+ ...line(`preview-line-${variant.id}`, {
113
+ ...product,
114
+ imageUrl: variant.images[0]?.url ?? product.imageUrl,
115
+ price: variant.price,
116
+ compareAtPrice: variant.compareAtPrice
117
+ }, 1),
118
+ variantId: variant.id,
119
+ variantSku: variant.sku || null,
120
+ variantLabel: label || null,
121
+ requiresShipping: variant.requiresShipping,
122
+ sellerId: product.seller?.id ?? null,
123
+ sellerName: product.seller?.name ?? null
124
+ });
125
+ }
126
+ }
127
+ async function items(client) {
128
+ if (state.items !== null) return state.items;
129
+ const products = (await client.getProducts({
130
+ pageSize: 4,
131
+ inStock: true
132
+ }).catch(() => null))?.products ?? [];
133
+ if (products.length === 0) {
134
+ state.items = [line("preview-line-sample", {
135
+ id: "preview-product",
136
+ name: "Producto de ejemplo",
137
+ slug: "",
138
+ url: null,
139
+ imageUrl: "",
140
+ price: 89,
141
+ compareAtPrice: null
142
+ }, 1)];
143
+ return state.items;
144
+ }
145
+ state.items = products.slice(0, 2).map((product, index) => ({
146
+ ...line(`preview-line-${product.id}`, product, index + 1),
147
+ sellerId: product.seller?.id ?? null,
148
+ sellerName: product.seller?.name ?? null
149
+ }));
150
+ return state.items;
151
+ }
152
+ function shippingMethod() {
153
+ const rate = RATES.find((candidate) => candidate.shippingMethodId === state.rate) ?? RATES[0];
154
+ return {
155
+ id: `preview-shipping-${rate.shippingMethodId}`,
156
+ shippingMethodId: rate.shippingMethodId,
157
+ rateId: rate.rateId ?? null,
158
+ name: rate.name ?? "Envío",
159
+ description: rate.description ?? null,
160
+ type: rate.target === "pickupPoint" ? "pickup" : "regular",
161
+ target: rate.target,
162
+ targetId: null,
163
+ fulfillmentLocationId: null,
164
+ total: rate.price,
165
+ estimatedDays: rate.estimatedDeliveryDays ?? null,
166
+ scheduledDate: null,
167
+ scheduledTime: null,
168
+ serviceCode: null,
169
+ sellerId: null,
170
+ shippingProfileId: null
171
+ };
172
+ }
173
+ async function snapshot(client) {
174
+ const [settings, lines] = await Promise.all([client.getSettings(), items(client)]);
175
+ const address = state.address ?? await previewAddress(settings.store);
176
+ const subtotal = lines.reduce((sum, item) => sum + item.unitPrice * item.quantity, 0);
177
+ const discount = state.codes.length > 0 ? Math.round(subtotal * .1 * 100) / 100 : 0;
178
+ const shipping = lines.some((item) => item.requiresShipping) ? shippingMethod() : null;
179
+ const shippingTotal = shipping?.total ?? 0;
180
+ return {
181
+ id: "preview-cart",
182
+ token: PREVIEW_CART_TOKEN,
183
+ cartNumber: "1043",
184
+ email: state.buyer.email,
185
+ phone: state.buyer.phone,
186
+ firstName: state.buyer.firstName,
187
+ lastName: state.buyer.lastName,
188
+ currencyCode: settings.store.currency,
189
+ status: "inProgress",
190
+ completedAt: null,
191
+ shippingAddress: address,
192
+ billingAddress: address,
193
+ promotionCodes: state.codes,
194
+ items: lines,
195
+ shippingMethods: shipping ? [shipping] : [],
196
+ paymentMethodCode: state.method,
197
+ totals: {
198
+ subtotal,
199
+ discountTotal: discount,
200
+ shippingOriginalTotal: shippingTotal,
201
+ shippingTotal,
202
+ taxTotal: 0,
203
+ warrantyTotal: 0,
204
+ total: subtotal - discount + shippingTotal
205
+ },
206
+ invoiceType: state.buyer.invoiceType,
207
+ identificationCountryCode: state.buyer.identificationCountryCode,
208
+ identificationType: state.buyer.identificationType,
209
+ identificationNumber: state.buyer.identificationNumber,
210
+ entityTaxId: state.buyer.entityTaxId,
211
+ entityName: state.buyer.entityName
212
+ };
213
+ }
214
+ async function paymentMethods(client) {
215
+ const configured = await client.getPaymentMethods().catch(() => []);
216
+ if (configured.length === 0) return SAMPLE_METHODS;
217
+ return configured.map((method, index) => ({
218
+ code: method.code,
219
+ name: method.name,
220
+ description: null,
221
+ kind: method.kind,
222
+ isActive: true,
223
+ isDefault: index === 0,
224
+ isManual: method.kind === "offline",
225
+ sortOrder: method.sortOrder,
226
+ providerId: null,
227
+ checkoutMode: null,
228
+ brands: method.brands,
229
+ bankAccounts: [],
230
+ publicConfiguration: {}
231
+ }));
232
+ }
233
+ async function add(client, variantId, quantity) {
234
+ const lines = await items(client);
235
+ const existing = lines.find((item) => item.variantId === variantId);
236
+ if (existing) {
237
+ state.items = lines.map((item) => item === existing ? {
238
+ ...item,
239
+ quantity: item.quantity + quantity
240
+ } : item);
241
+ return snapshot(client);
242
+ }
243
+ const known = variants.get(variantId);
244
+ if (known) state.items = [...lines, {
245
+ ...known,
246
+ quantity
247
+ }];
248
+ return snapshot(client);
249
+ }
250
+ async function setQuantity(client, id, quantity) {
251
+ const lines = await items(client);
252
+ if (quantity <= 0) state.items = lines.filter((item) => item.id !== id);
253
+ else state.items = lines.map((item) => item.id === id ? {
254
+ ...item,
255
+ quantity
256
+ } : item);
257
+ return snapshot(client);
258
+ }
259
+ function shippingOptions() {
260
+ return { groups: [{
261
+ sellerId: null,
262
+ sellerName: null,
263
+ shippingProfileId: null,
264
+ rates: RATES
265
+ }] };
266
+ }
267
+ function ours(params) {
268
+ return params.cartToken === PREVIEW_CART_TOKEN;
269
+ }
270
+ function previewCart(client) {
271
+ return {
272
+ getProductBySlug: async (slug, options) => {
273
+ const product = await client.getProductBySlug(slug, options);
274
+ rememberProduct(product);
275
+ return product;
276
+ },
277
+ createCart: () => snapshot(client),
278
+ getCart: (params) => ours(params) ? snapshot(client) : client.getCart(params),
279
+ addCartItem: (params) => ours(params) ? add(client, params.variantId, params.quantity) : client.addCartItem(params),
280
+ updateCartItemQuantity: (params) => ours(params) ? setQuantity(client, params.cartItemId, params.quantity) : client.updateCartItemQuantity(params),
281
+ removeCartItem: (params) => ours(params) ? setQuantity(client, params.cartItemId, 0) : client.removeCartItem(params),
282
+ getCartCheckout: async (params) => {
283
+ if (!ours(params)) return client.getCartCheckout(params);
284
+ const [cart, methods] = await Promise.all([snapshot(client), paymentMethods(client)]);
285
+ return {
286
+ cart,
287
+ paymentMethods: { methods: methods.map((method) => ({
288
+ ...method,
289
+ discountAmount: null
290
+ })) },
291
+ orderBumps: []
292
+ };
293
+ },
294
+ getShippingOptions: (params) => ours(params) ? Promise.resolve(shippingOptions()) : client.getShippingOptions(params),
295
+ putCartShippingMethod: (params) => {
296
+ if (!ours(params)) return client.putCartShippingMethod(params);
297
+ state.rate = params.shippingMethodId;
298
+ return snapshot(client);
299
+ },
300
+ putCartPaymentMethod: (params) => {
301
+ if (!ours(params)) return client.putCartPaymentMethod(params);
302
+ state.method = params.paymentMethodCode;
303
+ return snapshot(client);
304
+ },
305
+ patchCartBuyer: (params) => {
306
+ if (!ours(params)) return client.patchCartBuyer(params);
307
+ state.buyer = {
308
+ email: params.email,
309
+ firstName: params.firstName,
310
+ lastName: params.lastName,
311
+ phone: params.phone,
312
+ identificationCountryCode: params.identificationCountryCode ?? null,
313
+ identificationType: params.identificationType ?? null,
314
+ identificationNumber: params.identificationNumber ?? null,
315
+ entityTaxId: params.entityTaxId ?? null,
316
+ entityName: params.entityName ?? null,
317
+ invoiceType: params.invoiceType ?? state.buyer.invoiceType
318
+ };
319
+ return snapshot(client);
320
+ },
321
+ patchCartAddresses: async (params) => {
322
+ if (!ours(params)) return client.patchCartAddresses(params);
323
+ const address = params.shippingAddress;
324
+ if (address) state.address = {
325
+ name: address.name,
326
+ address1: address.address1,
327
+ city: address.city,
328
+ countryCode: address.countryCode,
329
+ company: null,
330
+ address2: address.address2 ?? null,
331
+ department: address.department ?? null,
332
+ province: address.province ?? null,
333
+ postalCode: address.postalCode ?? null,
334
+ district: address.district ?? null,
335
+ phone: address.phone ?? null,
336
+ latitude: null,
337
+ longitude: null
338
+ };
339
+ return snapshot(client);
340
+ },
341
+ addCartPromotionCode: (params) => {
342
+ if (!ours(params)) return client.addCartPromotionCode(params);
343
+ if (!state.codes.includes(params.code)) state.codes = [...state.codes, params.code];
344
+ return snapshot(client);
345
+ },
346
+ removeCartPromotionCode: (params) => {
347
+ if (!ours(params)) return client.removeCartPromotionCode(params);
348
+ state.codes = state.codes.filter((code) => code !== params.code);
349
+ return snapshot(client);
350
+ },
351
+ uploadPaymentReceipt: (params) => ours(params) ? Promise.resolve({
352
+ id: "preview-receipt",
353
+ url: ""
354
+ }) : client.uploadPaymentReceipt(params),
355
+ checkoutCart: async (params) => {
356
+ if (!ours(params)) return client.checkoutCart(params);
357
+ const cart = await snapshot(client);
358
+ state.items = null;
359
+ state.codes = [];
360
+ state.method = null;
361
+ return {
362
+ orderId: "preview-order-1",
363
+ orderNumber: "1",
364
+ orderStatusUrl: "/orders/preview-order-1",
365
+ orderGroup: "preview-order-group",
366
+ orderIds: ["preview-order-1"],
367
+ payment: null,
368
+ cart: {
369
+ ...cart,
370
+ status: "completed"
371
+ }
372
+ };
373
+ }
374
+ };
375
+ }
376
+ export { PREVIEW_CART_TOKEN, paymentMethods, previewCart, rememberProduct };
@@ -0,0 +1,51 @@
1
+ // src/product-preview.ts
2
+ const BAR_ID = "ecomiq-product-preview";
3
+ const BAR = `<div id="${BAR_ID}" role="region" aria-label="Vista previa"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M2 12s3.6-7 10-7 10 7 10 7-3.6 7-10 7S2 12 2 12Z"/><circle cx="12" cy="12" r="3"/></svg><strong>Vista previa</strong><span>Este producto no está publicado. Solo tú lo ves.</span><button type="button">Ocultar barra</button></div><style>${[
4
+ `#${BAR_ID}{position:fixed;left:0;right:0;bottom:0;z-index:2147483647;box-sizing:border-box;display:flex;align-items:center;gap:10px;height:46px;margin:0;padding:0 16px;background:#1f1f1f;color:#fff;font:14px/1.2 system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;text-align:left}`,
5
+ `#${BAR_ID} svg{display:block;flex:none}`,
6
+ `#${BAR_ID} strong{flex:none;font-weight:600}`,
7
+ `#${BAR_ID} span{flex:1;min-width:0;overflow:hidden;color:#a3a3a3;white-space:nowrap;text-overflow:ellipsis}`,
8
+ `#${BAR_ID} button{flex:none;margin:0;padding:6px 12px;border:1px solid #4d4d4d;border-radius:6px;background:transparent;color:#fff;font:inherit;cursor:pointer}`,
9
+ `#${BAR_ID} button:hover{background:#2e2e2e}`,
10
+ `body:has(#${BAR_ID}){padding-bottom:46px}`
11
+ ].join("")}</style><script>${`(()=>{const bar=document.getElementById("${BAR_ID}");if(!bar)return;const path=location.pathname;const timer=setInterval(()=>{if(location.pathname!==path)hide()},500);function hide(){clearInterval(timer);bar.remove()}bar.querySelector("button").addEventListener("click",hide)})()`}<\/script>`;
12
+ function productPreviewFrom(request) {
13
+ const key = new URL(request.url).searchParams.get("preview_key");
14
+ if (!key) return void 0;
15
+ return {
16
+ key,
17
+ shown: false
18
+ };
19
+ }
20
+ function productPreviewClient(client, preview) {
21
+ return {
22
+ ...client,
23
+ resolveUrl: async (path) => {
24
+ const resolved = await client.resolveUrl(path, { previewKey: preview.key });
25
+ if (resolved?.kind === "product" && resolved.product.isPreview) preview.shown = true;
26
+ return resolved;
27
+ },
28
+ getProductBySlug: async (slug) => {
29
+ const product = await client.getProductBySlug(slug, { previewKey: preview.key });
30
+ if (product.isPreview) preview.shown = true;
31
+ return product;
32
+ }
33
+ };
34
+ }
35
+ async function productPreviewResponse(response) {
36
+ const headers = new Headers(response.headers);
37
+ headers.set("Cache-Control", "private, no-store");
38
+ headers.set("X-Robots-Tag", "noindex");
39
+ const init = {
40
+ status: response.status,
41
+ statusText: response.statusText,
42
+ headers
43
+ };
44
+ if (!headers.get("Content-Type")?.includes("text/html")) return new Response(response.body, init);
45
+ headers.delete("Content-Length");
46
+ const html = await response.text();
47
+ const end = html.lastIndexOf("</body>");
48
+ if (end === -1) return new Response(html + BAR, init);
49
+ return new Response(html.slice(0, end) + BAR + html.slice(end), init);
50
+ }
51
+ export { productPreviewClient, productPreviewFrom, productPreviewResponse };
@@ -0,0 +1,5 @@
1
+ import { StorefrontClient } from "@ecomiq/core";
2
+ export type ProductPreview = {
3
+ key: string;
4
+ shown: boolean;
5
+ };
@@ -0,0 +1,46 @@
1
+ // src/product-variants.ts
2
+ function isVariantAvailable(variant) {
3
+ return variant.isAvailable !== false;
4
+ }
5
+ function variantOptions(variants) {
6
+ const groups = /* @__PURE__ */ new Map();
7
+ for (const variant of variants) for (const option of variant.options) {
8
+ const group = groups.get(option.key) ?? {
9
+ name: option.name,
10
+ values: []
11
+ };
12
+ if (!group.values.includes(option.value)) group.values.push(option.value);
13
+ groups.set(option.key, group);
14
+ }
15
+ return [...groups.entries()].map(([key, group]) => ({
16
+ key,
17
+ ...group
18
+ }));
19
+ }
20
+ function pickVariant(variants, current, key, value) {
21
+ const wanted = current.options.map((option) => {
22
+ if (option.key === key) return {
23
+ ...option,
24
+ value
25
+ };
26
+ return option;
27
+ });
28
+ const exact = variants.find((variant) => wanted.every((option) => variant.options.some((candidate) => candidate.key === option.key && candidate.value === option.value)));
29
+ if (exact) return exact;
30
+ return variants.find((variant) => variant.options.some((option) => option.key === key && option.value === value)) ?? null;
31
+ }
32
+ function variantSwatches(variants, key, values) {
33
+ const images = /* @__PURE__ */ new Map();
34
+ for (const value of values) {
35
+ const image = variants.find((variant) => variant.options.some((option) => option.key === key && option.value === value) && variant.images.some((image) => image.type === "image"))?.images.filter((candidate) => candidate.type === "image").sort((a, b) => a.order - b.order)[0];
36
+ if (image === void 0) return null;
37
+ images.set(value, image.url);
38
+ }
39
+ if (new Set(images.values()).size < values.length) return null;
40
+ return images;
41
+ }
42
+ function discountPercent(value, compareAt) {
43
+ if (compareAt == null || compareAt <= value || compareAt <= 0) return 0;
44
+ return Math.round((compareAt - value) / compareAt * 100);
45
+ }
46
+ export { discountPercent, isVariantAvailable, pickVariant, variantOptions, variantSwatches };
@@ -0,0 +1,12 @@
1
+ import { ProductDetail } from "@ecomiq/core";
2
+ export type ProductVariant = ProductDetail["variants"][number];
3
+ export type VariantOption = {
4
+ key: string;
5
+ name: string;
6
+ values: string[];
7
+ };
8
+ export declare function isVariantAvailable(variant: ProductVariant): boolean;
9
+ export declare function variantOptions(variants: ProductVariant[]): VariantOption[];
10
+ export declare function pickVariant(variants: ProductVariant[], current: ProductVariant, key: string, value: string): ProductVariant | null;
11
+ export declare function variantSwatches(variants: ProductVariant[], key: string, values: string[]): Map<string, string> | null;
12
+ export declare function discountPercent(value: number, compareAt: number | null | undefined): number;
@@ -0,0 +1,194 @@
1
+ import { text } from "./form-BtQcbXlJ.js";
2
+ import { customer, customerHeaders } from "./session-CKvmFJyg.js";
3
+ import { found, store, storeHeaders } from "./store-8Q-_LFrQ.js";
4
+ import { data, redirect } from "react-router";
5
+ import { ApiError, getOrderReviewContext, getOrderTracking, sanitizeHtml } from "@ecomiq/core";
6
+ import { z } from "zod";
7
+ // src/public-pages.ts
8
+ const SUGGESTION_MIN_LENGTH = 2;
9
+ const SUGGESTION_MAX_LENGTH = 80;
10
+ const SUGGESTION_LIMIT = 6;
11
+ const PageContent = z.object({
12
+ title: z.string().optional(),
13
+ html: z.string().optional(),
14
+ seo: z.object({
15
+ title: z.string().nullish(),
16
+ description: z.string().nullish()
17
+ }).optional()
18
+ });
19
+ function places(items) {
20
+ return items.map((item) => ({
21
+ code: item.code,
22
+ name: item.name
23
+ }));
24
+ }
25
+ async function loadGeo(request, context) {
26
+ const client = store(context);
27
+ const params = new URL(request.url).searchParams;
28
+ const { store: settings } = await client.getSettings();
29
+ const countryCode = settings.countryCode;
30
+ const department = params.get("department");
31
+ const province = params.get("province");
32
+ const none = [];
33
+ const [departments, provinces, districts] = await Promise.all([
34
+ client.getDepartments({ countryCode }).catch(() => none),
35
+ department ? client.getProvinces({
36
+ countryCode,
37
+ departmentCode: department
38
+ }).catch(() => none) : none,
39
+ province ? client.getDistricts({
40
+ countryCode,
41
+ provinceCode: province
42
+ }).catch(() => none) : none
43
+ ]);
44
+ return {
45
+ departments: places(departments),
46
+ provinces: places(provinces),
47
+ districts: places(districts)
48
+ };
49
+ }
50
+ async function loadSearchSuggestions(request, context) {
51
+ const q = new URL(request.url).searchParams.get("q")?.trim() ?? "";
52
+ if (q.length < SUGGESTION_MIN_LENGTH) return {
53
+ q,
54
+ products: []
55
+ };
56
+ return {
57
+ q,
58
+ products: await store(context).autocompleteProducts({
59
+ search: q.slice(0, SUGGESTION_MAX_LENGTH),
60
+ limit: SUGGESTION_LIMIT
61
+ }).catch(() => [])
62
+ };
63
+ }
64
+ async function loadTracking(request, context, code) {
65
+ const typed = new URL(request.url).searchParams.get("code")?.trim();
66
+ if (typed) throw redirect(`/track/${encodeURIComponent(typed)}`);
67
+ const client = store(context);
68
+ const settings = await client.getSettings();
69
+ const place = {
70
+ language: `${settings.store.language}-${settings.store.countryCode}`,
71
+ timeZone: settings.store.timeZone
72
+ };
73
+ if (!code) return {
74
+ code: "",
75
+ tracking: null,
76
+ missing: false,
77
+ ...place
78
+ };
79
+ const tracking = await getOrderTracking(client, code, await storeHeaders(client)).catch(() => null);
80
+ return {
81
+ code,
82
+ tracking,
83
+ missing: tracking === null,
84
+ ...place
85
+ };
86
+ }
87
+ async function loadReview(context, token) {
88
+ const client = store(context);
89
+ return { review: await found(getOrderReviewContext(client, token, await storeHeaders(client)), (status) => status < 500) };
90
+ }
91
+ async function reviewAction(request, context, token) {
92
+ const client = store(context);
93
+ const form = await request.formData();
94
+ const review = await found(getOrderReviewContext(client, token, await storeHeaders(client)), (status) => status < 500);
95
+ const rating = Number(text(form, "rating"));
96
+ const content = text(form, "content");
97
+ const name = text(form, "name");
98
+ if (!Number.isInteger(rating) || rating < 1 || rating > 5 || !content || !name) return data({
99
+ ok: false,
100
+ error: "Elige una calificación y cuéntanos tu experiencia."
101
+ }, { status: 400 });
102
+ try {
103
+ await client.createProductReview({
104
+ productId: text(form, "productId"),
105
+ rating,
106
+ content,
107
+ title: text(form, "title") || void 0,
108
+ reviewerName: name,
109
+ reviewerEmail: review.email ?? "",
110
+ orderId: review.orderId,
111
+ reviewToken: token
112
+ });
113
+ return {
114
+ ok: true,
115
+ error: null
116
+ };
117
+ } catch (error) {
118
+ if (error instanceof ApiError && error.status === 409) return data({
119
+ ok: false,
120
+ error: "Ya opinaste sobre este producto."
121
+ }, { status: 400 });
122
+ return data({
123
+ ok: false,
124
+ error: "No pudimos guardar tu opinión."
125
+ }, { status: 400 });
126
+ }
127
+ }
128
+ async function productReviewAction(request, context) {
129
+ const current = await customer(request, context);
130
+ if (current === null) return data({
131
+ ok: false,
132
+ error: "Inicia sesión para dejar tu opinión."
133
+ }, { status: 401 });
134
+ const form = await request.formData();
135
+ const rating = Number(text(form, "rating"));
136
+ const content = text(form, "content");
137
+ const name = text(form, "name");
138
+ if (!Number.isInteger(rating) || rating < 1 || rating > 5 || !content || !name) return data({
139
+ ok: false,
140
+ error: "Elige una calificación, escribe tu nombre y cuéntanos tu experiencia."
141
+ }, { status: 400 });
142
+ try {
143
+ await store(context).createCustomerProductReview({
144
+ productId: text(form, "productId"),
145
+ rating,
146
+ content,
147
+ title: text(form, "title") || void 0,
148
+ reviewerName: name
149
+ }, customerHeaders(current));
150
+ return {
151
+ ok: true,
152
+ error: null
153
+ };
154
+ } catch (error) {
155
+ if (error instanceof ApiError && error.status === 409) return data({
156
+ ok: false,
157
+ error: "Ya opinaste sobre este producto."
158
+ }, { status: 400 });
159
+ if (error instanceof ApiError && error.code === "Customers.ProfileRequired") return data({
160
+ ok: false,
161
+ error: "Completa tu perfil para dejar tu opinión."
162
+ }, { status: 400 });
163
+ return data({
164
+ ok: false,
165
+ error: "No pudimos guardar tu opinión."
166
+ }, { status: 400 });
167
+ }
168
+ }
169
+ async function readPage(context, handle) {
170
+ const page = await store(context).getPageBySlug(handle).catch((error) => {
171
+ if (error instanceof ApiError && error.status === 404) return null;
172
+ throw error;
173
+ });
174
+ if (page === null) return null;
175
+ return pageData(page);
176
+ }
177
+ async function loadPage(context, handle) {
178
+ return pageData(await found(store(context).getPageBySlug(handle)));
179
+ }
180
+ function pageData(page) {
181
+ const parsed = PageContent.safeParse(page.settings);
182
+ let content = {};
183
+ if (parsed.success) content = parsed.data;
184
+ return {
185
+ title: content.title ?? page.name,
186
+ html: sanitizeHtml(content.html ?? ""),
187
+ layout: page.layout,
188
+ seo: {
189
+ title: content.seo?.title ?? content.title ?? page.name,
190
+ description: content.seo?.description ?? ""
191
+ }
192
+ };
193
+ }
194
+ export { loadGeo, loadPage, loadReview, loadSearchSuggestions, loadTracking, productReviewAction, readPage, reviewAction };