@asteby/storefront-react 0.11.0 → 0.12.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 CHANGED
@@ -520,6 +520,10 @@ export const pay = createEmbeddedPayHandlers({
520
520
 
521
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
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
+ - El formulario de tarjeta se abre justo debajo de su fila (no al final de todas), con el correo del formulario de la página ya puesto (`payerEmailField`, por omisión `email`): el Brick no vuelve a pedirlo. En página oscura monta el tema base `dark` del proveedor (`readPaymentScheme`: token `--sf-pay-scheme` o `color-scheme`), refinado con los tokens `--sf-pay-*` (texto, fondos, contorno, radios, relleno).
524
+ - La elección se recuerda por carrito (`scope`) en `sessionStorage` (`rememberChoice`, por omisión sí): recargar, volver con «atrás» desde el proveedor o pasar por el paso de dirección no pide elegir de nuevo; si la fila ya no se publica, vuelve el valor por omisión del servidor. Solo se guarda el valor de la fila y el punto de efectivo.
525
+ - `cashPointsVisible={4}` deja a la vista los primeros puntos de efectivo y manda el resto a «Ver más puntos de pago» (se abre solo si el punto recordado está ahí).
526
+ - Botón: «Generar ficha de pago $X» con efectivo (`placeOrderCash`) y «Elige la entrega para continuar» mientras falta la entrega (`chooseDelivery`; al pulsarlo señala el campo que falta en vez de pagar).
523
527
 
524
528
  ## Entrega y marcas (`@asteby/storefront-react/checkout`)
525
529
 
@@ -536,8 +540,29 @@ import '@asteby/storefront-react/checkout.css' // opcional: disposición, insign
536
540
  </fieldset>
537
541
  ```
538
542
 
543
+ Cotizaciones largas (`layout="recommended"`): con 10+ servicios, la lista plana obliga a comparar todo. Con `layout="recommended"` se ven hasta tres tarifas (`recommendedCount`) con su etiqueta: la más económica, la más rápida y la de mejor equilibrio precio-tiempo («Recomendado»); el resto queda en «Ver más opciones (N)» (`<details>`, funciona sin JavaScript) agrupado por paquetería, con la marca y el nombre UNA vez por grupo (cada radio conserva su nombre completo para lectores de pantalla). Los servicios repetidos (misma paquetería y servicio cotizados por dos proveedores) se quedan con el más barato. Si la tarifa elegida está dentro, la lista se abre sola (también en el HTML del servidor). La lógica pura está en `recommendRates()` / `dedupeRates()`. `error` (+ `onRetry`) muestra un aviso amable con «Intentar de nuevo» cuando no se pudo cotizar.
544
+
539
545
  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
546
 
547
+ ### Campos, validación en línea y resumen del pedido
548
+
549
+ Piezas del formulario de pago iguales en todas las tiendas (también en `@asteby/storefront-react/checkout`):
550
+
551
+ - `ContactFields` y `AddressFields`: correo (`type="email"`, `inputMode="email"`), teléfono (`tel`), nombre (`given-name`) y apellidos (`family-name`); dirección en el orden en que se llena en México: código postal primero, estado, ciudad o municipio, colonia (`address-level3`, campo propio `neighborhood` de la API), calle y número, número interior (opcional) y referencias (opcional, `reference`). Sin país escrito en el código: el formato del código postal (`postalCode={{ pattern, maxLength, inputMode, title }}`), la lista de estados (`provinces`, de la configuración de la región) y la consulta por código postal (`lookupPostalCode`, una ruta propia sobre un catálogo) los pone la tienda. Con la consulta, estado y ciudad se llenan solos (nunca sobre lo que el comprador escribió) y las colonias salen como sugerencias (`<datalist>`). Sin ella, son campos de texto normales.
552
+ - `useFieldErrors(formRef)` + `CheckoutField` + `ErrorSummary`: validación en línea con las reglas del propio HTML (`required`, `type`, `pattern`…). Al salir de un campo con un valor inválido aparece el texto debajo del campo (`aria-invalid`, `aria-describedby`); se borra al corregirlo. Al enviar (o con `reportValidity()`, que usa `PaymentMethodSection`) los globos del navegador se reemplazan por los textos en línea y un resumen enfocable con enlaces a cada campo (WCAG 3.3.1). Los campos que rechace el servidor (`serverFields`) salen igual. Sin JavaScript, el navegador valida como siempre.
553
+ - `OrderSummary`: líneas y totales de `cart.cost` tal cual (subtotal, descuentos por código, envío «Al elegir la entrega» / «Actualizando…» / «Gratis», impuestos aparte o «Incluye $X de impuestos», total con `aria-live`). `OrderSummaryDisclosure` lo envuelve para teléfono: barra plegada arriba con el total («Ver resumen del pedido · $857.82»), `<details>` nativo, sin salto al hidratar. La tienda la muestra solo en pantallas angostas y el resumen fijo (`sticky`) en escritorio.
554
+
555
+ ```tsx
556
+ const v = useFieldErrors(formRef, { serverFields: actionData?.fields })
557
+ <ErrorSummary items={v.summary} focusKey={v.summaryKey} />
558
+ <ContactFields errors={v.errors} defaults={{ email: cart.buyer.email }} />
559
+ <AddressFields errors={v.errors} countryCode="MX" defaults={cart.shipping_address}
560
+ postalCode={{ pattern: '[0-9]{5}', maxLength: 5, inputMode: 'numeric', title: 'Escribe los 5 dígitos.' }} />
561
+ <OrderSummaryDisclosure total={cart.cost.total} className="lg:hidden">
562
+ <OrderSummary title={false} lines={cart.lines} cost={cart.cost} />
563
+ </OrderSummaryDisclosure>
564
+ ```
565
+
541
566
  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. Precedencia de lo que dibuja `<BrandMark>`: `logo_url` https del proveedor > logo real incluido > insignia tipográfica de respaldo (marcas sin logo disponible) > monograma neutro (marca desconocida). Los logos reales van incrustados como data URI (cero peticiones a terceros, mismo tamaño en servidor y navegador), sin recolorear, sobre una placa blanca con filo sutil para que se lean igual en tema claro y oscuro (`--sf-brand-mark-plate` y `--sf-brand-mark-ring` la ajustan). El elemento lleva `data-sf-brand-mark="<clave>"` y `data-sf-brand-source="provider|logo|badge"`; con `title` se anuncia con el nombre comercial, sin él es decorativo.
542
567
 
543
568
  **Procedencia de los logos.** Son marcas registradas de sus titulares y se muestran sin alteración solo para identificar el servicio o método de pago que la tienda ofrece, sin sugerir patrocinio; cada tienda debe respetar las guías de marca de cada titular. Fuente, licencia, fecha y versión (color/monocroma) de cada uno, y las marcas que quedaron con insignia por no tener fuente con condiciones claras, están en `src/checkout/brands/LOGOS.md` (se regenera con `node scripts/build-logos.mjs`). Para usar un logo propio o licenciado: `<BrandMark brand="redpack" logoUrl="https://cdn.mitienda.mx/redpack.svg" title="Redpack" />`; en pagos, `PaymentPoint.logo_url`. Solo se acepta `https:`.