@nevios/storefront-kit 0.1.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.
@@ -0,0 +1,931 @@
1
+ import * as React from 'react';
2
+ import { StorefrontClient, Money, Product, ProductMedia, ProductVariant, CollectionDetail, ProductSort, Cart, AddLineInput, CartLine, Checkout, CreateCheckoutInput, SetAddressInput, ShippingQuote, PaymentMethod, OrderStatus, Customer, MagicLinkResult, ReorderResult } from '@nevios/storefront-js';
3
+
4
+ /**
5
+ * NeviosProvider — puts a configured storefront client on React context so
6
+ * every kit component + hook can reach it. Wrap your app once at the root.
7
+ *
8
+ * import { createStorefrontClient } from "@nevios/storefront-js";
9
+ * import { NeviosProvider } from "@nevios/storefront-kit";
10
+ *
11
+ * const client = createStorefrontClient({ publishableKey, market });
12
+ * <NeviosProvider client={client}>{children}</NeviosProvider>
13
+ */
14
+
15
+ interface NeviosProviderProps {
16
+ client: StorefrontClient;
17
+ children: React.ReactNode;
18
+ }
19
+ declare function NeviosProvider({ client, children }: NeviosProviderProps): React.ReactElement;
20
+ /** Access the storefront client from any kit component / hook. */
21
+ declare function useStorefront(): StorefrontClient;
22
+ /** Non-throwing client access — returns null when no <NeviosProvider> is
23
+ * mounted. For presentational components that want optional client config
24
+ * (e.g. `imageBase` for responsive images) but must still render standalone. */
25
+ declare function useStorefrontOptional(): StorefrontClient | null;
26
+
27
+ /**
28
+ * Theme contract — the customization surface (layer 1) merchants edit in
29
+ * `nevios.config.ts`. Tokens are injected as CSS custom properties on a
30
+ * wrapper, so every kit component reads `var(--nv-…)` and re-skins with zero
31
+ * code. Mirrors the internal `/design` token model, pointed outward.
32
+ *
33
+ * <ThemeProvider theme={{ brand: "#b1442e", radius: "12px" }}>
34
+ * {storefront}
35
+ * </ThemeProvider>
36
+ */
37
+
38
+ /** The full token set. All optional — unset tokens fall back to defaults. */
39
+ interface StorefrontTheme {
40
+ /** Primary brand / CTA color. */
41
+ brand?: string;
42
+ brandForeground?: string;
43
+ background?: string;
44
+ foreground?: string;
45
+ muted?: string;
46
+ border?: string;
47
+ /** Corner radius for cards/inputs/buttons. */
48
+ radius?: string;
49
+ /** Base font family. */
50
+ fontFamily?: string;
51
+ }
52
+ /** Resolve a theme into the CSS-var style object the provider applies. */
53
+ declare function themeToCssVars(theme?: StorefrontTheme): React.CSSProperties;
54
+ interface ThemeProviderProps {
55
+ theme?: StorefrontTheme;
56
+ children: React.ReactNode;
57
+ /** Wrapper element (default `div`). */
58
+ as?: keyof React.JSX.IntrinsicElements;
59
+ }
60
+ declare function ThemeProvider({ theme, children, as: Tag, }: ThemeProviderProps): React.ReactElement;
61
+
62
+ /**
63
+ * English message bundle — the canonical key set. Every other locale bundle is
64
+ * typed as `Messages` (a `Record<MessageKey, string>`), so the compiler forces
65
+ * it to define exactly these keys: a missing or stray key is a type error.
66
+ *
67
+ * Keys are dot-namespaced by surface (`cart.*`, `checkout.*`, `order.*`).
68
+ * `{name}` placeholders are interpolated by `t(key, { name })`. Plural keys end
69
+ * in a CLDR category (`.one` / `.few` / `.many` / `.other`); call them via the
70
+ * base key with a `count` var — `t("shipping.days", { count })` — and the
71
+ * provider picks the category for the active locale via `Intl.PluralRules`.
72
+ */
73
+ declare const en: {
74
+ "common.free": string;
75
+ "common.close": string;
76
+ "common.loadingShort": string;
77
+ "catalog.addToCart": string;
78
+ "catalog.noProducts": string;
79
+ "catalog.soldOut": string;
80
+ "catalog.addError": string;
81
+ "catalog.inStock": string;
82
+ "catalog.preorder": string;
83
+ "catalog.filters.sort": string;
84
+ "catalog.filters.sortNewest": string;
85
+ "catalog.filters.sortOldest": string;
86
+ "catalog.filters.sortTitleAsc": string;
87
+ "catalog.filters.sortTitleDesc": string;
88
+ "catalog.filters.sortPriceAsc": string;
89
+ "catalog.filters.sortPriceDesc": string;
90
+ "catalog.filters.priceRange": string;
91
+ "catalog.filters.min": string;
92
+ "catalog.filters.max": string;
93
+ "catalog.filters.tags": string;
94
+ "catalog.filters.inStockOnly": string;
95
+ "catalog.filters.clear": string;
96
+ "catalog.backInStock.prompt": string;
97
+ "catalog.backInStock.email": string;
98
+ "catalog.backInStock.notify": string;
99
+ "catalog.backInStock.success": string;
100
+ "catalog.backInStock.error": string;
101
+ "cart.title": string;
102
+ "cart.empty": string;
103
+ "cart.remove": string;
104
+ "cart.increaseQty": string;
105
+ "cart.decreaseQty": string;
106
+ "cart.checkout": string;
107
+ "cart.subtotal": string;
108
+ "cart.tax": string;
109
+ "cart.total": string;
110
+ "totals.subtotal": string;
111
+ "totals.discount": string;
112
+ "totals.shipping": string;
113
+ "totals.paymentFee": string;
114
+ "totals.taxIncluded": string;
115
+ "totals.total": string;
116
+ "checkout.stepAddress": string;
117
+ "checkout.stepShipping": string;
118
+ "checkout.stepPayment": string;
119
+ "checkout.loading": string;
120
+ "checkout.empty": string;
121
+ "checkout.shippingAddress": string;
122
+ "checkout.continueToShipping": string;
123
+ "checkout.email": string;
124
+ "checkout.firstName": string;
125
+ "checkout.lastName": string;
126
+ "checkout.company": string;
127
+ "checkout.address": string;
128
+ "checkout.apartment": string;
129
+ "checkout.city": string;
130
+ "checkout.postalCode": string;
131
+ "checkout.country": string;
132
+ "checkout.phone": string;
133
+ "checkout.shippingMethod": string;
134
+ "checkout.continueToPayment": string;
135
+ "checkout.loadingShipping": string;
136
+ "checkout.noShipping": string;
137
+ "checkout.payment": string;
138
+ "checkout.loadingPayment": string;
139
+ "checkout.noPayment": string;
140
+ "checkout.payNow": string;
141
+ "checkout.placeOrder": string;
142
+ "checkout.gatewayRedirectNote": string;
143
+ "checkout.thankYou": string;
144
+ "checkout.orderPlacedBody": string;
145
+ "shipping.days.one": string;
146
+ "shipping.days.few": string;
147
+ "shipping.days.many": string;
148
+ "shipping.days.other": string;
149
+ "shipping.daysRange": string;
150
+ "order.title": string;
151
+ "order.placedOn": string;
152
+ "order.loading": string;
153
+ "order.loadError": string;
154
+ "order.notFound": string;
155
+ "order.confirmLoading": string;
156
+ "order.confirmLoadError": string;
157
+ "order.confirmed": string;
158
+ "order.items": string;
159
+ "order.shipping": string;
160
+ "order.shipsTo": string;
161
+ "order.tracking": string;
162
+ "order.payment": string;
163
+ "order.method": string;
164
+ "order.status": string;
165
+ "order.downloadInvoice": string;
166
+ "order.contactSupport": string;
167
+ "order.trackOrder": string;
168
+ "order.phase.placed": string;
169
+ "order.phase.paid": string;
170
+ "order.phase.fulfilled": string;
171
+ "order.phase.shipped": string;
172
+ "order.phase.delivered": string;
173
+ "order.terminal.cancelled": string;
174
+ "order.terminal.refunded": string;
175
+ "order.terminal.returned": string;
176
+ "error.notFound.title": string;
177
+ "error.notFound.body": string;
178
+ "error.generic.title": string;
179
+ "error.generic.body": string;
180
+ "error.home": string;
181
+ "account.title": string;
182
+ "account.signIn": string;
183
+ "account.signInBlurb": string;
184
+ "account.email": string;
185
+ "account.sendLink": string;
186
+ "account.checkEmail": string;
187
+ "account.signOut": string;
188
+ "account.greeting": string;
189
+ "account.orders": string;
190
+ "account.noOrders": string;
191
+ "account.addresses": string;
192
+ "account.noAddresses": string;
193
+ "account.viewOrder": string;
194
+ "account.verifying": string;
195
+ "account.verifyError": string;
196
+ "account.openDevLink": string;
197
+ "account.profile": string;
198
+ "account.editProfile": string;
199
+ "account.firstName": string;
200
+ "account.lastName": string;
201
+ "account.phone": string;
202
+ "account.acceptsMarketing": string;
203
+ "account.save": string;
204
+ "account.cancel": string;
205
+ "account.saved": string;
206
+ "account.saveError": string;
207
+ "account.addAddress": string;
208
+ "account.editAddress": string;
209
+ "account.deleteAddress": string;
210
+ "account.confirmDelete": string;
211
+ "account.setDefault": string;
212
+ "account.default": string;
213
+ "account.company": string;
214
+ "account.address": string;
215
+ "account.addressLine2": string;
216
+ "account.city": string;
217
+ "account.postalCode": string;
218
+ "account.country": string;
219
+ "account.reorder": string;
220
+ "account.reorderDone": string;
221
+ "account.reorderPartial": string;
222
+ "account.reorderError": string;
223
+ };
224
+ /** Every message key, derived from the English bundle (the source of truth). */
225
+ type MessageKey = keyof typeof en;
226
+ /** A complete message bundle for one locale. */
227
+ type Messages = Record<MessageKey, string>;
228
+
229
+ /**
230
+ * I18nProvider + useT — the kit's translation layer. UI strings are bundled
231
+ * (zero network calls); product/collection *content* is localized server-side
232
+ * via the SDK's `X-Locale`. Wrap your app once with the resolved locale:
233
+ *
234
+ * <I18nProvider locale="cs-CZ">{app}</I18nProvider> // auto-picks the cs pack
235
+ * <I18nProvider locale="fr-FR" messages={fr}>… // bring your own pack
236
+ *
237
+ * Components call `const t = useT()` and `t("checkout.payNow")`. Pluralize with
238
+ * a `count` var — `t("shipping.days", { count })` — resolved via Intl.PluralRules
239
+ * for the active locale. With no provider mounted, `useT` falls back to English,
240
+ * so kit components never crash un-wrapped.
241
+ */
242
+
243
+ type TVars = Record<string, string | number>;
244
+ type TFunction = (key: MessageKey | (string & {}), vars?: TVars) => string;
245
+ /** Pick a bundled pack by language subtag ("cs-CZ" → cs); default English. */
246
+ declare function bundledMessages(locale?: string): Messages;
247
+ interface I18nValue {
248
+ locale: string;
249
+ messages: Messages;
250
+ t: TFunction;
251
+ }
252
+ interface I18nProviderProps {
253
+ /** BCP-47 locale — drives pluralization + (when `messages` is omitted) which
254
+ * bundled pack is used. */
255
+ locale?: string;
256
+ /** Override / extend the messages. Merged over the bundled pack for `locale`,
257
+ * so you can ship custom copy or add a locale the kit doesn't bundle. */
258
+ messages?: Partial<Messages>;
259
+ children: React.ReactNode;
260
+ }
261
+ declare function I18nProvider({ locale, messages, children, }: I18nProviderProps): React.ReactElement;
262
+ /** Full i18n context — locale + messages + t. Falls back to English when no
263
+ * <I18nProvider> is mounted. */
264
+ declare function useI18n(): I18nValue;
265
+ /** The translate function for the active locale. */
266
+ declare function useT(): TFunction;
267
+
268
+ /**
269
+ * Czech message bundle. Typed as `Messages`, so the compiler guarantees it
270
+ * stays in sync with the canonical English key set in `en.ts`. Czech uses four
271
+ * plural categories (one / few / many / other) — see `shipping.days.*`.
272
+ */
273
+
274
+ declare const cs: Messages;
275
+
276
+ /**
277
+ * MarketSwitcher — lets a shopper change market (and with it currency + locale).
278
+ * Headless about *how* you switch: pass `hrefFor` to navigate to each market's
279
+ * domain/path (the storefront resolves the market from there), or `onSelect`
280
+ * to handle it yourself (e.g. set a cookie + reload). Feed it the list from
281
+ * `client.markets()`.
282
+ *
283
+ * <MarketSwitcher markets={markets} current={market}
284
+ * hrefFor={(m) => m.domain ? `https://${m.domain}` : `/${m.handle}`} />
285
+ */
286
+
287
+ /** The minimal market shape the switcher needs. Both the SDK's
288
+ * `StorefrontMarket` (from `client.markets()`) and a hand-written config entry
289
+ * satisfy it — `label` wins for display, else `name (CURRENCY)`. */
290
+ interface MarketOption {
291
+ handle: string;
292
+ label?: string;
293
+ name?: string;
294
+ currency?: string;
295
+ locale?: string;
296
+ domain?: string | null;
297
+ }
298
+ interface MarketSwitcherProps {
299
+ markets: readonly MarketOption[];
300
+ /** Current market handle (the selected option). */
301
+ current?: string;
302
+ /** Map a market → the URL to switch to. When set, changing the select
303
+ * navigates there. */
304
+ hrefFor?: (market: MarketOption) => string;
305
+ /** Or handle the switch yourself (cookie + reload). Takes precedence over
306
+ * `hrefFor` if both are given. */
307
+ onSelect?: (market: MarketOption) => void;
308
+ /** Option label. Default: `label`, else `"Name (CURRENCY)"`, else handle. */
309
+ renderLabel?: (market: MarketOption) => string;
310
+ "aria-label"?: string;
311
+ className?: string;
312
+ style?: React.CSSProperties;
313
+ }
314
+ declare function MarketSwitcher({ markets, current, hrefFor, onSelect, renderLabel, "aria-label": ariaLabel, className, style, }: MarketSwitcherProps): React.ReactElement | null;
315
+
316
+ /**
317
+ * Money formatting + display. `formatMoney` is the headless helper; `PriceMoney`
318
+ * renders the display price with an optional struck-through compare-at.
319
+ */
320
+
321
+ /** Format minor units (cents) + currency → a localized string ("2 999,00 Kč"). */
322
+ declare function formatCents(cents: number, currency: string, locale?: string): string;
323
+ /** Format a Money → a localized currency string. */
324
+ declare function formatMoney(money: Money, locale?: string): string;
325
+ interface PriceMoneyProps {
326
+ money: Money;
327
+ /** Show the struck-through compare-at price when one is set. */
328
+ showCompareAt?: boolean;
329
+ /** Override the formatting locale (defaults to the I18nProvider locale). */
330
+ locale?: string;
331
+ }
332
+ declare function PriceMoney({ money, showCompareAt, locale, }: PriceMoneyProps): React.ReactElement;
333
+
334
+ /**
335
+ * ProductCard — a product tile for grids (collection pages, search). Image +
336
+ * title + price range. Presentational: pass a `Product`; pass `href` to make
337
+ * the whole tile a link to the PDP. Override via the slot registry to restyle
338
+ * just this without touching the rest.
339
+ */
340
+
341
+ interface ProductCardProps {
342
+ product: Product;
343
+ /** When set, the whole card links here (the eshop owns its URL scheme). */
344
+ href?: string;
345
+ locale?: string;
346
+ }
347
+ declare function ProductCard({ product, href, locale }: ProductCardProps): React.ReactElement;
348
+
349
+ /**
350
+ * ProductGallery — the PDP image gallery: a main image + thumbnail strip.
351
+ * Client-interactive (thumbnail selects the main image). Presentational data.
352
+ */
353
+
354
+ interface ProductGalleryProps {
355
+ media: ProductMedia[];
356
+ alt?: string;
357
+ }
358
+ declare function ProductGallery({ media, alt }: ProductGalleryProps): React.ReactElement;
359
+
360
+ /**
361
+ * VariantPicker — one selector row per product option (Color, Size…). Resolves
362
+ * the matching variant from the selected values and reports it via `onChange`,
363
+ * so the PDP knows which variant to price + add to cart. Defaults to the first
364
+ * variant. Single-option-less products (one default variant) render nothing.
365
+ */
366
+
367
+ interface VariantPickerProps {
368
+ product: Product;
369
+ onChange?: (variant: ProductVariant | null) => void;
370
+ }
371
+ declare function VariantPicker({ product, onChange }: VariantPickerProps): React.ReactElement | null;
372
+
373
+ /**
374
+ * ProductDetailPage — the PDP composition: gallery + title + live price for the
375
+ * selected variant + variant picker + an add-to-cart slot. Presentational:
376
+ * the Remix loader fetches the `Product`, this renders it. `addToCart` is a
377
+ * render slot the cart phase (P2) fills with an <AddToCart> bound to the
378
+ * currently-selected variant.
379
+ */
380
+
381
+ interface ProductDetailPageProps {
382
+ product: Product;
383
+ locale?: string;
384
+ /** Render slot for the add-to-cart control, bound to the selected variant. */
385
+ addToCart?: (variant: ProductVariant | null) => React.ReactNode;
386
+ }
387
+ declare function ProductDetailPage({ product, locale, addToCart, }: ProductDetailPageProps): React.ReactElement;
388
+
389
+ /**
390
+ * CollectionPage — collection header + a responsive grid of ProductCards in the
391
+ * collection's curated order. Presentational: the Remix loader fetches the
392
+ * `CollectionDetail` (collection + its products), this renders it. `productHref`
393
+ * lets the eshop own its URL scheme.
394
+ */
395
+
396
+ interface CollectionPageProps {
397
+ collection: CollectionDetail;
398
+ /** Map a product → its PDP URL (the eshop owns routing). */
399
+ productHref?: (product: Product) => string;
400
+ locale?: string;
401
+ }
402
+ declare function CollectionPage({ collection, productHref, locale, }: CollectionPageProps): React.ReactElement;
403
+
404
+ /**
405
+ * StockBadge — a small availability pill for a variant. Reads
406
+ * `variant.availability.status` (in_stock | preorder | out_of_stock) and renders
407
+ * a themed label. Renders nothing for an untracked in-stock variant when
408
+ * `hideInStock` is set (keeps the PDP quiet for always-available goods).
409
+ */
410
+
411
+ interface StockBadgeProps {
412
+ variant: ProductVariant | null;
413
+ /** Don't render anything when the variant is in stock (default false). */
414
+ hideInStock?: boolean;
415
+ }
416
+ declare function StockBadge({ variant, hideInStock }: StockBadgeProps): React.ReactElement | null;
417
+
418
+ /**
419
+ * BackInStockForm — an email capture shown when a variant is out of stock.
420
+ * Submits to `client.catalog.inventory.subscribe(variantId, email)`. Renders
421
+ * nothing unless the variant's status is `out_of_stock`, so it's safe to drop
422
+ * straight into a PDP next to (or instead of) the add-to-cart button.
423
+ */
424
+
425
+ interface BackInStockFormProps {
426
+ variant: ProductVariant | null;
427
+ /** Prefill the email (e.g. the signed-in customer's). */
428
+ defaultEmail?: string;
429
+ onSuccess?: () => void;
430
+ }
431
+ declare function BackInStockForm({ variant, defaultEmail, onSuccess, }: BackInStockFormProps): React.ReactElement | null;
432
+
433
+ /**
434
+ * Product list filter + sort controls — presentational + controlled. Each holds
435
+ * no state; the parent owns a `ProductListOptions` object, passes the current
436
+ * value in, and re-queries on change. Themeable via `--nv-*`.
437
+ *
438
+ * const [opts, setOpts] = React.useState<ProductListOptions>({ sort: "newest" });
439
+ * <SortSelect value={opts.sort} onChange={(sort) => setOpts({ ...opts, sort, offset: 0 })} />
440
+ * // re-run client.catalog.products(opts) when opts changes
441
+ */
442
+
443
+ interface SortSelectProps {
444
+ value?: ProductSort;
445
+ onChange: (sort: ProductSort) => void;
446
+ }
447
+ declare function SortSelect({ value, onChange }: SortSelectProps): React.ReactElement;
448
+ interface AvailabilityFilterProps {
449
+ checked?: boolean;
450
+ onChange: (checked: boolean) => void;
451
+ }
452
+ declare function AvailabilityFilter({ checked, onChange, }: AvailabilityFilterProps): React.ReactElement;
453
+ interface PriceRangeFilterProps {
454
+ /** Current bounds in cents (undefined = open-ended). */
455
+ minCents?: number;
456
+ maxCents?: number;
457
+ currency: string;
458
+ onChange: (minCents: number | undefined, maxCents: number | undefined) => void;
459
+ locale?: string;
460
+ }
461
+ /** Two minor-unit (cents) inputs. Emits cents; renders the currency symbol as a
462
+ * hint via the active locale. Empty input → undefined (open-ended). */
463
+ declare function PriceRangeFilter({ minCents, maxCents, currency, onChange, locale, }: PriceRangeFilterProps): React.ReactElement;
464
+ interface TagFilterProps {
465
+ /** All selectable tags (the eshop supplies these, e.g. from its nav). */
466
+ tags: string[];
467
+ selected?: string[];
468
+ onChange: (selected: string[]) => void;
469
+ }
470
+ /** Toggleable tag chips. Multi-select; emits the selected list. */
471
+ declare function TagFilter({ tags, selected, onChange }: TagFilterProps): React.ReactElement | null;
472
+
473
+ /**
474
+ * CartProvider + useCart — shared cart state for the whole app. The drawer, the
475
+ * PDP add-to-cart, and a header cart count all read the same cart and re-render
476
+ * together. Wraps the SDK's cart namespace (which holds the token) with React
477
+ * state. Mount once inside <NeviosProvider>.
478
+ *
479
+ * <NeviosProvider client={client}>
480
+ * <CartProvider>{app}</CartProvider>
481
+ * </NeviosProvider>
482
+ */
483
+
484
+ interface CartState {
485
+ cart: Cart | null;
486
+ /** True while a cart request is in flight. */
487
+ loading: boolean;
488
+ itemCount: number;
489
+ addLine(input: AddLineInput): Promise<Cart>;
490
+ updateLine(lineId: string, quantity: number): Promise<Cart>;
491
+ removeLine(lineId: string): Promise<Cart>;
492
+ /** Re-fetch the cart from the server. */
493
+ refresh(): Promise<void>;
494
+ }
495
+ declare function CartProvider({ children }: {
496
+ children: React.ReactNode;
497
+ }): React.ReactElement;
498
+ declare function useCart(): CartState;
499
+
500
+ /**
501
+ * AddToCart — the PDP buy button. Bound to a selected variant; adds it to the
502
+ * shared cart. Drop into ProductDetailPage's `addToCart` slot:
503
+ *
504
+ * <ProductDetailPage product={p} addToCart={(v) => <AddToCart variant={v} />} />
505
+ */
506
+
507
+ interface AddToCartProps {
508
+ variant: ProductVariant | null;
509
+ quantity?: number;
510
+ /** Button label. Defaults to "Add to cart". */
511
+ children?: React.ReactNode;
512
+ onAdded?: () => void;
513
+ }
514
+ declare function AddToCart({ variant, quantity, children, onAdded, }: AddToCartProps): React.ReactElement;
515
+
516
+ /**
517
+ * CartLineItem — one cart row: thumbnail, title + variant, a quantity stepper,
518
+ * line total, and remove. Wired to the shared cart (update/remove).
519
+ */
520
+
521
+ interface CartLineItemProps {
522
+ line: CartLine;
523
+ locale?: string;
524
+ }
525
+ declare function CartLineItem({ line, locale }: CartLineItemProps): React.ReactElement;
526
+
527
+ /**
528
+ * CartSummary — subtotal / tax / total + a checkout CTA. Reads the shared cart.
529
+ * The checkout action is the eshop's (a link to its checkout route, or a
530
+ * callback) — the P3 checkout phase wires it.
531
+ */
532
+
533
+ interface CartSummaryProps {
534
+ /** Checkout button label (defaults to the localized "Checkout"). */
535
+ checkoutLabel?: string;
536
+ /** Link to the eshop's checkout route. */
537
+ checkoutHref?: string;
538
+ /** Or a callback (e.g. checkout.create() then navigate). */
539
+ onCheckout?: () => void;
540
+ locale?: string;
541
+ }
542
+ declare function CartSummary({ checkoutLabel, checkoutHref, onCheckout, locale, }: CartSummaryProps): React.ReactElement | null;
543
+
544
+ /**
545
+ * CartDrawer — a slide-in panel with the cart lines + summary. Controlled
546
+ * (`open`/`onClose`). Reads the shared cart; the checkout CTA is passed through
547
+ * to CartSummary.
548
+ */
549
+
550
+ interface CartDrawerProps extends CartSummaryProps {
551
+ open: boolean;
552
+ onClose: () => void;
553
+ /** Drawer heading (defaults to the localized "Cart"). */
554
+ title?: string;
555
+ }
556
+ declare function CartDrawer({ open, onClose, title, ...summary }: CartDrawerProps): React.ReactElement | null;
557
+
558
+ /**
559
+ * CheckoutProvider + useCheckout — shared checkout state for the flow. Wraps the
560
+ * SDK's checkout namespace (which holds the token, created from the cart token)
561
+ * with React state, so AddressForm, ShippingPicker, PaymentSection, and
562
+ * OrderSummary all read and mutate the same checkout and re-render together.
563
+ *
564
+ * Mount inside <NeviosProvider> on the checkout route:
565
+ * <CheckoutProvider>{<CheckoutFlow />}</CheckoutProvider>
566
+ *
567
+ * The provider resumes an in-progress checkout from the stored token on mount;
568
+ * call `create(cartToken)` from the cart's "Checkout" CTA to start one.
569
+ */
570
+
571
+ /** Outcome of `pay()` — a gateway redirect, or a placed order. */
572
+ type PayResult = {
573
+ kind: "redirect";
574
+ url: string;
575
+ } | {
576
+ kind: "order";
577
+ checkout: Checkout;
578
+ };
579
+ interface PayOptions {
580
+ /** Where the gateway returns the customer after paying. */
581
+ returnUrl?: string;
582
+ /** Where the gateway returns the customer on cancel. */
583
+ cancelUrl?: string;
584
+ /** Idempotency key for the place-order call. Defaults to the checkout token,
585
+ * which makes completing the same checkout retry-safe. */
586
+ idempotencyKey?: string;
587
+ /** Redirect the browser to the gateway automatically (gateway methods only).
588
+ * Default true; pass false to handle the redirect yourself. */
589
+ redirect?: boolean;
590
+ }
591
+ interface CheckoutState {
592
+ checkout: Checkout | null;
593
+ /** True while a checkout request is in flight. */
594
+ loading: boolean;
595
+ /** The last error from a checkout op (cleared on the next successful op). */
596
+ error: Error | null;
597
+ /** Snapshot the cart into a fresh checkout and hold its token. */
598
+ create(cartToken: string, input?: CreateCheckoutInput): Promise<Checkout>;
599
+ /** Set email + shipping (and optional billing) address. */
600
+ setAddress(input: SetAddressInput): Promise<Checkout>;
601
+ /** Available shipping options for the current address. */
602
+ shippingQuotes(): Promise<ShippingQuote[]>;
603
+ /** Choose a shipping method + rate. */
604
+ setShippingMethod(methodId: string, rateId: string): Promise<Checkout>;
605
+ /** Apply / remove a discount code. */
606
+ applyDiscount(code: string): Promise<Checkout>;
607
+ removeDiscount(code: string): Promise<Checkout>;
608
+ /** Enabled payment methods for the market — the picker rows. */
609
+ paymentMethods(): Promise<PaymentMethod[]>;
610
+ /** Choose a payment method (folds any surcharge into the total). */
611
+ setPaymentMethod(method: string): Promise<Checkout>;
612
+ /** Place the order. Gateway methods start the payment and (by default)
613
+ * redirect the browser to the gateway; cod/bank/manual complete directly. */
614
+ pay(opts?: PayOptions): Promise<PayResult>;
615
+ /** Re-fetch the checkout from the server. */
616
+ refresh(): Promise<void>;
617
+ /** Forget the checkout token (e.g. after the order is placed). */
618
+ clear(): void;
619
+ }
620
+ declare function CheckoutProvider({ children, }: {
621
+ children: React.ReactNode;
622
+ }): React.ReactElement;
623
+ declare function useCheckout(): CheckoutState;
624
+
625
+ /**
626
+ * CheckoutFlow — the multi-step checkout, composed: address → shipping →
627
+ * payment, with a live OrderSummary alongside. Drop it onto your checkout route
628
+ * inside <CheckoutProvider>; it resumes the checkout from the stored token.
629
+ *
630
+ * <CheckoutProvider>
631
+ * <CheckoutFlow onOrderPlaced={(c) => navigate(`/order/${c.order_id}`)} />
632
+ * </CheckoutProvider>
633
+ *
634
+ * Each step is a standalone component (AddressForm / ShippingPicker /
635
+ * PaymentSection) — use them directly for a fully custom layout.
636
+ */
637
+
638
+ interface CheckoutFlowProps {
639
+ /** If set and no checkout exists yet, create one from this cart token. */
640
+ cartToken?: string;
641
+ /** Called when a (non-gateway) order is placed. Gateway flows redirect away
642
+ * before this fires. */
643
+ onOrderPlaced?: (checkout: Checkout) => void;
644
+ /** Rendered when there's nothing to check out (no checkout, no cart token). */
645
+ emptyState?: React.ReactNode;
646
+ /** Rendered after a successful order (else a default confirmation). */
647
+ renderConfirmation?: (checkout: Checkout) => React.ReactNode;
648
+ /** Gateway return/cancel URLs (forwarded to PaymentSection). */
649
+ returnUrl?: string;
650
+ cancelUrl?: string;
651
+ locale?: string;
652
+ }
653
+ declare function CheckoutFlow({ cartToken, onOrderPlaced, emptyState, renderConfirmation, returnUrl, cancelUrl, locale, }: CheckoutFlowProps): React.ReactElement;
654
+
655
+ /**
656
+ * AddressForm — collects email + shipping address (the checkout's first step).
657
+ * On submit it calls `setAddress` on the shared checkout, then `onComplete`.
658
+ * Controlled locally; seeds from the checkout if one already has an address
659
+ * (resumed flow). Billing defaults to the shipping address (same_as_shipping).
660
+ */
661
+
662
+ interface AddressFormProps {
663
+ /** Override the section heading (defaults to the localized "Shipping address"). */
664
+ title?: string;
665
+ /** Override the submit label (defaults to the localized "Continue to shipping"). */
666
+ submitLabel?: string;
667
+ /** Called after the address is saved. */
668
+ onComplete?: () => void;
669
+ }
670
+ declare function AddressForm({ title, submitLabel, onComplete, }: AddressFormProps): React.ReactElement;
671
+
672
+ /**
673
+ * ShippingPicker — fetches the shipping options for the checkout's address and
674
+ * lets the customer pick one. Selecting a row calls `setShippingMethod` (which
675
+ * recomputes totals). Requires the address step to be done first.
676
+ */
677
+
678
+ interface ShippingPickerProps {
679
+ /** Override the section heading (defaults to the localized "Shipping method"). */
680
+ title?: string;
681
+ /** Override the submit label (defaults to "Continue to payment"). */
682
+ submitLabel?: string;
683
+ /** Called once a method is selected and saved. */
684
+ onComplete?: () => void;
685
+ locale?: string;
686
+ }
687
+ declare function ShippingPicker({ title, submitLabel, onComplete, locale, }: ShippingPickerProps): React.ReactElement;
688
+
689
+ /**
690
+ * PaymentSection — lists the enabled payment methods, lets the customer pick
691
+ * one, and places the order. The category drives the final action:
692
+ * • gateway → `pay()` starts the payment and redirects to the gateway
693
+ * • cod/bank/manual → `pay()` completes the order directly → `onOrderPlaced`
694
+ * The storefront never embeds a gateway — paying a card means a redirect.
695
+ */
696
+
697
+ interface PaymentSectionProps {
698
+ title?: string;
699
+ /** Where the gateway returns the customer after paying (gateway methods).
700
+ * Defaults to the current URL. */
701
+ returnUrl?: string;
702
+ cancelUrl?: string;
703
+ /** Called when a non-gateway order is placed (gateway flows redirect away). */
704
+ onOrderPlaced?: (checkout: Checkout) => void;
705
+ locale?: string;
706
+ }
707
+ declare function PaymentSection({ title, returnUrl, cancelUrl, onOrderPlaced, locale, }: PaymentSectionProps): React.ReactElement;
708
+
709
+ /**
710
+ * OrderSummary — the checkout's running total: line items + the full breakdown
711
+ * (subtotal · discount · shipping · tax · surcharge · total). Reads the shared
712
+ * checkout; pass `checkout` explicitly to render it standalone (e.g. SSR).
713
+ */
714
+
715
+ interface OrderSummaryProps {
716
+ /** Override the shared checkout (else read from <CheckoutProvider>). */
717
+ checkout?: Checkout;
718
+ /** Hide the line items, show totals only. */
719
+ totalsOnly?: boolean;
720
+ locale?: string;
721
+ }
722
+ declare function OrderSummary({ checkout: override, totalsOnly, locale, }: OrderSummaryProps): React.ReactElement | null;
723
+
724
+ interface OrderStatusState {
725
+ order: OrderStatus | null;
726
+ loading: boolean;
727
+ error: Error | null;
728
+ reload(): void;
729
+ }
730
+ declare function useOrderStatus(statusToken: string | null, initial?: OrderStatus | null): OrderStatusState;
731
+
732
+ /**
733
+ * OrderConfirmation — the compact post-checkout "thank you" block. Drop it on
734
+ * the return route after `checkout.complete()` / a gateway redirect back, keyed
735
+ * by the order's status token (`checkout.order_status_token`). Pass a
736
+ * pre-fetched `order` to render server-side.
737
+ */
738
+
739
+ interface OrderConfirmationProps {
740
+ /** The order's status token (from `checkout.order_status_token`). */
741
+ statusToken?: string | null;
742
+ /** Pre-fetched order (SSR / loader) — skips the client fetch. */
743
+ order?: OrderStatus;
744
+ /** Link to the full order status page. */
745
+ statusHref?: string;
746
+ /** Heading copy (defaults to the localized "Thank you for your order!"). */
747
+ title?: string;
748
+ locale?: string;
749
+ }
750
+ declare function OrderConfirmation({ statusToken, order: initial, statusHref, title, locale, }: OrderConfirmationProps): React.ReactElement;
751
+
752
+ /**
753
+ * OrderStatusPage — the full post-purchase status view: phase timeline (or a
754
+ * terminal banner), line items, totals, shipping method + tracking, the
755
+ * redacted delivery location, and payment. Keyed by the order's status token;
756
+ * pass a pre-fetched `order` to render server-side (Remix loader).
757
+ */
758
+
759
+ interface OrderStatusPageProps {
760
+ statusToken?: string | null;
761
+ /** Pre-fetched order (SSR / loader) — skips the client fetch. */
762
+ order?: OrderStatus;
763
+ /** Contact-support callback (shown when the order allows it). */
764
+ onContactSupport?: () => void;
765
+ locale?: string;
766
+ }
767
+ declare function OrderStatusPage({ statusToken, order: initial, onContactSupport, locale, }: OrderStatusPageProps): React.ReactElement;
768
+
769
+ /**
770
+ * AccountProvider + useAccount — shared logged-in-customer state. Resolves the
771
+ * session on mount (account.me); LoginForm / AccountDashboard / OrderHistory all
772
+ * read the same customer. Mount inside <NeviosProvider> (it needs the client).
773
+ */
774
+
775
+ interface AccountState {
776
+ customer: Customer | null;
777
+ signedIn: boolean;
778
+ /** True until the initial session check resolves. */
779
+ loading: boolean;
780
+ requestMagicLink(email: string): Promise<MagicLinkResult>;
781
+ /** Exchange a magic token for a session (sets `customer`). */
782
+ verify(token: string): Promise<Customer>;
783
+ logout(): Promise<void>;
784
+ refresh(): Promise<void>;
785
+ }
786
+ declare function AccountProvider({ children }: {
787
+ children: React.ReactNode;
788
+ }): React.ReactElement;
789
+ declare function useAccount(): AccountState;
790
+ type VerifyStatus = "idle" | "verifying" | "success" | "error";
791
+ /** Drive the magic-link callback route: pass the token from the URL, get back a
792
+ * status to render (and redirect on "success"). */
793
+ declare function useMagicLinkVerify(token: string | null): {
794
+ status: VerifyStatus;
795
+ };
796
+
797
+ /**
798
+ * LoginForm — passwordless sign-in. Enter an email → we email a one-time link →
799
+ * "check your email". For test keys the API returns the link, which we surface
800
+ * as a dev shortcut so you can sign in without a real inbox.
801
+ */
802
+
803
+ interface LoginFormProps {
804
+ /** Route that handles the magic link (default "/account/verify"). The dev
805
+ * shortcut links here as `${verifyPath}?token=…`. */
806
+ verifyPath?: string;
807
+ onSent?: (email: string) => void;
808
+ }
809
+ declare function LoginForm({ verifyPath, onSent }: LoginFormProps): React.ReactElement;
810
+
811
+ /**
812
+ * AccountDashboard — the signed-in header: greeting + sign-out. Compose
813
+ * OrderHistory / AddressBook (or your own) beneath it. Renders nothing while the
814
+ * session is still resolving; render <LoginForm> yourself when not signed in.
815
+ */
816
+
817
+ interface AccountDashboardProps {
818
+ children?: React.ReactNode;
819
+ }
820
+ declare function AccountDashboard({ children }: AccountDashboardProps): React.ReactElement | null;
821
+
822
+ /**
823
+ * OrderHistory — the signed-in customer's past orders, each linking to its
824
+ * public status page. Fetches on mount once signed in.
825
+ */
826
+
827
+ interface OrderHistoryProps {
828
+ /** Map an order's status token → its status-page URL (default `/order/{token}`). */
829
+ statusHref?: (statusToken: string) => string;
830
+ /** Where to send the shopper after a successful reorder (default `/cart`).
831
+ * Ignored when `onReorder` is provided. */
832
+ cartHref?: string;
833
+ /** Called after a reorder succeeds — override the default navigation. */
834
+ onReorder?: (result: ReorderResult) => void;
835
+ locale?: string;
836
+ }
837
+ declare function OrderHistory({ statusHref, cartHref, onReorder, locale, }: OrderHistoryProps): React.ReactElement;
838
+
839
+ /**
840
+ * AddressBook — the signed-in customer's saved addresses with full management:
841
+ * add, edit, delete, and set-default. Each mutation calls the SDK then refetches
842
+ * the list. The form is the shared <AddressForm>.
843
+ */
844
+
845
+ declare function AddressBook(): React.ReactElement;
846
+
847
+ /**
848
+ * ProfileEditor — view + edit the signed-in customer's name, phone, and
849
+ * marketing consent (email is identity, shown read-only). Calls
850
+ * `account.updateProfile` and refreshes the shared account state on save.
851
+ */
852
+
853
+ declare function ProfileEditor(): React.ReactElement | null;
854
+
855
+ /**
856
+ * ProductJsonLd — schema.org/Product structured data for rich results (price,
857
+ * availability, brand). Drop it in the PDP <head> (or anywhere; it's a script).
858
+ * Availability maps from the variant stock state the storefront now projects.
859
+ *
860
+ * <ProductJsonLd product={product} url={`https://shop.example.com/products/${product.handle}`} />
861
+ */
862
+
863
+ interface ProductJsonLdProps {
864
+ product: Product;
865
+ /** Absolute canonical URL of this product page. */
866
+ url: string;
867
+ /** Origin used to absolutize relative media URLs (defaults to `url`'s origin). */
868
+ baseUrl?: string;
869
+ /** Brand name (defaults to `product.vendor`). */
870
+ brandName?: string;
871
+ }
872
+ declare function ProductJsonLd({ product, url, baseUrl, brandName, }: ProductJsonLdProps): React.ReactElement;
873
+
874
+ /**
875
+ * BreadcrumbJsonLd — schema.org/BreadcrumbList for the trail Google shows under
876
+ * a result. Pass the crumbs in order (Home → Collection → Product); each needs
877
+ * an absolute URL.
878
+ *
879
+ * <BreadcrumbJsonLd items={[
880
+ * { name: "Home", url: "https://shop.example.com/" },
881
+ * { name: "Shoes", url: "https://shop.example.com/collections/shoes" },
882
+ * { name: product.title, url: productUrl },
883
+ * ]} />
884
+ */
885
+
886
+ interface BreadcrumbItem {
887
+ name: string;
888
+ url: string;
889
+ }
890
+ interface BreadcrumbJsonLdProps {
891
+ items: BreadcrumbItem[];
892
+ }
893
+ declare function BreadcrumbJsonLd({ items }: BreadcrumbJsonLdProps): React.ReactElement | null;
894
+
895
+ /**
896
+ * OrganizationJsonLd — schema.org/Organization for the shop itself. Mount once
897
+ * (e.g. in the root layout): one Organization per domain is the best practice.
898
+ *
899
+ * <OrganizationJsonLd name={shop.name} url="https://shop.example.com" logo={shop.logo} />
900
+ */
901
+
902
+ interface OrganizationJsonLdProps {
903
+ name: string;
904
+ url?: string;
905
+ /** Logo URL (absolute). */
906
+ logo?: string;
907
+ /** Social / profile URLs. */
908
+ sameAs?: string[];
909
+ }
910
+ declare function OrganizationJsonLd({ name, url, logo, sameAs, }: OrganizationJsonLdProps): React.ReactElement;
911
+
912
+ /**
913
+ * JSON-LD helpers. Structured data is *data*, but it's embedded in an inline
914
+ * `<script>` in the HTML, so it must be escaped against the one thing that can
915
+ * break out of that context: a literal `</script>` (and stray `<`, `>`, `&`).
916
+ * `serializeJsonLd` hex-escapes those; `<JsonLd>` renders the script tag.
917
+ */
918
+
919
+ /** JSON-safe + HTML-script-safe serialization for embedding in `<script>`. */
920
+ declare function serializeJsonLd(data: unknown): string;
921
+ /** Strip HTML tags + collapse whitespace → plain text (for JSON-LD descriptions). */
922
+ declare function stripHtml(html: string | null | undefined): string | undefined;
923
+ /** Absolutize a possibly-relative URL against an origin. */
924
+ declare function absoluteUrl(url: string, base?: string): string;
925
+ interface JsonLdProps {
926
+ data: unknown;
927
+ }
928
+ /** Render a JSON-LD `<script>` for the given (already-shaped) data object. */
929
+ declare function JsonLd({ data }: JsonLdProps): React.ReactElement;
930
+
931
+ export { AccountDashboard, type AccountDashboardProps, AccountProvider, type AccountState, AddToCart, type AddToCartProps, AddressBook, AddressForm, type AddressFormProps, AvailabilityFilter, type AvailabilityFilterProps, BackInStockForm, type BackInStockFormProps, type BreadcrumbItem, BreadcrumbJsonLd, type BreadcrumbJsonLdProps, CartDrawer, type CartDrawerProps, CartLineItem, type CartLineItemProps, CartProvider, type CartState, CartSummary, type CartSummaryProps, CheckoutFlow, type CheckoutFlowProps, CheckoutProvider, type CheckoutState, CollectionPage, type CollectionPageProps, I18nProvider, type I18nProviderProps, type I18nValue, JsonLd, type JsonLdProps, LoginForm, type LoginFormProps, type MarketOption, MarketSwitcher, type MarketSwitcherProps, type MessageKey, type Messages, NeviosProvider, type NeviosProviderProps, OrderConfirmation, type OrderConfirmationProps, OrderHistory, type OrderHistoryProps, OrderStatusPage, type OrderStatusPageProps, type OrderStatusState, OrderSummary, type OrderSummaryProps, OrganizationJsonLd, type OrganizationJsonLdProps, type PayOptions, type PayResult, PaymentSection, type PaymentSectionProps, PriceMoney, type PriceMoneyProps, PriceRangeFilter, type PriceRangeFilterProps, ProductCard, type ProductCardProps, ProductDetailPage, type ProductDetailPageProps, ProductGallery, type ProductGalleryProps, ProductJsonLd, type ProductJsonLdProps, ProfileEditor, ShippingPicker, type ShippingPickerProps, SortSelect, type SortSelectProps, StockBadge, type StockBadgeProps, type StorefrontTheme, type TFunction, type TVars, TagFilter, type TagFilterProps, ThemeProvider, type ThemeProviderProps, VariantPicker, type VariantPickerProps, type VerifyStatus, absoluteUrl, bundledMessages, cs, en, formatCents, formatMoney, serializeJsonLd, stripHtml, themeToCssVars, useAccount, useCart, useCheckout, useI18n, useMagicLinkVerify, useOrderStatus, useStorefront, useStorefrontOptional, useT };