@asteby/storefront-react 0.11.1 → 0.13.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.
@@ -1,6 +1,155 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode } from 'react';
3
- import { ShippingRate, PickupOption, Money } from '@asteby/storefront';
3
+ import { Address, CartLine, CartCost, Money, ShippingRate, PickupOption } from '@asteby/storefront';
4
+ import { F as FieldErrors, g as FieldMessages, a as CheckoutFieldClassNames } from './fields-vnMUi2HB.js';
5
+ export { C as CheckoutField, b as CheckoutFieldProps, c as CheckoutSelectProps, E as ErrorSummary, d as ErrorSummaryItem, e as ErrorSummaryProps, f as FieldErrorsState, U as UseFieldErrorsOptions, h as fieldMessages, u as useFieldErrors, v as validationMessage } from './fields-vnMUi2HB.js';
6
+
7
+ type AddressFieldKey = 'zip' | 'province' | 'city' | 'neighborhood' | 'address1' | 'address2' | 'reference';
8
+ type ContactFieldKey = 'email' | 'phone' | 'first_name' | 'last_name';
9
+ type AddressFieldsMessages = Record<AddressFieldKey | ContactFieldKey, string> & {
10
+ provincePlaceholder: string;
11
+ address1Hint: string;
12
+ referenceHint: string;
13
+ emailHint: string;
14
+ phoneHint: string;
15
+ lookupFilled: string;
16
+ };
17
+ declare function addressFieldsMessages(locale?: string | null, overrides?: Partial<AddressFieldsMessages> | null): AddressFieldsMessages;
18
+ type FieldLayoutClassNames = CheckoutFieldClassNames & {
19
+ /** Extra class of a field that should span the whole row in a two-column grid. */
20
+ wide?: string;
21
+ /** Extra class of a field that fits half a row. */
22
+ half?: string;
23
+ };
24
+ type Common = {
25
+ /** Inline errors by field name (`useFieldErrors().errors`). */
26
+ errors?: FieldErrors;
27
+ locale?: string;
28
+ messages?: Partial<AddressFieldsMessages>;
29
+ fieldMessages?: Partial<FieldMessages>;
30
+ classNames?: FieldLayoutClassNames;
31
+ };
32
+ type ContactFieldsProps = Common & {
33
+ defaults?: Partial<Record<ContactFieldKey, string | null>>;
34
+ /** Form names. Default: the keys. */
35
+ names?: Partial<Record<ContactFieldKey, string>>;
36
+ /** Phone format from the shop or region (e.g. `{ pattern: '[0-9 +()-]{10,}', title: '10 dígitos' }`). */
37
+ phone?: {
38
+ pattern?: string;
39
+ title?: string;
40
+ minLength?: number;
41
+ };
42
+ /** Explain why e-mail and phone are needed (default true). */
43
+ hints?: boolean;
44
+ };
45
+ /** E-mail, phone, given and family name with their autofill tokens and the right mobile keyboards. */
46
+ declare function ContactFields({ defaults, names, errors, phone, hints, locale, messages, fieldMessages: fm, classNames: cx }: ContactFieldsProps): react.JSX.Element;
47
+ /** What a postal-code lookup answers. Every field optional: only what the source knows. */
48
+ type PostalCodeInfo = {
49
+ province?: string | null;
50
+ city?: string | null;
51
+ neighborhoods?: readonly string[] | null;
52
+ };
53
+ type AddressFieldsProps = Common & {
54
+ defaults?: Partial<Pick<Address, 'zip' | 'province' | 'city' | 'neighborhood' | 'address1' | 'address2' | 'reference'>> | null;
55
+ /** Form names. Default: the keys (the `AddressInput` fields of the Storefront API). */
56
+ names?: Partial<Record<AddressFieldKey, string>>;
57
+ /** ISO country of the address (hidden field `country_code`). */
58
+ countryCode: string;
59
+ /** States of the country (from the region config). With them, "State" is a `<select>`; the value sent is `name`. */
60
+ provinces?: ReadonlyArray<{
61
+ code?: string | null;
62
+ name: string;
63
+ }> | null;
64
+ /** Postal-code format of the country (from the region config), e.g. `{ pattern: '[0-9]{5}', maxLength: 5, inputMode: 'numeric', title: '5 dígitos' }`. */
65
+ postalCode?: {
66
+ pattern?: string;
67
+ maxLength?: number;
68
+ inputMode?: 'numeric' | 'text';
69
+ title?: string;
70
+ };
71
+ /**
72
+ * Fills state and city (and suggests colonias) from the postal code, when the shop has a source (a same-origin
73
+ * route over a postal-code catalog). Called once the code matches `postalCode.pattern` (or on leaving the field).
74
+ * Never overwrites what the buyer typed.
75
+ */
76
+ lookupPostalCode?: (zip: string) => Promise<PostalCodeInfo | null>;
77
+ /** Show the colonia field: `true` (default, optional), `'required'`, or `false`. */
78
+ neighborhood?: boolean | 'required';
79
+ /** Show the delivery references field (default true, optional). */
80
+ reference?: boolean;
81
+ /** Rendered after the fields (e.g. "save this address"). */
82
+ children?: ReactNode;
83
+ };
84
+ /**
85
+ * Shipping address in the order buyers fill it: postal code, state, city, colonia, street and number, interior and
86
+ * references. Autofill tokens: `postal-code`, `address-level1/2/3`, `address-line1/2`. The postal code uses the
87
+ * numeric keyboard when the country format is numeric.
88
+ */
89
+ declare function AddressFields(props: AddressFieldsProps): react.JSX.Element;
90
+
91
+ type OrderSummaryMessages = {
92
+ title: string;
93
+ subtotal: string;
94
+ discount: string;
95
+ shipping: string;
96
+ /** Shipping not chosen yet. */
97
+ shippingPending: string;
98
+ /** Shipping being saved / re-read. */
99
+ updating: string;
100
+ free: string;
101
+ taxes: string;
102
+ /** Taxes already inside the prices, `{amount}`. */
103
+ taxesIncluded: string;
104
+ total: string;
105
+ /** `{n}` = quantity. */
106
+ quantity: string;
107
+ show: string;
108
+ hide: string;
109
+ };
110
+ declare function orderSummaryMessages(locale?: string | null, overrides?: Partial<OrderSummaryMessages> | null): OrderSummaryMessages;
111
+ type OrderSummaryClassNames = Partial<Record<'root' | 'title' | 'lines' | 'line' | 'media' | 'qty' | 'lineTitle' | 'variant' | 'linePrice' | 'totals' | 'row' | 'discount' | 'muted' | 'free' | 'total' | 'note', string>>;
112
+ type OrderSummaryProps = {
113
+ lines: readonly CartLine[];
114
+ /** `cart.cost` as the server sends it. */
115
+ cost: CartCost;
116
+ /** The delivery is being saved and the cart re-read: shipping and total say so (`aria-busy`). */
117
+ updating?: boolean;
118
+ /** Picture of a line (e.g. `<ProductImage>`), 48-64 px. The quantity badge sits on it. */
119
+ renderLineMedia?: (line: CartLine) => ReactNode;
120
+ renderAmount?: (amount: Money) => ReactNode;
121
+ /** Heading. `false` hides it (the disclosure already names the block). */
122
+ title?: ReactNode | false;
123
+ /** Heading level. Default 2. */
124
+ headingLevel?: 2 | 3;
125
+ locale?: string;
126
+ messages?: Partial<OrderSummaryMessages>;
127
+ classNames?: OrderSummaryClassNames;
128
+ /** Rendered between the lines and the totals (e.g. a discount code form). */
129
+ children?: ReactNode;
130
+ };
131
+ /** Lines and totals of the order. The total row is `aria-live`, so a new total after choosing delivery is announced. */
132
+ declare function OrderSummary(props: OrderSummaryProps): react.JSX.Element;
133
+ type OrderSummaryDisclosureProps = {
134
+ /** Total shown on the collapsed bar (`cart.cost.total`). */
135
+ total: Money;
136
+ updating?: boolean;
137
+ renderAmount?: (amount: Money) => ReactNode;
138
+ locale?: string;
139
+ messages?: Partial<OrderSummaryMessages>;
140
+ /** Start open (default closed). */
141
+ defaultOpen?: boolean;
142
+ className?: string;
143
+ classNames?: Partial<Record<'summary' | 'label' | 'total' | 'panel', string>>;
144
+ /** Usually an `<OrderSummary title={false} … />`. */
145
+ children: ReactNode;
146
+ };
147
+ /**
148
+ * Phones: the order summary as a collapsed bar at the top ("Show order summary · $1,234.00"). Native `<details>`:
149
+ * works without JavaScript, the server HTML is already the final layout (no shift on hydration). Show it only on
150
+ * narrow screens and the full summary on wide ones (the shop's CSS).
151
+ */
152
+ declare function OrderSummaryDisclosure({ total, updating, renderAmount, locale: loc, messages, defaultOpen, className, classNames: cx, children }: OrderSummaryDisclosureProps): react.JSX.Element;
4
153
 
5
154
  type BrandMarkProps = {
6
155
  /** Provider identifier (`fedex`, `oxxo`, `mercadopago`, `7eleven`…). Unknown keys get a neutral monogram. */
@@ -61,7 +210,7 @@ type Brand = {
61
210
  /** Short wordmark drawn in the badge (`\n` = two lines). Default: `name`. */
62
211
  mark?: string;
63
212
  /** Special drawings instead of a wordmark. */
64
- shape?: 'mastercard';
213
+ shape?: 'mastercard' | 'transfer';
65
214
  };
66
215
  /** `"FedEx México"`, `"fedex_mx"` and `"FEDEX"` all become `fedex`. Lowercase ASCII letters and digits only. */
67
216
  declare function brandKey(raw: string | null | undefined): string;
@@ -107,6 +256,15 @@ type DeliveryMessages = {
107
256
  loading: string;
108
257
  /** The quote expired or changed and the rates were reloaded. */
109
258
  requoted: string;
259
+ /** Tag of the recommended rate that balances price and arrival time (`layout="recommended"`). */
260
+ bestValue: string;
261
+ /** Toggle of the other rates, `{n}` = how many. */
262
+ moreOptions: string;
263
+ /** Title of the group of rates without a carrier. */
264
+ otherCarriers: string;
265
+ /** The rates could not be quoted (`error`). */
266
+ error: string;
267
+ retry: string;
110
268
  };
111
269
  /** Messages for a locale (`es*` default, `en*`), with optional overrides. */
112
270
  declare function deliveryMessages(locale?: string | null, overrides?: Partial<DeliveryMessages> | null): DeliveryMessages;
@@ -159,7 +317,7 @@ declare function isQuoteChange(err: {
159
317
  */
160
318
  declare function matchRate<R extends Pick<ShippingRate, 'id' | 'carrier' | 'service_code' | 'title'>>(previous: Pick<ShippingRate, 'carrier' | 'service_code' | 'title'> | null | undefined, rates: readonly R[]): R | null;
161
319
 
162
- type DeliveryOptionsClassNames = Partial<Record<'root' | 'option' | 'radio' | 'mark' | 'body' | 'title' | 'carrier' | 'service' | 'eta' | 'badges' | 'badge' | 'price' | 'free' | 'note' | 'partial' | 'skeleton', string>>;
320
+ type DeliveryOptionsClassNames = Partial<Record<'root' | 'option' | 'radio' | 'mark' | 'body' | 'title' | 'carrier' | 'service' | 'eta' | 'badges' | 'badge' | 'price' | 'free' | 'note' | 'partial' | 'skeleton' | 'more' | 'moreSummary' | 'group' | 'groupTitle' | 'error' | 'retry', string>>;
163
321
  type DeliveryOptionsProps = {
164
322
  rates: readonly ShippingRate[];
165
323
  pickup?: readonly PickupOption[];
@@ -193,6 +351,21 @@ type DeliveryOptionsProps = {
193
351
  messages?: Partial<DeliveryMessages>;
194
352
  renderAmount?: (amount: Money) => ReactNode;
195
353
  classNames?: DeliveryOptionsClassNames;
354
+ /**
355
+ * `list` (default): every rate, as the server orders them. `recommended`: up to `recommendedCount` rates (cheapest,
356
+ * fastest and the best balance, tagged) and the rest under "Show more options (N)", grouped by carrier so the carrier
357
+ * name is not repeated on every row. Repeated services are dropped (the cheapest stays). Works without JavaScript
358
+ * (`<details>`); it opens by itself when the chosen rate is inside.
359
+ */
360
+ layout?: 'list' | 'recommended';
361
+ /** Rates recommended in `layout="recommended"`. Default 3. */
362
+ recommendedCount?: number;
363
+ /**
364
+ * The rates could not be quoted (provider down, timeout): one friendly alert instead of the list, with a retry button
365
+ * when `onRetry` is set. `true` uses the default text; a string replaces it.
366
+ */
367
+ error?: boolean | string;
368
+ onRetry?: () => void;
196
369
  /** `data-testid` of every radio. */
197
370
  testId?: string;
198
371
  /** Rows the shop renders before the rates (e.g. "home delivery, rates after the address"). */
@@ -209,4 +382,55 @@ type DeliveryOptionsProps = {
209
382
  */
210
383
  declare function DeliveryOptions(props: DeliveryOptionsProps): react.JSX.Element;
211
384
 
212
- export { type Brand, type BrandKind, BrandMark, type BrandMarkProps, type BrandMarkSource, type DeliveryMessages, DeliveryOptions, type DeliveryOptionsClassNames, type DeliveryOptionsProps, type QuoteNote, type RateBadge, brandKey, brandLogo, brandName, deliveryMessages, findBrand, isQuoteChange, listBrands, matchRate, quoteDeadline, quoteNote, rateBadges, rateCarrier, rateEta, rateService };
385
+ /**
386
+ * Which carrier rates to show first. Pure: no DOM, no amounts computed (costs are only compared, as the server sends
387
+ * them). A long quote (10+ services, several per carrier) becomes up to three recommended rows (the cheapest, the
388
+ * fastest and the best balance of both) plus the rest grouped by carrier, so the buyer compares three things instead of
389
+ * scanning a flat list.
390
+ */
391
+
392
+ /** Why a rate is recommended. `best_value` balances price and arrival time. */
393
+ type RateTag = 'cheapest' | 'fastest' | 'best_value';
394
+ type RecommendedRate<R extends ShippingRate = ShippingRate> = {
395
+ rate: R;
396
+ tags: RateTag[];
397
+ };
398
+ type RateGroup<R extends ShippingRate = ShippingRate> = {
399
+ /** Brand key of the carrier (`fedex`), or `''` for rates without one. */
400
+ key: string;
401
+ /** Carrier as the server sends it (first rate of the group), for `BrandMark` and the group name. */
402
+ carrier: string | null;
403
+ rates: R[];
404
+ };
405
+ type RecommendRatesOptions = {
406
+ /** How many rates to recommend. Default 3. */
407
+ count?: number;
408
+ /**
409
+ * With this many rates or fewer every rate is recommended (no "more options"): hiding one or two rates behind a
410
+ * toggle costs more than it saves. Default `count + 1`.
411
+ */
412
+ collapseAfter?: number;
413
+ /** Drop repeated services (same carrier and service, e.g. quoted by two providers), keeping the cheapest. Default true. */
414
+ dedupe?: boolean;
415
+ };
416
+ type RecommendedRates<R extends ShippingRate = ShippingRate> = {
417
+ recommended: RecommendedRate<R>[];
418
+ /** Everything else, grouped by carrier; groups ordered by their cheapest rate, rates by cost. */
419
+ more: RateGroup<R>[];
420
+ /** Number of rates in `more`. */
421
+ moreCount: number;
422
+ };
423
+ /** Repeated services (same carrier, same service code or title, same arrival): only the cheapest stays. Order kept. */
424
+ declare function dedupeRates<R extends ShippingRate>(rates: readonly R[]): R[];
425
+ /**
426
+ * Up to `count` recommended rates and the rest by carrier.
427
+ * - **cheapest**: lowest cost (only when every rate shares the currency); a tie goes to the faster one.
428
+ * - **fastest**: fewest business days; a tie goes to the cheaper one. Only when some rate is strictly faster than the
429
+ * cheapest, so the tag always tells the buyer something.
430
+ * - **best_value**: the remaining rate with the best combined position in price and in time (sum of ranks), a tie goes
431
+ * to the cheaper one. Fills the remaining slots.
432
+ * Recommended rows come back cheapest first. Pickup is not a rate and is never hidden (the component shows it apart).
433
+ */
434
+ declare function recommendRates<R extends ShippingRate>(input: readonly R[], options?: RecommendRatesOptions): RecommendedRates<R>;
435
+
436
+ export { type AddressFieldKey, AddressFields, type AddressFieldsMessages, type AddressFieldsProps, type Brand, type BrandKind, BrandMark, type BrandMarkProps, type BrandMarkSource, CheckoutFieldClassNames, type ContactFieldKey, ContactFields, type ContactFieldsProps, type DeliveryMessages, DeliveryOptions, type DeliveryOptionsClassNames, type DeliveryOptionsProps, FieldErrors, type FieldLayoutClassNames, FieldMessages, OrderSummary, type OrderSummaryClassNames, OrderSummaryDisclosure, type OrderSummaryDisclosureProps, type OrderSummaryMessages, type OrderSummaryProps, type PostalCodeInfo, type QuoteNote, type RateBadge, type RateGroup, type RateTag, type RecommendRatesOptions, type RecommendedRate, type RecommendedRates, addressFieldsMessages, brandKey, brandLogo, brandName, dedupeRates, deliveryMessages, findBrand, isQuoteChange, listBrands, matchRate, orderSummaryMessages, quoteDeadline, quoteNote, rateBadges, rateCarrier, rateEta, rateService, recommendRates };