@asteby/storefront-react 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -0
- package/dist/cart.js +2 -1
- package/dist/cart.js.map +1 -1
- package/dist/checkout.cjs +440 -0
- package/dist/checkout.cjs.map +1 -0
- package/dist/checkout.css +100 -0
- package/dist/checkout.d.cts +197 -0
- package/dist/checkout.d.ts +197 -0
- package/dist/checkout.js +243 -0
- package/dist/checkout.js.map +1 -0
- package/dist/chunk-DSZVJ2PW.js +180 -0
- package/dist/chunk-DSZVJ2PW.js.map +1 -0
- package/dist/chunk-T52H5HL3.js +11 -0
- package/dist/chunk-T52H5HL3.js.map +1 -0
- package/dist/{chunk-2WZIWIBW.js → chunk-ZBH7JYU4.js} +4 -10
- package/dist/chunk-ZBH7JYU4.js.map +1 -0
- package/dist/payments.cjs +223 -13
- package/dist/payments.cjs.map +1 -1
- package/dist/payments.css +27 -0
- package/dist/payments.d.cts +19 -4
- package/dist/payments.d.ts +19 -4
- package/dist/payments.js +54 -14
- package/dist/payments.js.map +1 -1
- package/dist/promotions.js +2 -1
- package/dist/promotions.js.map +1 -1
- package/package.json +13 -2
- package/dist/chunk-2WZIWIBW.js.map +0 -1
package/README.md
CHANGED
|
@@ -518,6 +518,28 @@ export const pay = createEmbeddedPayHandlers({
|
|
|
518
518
|
- CSP solo para `/pagar`: `paymentCspHeaders([client], { mode: paymentCspMode(env.PAY_CSP, isProd), nonce: paymentNonce(), scriptHashes, imgHttps })` y `paymentNonceFromHeaders` para `ServerRouter`.
|
|
519
519
|
- Accesibilidad: un `fieldset` con leyenda y radios nativos, avisos en `role="status"`/`alert`, botón de 44 px que explica su estado ocupado; pruebas con axe.
|
|
520
520
|
|
|
521
|
+
- Marcas (por omisión, `brandMarks`): la marca del proveedor en sus filas de cuenta y sin tarjeta, las de los primeros puntos de pago en la fila de efectivo y junto a cada punto (`payment_point` o `id`; `logo_url` del proveedor gana), y las redes que pase la tienda en la fila de tarjeta (`cardBrands={['visa', 'mastercard', 'amex']}`). `brandMarks={false}` deja las filas en texto.
|
|
522
|
+
- El total del botón siempre lleva la entrega: `syncDelivery` se llama una vez por entrega con cualquier fila (no solo con tarjeta); mientras se guarda, el botón no muestra un total viejo.
|
|
523
|
+
|
|
524
|
+
## Entrega y marcas (`@asteby/storefront-react/checkout`)
|
|
525
|
+
|
|
526
|
+
Las tarifas de envío y las sucursales de «Entrega» como radios nativos, iguales en todas las tiendas: marca y nombre comercial de la paquetería (`fedex` → FedEx), servicio sin repetir la paquetería, llegada en días hábiles («Llega en 4 días hábiles»), insignias discretas de «Más económico» / «Más rápido» (solo si una tarifa lo es estrictamente) y el precio tal cual lo manda OPS. La vigencia de la cotización es UNA sola nota para toda la lista, en la zona horaria del comprador («Precios de envío vigentes hasta las 9:39 p.m.»), que aparece tras hidratar en una línea reservada (sin salto de diseño). `loading` pinta filas esqueleto al recotizar.
|
|
527
|
+
|
|
528
|
+
```tsx
|
|
529
|
+
import { DeliveryOptions } from '@asteby/storefront-react/checkout'
|
|
530
|
+
import '@asteby/storefront-react/checkout.css' // opcional: disposición, insignias, esqueleto y nota
|
|
531
|
+
|
|
532
|
+
<fieldset>
|
|
533
|
+
<legend>Entrega</legend>
|
|
534
|
+
<DeliveryOptions rates={delivery.rates} pickup={delivery.pickup} partial={delivery.partial}
|
|
535
|
+
renderAmount={(m) => <Money data={m} />} classNames={{ option: 'card has-checked:border-accent' }} />
|
|
536
|
+
</fieldset>
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
Tarifa vencida o cambiada: si guardar la entrega falla con `isQuoteChange(err)` (códigos `quote_expired`/`rate_expired`…, un 409, o el 422 genérico de servidores anteriores), la tienda recarga las tarifas conservando la dirección, vuelve a elegir el mismo servicio con `matchRate(anterior, nuevas)`, pasa `requoted` a `DeliveryOptions` y resuelve `syncDelivery` con `'requote'`: `PaymentMethodSection` muestra un aviso (no un error) y vuelve a intentar con la nueva tarifa.
|
|
540
|
+
|
|
541
|
+
Catálogo compartido de marcas (`brandKey`, `brandName`, `findBrand`, `<BrandMark brand="oxxo" />`): paqueterías (FedEx, DHL, Estafeta, Paquetexpress, UPS, Redpack, 99 Minutos, J&T…), redes de tarjeta (Visa, Mastercard, American Express, Carnet), billeteras (Mercado Pago, PayPal…) y puntos de efectivo y bancos de México (OXXO, SPEI/STP, 7-Eleven, Circle K, Soriana, Extra, BBVA…). La clave es el identificador que ya mandan los proveedores. Las marcas son insignias tipográficas en SVG en línea con el color de la marca (sin archivos de logos de terceros, sin peticiones); una marca desconocida lleva un monograma neutro, y un `logo_url` https del proveedor reemplaza la insignia. Cada insignia trae su propio fondo (contraste igual en tema claro y oscuro); `--sf-brand-mark-ring` ajusta el filo.
|
|
542
|
+
|
|
521
543
|
## Promociones y venta cruzada (`@asteby/storefront-react/promotions`)
|
|
522
544
|
|
|
523
545
|
Mecanismos sin contenido: los textos y montos llegan como datos de OPS (`Cart.promotions`, `GET /storefront/promotions`, `carts.recommendations`).
|
package/dist/cart.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useModalDialog } from './chunk-ZBH7JYU4.js';
|
|
2
|
+
import { useResolvedLocale } from './chunk-T52H5HL3.js';
|
|
2
3
|
import './chunk-DQBL2DFJ.js';
|
|
3
4
|
import { useSyncExternalStore, useCallback, useRef, useEffect, useId } from 'react';
|
|
4
5
|
import { formatMoney } from '@asteby/storefront';
|
package/dist/cart.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cart-drawer/store.ts","../src/cart-drawer/cart-drawer.tsx"],"names":["useEffect"],"mappings":"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","file":"cart.js","sourcesContent":["import { useCallback, useEffect, useRef, useSyncExternalStore } from 'react'\n\n// Estado mínimo del cajón del carrito, fuera de React: cualquier parte de la tienda (cabecera, tarjeta, ficha)\n// lo abre sin pasar props. Es del navegador; en el servidor siempre está cerrado.\n\nlet isOpen = false\nconst listeners = new Set<() => void>()\n\nfunction set(next: boolean) {\n if (isOpen === next) return\n isOpen = next\n for (const l of [...listeners]) l()\n}\n\nconst subscribe = (l: () => void) => {\n listeners.add(l)\n return () => {\n listeners.delete(l)\n }\n}\n\n/** Abre el cajón del carrito desde cualquier parte. */\nexport function openCartDrawer() {\n set(true)\n}\n\n/** Cierra el cajón del carrito. */\nexport function closeCartDrawer() {\n set(false)\n}\n\nexport function toggleCartDrawer() {\n set(!isOpen)\n}\n\nexport function isCartDrawerOpen() {\n return isOpen\n}\n\n/** Estado y acciones del cajón. `open` es `false` en el servidor y en la primera pintura. */\nexport function useCartDrawer() {\n const open = useSyncExternalStore(subscribe, () => isOpen, () => false)\n const toggle = useCallback(() => toggleCartDrawer(), [])\n return { open, openDrawer: openCartDrawer, closeDrawer: closeCartDrawer, toggle }\n}\n\n/**\n * Abre el cajón cuando termina un \"agregar al carrito\". `busy` es verdadero mientras hay un agregado en vuelo\n * (en React Router: algún fetcher con la acción del carrito e intención de agregar). Con `skip` verdadero al\n * terminar (error, agregado silencioso) no se abre.\n */\nexport function useOpenCartDrawerWhenDone(busy: boolean, options: { skip?: boolean } = {}) {\n const was = useRef(false)\n const skip = useRef(false)\n skip.current = !!options.skip\n useEffect(() => {\n if (was.current && !busy && !skip.current) openCartDrawer()\n was.current = busy\n }, [busy])\n}\n\ntype ClickLike = {\n defaultPrevented: boolean\n button: number\n metaKey: boolean\n ctrlKey: boolean\n shiftKey: boolean\n altKey: boolean\n preventDefault: () => void\n}\n\n/**\n * `onClick` para el enlace \"Mi carrito\" de la cabecera: con un clic normal abre el cajón; con clic con\n * modificador, clic central o sin JavaScript el `href` (la página del carrito) sigue funcionando.\n */\nexport function handleCartLinkClick(e: ClickLike) {\n if (e.defaultPrevented || e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return\n e.preventDefault()\n openCartDrawer()\n}\n","import { useEffect, useId, type ElementType, type ReactNode } from 'react'\nimport { formatMoney, type Cart, type CartLine, type Money } from '@asteby/storefront'\nimport { useModalDialog } from '../dialog.js'\nimport { useResolvedLocale } from '../locale.js'\nimport { closeCartDrawer, useCartDrawer } from './store.js'\n\nexport type CartDrawerLabels = {\n /** Título; el cajón agrega \" (N)\" con la cantidad de unidades. */\n title: string\n /** Texto accesible del botón de cierre. */\n close: string\n empty: string\n emptyHint?: string\n /** Texto del enlace \"seguir comprando\" del estado vacío (se muestra con `paths.browse`). */\n browse?: string\n subtotal: string\n /** Nota bajo el subtotal. */\n note?: string\n checkout: string\n viewCart: string\n remove: string\n increase: string\n decrease: string\n}\n\nexport type CartDrawerPaths = {\n /** Página del carrito: acción de las mutaciones y destino de \"ver carrito\". */\n cart: string\n checkout: string\n browse?: string\n /** Enlace de la línea al producto; sin esto el título no es enlace. */\n product?: (handle: string, variantId: string) => string\n}\n\n/** Contrato de la acción de ruta del carrito de la tienda (nombres de campo e intenciones). */\nexport type CartDrawerFormContract = {\n intentField?: string\n lineField?: string\n quantityField?: string\n updateIntent?: string\n removeIntent?: string\n}\n\nexport type CartDrawerShipping = {\n /** Mensaje ya calculado por la tienda con lo que manda OPS. */\n message: ReactNode\n /** 0..100 */\n percent: number\n reached?: boolean\n progressLabel: string\n}\n\nexport type CartDrawerLineForm = {\n /** Componente de formulario (`'form'`, o `fetcher.Form` del router para mejorar sin recargar). */\n Form: ElementType\n /** Datos en vuelo del formulario, para pintar la cantidad de forma optimista. */\n formData?: FormData | null | undefined\n}\n\nexport type CartDrawerLinkProps = { href: string; className?: string | undefined; children: ReactNode; onClick?: () => void }\n\nexport type CartDrawerSlot =\n | 'dialog' | 'panel' | 'header' | 'title' | 'close' | 'empty' | 'body' | 'shipping' | 'bar' | 'barFill' | 'lines' | 'line'\n | 'image' | 'lineTitle' | 'variant' | 'price' | 'qty' | 'qtyButton' | 'qtyValue' | 'remove' | 'upsell' | 'footer' | 'subtotal'\n | 'note' | 'actions' | 'checkout' | 'viewCart' | 'browse' | 'emptyTitle' | 'emptyHint' | 'shippingMessage' | 'lineMain'\n | 'lineHead' | 'lineText' | 'controls' | 'upsellTitle' | 'subtotalLabel' | 'subtotalValue'\n\nexport type CartDrawerIcons = { close?: ReactNode; decrease?: ReactNode; increase?: ReactNode; shipping?: ReactNode; shippingReached?: ReactNode }\n\nexport type CartDrawerProps = {\n /** `cart.cost` y cada línea vienen de OPS; el cajón no calcula nada. */\n cart: Cart | null | undefined\n labels: CartDrawerLabels\n paths: CartDrawerPaths\n form?: CartDrawerFormContract\n /** Hook que da el formulario de cada línea. Por omisión `<form method=\"post\">` (funciona sin JavaScript). */\n useLineForm?: () => CartDrawerLineForm\n shipping?: CartDrawerShipping | null\n /** Aviso fijo cuando no hay barra de envío (p. ej. \"Envío gratis\"). */\n notice?: ReactNode\n /** Sección \"podría interesarte\" (la tienda decide qué mostrar). */\n upsell?: ReactNode\n upsellTitle?: string\n renderLine?: (line: CartLine, defaults: { controls: ReactNode; price: ReactNode; image: ReactNode }) => ReactNode\n renderImage?: (line: CartLine) => ReactNode\n renderMoney?: (money: Money) => ReactNode\n renderLink?: (props: CartDrawerLinkProps) => ReactNode\n /** Omite el variante cuando es el valor por defecto de OPS (\"Default Title\"). */\n isDefaultVariantTitle?: (title: string) => boolean\n icons?: CartDrawerIcons\n /** Clases por pieza (además de los `data-sf-cart-*`), para tiendas con Tailwind. */\n classNames?: Partial<Record<CartDrawerSlot, string>>\n locale?: string\n /** Se llama al abrir/cerrar por cualquier vía. */\n onOpenChange?: (open: boolean) => void\n}\n\nconst DEFAULT_FORM: Required<CartDrawerFormContract> = {\n intentField: 'intent',\n lineField: 'line_id',\n quantityField: 'quantity',\n updateIntent: 'update',\n removeIntent: 'remove',\n}\n\nconst useNativeForm = (): CartDrawerLineForm => ({ Form: 'form' })\n\nconst defaultIsDefaultVariant = (t: string) => /^default title$/i.test(t.trim())\n\nfunction useBodyScrollLock(locked: boolean) {\n useEffect(() => {\n if (!locked || typeof document === 'undefined') return\n const el = document.documentElement\n const prev = el.style.overflow\n el.style.overflow = 'hidden'\n return () => {\n el.style.overflow = prev\n }\n }, [locked])\n}\n\n/**\n * Cajón lateral del carrito (\"Tu carrito (N)\"). Sin textos ni marca: todo llega por props.\n * Se monta una vez (en la raíz) y se abre con `openCartDrawer()` / `useCartDrawer()`.\n * `<dialog>` modal: `role=\"dialog\"`, `aria-modal`, foco atrapado y devuelto al abridor, Esc y clic fuera cierran,\n * el fondo no hace scroll. Las mutaciones usan la acción de ruta de la tienda (formularios nativos que\n * funcionan sin JavaScript, o el `Form` de un fetcher con `useLineForm`). Estilos: `@asteby/storefront-react/cart.css`\n * (tokens de la tienda) y/o `classNames`.\n */\nexport function CartDrawer(props: CartDrawerProps) {\n const { cart, labels, paths, shipping, notice, upsell, upsellTitle, icons, classNames: cx = {}, onOpenChange } = props\n const locale = useResolvedLocale(props.locale)\n const { open } = useCartDrawer()\n const titleId = useId()\n const upsellId = useId()\n const { ref, onBackdropClick } = useModalDialog({ open, onClose: () => closeCartDrawer() })\n useBodyScrollLock(open)\n useEffect(() => {\n onOpenChange?.(open)\n }, [open]) // eslint-disable-line react-hooks/exhaustive-deps\n\n if (!open) return null\n\n const money = props.renderMoney ?? ((m: Money) => formatMoney(m, locale))\n const link = props.renderLink ?? (({ href, className, children, onClick }: CartDrawerLinkProps) => (\n <a href={href} className={className} onClick={onClick}>{children}</a>\n ))\n const count = cart?.total_quantity ?? 0\n const lines = cart?.lines ?? []\n const empty = !cart || lines.length === 0\n const close = () => closeCartDrawer()\n\n return (\n <dialog\n ref={ref}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={titleId}\n onClick={onBackdropClick}\n onClose={close}\n className={cx.dialog}\n data-sf-cart-drawer=\"\"\n >\n <div className={cx.panel} data-sf-cart-panel=\"\">\n <div className={cx.header} data-sf-cart-header=\"\">\n <h2 id={titleId} tabIndex={-1} className={cx.title} data-sf-cart-title=\"\">\n {labels.title}{count > 0 ? ` (${count})` : ''}\n </h2>\n <button type=\"button\" onClick={close} aria-label={labels.close} className={cx.close} data-sf-cart-close=\"\" data-sf-autofocus=\"\">\n {icons?.close ?? <span aria-hidden=\"true\">✕</span>}\n </button>\n </div>\n\n {empty ? (\n <div className={cx.empty} data-sf-cart-empty=\"\">\n <p className={cx.emptyTitle} data-sf-cart-empty-title=\"\">{labels.empty}</p>\n {labels.emptyHint ? <p className={cx.emptyHint} data-sf-cart-empty-hint=\"\">{labels.emptyHint}</p> : null}\n {paths.browse && labels.browse ? link({ href: paths.browse, className: cx.browse, children: labels.browse, onClick: close }) : null}\n </div>\n ) : (\n <>\n <div className={cx.body} data-sf-cart-body=\"\">\n {shipping ? (\n <div className={cx.shipping} data-sf-cart-shipping=\"\" data-reached={shipping.reached || undefined}>\n <p className={cx.shippingMessage}>\n {shipping.reached ? icons?.shippingReached : icons?.shipping}\n {shipping.message}\n </p>\n <div\n role=\"progressbar\"\n aria-valuemin={0}\n aria-valuemax={100}\n aria-valuenow={Math.round(shipping.percent)}\n aria-label={shipping.progressLabel}\n className={cx.bar}\n data-sf-cart-bar=\"\"\n >\n <div className={cx.barFill} data-sf-cart-bar-fill=\"\" style={{ width: `${Math.max(0, Math.min(100, shipping.percent))}%` }} />\n </div>\n </div>\n ) : notice ? (\n <p className={[cx.shipping, cx.shippingMessage].filter(Boolean).join(\" \") || undefined} data-sf-cart-shipping=\"\" data-notice=\"\">{icons?.shippingReached}{notice}</p>\n ) : null}\n\n <ul className={cx.lines} data-sf-cart-lines=\"\">\n {lines.map((line) => (\n <DrawerLine key={line.id} line={line} props={props} money={money} link={link} close={close} />\n ))}\n </ul>\n\n {upsell ? (\n <section className={cx.upsell} data-sf-cart-upsell=\"\" aria-labelledby={upsellTitle ? upsellId : undefined}>\n {upsellTitle ? <h3 id={upsellId} className={cx.upsellTitle}>{upsellTitle}</h3> : null}\n {upsell}\n </section>\n ) : null}\n </div>\n\n <div className={cx.footer} data-sf-cart-footer=\"\">\n <div className={cx.subtotal} data-sf-cart-subtotal=\"\">\n <span className={cx.subtotalLabel}>{labels.subtotal}</span>\n <span className={cx.subtotalValue} data-sf-cart-subtotal-value=\"\">{cart ? money(cart.cost.subtotal) : null}</span>\n </div>\n {labels.note ? <p className={cx.note} data-sf-cart-note=\"\">{labels.note}</p> : null}\n <div className={cx.actions} data-sf-cart-actions=\"\">\n {link({ href: paths.checkout, className: cx.checkout, children: labels.checkout, onClick: close })}\n {link({ href: paths.cart, className: cx.viewCart, children: labels.viewCart, onClick: close })}\n </div>\n </div>\n </>\n )}\n </div>\n </dialog>\n )\n}\n\nfunction DrawerLine({\n line,\n props,\n money,\n link,\n close,\n}: {\n line: CartLine\n props: CartDrawerProps\n money: (m: Money) => ReactNode\n link: (p: CartDrawerLinkProps) => ReactNode\n close: () => void\n}) {\n const { labels, paths, icons, classNames: cx = {} } = props\n const f = { ...DEFAULT_FORM, ...props.form }\n const { Form, formData } = (props.useLineForm ?? useNativeForm)()\n const quantity = formData ? Number(formData.get(f.quantityField) ?? 0) : line.quantity\n if (formData && (formData.get(f.intentField) === f.removeIntent || quantity === 0)) return null\n\n const merch = line.merchandise\n const isDefault = props.isDefaultVariantTitle ?? defaultIsDefaultVariant\n const title = merch.product.title\n const href = paths.product?.(merch.product.handle, merch.id)\n const img = merch.image ?? merch.product.featured_image\n const image = props.renderImage ? props.renderImage(line) : img ? (\n <img src={img.url} alt={img.alt ?? ''} width={80} height={80} loading=\"lazy\" decoding=\"async\" />\n ) : null\n\n const imageNode = <span className={cx.image} data-sf-cart-image=\"\">{image}</span>\n const price = <span className={cx.price} data-sf-cart-price=\"\">{money(line.cost.total)}</span>\n const controls = (\n <div className={cx.controls} data-sf-cart-controls=\"\">\n <Form method=\"post\" action={paths.cart} className={cx.qty} data-sf-cart-qty=\"\">\n <input type=\"hidden\" name={f.intentField} value={f.updateIntent} />\n <input type=\"hidden\" name={f.lineField} value={line.id} />\n <button type=\"submit\" name={f.quantityField} value={quantity - 1} aria-label={labels.decrease} className={cx.qtyButton} data-sf-cart-qty-button=\"\">\n {icons?.decrease ?? <span aria-hidden=\"true\">−</span>}\n </button>\n <span className={cx.qtyValue} aria-live=\"polite\" data-sf-cart-qty-value=\"\">{quantity}</span>\n <button type=\"submit\" name={f.quantityField} value={quantity + 1} aria-label={labels.increase} className={cx.qtyButton} data-sf-cart-qty-button=\"\">\n {icons?.increase ?? <span aria-hidden=\"true\">+</span>}\n </button>\n </Form>\n <Form method=\"post\" action={paths.cart} data-sf-cart-remove-form=\"\">\n <input type=\"hidden\" name={f.intentField} value={f.removeIntent} />\n <input type=\"hidden\" name={f.lineField} value={line.id} />\n <button type=\"submit\" className={cx.remove} data-sf-cart-remove=\"\">{labels.remove}</button>\n </Form>\n </div>\n )\n\n if (props.renderLine) return <li key={line.id} className={cx.line} data-sf-cart-line=\"\">{props.renderLine(line, { controls, price, image: imageNode })}</li>\n\n return (\n <li className={cx.line} data-sf-cart-line=\"\">\n {imageNode}\n <div className={cx.lineMain} data-sf-cart-line-main=\"\">\n <div className={cx.lineHead} data-sf-cart-line-head=\"\">\n <div className={cx.lineText} data-sf-cart-line-text=\"\">\n {href ? link({ href, className: cx.lineTitle, children: title, onClick: close }) : <span className={cx.lineTitle} data-sf-cart-line-title=\"\">{title}</span>}\n {!isDefault(merch.title) ? <p className={cx.variant} data-sf-cart-variant=\"\">{merch.title}</p> : null}\n </div>\n {price}\n </div>\n {controls}\n </div>\n </li>\n )\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/cart-drawer/store.ts","../src/cart-drawer/cart-drawer.tsx"],"names":["useEffect"],"mappings":"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","file":"cart.js","sourcesContent":["import { useCallback, useEffect, useRef, useSyncExternalStore } from 'react'\n\n// Estado mínimo del cajón del carrito, fuera de React: cualquier parte de la tienda (cabecera, tarjeta, ficha)\n// lo abre sin pasar props. Es del navegador; en el servidor siempre está cerrado.\n\nlet isOpen = false\nconst listeners = new Set<() => void>()\n\nfunction set(next: boolean) {\n if (isOpen === next) return\n isOpen = next\n for (const l of [...listeners]) l()\n}\n\nconst subscribe = (l: () => void) => {\n listeners.add(l)\n return () => {\n listeners.delete(l)\n }\n}\n\n/** Abre el cajón del carrito desde cualquier parte. */\nexport function openCartDrawer() {\n set(true)\n}\n\n/** Cierra el cajón del carrito. */\nexport function closeCartDrawer() {\n set(false)\n}\n\nexport function toggleCartDrawer() {\n set(!isOpen)\n}\n\nexport function isCartDrawerOpen() {\n return isOpen\n}\n\n/** Estado y acciones del cajón. `open` es `false` en el servidor y en la primera pintura. */\nexport function useCartDrawer() {\n const open = useSyncExternalStore(subscribe, () => isOpen, () => false)\n const toggle = useCallback(() => toggleCartDrawer(), [])\n return { open, openDrawer: openCartDrawer, closeDrawer: closeCartDrawer, toggle }\n}\n\n/**\n * Abre el cajón cuando termina un \"agregar al carrito\". `busy` es verdadero mientras hay un agregado en vuelo\n * (en React Router: algún fetcher con la acción del carrito e intención de agregar). Con `skip` verdadero al\n * terminar (error, agregado silencioso) no se abre.\n */\nexport function useOpenCartDrawerWhenDone(busy: boolean, options: { skip?: boolean } = {}) {\n const was = useRef(false)\n const skip = useRef(false)\n skip.current = !!options.skip\n useEffect(() => {\n if (was.current && !busy && !skip.current) openCartDrawer()\n was.current = busy\n }, [busy])\n}\n\ntype ClickLike = {\n defaultPrevented: boolean\n button: number\n metaKey: boolean\n ctrlKey: boolean\n shiftKey: boolean\n altKey: boolean\n preventDefault: () => void\n}\n\n/**\n * `onClick` para el enlace \"Mi carrito\" de la cabecera: con un clic normal abre el cajón; con clic con\n * modificador, clic central o sin JavaScript el `href` (la página del carrito) sigue funcionando.\n */\nexport function handleCartLinkClick(e: ClickLike) {\n if (e.defaultPrevented || e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return\n e.preventDefault()\n openCartDrawer()\n}\n","import { useEffect, useId, type ElementType, type ReactNode } from 'react'\nimport { formatMoney, type Cart, type CartLine, type Money } from '@asteby/storefront'\nimport { useModalDialog } from '../dialog.js'\nimport { useResolvedLocale } from '../locale.js'\nimport { closeCartDrawer, useCartDrawer } from './store.js'\n\nexport type CartDrawerLabels = {\n /** Título; el cajón agrega \" (N)\" con la cantidad de unidades. */\n title: string\n /** Texto accesible del botón de cierre. */\n close: string\n empty: string\n emptyHint?: string\n /** Texto del enlace \"seguir comprando\" del estado vacío (se muestra con `paths.browse`). */\n browse?: string\n subtotal: string\n /** Nota bajo el subtotal. */\n note?: string\n checkout: string\n viewCart: string\n remove: string\n increase: string\n decrease: string\n}\n\nexport type CartDrawerPaths = {\n /** Página del carrito: acción de las mutaciones y destino de \"ver carrito\". */\n cart: string\n checkout: string\n browse?: string\n /** Enlace de la línea al producto; sin esto el título no es enlace. */\n product?: (handle: string, variantId: string) => string\n}\n\n/** Contrato de la acción de ruta del carrito de la tienda (nombres de campo e intenciones). */\nexport type CartDrawerFormContract = {\n intentField?: string\n lineField?: string\n quantityField?: string\n updateIntent?: string\n removeIntent?: string\n}\n\nexport type CartDrawerShipping = {\n /** Mensaje ya calculado por la tienda con lo que manda OPS. */\n message: ReactNode\n /** 0..100 */\n percent: number\n reached?: boolean\n progressLabel: string\n}\n\nexport type CartDrawerLineForm = {\n /** Componente de formulario (`'form'`, o `fetcher.Form` del router para mejorar sin recargar). */\n Form: ElementType\n /** Datos en vuelo del formulario, para pintar la cantidad de forma optimista. */\n formData?: FormData | null | undefined\n}\n\nexport type CartDrawerLinkProps = { href: string; className?: string | undefined; children: ReactNode; onClick?: () => void }\n\nexport type CartDrawerSlot =\n | 'dialog' | 'panel' | 'header' | 'title' | 'close' | 'empty' | 'body' | 'shipping' | 'bar' | 'barFill' | 'lines' | 'line'\n | 'image' | 'lineTitle' | 'variant' | 'price' | 'qty' | 'qtyButton' | 'qtyValue' | 'remove' | 'upsell' | 'footer' | 'subtotal'\n | 'note' | 'actions' | 'checkout' | 'viewCart' | 'browse' | 'emptyTitle' | 'emptyHint' | 'shippingMessage' | 'lineMain'\n | 'lineHead' | 'lineText' | 'controls' | 'upsellTitle' | 'subtotalLabel' | 'subtotalValue'\n\nexport type CartDrawerIcons = { close?: ReactNode; decrease?: ReactNode; increase?: ReactNode; shipping?: ReactNode; shippingReached?: ReactNode }\n\nexport type CartDrawerProps = {\n /** `cart.cost` y cada línea vienen de OPS; el cajón no calcula nada. */\n cart: Cart | null | undefined\n labels: CartDrawerLabels\n paths: CartDrawerPaths\n form?: CartDrawerFormContract\n /** Hook que da el formulario de cada línea. Por omisión `<form method=\"post\">` (funciona sin JavaScript). */\n useLineForm?: () => CartDrawerLineForm\n shipping?: CartDrawerShipping | null\n /** Aviso fijo cuando no hay barra de envío (p. ej. \"Envío gratis\"). */\n notice?: ReactNode\n /** Sección \"podría interesarte\" (la tienda decide qué mostrar). */\n upsell?: ReactNode\n upsellTitle?: string\n renderLine?: (line: CartLine, defaults: { controls: ReactNode; price: ReactNode; image: ReactNode }) => ReactNode\n renderImage?: (line: CartLine) => ReactNode\n renderMoney?: (money: Money) => ReactNode\n renderLink?: (props: CartDrawerLinkProps) => ReactNode\n /** Omite el variante cuando es el valor por defecto de OPS (\"Default Title\"). */\n isDefaultVariantTitle?: (title: string) => boolean\n icons?: CartDrawerIcons\n /** Clases por pieza (además de los `data-sf-cart-*`), para tiendas con Tailwind. */\n classNames?: Partial<Record<CartDrawerSlot, string>>\n locale?: string\n /** Se llama al abrir/cerrar por cualquier vía. */\n onOpenChange?: (open: boolean) => void\n}\n\nconst DEFAULT_FORM: Required<CartDrawerFormContract> = {\n intentField: 'intent',\n lineField: 'line_id',\n quantityField: 'quantity',\n updateIntent: 'update',\n removeIntent: 'remove',\n}\n\nconst useNativeForm = (): CartDrawerLineForm => ({ Form: 'form' })\n\nconst defaultIsDefaultVariant = (t: string) => /^default title$/i.test(t.trim())\n\nfunction useBodyScrollLock(locked: boolean) {\n useEffect(() => {\n if (!locked || typeof document === 'undefined') return\n const el = document.documentElement\n const prev = el.style.overflow\n el.style.overflow = 'hidden'\n return () => {\n el.style.overflow = prev\n }\n }, [locked])\n}\n\n/**\n * Cajón lateral del carrito (\"Tu carrito (N)\"). Sin textos ni marca: todo llega por props.\n * Se monta una vez (en la raíz) y se abre con `openCartDrawer()` / `useCartDrawer()`.\n * `<dialog>` modal: `role=\"dialog\"`, `aria-modal`, foco atrapado y devuelto al abridor, Esc y clic fuera cierran,\n * el fondo no hace scroll. Las mutaciones usan la acción de ruta de la tienda (formularios nativos que\n * funcionan sin JavaScript, o el `Form` de un fetcher con `useLineForm`). Estilos: `@asteby/storefront-react/cart.css`\n * (tokens de la tienda) y/o `classNames`.\n */\nexport function CartDrawer(props: CartDrawerProps) {\n const { cart, labels, paths, shipping, notice, upsell, upsellTitle, icons, classNames: cx = {}, onOpenChange } = props\n const locale = useResolvedLocale(props.locale)\n const { open } = useCartDrawer()\n const titleId = useId()\n const upsellId = useId()\n const { ref, onBackdropClick } = useModalDialog({ open, onClose: () => closeCartDrawer() })\n useBodyScrollLock(open)\n useEffect(() => {\n onOpenChange?.(open)\n }, [open]) // eslint-disable-line react-hooks/exhaustive-deps\n\n if (!open) return null\n\n const money = props.renderMoney ?? ((m: Money) => formatMoney(m, locale))\n const link = props.renderLink ?? (({ href, className, children, onClick }: CartDrawerLinkProps) => (\n <a href={href} className={className} onClick={onClick}>{children}</a>\n ))\n const count = cart?.total_quantity ?? 0\n const lines = cart?.lines ?? []\n const empty = !cart || lines.length === 0\n const close = () => closeCartDrawer()\n\n return (\n <dialog\n ref={ref}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={titleId}\n onClick={onBackdropClick}\n onClose={close}\n className={cx.dialog}\n data-sf-cart-drawer=\"\"\n >\n <div className={cx.panel} data-sf-cart-panel=\"\">\n <div className={cx.header} data-sf-cart-header=\"\">\n <h2 id={titleId} tabIndex={-1} className={cx.title} data-sf-cart-title=\"\">\n {labels.title}{count > 0 ? ` (${count})` : ''}\n </h2>\n <button type=\"button\" onClick={close} aria-label={labels.close} className={cx.close} data-sf-cart-close=\"\" data-sf-autofocus=\"\">\n {icons?.close ?? <span aria-hidden=\"true\">✕</span>}\n </button>\n </div>\n\n {empty ? (\n <div className={cx.empty} data-sf-cart-empty=\"\">\n <p className={cx.emptyTitle} data-sf-cart-empty-title=\"\">{labels.empty}</p>\n {labels.emptyHint ? <p className={cx.emptyHint} data-sf-cart-empty-hint=\"\">{labels.emptyHint}</p> : null}\n {paths.browse && labels.browse ? link({ href: paths.browse, className: cx.browse, children: labels.browse, onClick: close }) : null}\n </div>\n ) : (\n <>\n <div className={cx.body} data-sf-cart-body=\"\">\n {shipping ? (\n <div className={cx.shipping} data-sf-cart-shipping=\"\" data-reached={shipping.reached || undefined}>\n <p className={cx.shippingMessage}>\n {shipping.reached ? icons?.shippingReached : icons?.shipping}\n {shipping.message}\n </p>\n <div\n role=\"progressbar\"\n aria-valuemin={0}\n aria-valuemax={100}\n aria-valuenow={Math.round(shipping.percent)}\n aria-label={shipping.progressLabel}\n className={cx.bar}\n data-sf-cart-bar=\"\"\n >\n <div className={cx.barFill} data-sf-cart-bar-fill=\"\" style={{ width: `${Math.max(0, Math.min(100, shipping.percent))}%` }} />\n </div>\n </div>\n ) : notice ? (\n <p className={[cx.shipping, cx.shippingMessage].filter(Boolean).join(\" \") || undefined} data-sf-cart-shipping=\"\" data-notice=\"\">{icons?.shippingReached}{notice}</p>\n ) : null}\n\n <ul className={cx.lines} data-sf-cart-lines=\"\">\n {lines.map((line) => (\n <DrawerLine key={line.id} line={line} props={props} money={money} link={link} close={close} />\n ))}\n </ul>\n\n {upsell ? (\n <section className={cx.upsell} data-sf-cart-upsell=\"\" aria-labelledby={upsellTitle ? upsellId : undefined}>\n {upsellTitle ? <h3 id={upsellId} className={cx.upsellTitle}>{upsellTitle}</h3> : null}\n {upsell}\n </section>\n ) : null}\n </div>\n\n <div className={cx.footer} data-sf-cart-footer=\"\">\n <div className={cx.subtotal} data-sf-cart-subtotal=\"\">\n <span className={cx.subtotalLabel}>{labels.subtotal}</span>\n <span className={cx.subtotalValue} data-sf-cart-subtotal-value=\"\">{cart ? money(cart.cost.subtotal) : null}</span>\n </div>\n {labels.note ? <p className={cx.note} data-sf-cart-note=\"\">{labels.note}</p> : null}\n <div className={cx.actions} data-sf-cart-actions=\"\">\n {link({ href: paths.checkout, className: cx.checkout, children: labels.checkout, onClick: close })}\n {link({ href: paths.cart, className: cx.viewCart, children: labels.viewCart, onClick: close })}\n </div>\n </div>\n </>\n )}\n </div>\n </dialog>\n )\n}\n\nfunction DrawerLine({\n line,\n props,\n money,\n link,\n close,\n}: {\n line: CartLine\n props: CartDrawerProps\n money: (m: Money) => ReactNode\n link: (p: CartDrawerLinkProps) => ReactNode\n close: () => void\n}) {\n const { labels, paths, icons, classNames: cx = {} } = props\n const f = { ...DEFAULT_FORM, ...props.form }\n const { Form, formData } = (props.useLineForm ?? useNativeForm)()\n const quantity = formData ? Number(formData.get(f.quantityField) ?? 0) : line.quantity\n if (formData && (formData.get(f.intentField) === f.removeIntent || quantity === 0)) return null\n\n const merch = line.merchandise\n const isDefault = props.isDefaultVariantTitle ?? defaultIsDefaultVariant\n const title = merch.product.title\n const href = paths.product?.(merch.product.handle, merch.id)\n const img = merch.image ?? merch.product.featured_image\n const image = props.renderImage ? props.renderImage(line) : img ? (\n <img src={img.url} alt={img.alt ?? ''} width={80} height={80} loading=\"lazy\" decoding=\"async\" />\n ) : null\n\n const imageNode = <span className={cx.image} data-sf-cart-image=\"\">{image}</span>\n const price = <span className={cx.price} data-sf-cart-price=\"\">{money(line.cost.total)}</span>\n const controls = (\n <div className={cx.controls} data-sf-cart-controls=\"\">\n <Form method=\"post\" action={paths.cart} className={cx.qty} data-sf-cart-qty=\"\">\n <input type=\"hidden\" name={f.intentField} value={f.updateIntent} />\n <input type=\"hidden\" name={f.lineField} value={line.id} />\n <button type=\"submit\" name={f.quantityField} value={quantity - 1} aria-label={labels.decrease} className={cx.qtyButton} data-sf-cart-qty-button=\"\">\n {icons?.decrease ?? <span aria-hidden=\"true\">−</span>}\n </button>\n <span className={cx.qtyValue} aria-live=\"polite\" data-sf-cart-qty-value=\"\">{quantity}</span>\n <button type=\"submit\" name={f.quantityField} value={quantity + 1} aria-label={labels.increase} className={cx.qtyButton} data-sf-cart-qty-button=\"\">\n {icons?.increase ?? <span aria-hidden=\"true\">+</span>}\n </button>\n </Form>\n <Form method=\"post\" action={paths.cart} data-sf-cart-remove-form=\"\">\n <input type=\"hidden\" name={f.intentField} value={f.removeIntent} />\n <input type=\"hidden\" name={f.lineField} value={line.id} />\n <button type=\"submit\" className={cx.remove} data-sf-cart-remove=\"\">{labels.remove}</button>\n </Form>\n </div>\n )\n\n if (props.renderLine) return <li key={line.id} className={cx.line} data-sf-cart-line=\"\">{props.renderLine(line, { controls, price, image: imageNode })}</li>\n\n return (\n <li className={cx.line} data-sf-cart-line=\"\">\n {imageNode}\n <div className={cx.lineMain} data-sf-cart-line-main=\"\">\n <div className={cx.lineHead} data-sf-cart-line-head=\"\">\n <div className={cx.lineText} data-sf-cart-line-text=\"\">\n {href ? link({ href, className: cx.lineTitle, children: title, onClick: close }) : <span className={cx.lineTitle} data-sf-cart-line-title=\"\">{title}</span>}\n {!isDefault(merch.title) ? <p className={cx.variant} data-sf-cart-variant=\"\">{merch.title}</p> : null}\n </div>\n {price}\n </div>\n {controls}\n </div>\n </li>\n )\n}\n"]}
|
|
@@ -0,0 +1,440 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
+
var react = require('react');
|
|
5
|
+
var storefront = require('@asteby/storefront');
|
|
6
|
+
|
|
7
|
+
// src/checkout/brands.ts
|
|
8
|
+
var B = (key, name, kind, bg, fg, mark, shape) => ({
|
|
9
|
+
key,
|
|
10
|
+
name,
|
|
11
|
+
kind,
|
|
12
|
+
bg,
|
|
13
|
+
fg,
|
|
14
|
+
...mark ? { mark } : {},
|
|
15
|
+
...shape ? { shape } : {}
|
|
16
|
+
});
|
|
17
|
+
var LIST = [
|
|
18
|
+
// Parcel carriers (Mexico and global).
|
|
19
|
+
B("fedex", "FedEx", "carrier", "#4D148C", "#FFFFFF"),
|
|
20
|
+
B("dhl", "DHL", "carrier", "#FFCC00", "#B00410"),
|
|
21
|
+
B("estafeta", "Estafeta", "carrier", "#C8102E", "#FFFFFF"),
|
|
22
|
+
B("paquetexpress", "Paquetexpress", "carrier", "#0B4EA2", "#FFFFFF", "Paquet\nexpress"),
|
|
23
|
+
B("ups", "UPS", "carrier", "#351C15", "#FFB500"),
|
|
24
|
+
B("redpack", "Redpack", "carrier", "#C8102E", "#FFFFFF"),
|
|
25
|
+
B("99minutos", "99 Minutos", "carrier", "#00704A", "#FFFFFF", "99"),
|
|
26
|
+
B("jtexpress", "J&T Express", "carrier", "#C8102E", "#FFFFFF", "J&T"),
|
|
27
|
+
B("sendex", "Sendex", "carrier", "#003A70", "#FFFFFF"),
|
|
28
|
+
B("ampm", "AMPM", "carrier", "#1D1D1B", "#FFFFFF"),
|
|
29
|
+
B("tresguerras", "Tresguerras", "carrier", "#005BAC", "#FFFFFF", "3G"),
|
|
30
|
+
B("quiken", "Quiken", "carrier", "#1D1D1B", "#FFFFFF"),
|
|
31
|
+
B("imile", "iMile", "carrier", "#0057B8", "#FFFFFF"),
|
|
32
|
+
B("carssa", "Carssa", "carrier", "#00529B", "#FFFFFF"),
|
|
33
|
+
B("correosdemexico", "Correos de M\xE9xico", "carrier", "#7A1E3A", "#FFFFFF", "Correos\nM\xE9xico"),
|
|
34
|
+
B("usps", "USPS", "carrier", "#333366", "#FFFFFF"),
|
|
35
|
+
B("canadapost", "Canada Post", "carrier", "#DA291C", "#FFFFFF", "CPC"),
|
|
36
|
+
// Card networks.
|
|
37
|
+
B("visa", "Visa", "card", "#1A1F71", "#FFFFFF", "VISA"),
|
|
38
|
+
B("mastercard", "Mastercard", "card", "#FFFFFF", "#1D1D1B", "MC", "mastercard"),
|
|
39
|
+
B("amex", "American Express", "card", "#1F72CD", "#FFFFFF", "AMEX"),
|
|
40
|
+
B("carnet", "Carnet", "card", "#003B71", "#FFFFFF"),
|
|
41
|
+
// Wallets and payment providers.
|
|
42
|
+
B("mercadopago", "Mercado Pago", "wallet", "#00B1EA", "#0B1F4E", "mercado\npago"),
|
|
43
|
+
B("paypal", "PayPal", "wallet", "#003087", "#FFFFFF"),
|
|
44
|
+
B("clip", "Clip", "wallet", "#FC4C02", "#1D1D1B"),
|
|
45
|
+
B("applepay", "Apple Pay", "wallet", "#000000", "#FFFFFF", "Pay"),
|
|
46
|
+
B("googlepay", "Google Pay", "wallet", "#FFFFFF", "#3C4043", "G Pay"),
|
|
47
|
+
// Cash points and transfers (Mexico).
|
|
48
|
+
B("oxxo", "OXXO", "cash", "#E21E26", "#FFE600"),
|
|
49
|
+
B("spei", "SPEI", "bank", "#14365F", "#FFFFFF"),
|
|
50
|
+
B("stp", "STP", "bank", "#14365F", "#FFFFFF", "SPEI"),
|
|
51
|
+
B("7eleven", "7-Eleven", "cash", "#00704A", "#FFFFFF", "7-11"),
|
|
52
|
+
B("circlek", "Circle K", "cash", "#DA291C", "#FFFFFF", "K"),
|
|
53
|
+
B("soriana", "Soriana", "cash", "#C8102E", "#FFFFFF"),
|
|
54
|
+
B("extra", "Extra", "cash", "#E35205", "#FFFFFF"),
|
|
55
|
+
B("kiosko", "Kiosko", "cash", "#C8102E", "#FFFFFF"),
|
|
56
|
+
B("calimax", "Calimax", "cash", "#D52B1E", "#FFFFFF"),
|
|
57
|
+
B("farmaciasyza", "Farmacias Yza", "cash", "#0A5A9C", "#FFFFFF", "Yza"),
|
|
58
|
+
B("chedraui", "Chedraui", "cash", "#0047BB", "#FFFFFF"),
|
|
59
|
+
B("casaley", "Casa Ley", "cash", "#C8102E", "#FFFFFF", "Ley"),
|
|
60
|
+
B("telecomm", "Telecomm", "cash", "#6F1D46", "#FFFFFF"),
|
|
61
|
+
B("walmart", "Walmart", "cash", "#0071CE", "#FFFFFF"),
|
|
62
|
+
B("santander", "Santander", "bank", "#C00000", "#FFFFFF"),
|
|
63
|
+
B("bbva", "BBVA", "bank", "#004481", "#FFFFFF"),
|
|
64
|
+
B("citibanamex", "Citibanamex", "bank", "#004B8D", "#FFFFFF", "Citi"),
|
|
65
|
+
B("banorte", "Banorte", "bank", "#C8102E", "#FFFFFF")
|
|
66
|
+
];
|
|
67
|
+
var ALIASES = {
|
|
68
|
+
fedexmx: "fedex",
|
|
69
|
+
fedexexpress: "fedex",
|
|
70
|
+
dhlexpress: "dhl",
|
|
71
|
+
dhlmx: "dhl",
|
|
72
|
+
paquetexpres: "paquetexpress",
|
|
73
|
+
paqueteexpress: "paquetexpress",
|
|
74
|
+
jt: "jtexpress",
|
|
75
|
+
jandtexpress: "jtexpress",
|
|
76
|
+
noventaynueveminutos: "99minutos",
|
|
77
|
+
correos: "correosdemexico",
|
|
78
|
+
sepomex: "correosdemexico",
|
|
79
|
+
master: "mastercard",
|
|
80
|
+
americanexpress: "amex",
|
|
81
|
+
mercadopagomx: "mercadopago",
|
|
82
|
+
mp: "mercadopago",
|
|
83
|
+
clabe: "spei",
|
|
84
|
+
banktransfer: "spei",
|
|
85
|
+
seveneleven: "7eleven",
|
|
86
|
+
"711": "7eleven",
|
|
87
|
+
circulok: "circlek",
|
|
88
|
+
yza: "farmaciasyza",
|
|
89
|
+
bancomer: "bbva",
|
|
90
|
+
banamex: "citibanamex",
|
|
91
|
+
ley: "casaley"
|
|
92
|
+
};
|
|
93
|
+
var BY_KEY = new Map(LIST.map((b) => [b.key, b]));
|
|
94
|
+
function brandKey(raw) {
|
|
95
|
+
const flat = (raw ?? "").normalize("NFD").replace(/[̀-ͯ]/g, "").toLowerCase().replace(/&/g, "and").replace(/[^a-z0-9]/g, "");
|
|
96
|
+
const noCountry = flat.endsWith("mexico") && flat !== "correosdemexico" ? flat.slice(0, -6) : flat;
|
|
97
|
+
return ALIASES[noCountry] ?? (BY_KEY.has(noCountry) ? noCountry : ALIASES[flat] ?? flat);
|
|
98
|
+
}
|
|
99
|
+
function findBrand(raw) {
|
|
100
|
+
return BY_KEY.get(brandKey(raw)) ?? null;
|
|
101
|
+
}
|
|
102
|
+
function brandName(raw) {
|
|
103
|
+
const brand = findBrand(raw);
|
|
104
|
+
if (brand) return brand.name;
|
|
105
|
+
const text = (raw ?? "").trim();
|
|
106
|
+
if (!text) return null;
|
|
107
|
+
if (text !== text.toLowerCase() && text !== text.toUpperCase()) return text;
|
|
108
|
+
return text.toLowerCase().split(/[\s_-]+/).filter(Boolean).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
109
|
+
}
|
|
110
|
+
function listBrands(kind) {
|
|
111
|
+
return kind ? LIST.filter((b) => b.kind === kind) : [...LIST];
|
|
112
|
+
}
|
|
113
|
+
function safeLogo(url) {
|
|
114
|
+
if (!url) return null;
|
|
115
|
+
try {
|
|
116
|
+
return new URL(url).protocol === "https:" ? url : null;
|
|
117
|
+
} catch {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
function monogram(raw) {
|
|
122
|
+
const words = (brandName(raw) ?? raw).split(/\s+/).filter(Boolean);
|
|
123
|
+
const letters = words.length > 1 ? words.slice(0, 2).map((w) => w[0]) : [(words[0] ?? "?").slice(0, 2)];
|
|
124
|
+
return letters.join("").toUpperCase();
|
|
125
|
+
}
|
|
126
|
+
function BrandMark({ brand, logoUrl, size = 24, title, className }) {
|
|
127
|
+
const height = size;
|
|
128
|
+
const width = Math.round(size * 1.5);
|
|
129
|
+
const a11y = title ? { role: "img", "aria-label": title } : { "aria-hidden": true };
|
|
130
|
+
const logo = safeLogo(logoUrl);
|
|
131
|
+
const found = findBrand(brand);
|
|
132
|
+
const key = found?.key ?? "generic";
|
|
133
|
+
const style = { width, height, flex: "none" };
|
|
134
|
+
if (logo) {
|
|
135
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
136
|
+
"img",
|
|
137
|
+
{
|
|
138
|
+
src: logo,
|
|
139
|
+
alt: title ?? "",
|
|
140
|
+
width,
|
|
141
|
+
height,
|
|
142
|
+
loading: "lazy",
|
|
143
|
+
decoding: "async",
|
|
144
|
+
className,
|
|
145
|
+
style: { ...style, objectFit: "contain" },
|
|
146
|
+
"data-sf-brand-mark": key,
|
|
147
|
+
...title ? {} : { "aria-hidden": true }
|
|
148
|
+
}
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
const ring = "var(--sf-brand-mark-ring, rgb(127 127 127 / 0.35))";
|
|
152
|
+
if (found?.shape === "mastercard") {
|
|
153
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 48 32", width, height, className, style, "data-sf-brand-mark": key, focusable: "false", ...a11y, children: [
|
|
154
|
+
/* @__PURE__ */ jsxRuntime.jsx("rect", { x: "0.5", y: "0.5", width: "47", height: "31", rx: "5", fill: found.bg, stroke: ring }),
|
|
155
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "19", cy: "16", r: "9", fill: "#EB001B" }),
|
|
156
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "29", cy: "16", r: "9", fill: "#F79E1B" }),
|
|
157
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M24 8.52a9 9 0 0 1 0 14.96a9 9 0 0 1 0-14.96z", fill: "#FF5F00" })
|
|
158
|
+
] });
|
|
159
|
+
}
|
|
160
|
+
const text = found ? found.mark ?? found.name : monogram(brand ?? "");
|
|
161
|
+
const bg = found?.bg ?? "var(--sf-brand-mark-bg, #E7E9EE)";
|
|
162
|
+
const fg = found?.fg ?? "var(--sf-brand-mark-fg, #2B2F38)";
|
|
163
|
+
const lines = text.split("\n");
|
|
164
|
+
const longest = Math.max(...lines.map((l) => l.length));
|
|
165
|
+
const fontSize = lines.length > 1 ? longest <= 5 ? 11 : 9.5 : longest <= 2 ? 15 : longest <= 4 ? 12 : 10;
|
|
166
|
+
const fit = (l) => l.length > 5 ? { textLength: 40, lengthAdjust: "spacingAndGlyphs" } : {};
|
|
167
|
+
const italic = found?.key === "visa" || found?.key === "fedex" ? "italic" : void 0;
|
|
168
|
+
const common = {
|
|
169
|
+
textAnchor: "middle",
|
|
170
|
+
fill: fg,
|
|
171
|
+
fontFamily: "system-ui, -apple-system, 'Segoe UI', Roboto, Arial, sans-serif",
|
|
172
|
+
fontWeight: 800,
|
|
173
|
+
fontSize,
|
|
174
|
+
fontStyle: italic
|
|
175
|
+
};
|
|
176
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 48 32", width, height, className, style, "data-sf-brand-mark": key, focusable: "false", ...a11y, children: [
|
|
177
|
+
/* @__PURE__ */ jsxRuntime.jsx("rect", { x: "0.5", y: "0.5", width: "47", height: "31", rx: "5", fill: bg, stroke: ring }),
|
|
178
|
+
lines.length > 1 ? lines.slice(0, 2).map((l, i) => /* @__PURE__ */ jsxRuntime.jsx("text", { x: "24", y: i === 0 ? 15 : 25.5, ...common, ...fit(l), children: l }, i)) : /* @__PURE__ */ jsxRuntime.jsx("text", { x: "24", y: "16", dominantBaseline: "central", letterSpacing: longest <= 4 ? 0.3 : 0, ...common, ...fit(text), children: text })
|
|
179
|
+
] });
|
|
180
|
+
}
|
|
181
|
+
var StorefrontContext = react.createContext(null);
|
|
182
|
+
function useOptionalStorefront() {
|
|
183
|
+
return react.useContext(StorefrontContext);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// src/locale.ts
|
|
187
|
+
function useResolvedLocale(locale) {
|
|
188
|
+
const sf = useOptionalStorefront();
|
|
189
|
+
return locale ?? sf?.locale ?? "es-MX";
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// src/checkout/delivery.ts
|
|
193
|
+
var ES = {
|
|
194
|
+
etaOne: "Llega en 1 d\xEDa h\xE1bil",
|
|
195
|
+
etaMany: "Llega en {n} d\xEDas h\xE1biles",
|
|
196
|
+
etaRange: "Llega en {min} a {max} d\xEDas h\xE1biles",
|
|
197
|
+
etaUpTo: "Llega en m\xE1ximo {max} d\xEDas h\xE1biles",
|
|
198
|
+
etaFrom: "Llega en {min} d\xEDas h\xE1biles o m\xE1s",
|
|
199
|
+
cheapest: "M\xE1s econ\xF3mico",
|
|
200
|
+
fastest: "M\xE1s r\xE1pido",
|
|
201
|
+
free: "Gratis",
|
|
202
|
+
pickupTitle: "Recoger en {name}",
|
|
203
|
+
quoteToday: "Precios de env\xEDo vigentes hasta las {time}.",
|
|
204
|
+
quoteTomorrow: "Precios de env\xEDo vigentes hasta ma\xF1ana a las {time}.",
|
|
205
|
+
quoteLater: "Precios de env\xEDo vigentes hasta el {date}.",
|
|
206
|
+
quoteSoon: "Los precios de env\xEDo vencen pronto ({time}).",
|
|
207
|
+
partial: "No pudimos consultar todas las paqueter\xEDas. Estas son las opciones disponibles ahora.",
|
|
208
|
+
loading: "Buscando opciones de env\xEDo\u2026",
|
|
209
|
+
requoted: "Las tarifas de env\xEDo cambiaron y ya est\xE1n actualizadas. Revisa tu env\xEDo antes de pagar."
|
|
210
|
+
};
|
|
211
|
+
var EN = {
|
|
212
|
+
etaOne: "Arrives in 1 business day",
|
|
213
|
+
etaMany: "Arrives in {n} business days",
|
|
214
|
+
etaRange: "Arrives in {min} to {max} business days",
|
|
215
|
+
etaUpTo: "Arrives in up to {max} business days",
|
|
216
|
+
etaFrom: "Arrives in {min}+ business days",
|
|
217
|
+
cheapest: "Cheapest",
|
|
218
|
+
fastest: "Fastest",
|
|
219
|
+
free: "Free",
|
|
220
|
+
pickupTitle: "Pick up at {name}",
|
|
221
|
+
quoteToday: "Shipping prices valid until {time}.",
|
|
222
|
+
quoteTomorrow: "Shipping prices valid until tomorrow at {time}.",
|
|
223
|
+
quoteLater: "Shipping prices valid until {date}.",
|
|
224
|
+
quoteSoon: "Shipping prices expire soon ({time}).",
|
|
225
|
+
partial: "We couldn't reach every carrier. These are the options available now.",
|
|
226
|
+
loading: "Looking for delivery options\u2026",
|
|
227
|
+
requoted: "Shipping rates changed and are now up to date. Check your delivery before paying."
|
|
228
|
+
};
|
|
229
|
+
function deliveryMessages(locale, overrides) {
|
|
230
|
+
const base = (locale ?? "es-MX").toLowerCase().startsWith("en") ? EN : ES;
|
|
231
|
+
return overrides ? { ...base, ...overrides } : base;
|
|
232
|
+
}
|
|
233
|
+
var fill = (tpl, vars) => tpl.replace(/\{(\w+)\}/g, (_, k) => String(vars[k] ?? "")).replace(/\.\.$/, ".");
|
|
234
|
+
function rateCarrier(rate) {
|
|
235
|
+
return brandName(rate.carrier);
|
|
236
|
+
}
|
|
237
|
+
function rateService(rate) {
|
|
238
|
+
const title = rate.title.trim();
|
|
239
|
+
const carrier = rateCarrier(rate);
|
|
240
|
+
if (!carrier) return title;
|
|
241
|
+
for (const prefix of [carrier, rate.carrier ?? ""]) {
|
|
242
|
+
if (!prefix) continue;
|
|
243
|
+
if (title.toLowerCase().startsWith(prefix.toLowerCase())) {
|
|
244
|
+
const rest = title.slice(prefix.length).replace(/^[\s·:|-]+/, "");
|
|
245
|
+
if (rest) return rest;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
return title;
|
|
249
|
+
}
|
|
250
|
+
function rateEta(rate, messages = ES) {
|
|
251
|
+
const { eta_days_min: min, eta_days_max: max } = rate;
|
|
252
|
+
if (typeof min === "number" && typeof max === "number") {
|
|
253
|
+
if (min === max) return min === 1 ? messages.etaOne : fill(messages.etaMany, { n: min });
|
|
254
|
+
return fill(messages.etaRange, { min, max });
|
|
255
|
+
}
|
|
256
|
+
if (typeof max === "number") return max === 1 ? messages.etaOne : fill(messages.etaUpTo, { max });
|
|
257
|
+
if (typeof min === "number") return min === 1 ? messages.etaOne : fill(messages.etaFrom, { min });
|
|
258
|
+
return rate.eta ?? null;
|
|
259
|
+
}
|
|
260
|
+
var costOf = (r) => {
|
|
261
|
+
const n = Number(r.cost.amount);
|
|
262
|
+
return Number.isFinite(n) ? n : null;
|
|
263
|
+
};
|
|
264
|
+
var daysOf = (r) => r.eta_days_max ?? r.eta_days_min ?? null;
|
|
265
|
+
function rateBadges(rates) {
|
|
266
|
+
const out = /* @__PURE__ */ new Map();
|
|
267
|
+
if (rates.length < 2) return out;
|
|
268
|
+
const add = (id, b) => out.set(id, [...out.get(id) ?? [], b]);
|
|
269
|
+
const unique = (values) => {
|
|
270
|
+
const known = values.filter((v) => v[1] !== null);
|
|
271
|
+
if (known.length < 2) return null;
|
|
272
|
+
const min = Math.min(...known.map((v) => v[1]));
|
|
273
|
+
const winners = known.filter((v) => v[1] === min);
|
|
274
|
+
return winners.length === 1 ? winners[0][0] : null;
|
|
275
|
+
};
|
|
276
|
+
const currencies = new Set(rates.map((r) => r.cost.currency_code));
|
|
277
|
+
if (currencies.size === 1) {
|
|
278
|
+
const id = unique(rates.map((r) => [r.id, costOf(r)]));
|
|
279
|
+
if (id) add(id, "cheapest");
|
|
280
|
+
}
|
|
281
|
+
const fast = unique(rates.map((r) => [r.id, daysOf(r)]));
|
|
282
|
+
if (fast) add(fast, "fastest");
|
|
283
|
+
return out;
|
|
284
|
+
}
|
|
285
|
+
function quoteDeadline(rates) {
|
|
286
|
+
let best = null;
|
|
287
|
+
for (const r of rates) {
|
|
288
|
+
if (!r.expires_at) continue;
|
|
289
|
+
const d = new Date(r.expires_at);
|
|
290
|
+
if (Number.isNaN(d.getTime())) continue;
|
|
291
|
+
if (!best || d < best) best = d;
|
|
292
|
+
}
|
|
293
|
+
return best;
|
|
294
|
+
}
|
|
295
|
+
function quoteNote(deadline, opts = {}) {
|
|
296
|
+
if (!deadline) return null;
|
|
297
|
+
const now = opts.now ?? /* @__PURE__ */ new Date();
|
|
298
|
+
const left = deadline.getTime() - now.getTime();
|
|
299
|
+
if (left <= 0) return null;
|
|
300
|
+
const m = opts.messages ?? ES;
|
|
301
|
+
const locale = opts.locale ?? "es-MX";
|
|
302
|
+
const tz = opts.timeZone ? { timeZone: opts.timeZone } : {};
|
|
303
|
+
const time = new Intl.DateTimeFormat(locale, { hour: "numeric", minute: "2-digit", ...tz }).format(deadline);
|
|
304
|
+
if (left <= (opts.soonMinutes ?? 15) * 6e4) return { text: fill(m.quoteSoon, { time }), soon: true };
|
|
305
|
+
const day = (d) => new Intl.DateTimeFormat("en-CA", { year: "numeric", month: "2-digit", day: "2-digit", ...tz }).format(d);
|
|
306
|
+
if (day(deadline) === day(now)) return { text: fill(m.quoteToday, { time }), soon: false };
|
|
307
|
+
if (day(deadline) === day(new Date(now.getTime() + 864e5))) return { text: fill(m.quoteTomorrow, { time }), soon: false };
|
|
308
|
+
const date = new Intl.DateTimeFormat(locale, { day: "numeric", month: "short", hour: "numeric", minute: "2-digit", ...tz }).format(deadline);
|
|
309
|
+
return { text: fill(m.quoteLater, { date }), soon: false };
|
|
310
|
+
}
|
|
311
|
+
var QUOTE_CODES = /* @__PURE__ */ new Set(["quote_expired", "rate_expired", "rate_changed", "rate_unavailable", "rate_not_found", "stale_rate", "invalid_rate"]);
|
|
312
|
+
function isQuoteChange(err) {
|
|
313
|
+
if (!err) return false;
|
|
314
|
+
if (err.code && QUOTE_CODES.has(err.code)) return true;
|
|
315
|
+
if (err.status === 409) return true;
|
|
316
|
+
return err.status === 422 && (err.field === "rate_id" || err.field === "delivery" || err.field === "delivery.rate_id" || !err.field);
|
|
317
|
+
}
|
|
318
|
+
function matchRate(previous, rates) {
|
|
319
|
+
if (!previous) return null;
|
|
320
|
+
const norm = (s) => (s ?? "").trim().toLowerCase();
|
|
321
|
+
const sameCarrier = (r) => norm(r.carrier) === norm(previous.carrier);
|
|
322
|
+
if (previous.service_code) {
|
|
323
|
+
const hit = rates.find((r) => sameCarrier(r) && norm(r.service_code) === norm(previous.service_code));
|
|
324
|
+
if (hit) return hit;
|
|
325
|
+
}
|
|
326
|
+
return rates.find((r) => sameCarrier(r) && norm(r.title) === norm(previous.title)) ?? null;
|
|
327
|
+
}
|
|
328
|
+
var SR_ONLY = { position: "absolute", width: 1, height: 1, overflow: "hidden", clip: "rect(0 0 0 0)", whiteSpace: "nowrap" };
|
|
329
|
+
var useHydrated = () => react.useSyncExternalStore(
|
|
330
|
+
() => () => {
|
|
331
|
+
},
|
|
332
|
+
() => true,
|
|
333
|
+
() => false
|
|
334
|
+
);
|
|
335
|
+
function PickupGlyph({ size = 24 }) {
|
|
336
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 48 32", width: Math.round(size * 1.5), height: size, "aria-hidden": "true", focusable: "false", style: { flex: "none" }, "data-sf-brand-mark": "pickup", children: [
|
|
337
|
+
/* @__PURE__ */ jsxRuntime.jsx("rect", { x: "0.5", y: "0.5", width: "47", height: "31", rx: "5", fill: "var(--sf-brand-mark-bg, #E7E9EE)", stroke: "var(--sf-brand-mark-ring, rgb(127 127 127 / 0.35))" }),
|
|
338
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M15 13.5 17 9h14l2 4.5M15 13.5h18M15 13.5V23h18v-9.5M21 23v-5h6v5", fill: "none", stroke: "var(--sf-brand-mark-fg, #2B2F38)", strokeWidth: "1.8", strokeLinejoin: "round" })
|
|
339
|
+
] });
|
|
340
|
+
}
|
|
341
|
+
function DeliveryOptions(props) {
|
|
342
|
+
const {
|
|
343
|
+
rates,
|
|
344
|
+
pickup = [],
|
|
345
|
+
name = "delivery_choice",
|
|
346
|
+
rateValue = (r) => `rate:${r.id}`,
|
|
347
|
+
pickupValue = (b) => `pickup:${b.branch_id}`,
|
|
348
|
+
value,
|
|
349
|
+
onValueChange,
|
|
350
|
+
partial = false,
|
|
351
|
+
requoted = false,
|
|
352
|
+
loading = false,
|
|
353
|
+
timeZone,
|
|
354
|
+
marks = true,
|
|
355
|
+
badges: showBadges = true,
|
|
356
|
+
required = true,
|
|
357
|
+
renderAmount,
|
|
358
|
+
classNames: cx = {},
|
|
359
|
+
testId,
|
|
360
|
+
children
|
|
361
|
+
} = props;
|
|
362
|
+
const locale = useResolvedLocale(props.locale);
|
|
363
|
+
const m = react.useMemo(() => deliveryMessages(locale, props.messages), [locale, props.messages]);
|
|
364
|
+
const hydrated = useHydrated();
|
|
365
|
+
const badges = react.useMemo(() => showBadges ? rateBadges(rates) : /* @__PURE__ */ new Map(), [rates, showBadges]);
|
|
366
|
+
const firstValue = rates[0] ? rateValue(rates[0]) : null;
|
|
367
|
+
const defaultValue = props.defaultValue === void 0 ? firstValue : props.defaultValue;
|
|
368
|
+
const amount = (money) => Number(money.amount) === 0 ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cx.free, "data-sf-delivery-free": true, children: m.free }) : renderAmount ? renderAmount(money) : storefront.formatMoney(money, locale);
|
|
369
|
+
const mode = props.quoteNote ?? "always";
|
|
370
|
+
const deadline = mode === "never" ? null : quoteDeadline(rates);
|
|
371
|
+
const note = hydrated && deadline ? quoteNote(deadline, { locale, messages: m, ...timeZone ? { timeZone } : {} }) : null;
|
|
372
|
+
const shownNote = note && (mode === "always" || note.soon) ? note : null;
|
|
373
|
+
const radio = (v) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
374
|
+
"input",
|
|
375
|
+
{
|
|
376
|
+
type: "radio",
|
|
377
|
+
name,
|
|
378
|
+
value: v,
|
|
379
|
+
required,
|
|
380
|
+
className: cx.radio,
|
|
381
|
+
...value !== void 0 ? { checked: value === v, onChange: () => onValueChange?.(v) } : { defaultChecked: v === defaultValue, ...onValueChange ? { onChange: () => onValueChange(v) } : {} },
|
|
382
|
+
...testId ? { "data-testid": testId } : {}
|
|
383
|
+
}
|
|
384
|
+
);
|
|
385
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cx.root, "data-sf-delivery": true, "aria-busy": loading || void 0, children: [
|
|
386
|
+
partial ? /* @__PURE__ */ jsxRuntime.jsx("p", { role: "status", className: cx.partial, "data-sf-delivery-partial": true, children: m.partial }) : null,
|
|
387
|
+
requoted ? /* @__PURE__ */ jsxRuntime.jsx("p", { role: "status", className: cx.partial, "data-sf-delivery-requoted": true, children: m.requoted }) : null,
|
|
388
|
+
loading ? /* @__PURE__ */ jsxRuntime.jsx("span", { style: SR_ONLY, role: "status", "data-sf-delivery-loading": true, children: m.loading }) : null,
|
|
389
|
+
children,
|
|
390
|
+
loading && rates.length === 0 ? [0, 1, 2].map((i) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: cx.skeleton, "data-sf-delivery-skeleton": true, "aria-hidden": "true" }, i)) : null,
|
|
391
|
+
rates.map((rate) => {
|
|
392
|
+
const carrier = rateCarrier(rate);
|
|
393
|
+
const service = rateService(rate);
|
|
394
|
+
const eta = rateEta(rate, m);
|
|
395
|
+
const own = badges.get(rate.id) ?? [];
|
|
396
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("label", { className: cx.option, "data-sf-delivery-option": true, "data-loading": loading || void 0, children: [
|
|
397
|
+
radio(rateValue(rate)),
|
|
398
|
+
marks ? /* @__PURE__ */ jsxRuntime.jsx(BrandMark, { brand: rate.carrier ?? rate.provider ?? rate.title, size: 28, ...cx.mark ? { className: cx.mark } : {} }) : null,
|
|
399
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: cx.body, "data-sf-delivery-body": true, children: [
|
|
400
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cx.title, "data-sf-delivery-title": true, children: carrier ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
401
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cx.carrier, "data-sf-delivery-carrier": true, children: carrier }),
|
|
402
|
+
" ",
|
|
403
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cx.service, "data-sf-delivery-service": true, children: service })
|
|
404
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: cx.carrier, "data-sf-delivery-carrier": true, children: service }) }),
|
|
405
|
+
eta ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cx.eta, "data-sf-delivery-eta": true, children: eta }) : null,
|
|
406
|
+
own.length ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cx.badges, "data-sf-delivery-badges": true, children: own.map((b) => /* @__PURE__ */ jsxRuntime.jsx("span", { className: cx.badge, "data-sf-delivery-badge": b, children: b === "cheapest" ? m.cheapest : m.fastest }, b)) }) : null
|
|
407
|
+
] }),
|
|
408
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cx.price, "data-sf-delivery-price": true, children: amount(rate.cost) })
|
|
409
|
+
] }, rate.id);
|
|
410
|
+
}),
|
|
411
|
+
pickup.map((b) => /* @__PURE__ */ jsxRuntime.jsxs("label", { className: cx.option, "data-sf-delivery-option": true, "data-sf-delivery-pickup": true, children: [
|
|
412
|
+
radio(pickupValue(b)),
|
|
413
|
+
marks ? /* @__PURE__ */ jsxRuntime.jsx(PickupGlyph, { size: 28 }) : null,
|
|
414
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: cx.body, "data-sf-delivery-body": true, children: [
|
|
415
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cx.title, "data-sf-delivery-title": true, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: cx.carrier, "data-sf-delivery-carrier": true, children: m.pickupTitle.replace("{name}", b.name) }) }),
|
|
416
|
+
b.address || b.city ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cx.eta, "data-sf-delivery-eta": true, children: [b.address, b.city].filter(Boolean).join(", ") }) : null
|
|
417
|
+
] }),
|
|
418
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cx.price, "data-sf-delivery-price": true, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: cx.free, "data-sf-delivery-free": true, children: m.free }) })
|
|
419
|
+
] }, b.branch_id)),
|
|
420
|
+
deadline ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: cx.note, "data-sf-delivery-note": true, "data-soon": shownNote?.soon || void 0, "aria-live": "polite", children: shownNote?.text ?? "" }) : null
|
|
421
|
+
] });
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
exports.BrandMark = BrandMark;
|
|
425
|
+
exports.DeliveryOptions = DeliveryOptions;
|
|
426
|
+
exports.brandKey = brandKey;
|
|
427
|
+
exports.brandName = brandName;
|
|
428
|
+
exports.deliveryMessages = deliveryMessages;
|
|
429
|
+
exports.findBrand = findBrand;
|
|
430
|
+
exports.isQuoteChange = isQuoteChange;
|
|
431
|
+
exports.listBrands = listBrands;
|
|
432
|
+
exports.matchRate = matchRate;
|
|
433
|
+
exports.quoteDeadline = quoteDeadline;
|
|
434
|
+
exports.quoteNote = quoteNote;
|
|
435
|
+
exports.rateBadges = rateBadges;
|
|
436
|
+
exports.rateCarrier = rateCarrier;
|
|
437
|
+
exports.rateEta = rateEta;
|
|
438
|
+
exports.rateService = rateService;
|
|
439
|
+
//# sourceMappingURL=checkout.cjs.map
|
|
440
|
+
//# sourceMappingURL=checkout.cjs.map
|