@ecomiq/storefront 3.2.0 → 3.3.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 (39) hide show
  1. package/README.md +17 -0
  2. package/dist/{account-CLF4iS_r.js → account-DMM0ZZYb.js} +3 -3
  3. package/dist/analytics/{config-CtHbJ58z.js → config-rY3DYQyP.js} +1 -1
  4. package/dist/{cart-actions-DaGyBu9g.js → cart-actions-C2Csh1k0.js} +1 -1
  5. package/dist/{checkout-Dyq58gRY.js → checkout-DnfQ8WhP.js} +3 -3
  6. package/dist/{complaint-book-C_6Z1-f1.js → complaint-book-DvxhgbsM.js} +1 -1
  7. package/dist/entries/account.js +1 -1
  8. package/dist/entries/analytics.js +1 -1
  9. package/dist/entries/cart.js +1 -1
  10. package/dist/entries/checkout.js +2 -2
  11. package/dist/entries/order.js +2 -2
  12. package/dist/index.d.ts +2 -2
  13. package/dist/index.js +20 -20
  14. package/dist/{order-draft-DfEHthuU.js → order-draft-XI7gDVeO.js} +1 -1
  15. package/dist/{order-status-Bow-z55_.js → order-status-C61ywW-E.js} +2 -2
  16. package/dist/{page-seo-DFFDxVA7.js → page-seo-BdyKwykI.js} +2 -2
  17. package/dist/{pages-CPxkyi9N.js → pages-ClOPuk55.js} +3 -3
  18. package/dist/{public-pages-ax-EBPYN.js → public-pages-BZXH5gt9.js} +2 -2
  19. package/dist/{registration-DuOEfjVt.js → registration-BmWt3-eT.js} +3 -3
  20. package/dist/{section-preview-D-c1PIuT.js → section-preview-C7QbWAzE.js} +2 -2
  21. package/dist/sections/account-order.js +1 -1
  22. package/dist/sections/account-orders.js +1 -1
  23. package/dist/sections/checkout.js +2 -2
  24. package/dist/sections/complaint-book.js +1 -1
  25. package/dist/sections/draft-invoice.js +1 -1
  26. package/dist/sections/order-tracking.js +1 -1
  27. package/dist/{sections-Cdsudggy.js → sections-BkjGSM28.js} +1 -1
  28. package/dist/{seo-Tfib2qCv.js → seo-Cz1O5oxh.js} +2 -2
  29. package/dist/{session-BKu8g6ZJ.js → session-CsuzPSJs.js} +3 -3
  30. package/dist/{settings-B0NO2A6Y.js → settings-CiW3OroM.js} +20 -14
  31. package/dist/settings.d.ts +2 -1
  32. package/dist/{store-BrR5-uon.js → store-BGDvRGNS.js} +13 -5
  33. package/dist/store.d.ts +8 -4
  34. package/dist/{telemetry-HuZXWBPi.js → telemetry-k9sM5iBG.js} +3 -0
  35. package/dist/{templates-Bq8joT_y.js → templates-BM3WvMlA.js} +2 -2
  36. package/dist/{urls-DNwJJ6-F.js → urls-BR4wv2K2.js} +1 -1
  37. package/dist/{use-checkout-BElBkhVE.js → use-checkout-BmVOLp_x.js} +1 -1
  38. package/dist/{worker-DWh0nPh3.js → worker-BxlCSjSF.js} +2 -2
  39. package/package.json +2 -2
package/README.md CHANGED
@@ -191,6 +191,23 @@ Los ajustes disponibles son `setting.text`, `image`, `link`, `collection`,
191
191
  el valor inicial y debe ser literal; el segundo, la etiqueta que ve el
192
192
  comerciante.
193
193
 
194
+ ### Pedir los datos a la vez
195
+
196
+ Las lecturas que un loader pide a la vez viajan en una sola consulta. Cada
197
+ lectura que espera el resultado de otra suma un viaje a la API.
198
+
199
+ - Junta con `Promise.all` las lecturas que no dependen entre sí. Si hay un
200
+ respaldo (la colección elegida viene vacía → los más vendidos), pide las dos
201
+ listas juntas y elige después.
202
+ - `pickProducts` busca la colección por su slug: no leas antes la lista.
203
+ - Colecciones con foto de portada: `client.getCollectionCovers({ limit })` y
204
+ `withImages(client, colecciones)`, que usa las fotos que ya trae cada
205
+ colección.
206
+ - La primera colección, o las que sobran, con sus productos:
207
+ `client.getCollectionsWithProducts({ limit, products, sort })`.
208
+ - Productos con sus reseñas: `pickProductsWithReviews(client, fuente, { limit,
209
+ sortBy, sortDirection })`, con la misma fuente que `pickProducts`.
210
+
194
211
  ### Carrito
195
212
 
196
213
  ```tsx title="app/routes/cart.tsx"
@@ -3,9 +3,9 @@ import { identityDocumentError, isIdentityDocumentType } from "./documents-Ka-EL
3
3
  import { PHONE_ERROR, phoneError } from "./phone-B350moyr.js";
4
4
  import { ADDRESS_INTENTS, ORDER_REQUEST_INTENTS, isIntent } from "./form-contracts-0R112spH.js";
5
5
  import { readPlace } from "./place-CmW4hBWY.js";
6
- import { customerHeaders, requireCustomer, requireCustomerWith } from "./session-BKu8g6ZJ.js";
7
- import { found, readCountries, readDocumentCountries, store } from "./store-BrR5-uon.js";
8
- import { requestUrl } from "./urls-DNwJJ6-F.js";
6
+ import { customerHeaders, requireCustomer, requireCustomerWith } from "./session-CsuzPSJs.js";
7
+ import { found, readCountries, readDocumentCountries, store } from "./store-BGDvRGNS.js";
8
+ import { requestUrl } from "./urls-BR4wv2K2.js";
9
9
  import { data } from "react-router";
10
10
  import { ApiError } from "@ecomiq/core";
11
11
  // src/account.ts
@@ -1,4 +1,4 @@
1
- import { worker } from "../worker-DWh0nPh3.js";
1
+ import { worker } from "../worker-BxlCSjSF.js";
2
2
  import { readConsent } from "./cookies-CWsi-zSd.js";
3
3
  import { cartItem } from "./events-CWmKY7oX.js";
4
4
  // src/analytics/config.ts
@@ -2,7 +2,7 @@ import { cartCookie, cartToken, readCart } from "./cart-D7DxZ2lD.js";
2
2
  import { text } from "./form-BtQcbXlJ.js";
3
3
  import { CART_INTENTS, isIntent } from "./form-contracts-0R112spH.js";
4
4
  import { readPersonalization } from "./personalization-BSVlktZP.js";
5
- import { store } from "./store-BrR5-uon.js";
5
+ import { store } from "./store-BGDvRGNS.js";
6
6
  import { data, redirect } from "react-router";
7
7
  import { ApiError, CartItemModifierSchema } from "@ecomiq/core";
8
8
  import { z } from "zod";
@@ -1,5 +1,5 @@
1
1
  import { addressDefaults } from "./address-defaults-Bj8j8noq.js";
2
- import { trackingConsented } from "./analytics/config-CtHbJ58z.js";
2
+ import { trackingConsented } from "./analytics/config-rY3DYQyP.js";
3
3
  import { purchaseCookie } from "./analytics/cookies-CWsi-zSd.js";
4
4
  import { checkoutAnalytics } from "./analytics/events-CWmKY7oX.js";
5
5
  import { cartCookie, cartToken } from "./cart-D7DxZ2lD.js";
@@ -9,8 +9,8 @@ import { buyerDocumentError, isIdentityDocumentType } from "./documents-Ka-EL9m0
9
9
  import { CHECKOUT_INTENTS, isIntent } from "./form-contracts-0R112spH.js";
10
10
  import { PHONE_ERROR, phoneError } from "./phone-B350moyr.js";
11
11
  import { readPlace } from "./place-CmW4hBWY.js";
12
- import { customer, customerHeaders, requireCustomerRegistration } from "./session-BKu8g6ZJ.js";
13
- import { readCountries, readDocumentCountries, store } from "./store-BrR5-uon.js";
12
+ import { customer, customerHeaders, requireCustomerRegistration } from "./session-CsuzPSJs.js";
13
+ import { readCountries, readDocumentCountries, store } from "./store-BGDvRGNS.js";
14
14
  import { data, redirect, replace } from "react-router";
15
15
  import { ApiError, OrderPaymentStartSchema, StorefrontInvoiceTypeSchema } from "@ecomiq/core";
16
16
  import { z } from "zod";
@@ -3,7 +3,7 @@ import { COMPLAINT_DOCUMENT_TYPES, identityDocumentError } from "./documents-Ka-
3
3
  import { PHONE_ERROR, phoneError } from "./phone-B350moyr.js";
4
4
  import { optional, text } from "./form-BtQcbXlJ.js";
5
5
  import { rejectCrossOriginAction } from "./request-security-CRsRMgwj.js";
6
- import { found, readDocumentCountries, store } from "./store-BrR5-uon.js";
6
+ import { found, readDocumentCountries, store } from "./store-BGDvRGNS.js";
7
7
  import { data } from "react-router";
8
8
  import { ApiError, COMPLAINT_BOOK_ATTACHMENT_TYPES, COMPLAINT_BOOK_MAX_ATTACHMENTS, COMPLAINT_BOOK_MAX_ATTACHMENT_BYTES, ComplaintBookEntryInputSchema } from "@ecomiq/core";
9
9
  import { z } from "zod";
@@ -1,4 +1,4 @@
1
- import { addressAction, loadAccount, loadAddresses, loadOrder, loadOrders, loadProfile, orderFiltersQuery, orderRequestAction, profileAction, readOrderFilters } from "../account-CLF4iS_r.js";
1
+ import { addressAction, loadAccount, loadAddresses, loadOrder, loadOrders, loadProfile, orderFiltersQuery, orderRequestAction, profileAction, readOrderFilters } from "../account-DMM0ZZYb.js";
2
2
  import { mainPayment, orderStepLabel, orderStepOf, paymentLabel, paymentStatusLabel } from "../order-view-9IlBg5AF.js";
3
3
  import { useOrderPages } from "../order-pages-Dm6l5m0m.js";
4
4
  import { PayButton, PaymentPreview, ReorderButton, useOrderHeadline, useOrderStepDetail } from "../order-display-CK-5wCsa.js";
@@ -1,5 +1,5 @@
1
1
  import { Analytics } from "../analytics/analytics-CiG_O37p.js";
2
- import { readAnalytics } from "../analytics/config-CtHbJ58z.js";
2
+ import { readAnalytics } from "../analytics/config-rY3DYQyP.js";
3
3
  import { ConsentBanner, ConsentLink } from "../analytics/consent-banner-D36fpU89.js";
4
4
  import { catalogAnalytics } from "../analytics/events-CWmKY7oX.js";
5
5
  export { Analytics, ConsentBanner, ConsentLink, catalogAnalytics, readAnalytics };
@@ -1,5 +1,5 @@
1
1
  import { readCart } from "../cart-D7DxZ2lD.js";
2
- import { cartAction, loadCart } from "../cart-actions-DaGyBu9g.js";
2
+ import { cartAction, loadCart } from "../cart-actions-C2Csh1k0.js";
3
3
  import { CartForm, useCart } from "../cart-form-Bq_B-Rh6.js";
4
4
  import { useOptimisticCart } from "../optimistic-cart-DcJ8-tCw.js";
5
5
  import { CartDrawerProvider, useCartDrawer } from "../cart-drawer-B7PPsR69.js";
@@ -1,5 +1,5 @@
1
- import { checkoutAction, loadCheckout, shouldRevalidateCheckout } from "../checkout-Dyq58gRY.js";
2
- import { useCheckout } from "../use-checkout-BElBkhVE.js";
1
+ import { checkoutAction, loadCheckout, shouldRevalidateCheckout } from "../checkout-DnfQ8WhP.js";
2
+ import { useCheckout } from "../use-checkout-BmVOLp_x.js";
3
3
  import { useCheckoutPayment } from "../use-checkout-payment-C2t511ck.js";
4
4
  import { MercadoPagoDialog } from "../mercadopago-dialog-C8pRoGAB.js";
5
5
  import { StripeAuthentication, StripeDialog, findStripeWallet, useAvailableStripeWallets } from "../stripe-dialog-vlflY1WI.js";
@@ -1,5 +1,5 @@
1
- import { hasOrderPaymentContinuation, loadOrderStatus, orderPaymentAction, orderProgress, orderStepTitle } from "../order-status-Bow-z55_.js";
2
- import { loadOrderDraft, orderDraftAction } from "../order-draft-DfEHthuU.js";
1
+ import { hasOrderPaymentContinuation, loadOrderStatus, orderPaymentAction, orderProgress, orderStepTitle } from "../order-status-C61ywW-E.js";
2
+ import { loadOrderDraft, orderDraftAction } from "../order-draft-XI7gDVeO.js";
3
3
  import { useOrderPayment } from "../use-order-payment-BKIz_IO0.js";
4
4
  import { OrderPaymentContinuation } from "../order-payment-continuation-DEGeYVyv.js";
5
5
  import { OrderPaymentInReview } from "../order-payment-in-review-D81gcAOe.js";
package/dist/index.d.ts CHANGED
@@ -25,7 +25,7 @@ import { CategoryPage, CollectionPage, PageOptions, ProductPage, ProductReviews,
25
25
  import { money } from "./money.js";
26
26
  import { readPlace } from "./place.js";
27
27
  import { optional, safeNext, text } from "./form.js";
28
- import { ProductSource, SectionCatalog, SectionGroup, SectionProps, SectionRoot, pickProducts, section, setting } from "./settings.js";
28
+ import { ProductSource, SectionCatalog, SectionGroup, SectionProps, SectionRoot, pickProducts, pickProductsWithReviews, section, setting } from "./settings.js";
29
29
  import { Favicon } from "./favicon.js";
30
30
  import { Hidden } from "./hidden.js";
31
31
  import { SourceProvider, source, sourceValue } from "./sources.js";
@@ -48,4 +48,4 @@ import { storefrontContact } from "./store-contact.js";
48
48
  import { loadStorefrontTranslations, storefrontText } from "./storefront-text.js";
49
49
  import { StorefrontLanguageProvider, useStorefrontLocale, useStorefrontText } from "./storefront-language.js";
50
50
  import { storefrontRouteText } from "./route-text.js";
51
- export { type ActiveFilterChip, type AddressActionData, BankAccountList, COMPLAINT_DOCUMENT_TYPES, CUSTOMER_CSRF_FIELD, Captcha, type CaptchaProps, type CartActionData, type CartData, type CategoryData, type CategoryPage, type CheckoutActionData, type CheckoutAddressDefaults, type CheckoutData, type CheckoutPaymentMethod, type CheckoutRate, type CheckoutShippingGroup, type CheckoutStep, type CollectionPage, type ComplaintBookActionData, type ComplaintBookData, type ComplaintBookLink, type Customer, CustomerAvatar, CustomerCsrfField, type CustomerLoginData, CustomerLoginForm, type CustomerLoginFormProps, type CustomerRegistrationData, CustomerRegistrationForm, type CustomerRegistrationFormProps, type DocumentRule, FORM_CONTRACTS, Favicon, type FilterChipText, type FilterLabels, type FormContract, type GeoPlace, Hidden, IDENTITY_DOCUMENT_TYPES, type IdentityDocumentType, MAX_CART_QUANTITY, type OrderDraftActionData, type OrderDraftData, type OrderPaymentActionData, OrderPaymentContinuation, type OrderPaymentControls, OrderPaymentInReview, type OrderProgressStep, type OrderStatusData, type PageItem, type PageOptions, type PageSeo, type PageSeoInput, PaymentLogo, type PaymentMethodSaving, PhoneField, type PhoneFieldProps, type ProductPage, type ProductReviews, type ProductSource, type ProductVariant, type ProfileActionData, type ResolvedPage, type ResolvedUrl, type ReviewActionData, type ReviewSummary, RichText, SORT_OPTIONS, type SectionCatalog, type SectionData, type SectionEntry, type SectionGroup, type SectionLoadArgs, type SectionModules, SectionPreview, type SectionPreviewData, type SectionProps, type SectionRoot, type SortLabels, type SortValue, SourceProvider, StorefrontAnchor, type StorefrontAnchorProps, type StorefrontEnv, StorefrontLanguageProvider, StorefrontLink, type StorefrontLinkProps, type StorefrontLinks, type StorefrontPageData, type TemplateKind, type TemplateModule, type TemplateModules, type TrackingData, type VariantOption, type WorkerContext, activeFilterChips, activeFilterCount, addressAction, canonicalUrl, cartAction, cartCookie, cartToken, categorySeo, checkoutAction, checkoutAddressDefaults, checkoutProgress, checkoutStep, clearedFiltersHref, collectionImageCandidates, collectionPage, collectionSeo, complaintBookAction, complaintBookAttachmentError, complaintBookLinks, complaintBookNumber, completeCustomerLogin, createRequestHandler, culqiSourceKey, customer, customerCsrfToken, customerHeaders, defaultPaymentMethod, discountPercent, filterLabel, filterValueLabel, found, hasOrderPaymentContinuation, homeSeo, identityDocumentRule, isOrderDraftPayable, isSingleChoiceFilter, isVariantAvailable, loadAccount, loadAddresses, loadCart, loadCategory, loadCheckout, loadComplaintBook, loadCustomerRegistration, loadGeo, loadOrder, loadOrderDraft, loadOrderStatus, loadOrders, loadPage, loadProduct, loadProfile, loadReview, loadSearchSuggestions, loadSections, loadStorefrontTranslations, loadTracking, logout, money, needsShipping, optional, orderDraftAction, orderPaymentAction, orderProgress, orderStepTitle, pageItems, pageSeo, paymentLogoCodes, paymentMethodSaving, pickProducts, pickVariant, productPage, productReviewAction, productReviews, productSeo, profileAction, readCart, readCatalog, readCountries, readCustomerAddress, readPage, readPlace, readStorefrontLayout, readStorefrontLinks, requireCanonical, requireCustomer, requireCustomerRegistration, resolvePage, resolveUrl, reviewAction, safeNext, section, sectionKey, sectionPreview, sectionPreviewMeta, selectedFacetCount, seoMeta, setting, shouldRevalidateCatalogRoot, source, sourceValue, startCustomerLogin, store, storefrontContact, storefrontHref, storefrontRouteText, storefrontText, submitCustomerLogin, submitCustomerRegistration, templateComponent, templateName, templatePath, templated, text, useCheckout, useCustomerCsrfToken, useFacets, useGeoCascade, useOrderPayment, usePagination, useSearchSuggestions, useSection, useSort, useStorefrontLinkPublished, useStorefrontLocale, useStorefrontText, variantOptions, variantSwatches, withImages, withSectionBoundary, withSections, worker };
51
+ export { type ActiveFilterChip, type AddressActionData, BankAccountList, COMPLAINT_DOCUMENT_TYPES, CUSTOMER_CSRF_FIELD, Captcha, type CaptchaProps, type CartActionData, type CartData, type CategoryData, type CategoryPage, type CheckoutActionData, type CheckoutAddressDefaults, type CheckoutData, type CheckoutPaymentMethod, type CheckoutRate, type CheckoutShippingGroup, type CheckoutStep, type CollectionPage, type ComplaintBookActionData, type ComplaintBookData, type ComplaintBookLink, type Customer, CustomerAvatar, CustomerCsrfField, type CustomerLoginData, CustomerLoginForm, type CustomerLoginFormProps, type CustomerRegistrationData, CustomerRegistrationForm, type CustomerRegistrationFormProps, type DocumentRule, FORM_CONTRACTS, Favicon, type FilterChipText, type FilterLabels, type FormContract, type GeoPlace, Hidden, IDENTITY_DOCUMENT_TYPES, type IdentityDocumentType, MAX_CART_QUANTITY, type OrderDraftActionData, type OrderDraftData, type OrderPaymentActionData, OrderPaymentContinuation, type OrderPaymentControls, OrderPaymentInReview, type OrderProgressStep, type OrderStatusData, type PageItem, type PageOptions, type PageSeo, type PageSeoInput, PaymentLogo, type PaymentMethodSaving, PhoneField, type PhoneFieldProps, type ProductPage, type ProductReviews, type ProductSource, type ProductVariant, type ProfileActionData, type ResolvedPage, type ResolvedUrl, type ReviewActionData, type ReviewSummary, RichText, SORT_OPTIONS, type SectionCatalog, type SectionData, type SectionEntry, type SectionGroup, type SectionLoadArgs, type SectionModules, SectionPreview, type SectionPreviewData, type SectionProps, type SectionRoot, type SortLabels, type SortValue, SourceProvider, StorefrontAnchor, type StorefrontAnchorProps, type StorefrontEnv, StorefrontLanguageProvider, StorefrontLink, type StorefrontLinkProps, type StorefrontLinks, type StorefrontPageData, type TemplateKind, type TemplateModule, type TemplateModules, type TrackingData, type VariantOption, type WorkerContext, activeFilterChips, activeFilterCount, addressAction, canonicalUrl, cartAction, cartCookie, cartToken, categorySeo, checkoutAction, checkoutAddressDefaults, checkoutProgress, checkoutStep, clearedFiltersHref, collectionImageCandidates, collectionPage, collectionSeo, complaintBookAction, complaintBookAttachmentError, complaintBookLinks, complaintBookNumber, completeCustomerLogin, createRequestHandler, culqiSourceKey, customer, customerCsrfToken, customerHeaders, defaultPaymentMethod, discountPercent, filterLabel, filterValueLabel, found, hasOrderPaymentContinuation, homeSeo, identityDocumentRule, isOrderDraftPayable, isSingleChoiceFilter, isVariantAvailable, loadAccount, loadAddresses, loadCart, loadCategory, loadCheckout, loadComplaintBook, loadCustomerRegistration, loadGeo, loadOrder, loadOrderDraft, loadOrderStatus, loadOrders, loadPage, loadProduct, loadProfile, loadReview, loadSearchSuggestions, loadSections, loadStorefrontTranslations, loadTracking, logout, money, needsShipping, optional, orderDraftAction, orderPaymentAction, orderProgress, orderStepTitle, pageItems, pageSeo, paymentLogoCodes, paymentMethodSaving, pickProducts, pickProductsWithReviews, pickVariant, productPage, productReviewAction, productReviews, productSeo, profileAction, readCart, readCatalog, readCountries, readCustomerAddress, readPage, readPlace, readStorefrontLayout, readStorefrontLinks, requireCanonical, requireCustomer, requireCustomerRegistration, resolvePage, resolveUrl, reviewAction, safeNext, section, sectionKey, sectionPreview, sectionPreviewMeta, selectedFacetCount, seoMeta, setting, shouldRevalidateCatalogRoot, source, sourceValue, startCustomerLogin, store, storefrontContact, storefrontHref, storefrontRouteText, storefrontText, submitCustomerLogin, submitCustomerRegistration, templateComponent, templateName, templatePath, templated, text, useCheckout, useCustomerCsrfToken, useFacets, useGeoCascade, useOrderPayment, usePagination, useSearchSuggestions, useSection, useSort, useStorefrontLinkPublished, useStorefrontLocale, useStorefrontText, variantOptions, variantSwatches, withImages, withSectionBoundary, withSections, worker };
package/dist/index.js CHANGED
@@ -1,38 +1,38 @@
1
- import { createRequestHandler, worker } from "./worker-DWh0nPh3.js";
2
- import { collectionImageCandidates, found, readCountries, store, withImages } from "./store-BrR5-uon.js";
1
+ import { createRequestHandler, worker } from "./worker-BxlCSjSF.js";
2
+ import { collectionImageCandidates, found, readCountries, store, withImages } from "./store-BGDvRGNS.js";
3
3
  import { cartCookie, cartToken, readCart } from "./cart-D7DxZ2lD.js";
4
- import { MAX_CART_QUANTITY, cartAction, loadCart } from "./cart-actions-DaGyBu9g.js";
5
- import { checkoutAction, checkoutAddressDefaults, checkoutProgress, checkoutStep, defaultPaymentMethod, loadCheckout, needsShipping } from "./checkout-Dyq58gRY.js";
4
+ import { MAX_CART_QUANTITY, cartAction, loadCart } from "./cart-actions-C2Csh1k0.js";
5
+ import { checkoutAction, checkoutAddressDefaults, checkoutProgress, checkoutStep, defaultPaymentMethod, loadCheckout, needsShipping } from "./checkout-DnfQ8WhP.js";
6
6
  import { paymentMethodSaving } from "./payment-methods-B8ocTgFZ.js";
7
- import { useCheckout } from "./use-checkout-BElBkhVE.js";
8
- import { addressAction, loadAccount, loadAddresses, loadOrder, loadOrders, loadProfile, profileAction, readCustomerAddress } from "./account-CLF4iS_r.js";
9
- import { loadGeo, loadPage, loadReview, loadSearchSuggestions, loadTracking, productReviewAction, readPage, reviewAction } from "./public-pages-ax-EBPYN.js";
10
- import { hasOrderPaymentContinuation, loadOrderStatus, orderPaymentAction, orderProgress, orderStepTitle } from "./order-status-Bow-z55_.js";
11
- import { isOrderDraftPayable, loadOrderDraft, orderDraftAction } from "./order-draft-DfEHthuU.js";
7
+ import { useCheckout } from "./use-checkout-BmVOLp_x.js";
8
+ import { addressAction, loadAccount, loadAddresses, loadOrder, loadOrders, loadProfile, profileAction, readCustomerAddress } from "./account-DMM0ZZYb.js";
9
+ import { loadGeo, loadPage, loadReview, loadSearchSuggestions, loadTracking, productReviewAction, readPage, reviewAction } from "./public-pages-BZXH5gt9.js";
10
+ import { hasOrderPaymentContinuation, loadOrderStatus, orderPaymentAction, orderProgress, orderStepTitle } from "./order-status-C61ywW-E.js";
11
+ import { isOrderDraftPayable, loadOrderDraft, orderDraftAction } from "./order-draft-XI7gDVeO.js";
12
12
  import { useOrderPayment } from "./use-order-payment-BKIz_IO0.js";
13
13
  import { OrderPaymentContinuation } from "./order-payment-continuation-DEGeYVyv.js";
14
14
  import { OrderPaymentInReview } from "./order-payment-in-review-D81gcAOe.js";
15
15
  import { discountPercent, isVariantAvailable, pickVariant, variantOptions, variantSwatches } from "./product-variants-BNDHvs1y.js";
16
16
  import { SORT_OPTIONS, activeFilterChips, activeFilterCount, clearedFiltersHref, filterLabel, filterValueLabel, isSingleChoiceFilter, pageItems, selectedFacetCount, useFacets, useGeoCascade, usePagination, useSearchSuggestions, useSort } from "./catalog-hooks-Dk_58L_I.js";
17
- import { completeCustomerLogin, customer, customerCsrfToken, customerHeaders, logout, requireCustomer, requireCustomerRegistration, startCustomerLogin, submitCustomerLogin } from "./session-BKu8g6ZJ.js";
17
+ import { completeCustomerLogin, customer, customerCsrfToken, customerHeaders, logout, requireCustomer, requireCustomerRegistration, startCustomerLogin, submitCustomerLogin } from "./session-CsuzPSJs.js";
18
18
  import { CustomerCsrfField, useCustomerCsrfToken } from "./customer-csrf-C1oDX-Py.js";
19
19
  import { CUSTOMER_CSRF_FIELD, FORM_CONTRACTS } from "./form-contracts-0R112spH.js";
20
20
  import { culqiSourceKey } from "./culqi-three-ds-HP3mfrvV.js";
21
21
  import { readCatalog, shouldRevalidateCatalogRoot } from "./catalog-7gJ-l5hW.js";
22
- import { categorySeo, collectionSeo, homeSeo, pageSeo, productSeo, seoMeta } from "./page-seo-DFFDxVA7.js";
23
- import { canonicalUrl, loadCategory, loadProduct, requireCanonical, resolveUrl } from "./urls-DNwJJ6-F.js";
24
- import { collectionPage, productPage, productReviews, resolvePage } from "./pages-CPxkyi9N.js";
22
+ import { categorySeo, collectionSeo, homeSeo, pageSeo, productSeo, seoMeta } from "./page-seo-BdyKwykI.js";
23
+ import { canonicalUrl, loadCategory, loadProduct, requireCanonical, resolveUrl } from "./urls-BR4wv2K2.js";
24
+ import { collectionPage, productPage, productReviews, resolvePage } from "./pages-ClOPuk55.js";
25
25
  import { money } from "./money-DtGOtDri.js";
26
26
  import { readPlace } from "./place-CmW4hBWY.js";
27
27
  import { optional, safeNext, text } from "./form-BtQcbXlJ.js";
28
- import { pickProducts, section, setting } from "./settings-B0NO2A6Y.js";
28
+ import { pickProducts, pickProductsWithReviews, section, setting } from "./settings-CiW3OroM.js";
29
29
  import { Favicon } from "./favicon-YpyhVJ9H.js";
30
30
  import { Hidden } from "./hidden-CCWtOWKR.js";
31
31
  import { SourceProvider, source, sourceValue } from "./sources-B-3JFJfb.js";
32
32
  import { RichText } from "./rich-text-M-Ju8RL4.js";
33
- import { loadSections, sectionKey, useSection, withSectionBoundary, withSections } from "./sections-Cdsudggy.js";
34
- import { templateComponent, templateName, templatePath, templated } from "./templates-Bq8joT_y.js";
35
- import { SectionPreview, sectionPreview, sectionPreviewMeta } from "./section-preview-D-c1PIuT.js";
33
+ import { loadSections, sectionKey, useSection, withSectionBoundary, withSections } from "./sections-BkjGSM28.js";
34
+ import { templateComponent, templateName, templatePath, templated } from "./templates-BM3WvMlA.js";
35
+ import { SectionPreview, sectionPreview, sectionPreviewMeta } from "./section-preview-C7QbWAzE.js";
36
36
  import { StorefrontAnchor, StorefrontLink, readStorefrontLayout, readStorefrontLinks, storefrontHref, useStorefrontLinkPublished } from "./links-kFxBZfdb.js";
37
37
  import { PaymentLogo, paymentLogoCodes } from "./payment-logo-BoPaGJc_.js";
38
38
  import { BankAccountList } from "./bank-accounts-CktJ_34-.js";
@@ -40,12 +40,12 @@ import { CustomerAvatar } from "./customer-avatar-CJXSDroK.js";
40
40
  import { CustomerLoginForm } from "./customer-login-form-CnXH_JcT.js";
41
41
  import { Captcha } from "./captcha-BgiQrAfa.js";
42
42
  import { COMPLAINT_DOCUMENT_TYPES, IDENTITY_DOCUMENT_TYPES, identityDocumentRule } from "./documents-Ka-EL9m0.js";
43
- import { complaintBookAction, complaintBookAttachmentError, complaintBookLinks, complaintBookNumber, loadComplaintBook } from "./complaint-book-C_6Z1-f1.js";
44
- import { loadCustomerRegistration, submitCustomerRegistration } from "./registration-DuOEfjVt.js";
43
+ import { complaintBookAction, complaintBookAttachmentError, complaintBookLinks, complaintBookNumber, loadComplaintBook } from "./complaint-book-DvxhgbsM.js";
44
+ import { loadCustomerRegistration, submitCustomerRegistration } from "./registration-BmWt3-eT.js";
45
45
  import { CustomerRegistrationForm } from "./customer-registration-form-CwwytTsq.js";
46
46
  import { PhoneField } from "./phone-field-D4io3zeV.js";
47
47
  import { storefrontContact } from "./store-contact--hY6CoFb.js";
48
48
  import { loadStorefrontTranslations, storefrontText } from "./storefront-text-ClFfYMVk.js";
49
49
  import { StorefrontLanguageProvider, useStorefrontLocale, useStorefrontText } from "./storefront-language-20hJejSi.js";
50
50
  import { storefrontRouteText } from "./route-text-CkupKB1b.js";
51
- export { BankAccountList, COMPLAINT_DOCUMENT_TYPES, CUSTOMER_CSRF_FIELD, Captcha, CustomerAvatar, CustomerCsrfField, CustomerLoginForm, CustomerRegistrationForm, FORM_CONTRACTS, Favicon, Hidden, IDENTITY_DOCUMENT_TYPES, MAX_CART_QUANTITY, OrderPaymentContinuation, OrderPaymentInReview, PaymentLogo, PhoneField, RichText, SORT_OPTIONS, SectionPreview, SourceProvider, StorefrontAnchor, StorefrontLanguageProvider, StorefrontLink, activeFilterChips, activeFilterCount, addressAction, canonicalUrl, cartAction, cartCookie, cartToken, categorySeo, checkoutAction, checkoutAddressDefaults, checkoutProgress, checkoutStep, clearedFiltersHref, collectionImageCandidates, collectionPage, collectionSeo, complaintBookAction, complaintBookAttachmentError, complaintBookLinks, complaintBookNumber, completeCustomerLogin, createRequestHandler, culqiSourceKey, customer, customerCsrfToken, customerHeaders, defaultPaymentMethod, discountPercent, filterLabel, filterValueLabel, found, hasOrderPaymentContinuation, homeSeo, identityDocumentRule, isOrderDraftPayable, isSingleChoiceFilter, isVariantAvailable, loadAccount, loadAddresses, loadCart, loadCategory, loadCheckout, loadComplaintBook, loadCustomerRegistration, loadGeo, loadOrder, loadOrderDraft, loadOrderStatus, loadOrders, loadPage, loadProduct, loadProfile, loadReview, loadSearchSuggestions, loadSections, loadStorefrontTranslations, loadTracking, logout, money, needsShipping, optional, orderDraftAction, orderPaymentAction, orderProgress, orderStepTitle, pageItems, pageSeo, paymentLogoCodes, paymentMethodSaving, pickProducts, pickVariant, productPage, productReviewAction, productReviews, productSeo, profileAction, readCart, readCatalog, readCountries, readCustomerAddress, readPage, readPlace, readStorefrontLayout, readStorefrontLinks, requireCanonical, requireCustomer, requireCustomerRegistration, resolvePage, resolveUrl, reviewAction, safeNext, section, sectionKey, sectionPreview, sectionPreviewMeta, selectedFacetCount, seoMeta, setting, shouldRevalidateCatalogRoot, source, sourceValue, startCustomerLogin, store, storefrontContact, storefrontHref, storefrontRouteText, storefrontText, submitCustomerLogin, submitCustomerRegistration, templateComponent, templateName, templatePath, templated, text, useCheckout, useCustomerCsrfToken, useFacets, useGeoCascade, useOrderPayment, usePagination, useSearchSuggestions, useSection, useSort, useStorefrontLinkPublished, useStorefrontLocale, useStorefrontText, variantOptions, variantSwatches, withImages, withSectionBoundary, withSections, worker };
51
+ export { BankAccountList, COMPLAINT_DOCUMENT_TYPES, CUSTOMER_CSRF_FIELD, Captcha, CustomerAvatar, CustomerCsrfField, CustomerLoginForm, CustomerRegistrationForm, FORM_CONTRACTS, Favicon, Hidden, IDENTITY_DOCUMENT_TYPES, MAX_CART_QUANTITY, OrderPaymentContinuation, OrderPaymentInReview, PaymentLogo, PhoneField, RichText, SORT_OPTIONS, SectionPreview, SourceProvider, StorefrontAnchor, StorefrontLanguageProvider, StorefrontLink, activeFilterChips, activeFilterCount, addressAction, canonicalUrl, cartAction, cartCookie, cartToken, categorySeo, checkoutAction, checkoutAddressDefaults, checkoutProgress, checkoutStep, clearedFiltersHref, collectionImageCandidates, collectionPage, collectionSeo, complaintBookAction, complaintBookAttachmentError, complaintBookLinks, complaintBookNumber, completeCustomerLogin, createRequestHandler, culqiSourceKey, customer, customerCsrfToken, customerHeaders, defaultPaymentMethod, discountPercent, filterLabel, filterValueLabel, found, hasOrderPaymentContinuation, homeSeo, identityDocumentRule, isOrderDraftPayable, isSingleChoiceFilter, isVariantAvailable, loadAccount, loadAddresses, loadCart, loadCategory, loadCheckout, loadComplaintBook, loadCustomerRegistration, loadGeo, loadOrder, loadOrderDraft, loadOrderStatus, loadOrders, loadPage, loadProduct, loadProfile, loadReview, loadSearchSuggestions, loadSections, loadStorefrontTranslations, loadTracking, logout, money, needsShipping, optional, orderDraftAction, orderPaymentAction, orderProgress, orderStepTitle, pageItems, pageSeo, paymentLogoCodes, paymentMethodSaving, pickProducts, pickProductsWithReviews, pickVariant, productPage, productReviewAction, productReviews, productSeo, profileAction, readCart, readCatalog, readCountries, readCustomerAddress, readPage, readPlace, readStorefrontLayout, readStorefrontLinks, requireCanonical, requireCustomer, requireCustomerRegistration, resolvePage, resolveUrl, reviewAction, safeNext, section, sectionKey, sectionPreview, sectionPreviewMeta, selectedFacetCount, seoMeta, setting, shouldRevalidateCatalogRoot, source, sourceValue, startCustomerLogin, store, storefrontContact, storefrontHref, storefrontRouteText, storefrontText, submitCustomerLogin, submitCustomerRegistration, templateComponent, templateName, templatePath, templated, text, useCheckout, useCustomerCsrfToken, useFacets, useGeoCascade, useOrderPayment, usePagination, useSearchSuggestions, useSection, useSort, useStorefrontLinkPublished, useStorefrontLocale, useStorefrontText, variantOptions, variantSwatches, withImages, withSectionBoundary, withSections, worker };
@@ -1,4 +1,4 @@
1
- import { found, store } from "./store-BrR5-uon.js";
1
+ import { found, store } from "./store-BGDvRGNS.js";
2
2
  import { data, redirect } from "react-router";
3
3
  import { ApiError } from "@ecomiq/core";
4
4
  // src/order-draft.ts
@@ -1,7 +1,7 @@
1
1
  import { orderAnalytics } from "./analytics/events-CWmKY7oX.js";
2
2
  import { text } from "./form-BtQcbXlJ.js";
3
- import { found, store } from "./store-BrR5-uon.js";
4
- import { worker } from "./worker-DWh0nPh3.js";
3
+ import { found, store } from "./store-BGDvRGNS.js";
4
+ import { worker } from "./worker-BxlCSjSF.js";
5
5
  import { PAYMENT_RETURN_CONFIRMING, PAYMENT_RETURN_PARAM } from "./payment-return-5cjypwIw.js";
6
6
  import { data, redirect } from "react-router";
7
7
  import { ApiError, AuthenticateOrderPaymentInputSchema } from "@ecomiq/core";
@@ -1,6 +1,6 @@
1
1
  import { loadStorefrontTranslations, storefrontText } from "./storefront-text-ClFfYMVk.js";
2
- import { store } from "./store-BrR5-uon.js";
3
- import { absoluteUrl, canonicalOrigin, requestUrl } from "./urls-DNwJJ6-F.js";
2
+ import { store } from "./store-BGDvRGNS.js";
3
+ import { absoluteUrl, canonicalOrigin, requestUrl } from "./urls-BR4wv2K2.js";
4
4
  // src/page-seo.ts
5
5
  const DESCRIPTION_LENGTH = 160;
6
6
  const TITLE_LENGTH = 65;
@@ -1,8 +1,8 @@
1
1
  import { categoryAnalytics, collectionAnalytics, productAnalytics } from "./analytics/events-CWmKY7oX.js";
2
2
  import { readCatalog } from "./catalog-7gJ-l5hW.js";
3
- import { store } from "./store-BrR5-uon.js";
4
- import { requestUrl, requireCanonical } from "./urls-DNwJJ6-F.js";
5
- import { worker } from "./worker-DWh0nPh3.js";
3
+ import { store } from "./store-BGDvRGNS.js";
4
+ import { requestUrl, requireCanonical } from "./urls-BR4wv2K2.js";
5
+ import { worker } from "./worker-BxlCSjSF.js";
6
6
  import { data, redirect } from "react-router";
7
7
  import { CategoryDetailSchema, CollectionSchema, GraphQLResponseError, ProductDetailSchema, ProductSummarySchema, ProductsResponseSchema, graphQLSelection, sanitizeHtml } from "@ecomiq/core";
8
8
  import { z } from "zod";
@@ -1,6 +1,6 @@
1
1
  import { text } from "./form-BtQcbXlJ.js";
2
- import { customer, customerHeaders } from "./session-BKu8g6ZJ.js";
3
- import { found, store, storeHeaders } from "./store-BrR5-uon.js";
2
+ import { customer, customerHeaders } from "./session-CsuzPSJs.js";
3
+ import { found, store, storeHeaders } from "./store-BGDvRGNS.js";
4
4
  import { data, redirect } from "react-router";
5
5
  import { ApiError, getOrderReviewContext, getOrderTracking, sanitizeHtml } from "@ecomiq/core";
6
6
  import { z } from "zod";
@@ -1,9 +1,9 @@
1
1
  import { safeNext, text } from "./form-BtQcbXlJ.js";
2
2
  import { PHONE_ERROR, phoneError } from "./phone-B350moyr.js";
3
3
  import { rejectCrossOriginAction, rejectCustomerCsrf } from "./request-security-CRsRMgwj.js";
4
- import { customer, customerHeaders } from "./session-BKu8g6ZJ.js";
5
- import { store } from "./store-BrR5-uon.js";
6
- import { worker } from "./worker-DWh0nPh3.js";
4
+ import { customer, customerHeaders } from "./session-CsuzPSJs.js";
5
+ import { store } from "./store-BGDvRGNS.js";
6
+ import { worker } from "./worker-BxlCSjSF.js";
7
7
  import { data, redirect } from "react-router";
8
8
  import { ApiError, CustomerRegistrationInputSchema } from "@ecomiq/core";
9
9
  // src/registration.ts
@@ -1,5 +1,5 @@
1
- import { loadSections, withSections } from "./sections-Cdsudggy.js";
2
- import { worker } from "./worker-DWh0nPh3.js";
1
+ import { loadSections, withSections } from "./sections-BkjGSM28.js";
2
+ import { worker } from "./worker-BxlCSjSF.js";
3
3
  import { data, useLoaderData } from "react-router";
4
4
  import { createElement, useState } from "react";
5
5
  import { jsx } from "react/jsx-runtime";
@@ -1,6 +1,6 @@
1
1
  import { CustomerCsrfField } from "../customer-csrf-C1oDX-Py.js";
2
2
  import { money } from "../money-DtGOtDri.js";
3
- import { orderProgress } from "../order-status-Bow-z55_.js";
3
+ import { orderProgress } from "../order-status-C61ywW-E.js";
4
4
  import { useStorefrontLocale, useStorefrontText } from "../storefront-language-20hJejSi.js";
5
5
  import { PayButton, PaymentPreview, ReorderButton, useOrderStepDetail } from "../order-display-CK-5wCsa.js";
6
6
  import { orderStepLabel, orderStepOf, paymentStatusLabel } from "../order-view-9IlBg5AF.js";
@@ -2,7 +2,7 @@ import { money } from "../money-DtGOtDri.js";
2
2
  import { useStorefrontLocale, useStorefrontText } from "../storefront-language-20hJejSi.js";
3
3
  import { PayButton, PaymentPreview, ReorderButton, useOrderHeadline, useOrderStepDetail } from "../order-display-CK-5wCsa.js";
4
4
  import { mainPayment, orderStepLabel, orderStepOf } from "../order-view-9IlBg5AF.js";
5
- import { orderFiltersQuery } from "../account-CLF4iS_r.js";
5
+ import { orderFiltersQuery } from "../account-DMM0ZZYb.js";
6
6
  import { useOrderPages } from "../order-pages-Dm6l5m0m.js";
7
7
  import { Form, Link, useLocation, useNavigate } from "react-router";
8
8
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
@@ -2,7 +2,7 @@ import { BankAccountList } from "../bank-accounts-CktJ_34-.js";
2
2
  import { useStorefrontText } from "../storefront-language-20hJejSi.js";
3
3
  import { PaymentLogo } from "../payment-logo-BoPaGJc_.js";
4
4
  import { money } from "../money-DtGOtDri.js";
5
- import { section, setting } from "../settings-B0NO2A6Y.js";
5
+ import { section, setting } from "../settings-CiW3OroM.js";
6
6
  import { placeValue, useGeoCascade } from "../catalog-hooks-Dk_58L_I.js";
7
7
  import { EMAIL_ERROR, EMAIL_PATTERN } from "../buyer-rules-DBhUoaZX.js";
8
8
  import { CheckoutForm, OrderBumpForm, PromoCodeForm } from "../checkout-form-CbOIdENC.js";
@@ -13,7 +13,7 @@ import { PaymentMethods } from "../payment-methods-B8ocTgFZ.js";
13
13
  import { PhoneField } from "../phone-field-D4io3zeV.js";
14
14
  import { StripeAuthentication, StripeDialog, findStripeWallet, useAvailableStripeWallets } from "../stripe-dialog-vlflY1WI.js";
15
15
  import { summaryLines } from "../cart-summary-B6vtRGBO.js";
16
- import { useCheckout } from "../use-checkout-BElBkhVE.js";
16
+ import { useCheckout } from "../use-checkout-BmVOLp_x.js";
17
17
  import { useCheckoutPayment } from "../use-checkout-payment-C2t511ck.js";
18
18
  import { ItemPersonalization } from "../personalization-fields-BtNqpVpB.js";
19
19
  import { Link, useRouteLoaderData } from "react-router";
@@ -1,7 +1,7 @@
1
1
  import { Captcha } from "../captcha-BgiQrAfa.js";
2
2
  import { COMPLAINT_DOCUMENT_TYPES, identityDocumentRule } from "../documents-Ka-EL9m0.js";
3
3
  import { useStorefrontText } from "../storefront-language-20hJejSi.js";
4
- import { complaintBookAttachmentError, complaintBookNumber } from "../complaint-book-C_6Z1-f1.js";
4
+ import { complaintBookAttachmentError, complaintBookNumber } from "../complaint-book-DvxhgbsM.js";
5
5
  import { CustomerCsrfField } from "../customer-csrf-C1oDX-Py.js";
6
6
  import { money } from "../money-DtGOtDri.js";
7
7
  import { PhoneField } from "../phone-field-D4io3zeV.js";
@@ -1,7 +1,7 @@
1
1
  import { useStorefrontText } from "../storefront-language-20hJejSi.js";
2
2
  import { CustomerCsrfField } from "../customer-csrf-C1oDX-Py.js";
3
3
  import { money } from "../money-DtGOtDri.js";
4
- import { setting } from "../settings-B0NO2A6Y.js";
4
+ import { setting } from "../settings-CiW3OroM.js";
5
5
  import { orderSummaryLines } from "../cart-summary-B6vtRGBO.js";
6
6
  import { ItemPersonalization } from "../personalization-fields-BtNqpVpB.js";
7
7
  import { Form, Link, useNavigation } from "react-router";
@@ -1,4 +1,4 @@
1
- import { setting } from "../settings-B0NO2A6Y.js";
1
+ import { setting } from "../settings-CiW3OroM.js";
2
2
  import { Form } from "react-router";
3
3
  import { formatTrackingStatus } from "@ecomiq/core";
4
4
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -1,5 +1,5 @@
1
1
  import "./source-marker-DhqSkW7n.js";
2
- import { store } from "./store-BrR5-uon.js";
2
+ import { store } from "./store-BGDvRGNS.js";
3
3
  import { data, useLoaderData } from "react-router";
4
4
  import { Suspense, createElement, use } from "react";
5
5
  // src/sections.ts
@@ -1,5 +1,5 @@
1
- import { store } from "./store-BrR5-uon.js";
2
- import { absoluteUrl, canonicalOrigin } from "./urls-DNwJJ6-F.js";
1
+ import { store } from "./store-BGDvRGNS.js";
2
+ import { absoluteUrl, canonicalOrigin } from "./urls-BR4wv2K2.js";
3
3
  // src/seo.ts
4
4
  const PRIVATE_PATHS = [
5
5
  "/cart",
@@ -4,9 +4,9 @@ import { base64Url, customerCookies, customerSessionId, equalSecret } from "./cu
4
4
  import { safeNext } from "./form-BtQcbXlJ.js";
5
5
  import { PREVIEW_TOKEN } from "./preview-GypCcfup.js";
6
6
  import { customerClientHeaders, customerCsrfTokenForRequest, rejectCrossOriginAction } from "./request-security-CRsRMgwj.js";
7
- import { store } from "./store-BrR5-uon.js";
8
- import { requestUrl } from "./urls-DNwJJ6-F.js";
9
- import { worker } from "./worker-DWh0nPh3.js";
7
+ import { store } from "./store-BGDvRGNS.js";
8
+ import { requestUrl } from "./urls-BR4wv2K2.js";
9
+ import { worker } from "./worker-BxlCSjSF.js";
10
10
  import { data, redirect } from "react-router";
11
11
  import { ApiError } from "@ecomiq/core";
12
12
  import { z } from "zod";
@@ -41,38 +41,44 @@ function section(defaults, props) {
41
41
  }
42
42
  return values;
43
43
  }
44
- async function pickProducts(client, source) {
44
+ function productSourceQuery(source) {
45
45
  const limit = source.limit ?? 8;
46
46
  if (source.products && source.products.length > 0) {
47
47
  const slugs = source.products.slice(0, limit);
48
- return (await client.getProducts({
48
+ return {
49
49
  slugs,
50
50
  pageSize: slugs.length,
51
51
  includeFilters: false
52
- })).products;
52
+ };
53
53
  }
54
54
  if (source.collection) {
55
- const collections = await client.getCollections().catch(() => []);
56
55
  const slug = source.collection.trim().toLowerCase();
57
- const collection = collections.find((item) => item.slug.toLowerCase() === slug);
58
- if (collection === void 0) return [];
59
- return (await client.getProducts({
60
- collectionId: collection.id,
56
+ if (slug === "") return null;
57
+ return {
58
+ collections: [slug],
61
59
  pageSize: limit,
62
60
  sort: source.sort,
63
61
  includeFilters: false
64
- })).products;
62
+ };
65
63
  }
66
- if (source.category) return (await client.getProducts({
64
+ if (source.category) return {
67
65
  categories: [source.category],
68
66
  pageSize: limit,
69
67
  sort: source.sort,
70
68
  includeFilters: false
71
- })).products;
72
- return (await client.getProducts({
69
+ };
70
+ return {
73
71
  pageSize: limit,
74
72
  sort: source.sort,
75
73
  includeFilters: false
76
- })).products;
74
+ };
75
+ }
76
+ async function pickProducts(client, source) {
77
+ const query = productSourceQuery(source);
78
+ return query === null ? [] : (await client.getProducts(query)).products;
79
+ }
80
+ async function pickProductsWithReviews(client, source, reviews = {}) {
81
+ const query = productSourceQuery(source);
82
+ return query === null ? [] : client.getProductsWithReviews(query, reviews);
77
83
  }
78
- export { pickProducts, section, setting };
84
+ export { pickProducts, pickProductsWithReviews, section, setting };
@@ -1,4 +1,4 @@
1
- import { CatalogLink, CatalogLinkReference, ProductSort, ProductSummary, StorefrontClient } from "@ecomiq/core";
1
+ import { CatalogLink, CatalogLinkReference, ProductReviewsOptions, ProductSort, ProductSummary, ProductWithReviews, StorefrontClient } from "@ecomiq/core";
2
2
  import { ComponentProps, ReactNode } from "react";
3
3
  declare function link(url: string, label?: string, reference?: null): string;
4
4
  declare function link(url: string, label: string | undefined, reference: CatalogLinkReference): CatalogLink;
@@ -48,4 +48,5 @@ export type ProductSource = {
48
48
  sort?: ProductSort;
49
49
  };
50
50
  export declare function pickProducts(client: StorefrontClient, source: ProductSource): Promise<ProductSummary[]>;
51
+ export declare function pickProductsWithReviews(client: StorefrontClient, source: ProductSource, reviews?: ProductReviewsOptions): Promise<ProductWithReviews[]>;
51
52
  export {};
@@ -1,8 +1,8 @@
1
1
  import { apiCacheFetch, uncachedFetch } from "./api-cache-DsuIn5hX.js";
2
2
  import { previewClient } from "./preview-GypCcfup.js";
3
3
  import { productPreviewClient } from "./product-preview-BspMAecJ.js";
4
- import { observeStorefrontClient } from "./telemetry-HuZXWBPi.js";
5
- import { worker } from "./worker-DWh0nPh3.js";
4
+ import { observeStorefrontClient } from "./telemetry-k9sM5iBG.js";
5
+ import { worker } from "./worker-BxlCSjSF.js";
6
6
  import { data } from "react-router";
7
7
  import { ApiError, GraphQLResponseError, createClient } from "@ecomiq/core";
8
8
  import { z } from "zod";
@@ -13,6 +13,8 @@ const REQUEST_READS = /* @__PURE__ */ new Set([
13
13
  "getLayout",
14
14
  "getStoreId",
15
15
  "getCollections",
16
+ "getCollectionCovers",
17
+ "getCollectionsWithProducts",
16
18
  "getPaymentMethods",
17
19
  "getCollectionBySlug",
18
20
  "getPageBySlug",
@@ -24,6 +26,7 @@ const REQUEST_READS = /* @__PURE__ */ new Set([
24
26
  "getSellers",
25
27
  "getSellerBySlug",
26
28
  "getProducts",
29
+ "getProductsWithReviews",
27
30
  "getProductBySlug",
28
31
  "getRelatedProducts",
29
32
  "listProductReviews",
@@ -85,9 +88,14 @@ const CollectionImagesSchema = z.record(z.string(), z.object({ products: z.array
85
88
  async function collectionImageCandidates({ client, collections, pageSize }) {
86
89
  const missing = [...new Map(collections.filter((collection) => !collection.imageUrl).map((collection) => [collection.id, collection])).values()].sort((left, right) => left.id.localeCompare(right.id));
87
90
  const candidates = /* @__PURE__ */ new Map();
91
+ const pending = missing.filter((collection) => {
92
+ if (collection.imageCandidates === void 0) return true;
93
+ candidates.set(collection.id, collection.imageCandidates.slice(0, pageSize));
94
+ return false;
95
+ });
88
96
  const batches = [];
89
- for (let offset = 0; offset < missing.length; offset += 10) {
90
- const batch = missing.slice(offset, offset + 10);
97
+ for (let offset = 0; offset < pending.length; offset += 10) {
98
+ const batch = pending.slice(offset, offset + 10);
91
99
  const variables = Object.fromEntries(batch.map((collection, index) => [`c${index}`, {
92
100
  collectionId: collection.id,
93
101
  pageSize,
@@ -123,7 +131,7 @@ async function withImages(client, collections) {
123
131
  pageSize: 6
124
132
  });
125
133
  const used = /* @__PURE__ */ new Set();
126
- return collections.map((collection) => {
134
+ return collections.map(({ imageCandidates, ...collection }) => {
127
135
  const options = collection.imageUrl ? [collection.imageUrl] : candidates.get(collection.id) ?? [];
128
136
  const image = options.find((option) => !used.has(option)) ?? options[0] ?? null;
129
137
  if (image !== null) used.add(image);
package/dist/store.d.ts CHANGED
@@ -2,16 +2,20 @@ import { RouterContextProvider } from "react-router";
2
2
  import { Collection, StorefrontClient } from "@ecomiq/core";
3
3
  export declare function store(context: Readonly<RouterContextProvider>): StorefrontClient;
4
4
  export declare function found<T>(read: Promise<T>, missing?: (status: number) => boolean): Promise<T>;
5
+ type CoverableCollection = Collection & {
6
+ imageCandidates?: readonly string[];
7
+ };
5
8
  export declare function collectionImageCandidates({ client, collections, pageSize }: {
6
9
  client: StorefrontClient;
7
- collections: readonly Collection[];
10
+ collections: readonly CoverableCollection[];
8
11
  pageSize: number;
9
12
  }): Promise<ReadonlyMap<string, readonly string[]>>;
10
- export declare function withImages(client: StorefrontClient, collections: Collection[]): Promise<{
11
- collection: Collection;
13
+ export declare function withImages<T extends CoverableCollection>(client: StorefrontClient, collections: T[]): Promise<{
14
+ collection: Omit<T, "imageCandidates">;
12
15
  image: string | null;
13
16
  }[]>;
14
17
  export declare function readCountries(client: StorefrontClient): Promise<{
15
18
  code: string;
16
19
  name: string;
17
- }[]>;
20
+ }[]>;
21
+ export {};
@@ -28,6 +28,8 @@ const timedClientMethods = /* @__PURE__ */ new Set([
28
28
  "getLayout",
29
29
  "getStoreId",
30
30
  "getCollections",
31
+ "getCollectionCovers",
32
+ "getCollectionsWithProducts",
31
33
  "getPaymentMethods",
32
34
  "getCollectionBySlug",
33
35
  "getPageBySlug",
@@ -40,6 +42,7 @@ const timedClientMethods = /* @__PURE__ */ new Set([
40
42
  "getSellers",
41
43
  "getSellerBySlug",
42
44
  "getProducts",
45
+ "getProductsWithReviews",
43
46
  "getProductBySlug",
44
47
  "getRelatedProducts",
45
48
  "autocompleteProducts",
@@ -1,5 +1,5 @@
1
- import { loadSections, withSections } from "./sections-Cdsudggy.js";
2
- import { worker } from "./worker-DWh0nPh3.js";
1
+ import { loadSections, withSections } from "./sections-BkjGSM28.js";
2
+ import { worker } from "./worker-BxlCSjSF.js";
3
3
  // src/templates.ts
4
4
  const TEMPLATE = "ecomiqTemplate";
5
5
  const NAME = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
@@ -1,6 +1,6 @@
1
1
  import { readCatalog } from "./catalog-7gJ-l5hW.js";
2
2
  import { documentUrl } from "./document-url-CGsAl5Tf.js";
3
- import { store } from "./store-BrR5-uon.js";
3
+ import { store } from "./store-BGDvRGNS.js";
4
4
  import { data, redirect } from "react-router";
5
5
  import { sanitizeHtml } from "@ecomiq/core";
6
6
  // src/urls.ts
@@ -1,4 +1,4 @@
1
- import { checkoutAddressDefaults, checkoutProgress, checkoutStep, defaultPaymentMethod, needsShipping } from "./checkout-Dyq58gRY.js";
1
+ import { checkoutAddressDefaults, checkoutProgress, checkoutStep, defaultPaymentMethod, needsShipping } from "./checkout-DnfQ8WhP.js";
2
2
  import { useCustomerCsrfToken } from "./customer-csrf-C1oDX-Py.js";
3
3
  import { useFetcher, useNavigation, useSearchParams } from "react-router";
4
4
  // src/use-checkout.ts
@@ -1,9 +1,9 @@
1
1
  import { cartCookie } from "./cart-D7DxZ2lD.js";
2
2
  import "./preview-cart-CRSPTs6g.js";
3
3
  import { productPreviewFrom, productPreviewResponse } from "./product-preview-BspMAecJ.js";
4
- import { StorefrontSdkTiming, durationMetric } from "./telemetry-HuZXWBPi.js";
4
+ import { StorefrontSdkTiming, durationMetric } from "./telemetry-k9sM5iBG.js";
5
5
  import { privateCustomerResponse, rejectCrossOriginAction, rejectCustomerCsrf } from "./request-security-CRsRMgwj.js";
6
- import { seoResponse } from "./seo-Tfib2qCv.js";
6
+ import { seoResponse } from "./seo-Cz1O5oxh.js";
7
7
  import { confirmingPaymentUrl } from "./payment-return-5cjypwIw.js";
8
8
  import { RouterContextProvider, createContext, createRequestHandler } from "react-router";
9
9
  import { STOREFRONT_CACHE_REVISION_HEADER, StorefrontCacheTokenSchema } from "@ecomiq/core/storefront-cache-revision";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ecomiq/storefront",
3
- "version": "3.2.0",
3
+ "version": "3.3.0",
4
4
  "description": "Ecomiq para React Router: tienda, carrito, sesión de cliente y catálogo en un Worker",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -96,7 +96,7 @@
96
96
  "react-phone-number-input": "^3.4.17",
97
97
  "sharp": "^0.35.5",
98
98
  "zod": "^4.6.6",
99
- "@ecomiq/core": "^1.1.1"
99
+ "@ecomiq/core": "^1.2.0"
100
100
  },
101
101
  "peerDependencies": {
102
102
  "react": "^19.2.0",