@asteby/storefront-react 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +133 -0
- package/dist/chunk-C6QZNKRE.js +162 -0
- package/dist/chunk-C6QZNKRE.js.map +1 -0
- package/dist/components-B5XhSH-m.d.cts +54 -0
- package/dist/components-B5XhSH-m.d.ts +54 -0
- package/dist/index.d.cts +6 -54
- package/dist/index.d.ts +6 -54
- package/dist/index.js +6 -159
- package/dist/index.js.map +1 -1
- package/dist/mockups.cjs +525 -0
- package/dist/mockups.cjs.map +1 -0
- package/dist/mockups.d.cts +203 -0
- package/dist/mockups.d.ts +203 -0
- package/dist/mockups.js +401 -0
- package/dist/mockups.js.map +1 -0
- package/package.json +12 -2
package/README.md
CHANGED
|
@@ -196,6 +196,138 @@ const mine = useSelectedLocation({ initialId: urlSucursal }) // ?sucursal= + loc
|
|
|
196
196
|
`OpenStatus` (calcula tras montar; `now` fija el instante), `DirectionsLink`,
|
|
197
197
|
`PickupOption` (muestra lo que manda OPS: costo y días), `NearestLocationForm`.
|
|
198
198
|
|
|
199
|
+
## Mockups de respaldo (`@asteby/storefront-react/mockups`)
|
|
200
|
+
|
|
201
|
+
Cuando un producto de OPS no trae imagen, `ProductImage` dibuja una ilustración
|
|
202
|
+
SVG según el tipo de producto en lugar de un hueco: **llanta** (medida en cifras,
|
|
203
|
+
marca, modelo, índice de carga/velocidad, LT, run flat), **refacción** (ficha con
|
|
204
|
+
número de parte, OEM, compatibilidad y posición), **suplemento** (bote, frasco o
|
|
205
|
+
bolsa con nombre, sabor y presentación) y **genérico** (caja con monograma).
|
|
206
|
+
SSR, sin JavaScript en el cliente, sin red, sin `id`s; ~1–2 KB gzip por mockup.
|
|
207
|
+
|
|
208
|
+
```tsx
|
|
209
|
+
import { ProductImage } from '@asteby/storefront-react/mockups'
|
|
210
|
+
|
|
211
|
+
// Sustituye el `product.featured_image ? <Image …/> : null` de las tarjetas:
|
|
212
|
+
<ProductImage
|
|
213
|
+
product={product}
|
|
214
|
+
variant={selectedVariant} // opcional: su imagen gana; su sabor/presentación alimenta el mockup
|
|
215
|
+
widths={[240, 360, 480, 720]}
|
|
216
|
+
sizes="(min-width: 1024px) 25vw, 50vw"
|
|
217
|
+
priority={index < 4} // LCP (solo aplica a la imagen real)
|
|
218
|
+
className="h-full w-full object-cover"
|
|
219
|
+
/>
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
- **Con imagen** renderiza `<Image>` (srcset, `width`/`height`, `priority`); el
|
|
223
|
+
`alt` es el de OPS, o el título del producto si viene vacío.
|
|
224
|
+
- **Sin imagen** renderiza `<svg role="img" aria-label="Ilustración de referencia: …">`
|
|
225
|
+
con `<title>`: nunca se anuncia como foto. `alt=""` lo vuelve decorativo
|
|
226
|
+
(`aria-hidden`), útil cuando el nombre ya está junto a la imagen.
|
|
227
|
+
- **Nunca inventa ni muestra precios**: solo pinta lo que trae el producto
|
|
228
|
+
(atributos, `vendor`, título, opciones, variante). Sin medida no hay medida;
|
|
229
|
+
el sabor solo aparece con variante elegida o si la opción tiene un único valor.
|
|
230
|
+
Todo texto se limpia (controles/bidi), se recorta con `…` y React lo escapa.
|
|
231
|
+
- `image={null}` fuerza el mockup (p. ej. en una galería); `kind="tire"` fuerza el tipo.
|
|
232
|
+
|
|
233
|
+
### Qué tipo se dibuja
|
|
234
|
+
|
|
235
|
+
`kind` → `resolveKind` (prop o `MockupProvider`) → `resolveMockupKind(product)`:
|
|
236
|
+
|
|
237
|
+
1. Atributo `mockup_kind` (o `mockup`) en OPS, si ese tipo está registrado: el
|
|
238
|
+
dueño puede elegirlo sin tocar código.
|
|
239
|
+
2. Atributos: `size_key`, `section_width_mm`, `rim_diameter_in`, `speed_rating`… → `tire`;
|
|
240
|
+
`part_number`, `oem_number`, `mpn` → `part`.
|
|
241
|
+
3. Palabras en `product_type`, categoría y etiquetas (no en el título): llanta,
|
|
242
|
+
neumático, refacción, autoparte, proteína, creatina, colágeno, suplemento…
|
|
243
|
+
4. `generic`.
|
|
244
|
+
|
|
245
|
+
Atributos que lee cada uno (los del pack del giro, más alias comunes):
|
|
246
|
+
llanta `size_key|size`, `section_width_mm|width`, `aspect_ratio|aspect`,
|
|
247
|
+
`rim_diameter_in|rim`, `load_index`/`load_service`, `speed_rating`, `model`,
|
|
248
|
+
`light_truck`, `runflat`; refacción `part_number|mpn`, `oem_number`,
|
|
249
|
+
`fitment|compatibility|compatibilidad`, `position`; suplemento opción
|
|
250
|
+
`Sabor`/`Presentación` o atributos `flavor|sabor`, `presentation|net_content`,
|
|
251
|
+
`servings` (número) y `form|envase` (`cápsulas` → frasco, `bolsa` → bolsa).
|
|
252
|
+
|
|
253
|
+
### Personalizar sin tocar el SDK
|
|
254
|
+
|
|
255
|
+
**Colores y tipografía** con variables CSS. Por defecto toman el tema de la tienda
|
|
256
|
+
(`--color-muted`, `--color-foreground`, `--color-background`, `--color-primary`,
|
|
257
|
+
`--color-primary-foreground`, `--font-heading`/`--font-sans`, los que emite
|
|
258
|
+
`ThemeStyle`) y si no hay, grises neutros con `light-dark()` (modo oscuro cuando
|
|
259
|
+
la página declara `color-scheme: dark` o `light dark`).
|
|
260
|
+
|
|
261
|
+
```css
|
|
262
|
+
/* app/app.css de la tienda */
|
|
263
|
+
:root {
|
|
264
|
+
--mockup-bg: var(--color-muted); /* fondo del cuadro */
|
|
265
|
+
--mockup-ink: var(--color-foreground); /* texto sobre el fondo */
|
|
266
|
+
--mockup-muted: #6b7280; /* texto secundario sobre el fondo */
|
|
267
|
+
--mockup-surface: #001963; /* hule, envase, caja */
|
|
268
|
+
--mockup-surface-ink: #ffffff; /* texto sobre el envase */
|
|
269
|
+
--mockup-label: #ffffff; /* etiqueta / ficha */
|
|
270
|
+
--mockup-label-ink: #000c3c; /* texto sobre la etiqueta */
|
|
271
|
+
--mockup-accent: #f66123; /* acento: R16, banda de la ficha, tapa */
|
|
272
|
+
--mockup-accent-ink: #ffffff;
|
|
273
|
+
--mockup-font: "Archivo", sans-serif;
|
|
274
|
+
--mockup-font-mono: ui-monospace, monospace; /* números de parte */
|
|
275
|
+
--mockup-text-transform: uppercase; /* p. ej. nombres en MAYÚSCULAS */
|
|
276
|
+
}
|
|
277
|
+
.dark { --mockup-surface: #0b1440; }
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
**Tipo por tienda** (sin recompilar el SDK) y textos de la interfaz:
|
|
281
|
+
|
|
282
|
+
```tsx
|
|
283
|
+
// app/root.tsx
|
|
284
|
+
import { MockupProvider } from '@asteby/storefront-react/mockups'
|
|
285
|
+
|
|
286
|
+
<MockupProvider
|
|
287
|
+
resolveKind={(product, guess) => (product.category?.handle === 'shakers' ? 'generic' : guess)}
|
|
288
|
+
labels={{ illustration: 'Imagen ilustrativa', servings: 'servicios' }}
|
|
289
|
+
>
|
|
290
|
+
<Outlet />
|
|
291
|
+
</MockupProvider>
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
**Un mockup propio** (o reemplazar uno base). `MockupFrame` da el `<svg>`, el
|
|
295
|
+
fondo, las variables y la accesibilidad; `MockupText`, `wrapMockupText` y
|
|
296
|
+
`fitMockupFontSize` acomodan el texto sin medir el DOM.
|
|
297
|
+
|
|
298
|
+
```tsx
|
|
299
|
+
import {
|
|
300
|
+
BUILTIN_MOCKUPS, MockupFrame, MockupText, MockupProvider, createMockupRegistry,
|
|
301
|
+
cleanMockupText, tone, wrapMockupText, type MockupComponentProps,
|
|
302
|
+
} from '@asteby/storefront-react/mockups'
|
|
303
|
+
|
|
304
|
+
type Helmet = { title: string; shell: string | null }
|
|
305
|
+
|
|
306
|
+
function HelmetMockup({ data, label, labels, ...svg }: MockupComponentProps<Helmet>) {
|
|
307
|
+
return (
|
|
308
|
+
<MockupFrame kind="helmet" label={label} {...svg}>
|
|
309
|
+
<path d="M90 230a110 110 0 0 1 220 0v40H90z" style={tone('surface')} />
|
|
310
|
+
<MockupText lines={wrapMockupText(data.title, 24, 2)} x={200} y={330} size={22} />
|
|
311
|
+
{data.shell ? <MockupText lines={[data.shell]} x={200} y={372} size={14} tone="muted" /> : null}
|
|
312
|
+
</MockupFrame>
|
|
313
|
+
)
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
const registry = createMockupRegistry(BUILTIN_MOCKUPS).register('helmet', {
|
|
317
|
+
component: HelmetMockup,
|
|
318
|
+
fromProduct: (p) => ({ title: cleanMockupText(p.title) ?? '', shell: cleanMockupText(p.attributes?.shell, 24) }),
|
|
319
|
+
// describe: (d, labels) => `${labels.illustration}: ${d.title}` (opcional)
|
|
320
|
+
})
|
|
321
|
+
|
|
322
|
+
<MockupProvider registry={registry} resolveKind={(p, guess) => (p.product_type === 'Casco' ? 'helmet' : guess)}>…</MockupProvider>
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
`registerMockup(kind, renderer)` hace lo mismo sobre el registro por defecto
|
|
326
|
+
(llámalo una vez a nivel de módulo). Si registras solo un componente para un
|
|
327
|
+
tipo base (`registerMockup('tire', MiLlanta)`), recibe los datos del extractor
|
|
328
|
+
base (`TireMockupData`). Para dibujar sin producto completo:
|
|
329
|
+
`<ProductMockup kind="part" data={partMockupData(product)} />`.
|
|
330
|
+
|
|
199
331
|
## API
|
|
200
332
|
|
|
201
333
|
| Export | |
|
|
@@ -209,3 +341,4 @@ const mine = useSelectedLocation({ initialId: urlSucursal }) // ?sucursal= + loc
|
|
|
209
341
|
| `productJsonLd`, `organizationJsonLd`, `localBusinessJsonLd`, `breadcrumbJsonLd`, `faqJsonLd`, `collectionJsonLd`, `JsonLd`, `serializeJsonLd` | schema.org JSON-LD |
|
|
210
342
|
| `defineSection`, `SectionRegistry`, `createSectionRegistry`, `Sections`, `resolveSectionProps`, `sectionJsonSchema` | Content sections |
|
|
211
343
|
| `themeToCss`, `themeToCssVariables`, `ThemeStyle`, `themeFontsHref`, `tokenName` | SSR theme |
|
|
344
|
+
| `ProductImage`, `ProductMockup`, `MockupProvider`, `createMockupRegistry`, `registerMockup`, `BUILTIN_MOCKUPS`, `MockupFrame`, `MockupText`, `TireMockup`, `PartMockup`, `SupplementMockup`, `GenericMockup` | Mockups de respaldo (subpath `/mockups`) |
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { createContext, useMemo, useContext, createElement } from 'react';
|
|
2
|
+
import { createStorefrontClient, formatMoney, parseMoney } from '@asteby/storefront';
|
|
3
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
4
|
+
|
|
5
|
+
// src/context.tsx
|
|
6
|
+
var StorefrontContext = createContext(null);
|
|
7
|
+
function StorefrontProvider({ client, config, shop = null, locale, currency, children }) {
|
|
8
|
+
const configKey = config ? `${config.baseUrl}|${config.token}|${config.locale ?? ""}|${config.customerToken ?? ""}` : "";
|
|
9
|
+
const resolvedClient = useMemo(
|
|
10
|
+
() => client ?? (config ? createStorefrontClient(config) : null),
|
|
11
|
+
[client, configKey]
|
|
12
|
+
);
|
|
13
|
+
const value = useMemo(
|
|
14
|
+
() => ({
|
|
15
|
+
client: resolvedClient,
|
|
16
|
+
shop,
|
|
17
|
+
locale: locale ?? config?.locale ?? shop?.locale ?? "es-MX",
|
|
18
|
+
currency: currency ?? shop?.currency_code ?? "MXN"
|
|
19
|
+
}),
|
|
20
|
+
[resolvedClient, shop, locale, currency, config?.locale]
|
|
21
|
+
);
|
|
22
|
+
return /* @__PURE__ */ jsx(StorefrontContext.Provider, { value, children });
|
|
23
|
+
}
|
|
24
|
+
function useStorefront() {
|
|
25
|
+
const ctx = useContext(StorefrontContext);
|
|
26
|
+
if (!ctx) throw new Error("useStorefront must be used inside <StorefrontProvider>");
|
|
27
|
+
return ctx;
|
|
28
|
+
}
|
|
29
|
+
function useOptionalStorefront() {
|
|
30
|
+
return useContext(StorefrontContext);
|
|
31
|
+
}
|
|
32
|
+
function useStorefrontClient() {
|
|
33
|
+
const { client } = useStorefront();
|
|
34
|
+
if (!client) throw new Error("<StorefrontProvider> needs a `client` or `config` for browser-side calls");
|
|
35
|
+
return client;
|
|
36
|
+
}
|
|
37
|
+
function Money({
|
|
38
|
+
data,
|
|
39
|
+
as,
|
|
40
|
+
locale,
|
|
41
|
+
withoutTrailingZeros,
|
|
42
|
+
withoutCurrency,
|
|
43
|
+
currencyDisplay,
|
|
44
|
+
...rest
|
|
45
|
+
}) {
|
|
46
|
+
const sf = useOptionalStorefront();
|
|
47
|
+
const text = formatMoney(data, locale ?? sf?.locale, {
|
|
48
|
+
...withoutTrailingZeros !== void 0 ? { withoutTrailingZeros } : {},
|
|
49
|
+
...withoutCurrency !== void 0 ? { withoutCurrency } : {},
|
|
50
|
+
...currencyDisplay !== void 0 ? { currencyDisplay } : {}
|
|
51
|
+
});
|
|
52
|
+
return createElement(as ?? "span", rest, text);
|
|
53
|
+
}
|
|
54
|
+
var DEFAULT_IMAGE_WIDTHS = [320, 480, 640, 768, 1024, 1280, 1600];
|
|
55
|
+
var defaultImageLoader = (src, width, height) => {
|
|
56
|
+
try {
|
|
57
|
+
const isAbsolute = /^[a-z][a-z0-9+.-]*:/i.test(src);
|
|
58
|
+
const url = new URL(src, "http://relative.invalid");
|
|
59
|
+
url.searchParams.set("width", String(width));
|
|
60
|
+
if (height) url.searchParams.set("height", String(height));
|
|
61
|
+
return isAbsolute ? url.toString() : url.pathname + url.search + url.hash;
|
|
62
|
+
} catch {
|
|
63
|
+
return src;
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
function parseRatio(ratio) {
|
|
67
|
+
if (!ratio) return null;
|
|
68
|
+
const [w, h] = ratio.split(/[/:]/).map((n) => Number.parseFloat(n));
|
|
69
|
+
return w && h ? w / h : null;
|
|
70
|
+
}
|
|
71
|
+
function Image({
|
|
72
|
+
data,
|
|
73
|
+
sizes = "100vw",
|
|
74
|
+
widths = DEFAULT_IMAGE_WIDTHS,
|
|
75
|
+
loader = defaultImageLoader,
|
|
76
|
+
priority = false,
|
|
77
|
+
aspectRatio,
|
|
78
|
+
alt,
|
|
79
|
+
loading,
|
|
80
|
+
decoding,
|
|
81
|
+
...rest
|
|
82
|
+
}) {
|
|
83
|
+
const ratio = parseRatio(aspectRatio) ?? (data.width && data.height ? data.width / data.height : null);
|
|
84
|
+
let candidates = [...widths].sort((a, b) => a - b);
|
|
85
|
+
if (data.width) {
|
|
86
|
+
const capped = candidates.filter((w) => w <= data.width);
|
|
87
|
+
candidates = capped.length ? capped : [data.width];
|
|
88
|
+
}
|
|
89
|
+
const srcSet = loader ? candidates.map((w) => `${loader(data.url, w, ratio ? Math.round(w / ratio) : void 0)} ${w}w`).join(", ") : void 0;
|
|
90
|
+
const width = data.width ?? candidates[candidates.length - 1];
|
|
91
|
+
const height = data.height ?? (ratio && width ? Math.round(width / ratio) : void 0);
|
|
92
|
+
return /* @__PURE__ */ jsx(
|
|
93
|
+
"img",
|
|
94
|
+
{
|
|
95
|
+
src: data.url,
|
|
96
|
+
alt: alt ?? data.alt ?? "",
|
|
97
|
+
...srcSet ? { srcSet, sizes } : {},
|
|
98
|
+
...width ? { width } : {},
|
|
99
|
+
...height ? { height } : {},
|
|
100
|
+
loading: loading ?? (priority ? "eager" : "lazy"),
|
|
101
|
+
decoding: decoding ?? (priority ? "auto" : "async"),
|
|
102
|
+
...priority ? { fetchPriority: "high" } : {},
|
|
103
|
+
...rest
|
|
104
|
+
}
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
var VISUALLY_HIDDEN = {
|
|
108
|
+
position: "absolute",
|
|
109
|
+
width: 1,
|
|
110
|
+
height: 1,
|
|
111
|
+
padding: 0,
|
|
112
|
+
margin: -1,
|
|
113
|
+
overflow: "hidden",
|
|
114
|
+
clip: "rect(0, 0, 0, 0)",
|
|
115
|
+
whiteSpace: "nowrap",
|
|
116
|
+
border: 0
|
|
117
|
+
};
|
|
118
|
+
function ProductPrice({
|
|
119
|
+
product,
|
|
120
|
+
variant,
|
|
121
|
+
fromLabel = "Desde",
|
|
122
|
+
compareAtLabel = "Precio anterior",
|
|
123
|
+
locale,
|
|
124
|
+
withoutTrailingZeros,
|
|
125
|
+
...rest
|
|
126
|
+
}) {
|
|
127
|
+
let price = null;
|
|
128
|
+
let compareAt = null;
|
|
129
|
+
let isRange = false;
|
|
130
|
+
if (variant) {
|
|
131
|
+
price = variant.price;
|
|
132
|
+
compareAt = variant.compare_at_price;
|
|
133
|
+
} else if (product) {
|
|
134
|
+
price = product.price_range.min;
|
|
135
|
+
compareAt = product.compare_at_price_range?.min ?? null;
|
|
136
|
+
isRange = product.price_range.min.amount !== product.price_range.max.amount;
|
|
137
|
+
}
|
|
138
|
+
if (!price) return null;
|
|
139
|
+
const onSale = compareAt !== null && parseMoney(compareAt) > parseMoney(price);
|
|
140
|
+
const opts = { ...locale ? { locale } : {}, ...withoutTrailingZeros !== void 0 ? { withoutTrailingZeros } : {} };
|
|
141
|
+
return /* @__PURE__ */ jsxs("div", { "data-on-sale": onSale || void 0, ...rest, children: [
|
|
142
|
+
isRange ? /* @__PURE__ */ jsxs("span", { "data-price-prefix": "", children: [
|
|
143
|
+
fromLabel,
|
|
144
|
+
" "
|
|
145
|
+
] }) : null,
|
|
146
|
+
/* @__PURE__ */ jsx(Money, { data: price, "data-price": "", ...opts }),
|
|
147
|
+
onSale && compareAt ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
148
|
+
" ",
|
|
149
|
+
/* @__PURE__ */ jsxs("s", { "data-compare-at-price": "", children: [
|
|
150
|
+
/* @__PURE__ */ jsxs("span", { style: VISUALLY_HIDDEN, children: [
|
|
151
|
+
compareAtLabel,
|
|
152
|
+
": "
|
|
153
|
+
] }),
|
|
154
|
+
/* @__PURE__ */ jsx(Money, { data: compareAt, ...opts })
|
|
155
|
+
] })
|
|
156
|
+
] }) : null
|
|
157
|
+
] });
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export { DEFAULT_IMAGE_WIDTHS, Image, Money, ProductPrice, StorefrontProvider, defaultImageLoader, useOptionalStorefront, useStorefront, useStorefrontClient };
|
|
161
|
+
//# sourceMappingURL=chunk-C6QZNKRE.js.map
|
|
162
|
+
//# sourceMappingURL=chunk-C6QZNKRE.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/context.tsx","../src/components.tsx"],"names":["jsx"],"mappings":"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","file":"chunk-C6QZNKRE.js","sourcesContent":["import { createContext, useContext, useMemo, type ReactNode } from 'react'\nimport { createStorefrontClient, type Shop, type StorefrontClient, type StorefrontClientOptions } from '@asteby/storefront'\n\nexport type StorefrontContextValue = {\n /** Client for browser-side calls (use a public `pk_` token). */\n client: StorefrontClient | null\n shop: Shop | null\n /** BCP 47 locale used for formatting (defaults to `shop.locale`, then `es-MX`). */\n locale: string\n /** ISO 4217 currency (defaults to `shop.currency_code`, then `MXN`). */\n currency: string\n}\n\nconst StorefrontContext = createContext<StorefrontContextValue | null>(null)\n\nexport type StorefrontProviderProps = {\n /** A ready client. Takes precedence over `config`. */\n client?: StorefrontClient\n /** Options to create the browser client (use a `pk_` token). */\n config?: StorefrontClientOptions\n /** Shop info loaded on the server (root loader). */\n shop?: Shop | null\n locale?: string\n currency?: string\n children?: ReactNode\n}\n\n/**\n * Makes the storefront client, shop, locale and currency available to the\n * tree. SSR-safe: creating the client does not touch `window`.\n */\nexport function StorefrontProvider({ client, config, shop = null, locale, currency, children }: StorefrontProviderProps) {\n const configKey = config ? `${config.baseUrl}|${config.token}|${config.locale ?? ''}|${config.customerToken ?? ''}` : ''\n const resolvedClient = useMemo(\n () => client ?? (config ? createStorefrontClient(config) : null),\n [client, configKey],\n )\n const value = useMemo<StorefrontContextValue>(\n () => ({\n client: resolvedClient,\n shop,\n locale: locale ?? config?.locale ?? shop?.locale ?? 'es-MX',\n currency: currency ?? shop?.currency_code ?? 'MXN',\n }),\n [resolvedClient, shop, locale, currency, config?.locale],\n )\n return <StorefrontContext.Provider value={value}>{children}</StorefrontContext.Provider>\n}\n\n/** Storefront context. Throws outside `<StorefrontProvider>`. */\nexport function useStorefront(): StorefrontContextValue {\n const ctx = useContext(StorefrontContext)\n if (!ctx) throw new Error('useStorefront must be used inside <StorefrontProvider>')\n return ctx\n}\n\n/** Storefront context or `null` outside a provider (for components that work standalone). */\nexport function useOptionalStorefront(): StorefrontContextValue | null {\n return useContext(StorefrontContext)\n}\n\n/** The client from context; throws when the provider has none. */\nexport function useStorefrontClient(): StorefrontClient {\n const { client } = useStorefront()\n if (!client) throw new Error('<StorefrontProvider> needs a `client` or `config` for browser-side calls')\n return client\n}\n","import { createElement, type ComponentPropsWithoutRef, type ElementType, type ReactNode } from 'react'\nimport { formatMoney, parseMoney, type FormatMoneyOptions, type Image as ImageData, type Money as MoneyData, type Product, type ProductVariant } from '@asteby/storefront'\nimport { useOptionalStorefront } from './context.js'\n\n// ---------------------------------------------------------------------------\n// Money\n// ---------------------------------------------------------------------------\n\nexport type MoneyProps<As extends ElementType = 'span'> = FormatMoneyOptions & {\n data: MoneyData\n /** Element to render (default `span`). */\n as?: As\n /** Overrides the provider locale. */\n locale?: string\n} & Omit<ComponentPropsWithoutRef<As>, 'children' | 'as'>\n\n/** Formats `Money` with the provider locale (or `locale`). */\nexport function Money<As extends ElementType = 'span'>({\n data,\n as,\n locale,\n withoutTrailingZeros,\n withoutCurrency,\n currencyDisplay,\n ...rest\n}: MoneyProps<As>) {\n const sf = useOptionalStorefront()\n const text = formatMoney(data, locale ?? sf?.locale, {\n ...(withoutTrailingZeros !== undefined ? { withoutTrailingZeros } : {}),\n ...(withoutCurrency !== undefined ? { withoutCurrency } : {}),\n ...(currencyDisplay !== undefined ? { currencyDisplay } : {}),\n })\n return createElement(as ?? 'span', rest, text)\n}\n\n// ---------------------------------------------------------------------------\n// Image\n// ---------------------------------------------------------------------------\n\nexport const DEFAULT_IMAGE_WIDTHS = [320, 480, 640, 768, 1024, 1280, 1600] as const\n\n/** Builds the URL for one srcset width. */\nexport type ImageLoader = (src: string, width: number, height?: number) => string\n\n/**\n * Default loader: adds `?width=<w>` (the convention of most image CDNs and of\n * the OPS image proxy). URLs that cannot be parsed are returned unchanged.\n */\nexport const defaultImageLoader: ImageLoader = (src, width, height) => {\n try {\n const isAbsolute = /^[a-z][a-z0-9+.-]*:/i.test(src)\n const url = new URL(src, 'http://relative.invalid')\n url.searchParams.set('width', String(width))\n if (height) url.searchParams.set('height', String(height))\n return isAbsolute ? url.toString() : url.pathname + url.search + url.hash\n } catch {\n return src\n }\n}\n\nexport type ImageProps = Omit<ComponentPropsWithoutRef<'img'>, 'src' | 'srcSet' | 'width' | 'height'> & {\n data: ImageData\n /** `sizes` attribute (default `100vw`). */\n sizes?: string\n /** Candidate widths for `srcset` (capped at the intrinsic width when known). */\n widths?: readonly number[]\n /** URL builder per width (default adds `?width=`). Pass `null` to disable srcset. */\n loader?: ImageLoader | null\n /** Above-the-fold image: eager loading and `fetchpriority=\"high\"`. */\n priority?: boolean\n /** Forces an aspect ratio, e.g. `1/1` or `4/3`, used for width/height and srcset heights. */\n aspectRatio?: string\n}\n\nfunction parseRatio(ratio: string | undefined): number | null {\n if (!ratio) return null\n const [w, h] = ratio.split(/[/:]/).map((n) => Number.parseFloat(n))\n return w && h ? w / h : null\n}\n\n/** Responsive `<img>` with `srcset`, lazy by default, intrinsic size to avoid layout shift. */\nexport function Image({\n data,\n sizes = '100vw',\n widths = DEFAULT_IMAGE_WIDTHS,\n loader = defaultImageLoader,\n priority = false,\n aspectRatio,\n alt,\n loading,\n decoding,\n ...rest\n}: ImageProps) {\n const ratio = parseRatio(aspectRatio) ?? (data.width && data.height ? data.width / data.height : null)\n let candidates = [...widths].sort((a, b) => a - b)\n if (data.width) {\n const capped = candidates.filter((w) => w <= data.width!)\n candidates = capped.length ? capped : [data.width]\n }\n const srcSet = loader\n ? candidates.map((w) => `${loader(data.url, w, ratio ? Math.round(w / ratio) : undefined)} ${w}w`).join(', ')\n : undefined\n const width = data.width ?? candidates[candidates.length - 1]\n const height = data.height ?? (ratio && width ? Math.round(width / ratio) : undefined)\n return (\n <img\n src={data.url}\n alt={alt ?? data.alt ?? ''}\n {...(srcSet ? { srcSet, sizes } : {})}\n {...(width ? { width } : {})}\n {...(height ? { height } : {})}\n loading={loading ?? (priority ? 'eager' : 'lazy')}\n decoding={decoding ?? (priority ? 'auto' : 'async')}\n {...(priority ? { fetchPriority: 'high' as const } : {})}\n {...rest}\n />\n )\n}\n\n// ---------------------------------------------------------------------------\n// ProductPrice\n// ---------------------------------------------------------------------------\n\nconst VISUALLY_HIDDEN = {\n position: 'absolute',\n width: 1,\n height: 1,\n padding: 0,\n margin: -1,\n overflow: 'hidden',\n clip: 'rect(0, 0, 0, 0)',\n whiteSpace: 'nowrap',\n border: 0,\n} as const\n\nexport type ProductPriceProps = Omit<ComponentPropsWithoutRef<'div'>, 'children'> & {\n product?: Pick<Product, 'price_range' | 'compare_at_price_range'> | null\n variant?: Pick<ProductVariant, 'price' | 'compare_at_price'> | null\n /** Prefix shown when the product has a price range and no variant is selected (default `Desde`). */\n fromLabel?: ReactNode\n /** Accessible label for the compare-at price (default `Precio anterior`). */\n compareAtLabel?: string\n locale?: string\n withoutTrailingZeros?: boolean\n}\n\n/**\n * Price with optional compare-at (strikethrough). With a `variant` it shows\n * that variant; otherwise the product's minimum price (prefixed with\n * `fromLabel` when prices vary).\n */\nexport function ProductPrice({\n product,\n variant,\n fromLabel = 'Desde',\n compareAtLabel = 'Precio anterior',\n locale,\n withoutTrailingZeros,\n ...rest\n}: ProductPriceProps) {\n let price: MoneyData | null = null\n let compareAt: MoneyData | null = null\n let isRange = false\n if (variant) {\n price = variant.price\n compareAt = variant.compare_at_price\n } else if (product) {\n price = product.price_range.min\n compareAt = product.compare_at_price_range?.min ?? null\n isRange = product.price_range.min.amount !== product.price_range.max.amount\n }\n if (!price) return null\n const onSale = compareAt !== null && parseMoney(compareAt) > parseMoney(price)\n const opts = { ...(locale ? { locale } : {}), ...(withoutTrailingZeros !== undefined ? { withoutTrailingZeros } : {}) }\n return (\n <div data-on-sale={onSale || undefined} {...rest}>\n {isRange ? <span data-price-prefix=\"\">{fromLabel} </span> : null}\n <Money data={price} data-price=\"\" {...opts} />\n {onSale && compareAt ? (\n <>\n {' '}\n <s data-compare-at-price=\"\">\n <span style={VISUALLY_HIDDEN}>{compareAtLabel}: </span>\n <Money data={compareAt} {...opts} />\n </s>\n </>\n ) : null}\n </div>\n )\n}\n"]}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ComponentPropsWithoutRef, ElementType, ReactNode } from 'react';
|
|
3
|
+
import { Image as Image$1, FormatMoneyOptions, Money as Money$1, Product, ProductVariant } from '@asteby/storefront';
|
|
4
|
+
|
|
5
|
+
type MoneyProps<As extends ElementType = 'span'> = FormatMoneyOptions & {
|
|
6
|
+
data: Money$1;
|
|
7
|
+
/** Element to render (default `span`). */
|
|
8
|
+
as?: As;
|
|
9
|
+
/** Overrides the provider locale. */
|
|
10
|
+
locale?: string;
|
|
11
|
+
} & Omit<ComponentPropsWithoutRef<As>, 'children' | 'as'>;
|
|
12
|
+
/** Formats `Money` with the provider locale (or `locale`). */
|
|
13
|
+
declare function Money<As extends ElementType = 'span'>({ data, as, locale, withoutTrailingZeros, withoutCurrency, currencyDisplay, ...rest }: MoneyProps<As>): react.ReactElement<any, string | react.JSXElementConstructor<any>>;
|
|
14
|
+
declare const DEFAULT_IMAGE_WIDTHS: readonly [320, 480, 640, 768, 1024, 1280, 1600];
|
|
15
|
+
/** Builds the URL for one srcset width. */
|
|
16
|
+
type ImageLoader = (src: string, width: number, height?: number) => string;
|
|
17
|
+
/**
|
|
18
|
+
* Default loader: adds `?width=<w>` (the convention of most image CDNs and of
|
|
19
|
+
* the OPS image proxy). URLs that cannot be parsed are returned unchanged.
|
|
20
|
+
*/
|
|
21
|
+
declare const defaultImageLoader: ImageLoader;
|
|
22
|
+
type ImageProps = Omit<ComponentPropsWithoutRef<'img'>, 'src' | 'srcSet' | 'width' | 'height'> & {
|
|
23
|
+
data: Image$1;
|
|
24
|
+
/** `sizes` attribute (default `100vw`). */
|
|
25
|
+
sizes?: string;
|
|
26
|
+
/** Candidate widths for `srcset` (capped at the intrinsic width when known). */
|
|
27
|
+
widths?: readonly number[];
|
|
28
|
+
/** URL builder per width (default adds `?width=`). Pass `null` to disable srcset. */
|
|
29
|
+
loader?: ImageLoader | null;
|
|
30
|
+
/** Above-the-fold image: eager loading and `fetchpriority="high"`. */
|
|
31
|
+
priority?: boolean;
|
|
32
|
+
/** Forces an aspect ratio, e.g. `1/1` or `4/3`, used for width/height and srcset heights. */
|
|
33
|
+
aspectRatio?: string;
|
|
34
|
+
};
|
|
35
|
+
/** Responsive `<img>` with `srcset`, lazy by default, intrinsic size to avoid layout shift. */
|
|
36
|
+
declare function Image({ data, sizes, widths, loader, priority, aspectRatio, alt, loading, decoding, ...rest }: ImageProps): react.JSX.Element;
|
|
37
|
+
type ProductPriceProps = Omit<ComponentPropsWithoutRef<'div'>, 'children'> & {
|
|
38
|
+
product?: Pick<Product, 'price_range' | 'compare_at_price_range'> | null;
|
|
39
|
+
variant?: Pick<ProductVariant, 'price' | 'compare_at_price'> | null;
|
|
40
|
+
/** Prefix shown when the product has a price range and no variant is selected (default `Desde`). */
|
|
41
|
+
fromLabel?: ReactNode;
|
|
42
|
+
/** Accessible label for the compare-at price (default `Precio anterior`). */
|
|
43
|
+
compareAtLabel?: string;
|
|
44
|
+
locale?: string;
|
|
45
|
+
withoutTrailingZeros?: boolean;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Price with optional compare-at (strikethrough). With a `variant` it shows
|
|
49
|
+
* that variant; otherwise the product's minimum price (prefixed with
|
|
50
|
+
* `fromLabel` when prices vary).
|
|
51
|
+
*/
|
|
52
|
+
declare function ProductPrice({ product, variant, fromLabel, compareAtLabel, locale, withoutTrailingZeros, ...rest }: ProductPriceProps): react.JSX.Element | null;
|
|
53
|
+
|
|
54
|
+
export { DEFAULT_IMAGE_WIDTHS as D, Image as I, Money as M, ProductPrice as P, type ImageLoader as a, type ImageProps as b, type MoneyProps as c, type ProductPriceProps as d, defaultImageLoader as e };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ComponentPropsWithoutRef, ElementType, ReactNode } from 'react';
|
|
3
|
+
import { Image as Image$1, FormatMoneyOptions, Money as Money$1, Product, ProductVariant } from '@asteby/storefront';
|
|
4
|
+
|
|
5
|
+
type MoneyProps<As extends ElementType = 'span'> = FormatMoneyOptions & {
|
|
6
|
+
data: Money$1;
|
|
7
|
+
/** Element to render (default `span`). */
|
|
8
|
+
as?: As;
|
|
9
|
+
/** Overrides the provider locale. */
|
|
10
|
+
locale?: string;
|
|
11
|
+
} & Omit<ComponentPropsWithoutRef<As>, 'children' | 'as'>;
|
|
12
|
+
/** Formats `Money` with the provider locale (or `locale`). */
|
|
13
|
+
declare function Money<As extends ElementType = 'span'>({ data, as, locale, withoutTrailingZeros, withoutCurrency, currencyDisplay, ...rest }: MoneyProps<As>): react.ReactElement<any, string | react.JSXElementConstructor<any>>;
|
|
14
|
+
declare const DEFAULT_IMAGE_WIDTHS: readonly [320, 480, 640, 768, 1024, 1280, 1600];
|
|
15
|
+
/** Builds the URL for one srcset width. */
|
|
16
|
+
type ImageLoader = (src: string, width: number, height?: number) => string;
|
|
17
|
+
/**
|
|
18
|
+
* Default loader: adds `?width=<w>` (the convention of most image CDNs and of
|
|
19
|
+
* the OPS image proxy). URLs that cannot be parsed are returned unchanged.
|
|
20
|
+
*/
|
|
21
|
+
declare const defaultImageLoader: ImageLoader;
|
|
22
|
+
type ImageProps = Omit<ComponentPropsWithoutRef<'img'>, 'src' | 'srcSet' | 'width' | 'height'> & {
|
|
23
|
+
data: Image$1;
|
|
24
|
+
/** `sizes` attribute (default `100vw`). */
|
|
25
|
+
sizes?: string;
|
|
26
|
+
/** Candidate widths for `srcset` (capped at the intrinsic width when known). */
|
|
27
|
+
widths?: readonly number[];
|
|
28
|
+
/** URL builder per width (default adds `?width=`). Pass `null` to disable srcset. */
|
|
29
|
+
loader?: ImageLoader | null;
|
|
30
|
+
/** Above-the-fold image: eager loading and `fetchpriority="high"`. */
|
|
31
|
+
priority?: boolean;
|
|
32
|
+
/** Forces an aspect ratio, e.g. `1/1` or `4/3`, used for width/height and srcset heights. */
|
|
33
|
+
aspectRatio?: string;
|
|
34
|
+
};
|
|
35
|
+
/** Responsive `<img>` with `srcset`, lazy by default, intrinsic size to avoid layout shift. */
|
|
36
|
+
declare function Image({ data, sizes, widths, loader, priority, aspectRatio, alt, loading, decoding, ...rest }: ImageProps): react.JSX.Element;
|
|
37
|
+
type ProductPriceProps = Omit<ComponentPropsWithoutRef<'div'>, 'children'> & {
|
|
38
|
+
product?: Pick<Product, 'price_range' | 'compare_at_price_range'> | null;
|
|
39
|
+
variant?: Pick<ProductVariant, 'price' | 'compare_at_price'> | null;
|
|
40
|
+
/** Prefix shown when the product has a price range and no variant is selected (default `Desde`). */
|
|
41
|
+
fromLabel?: ReactNode;
|
|
42
|
+
/** Accessible label for the compare-at price (default `Precio anterior`). */
|
|
43
|
+
compareAtLabel?: string;
|
|
44
|
+
locale?: string;
|
|
45
|
+
withoutTrailingZeros?: boolean;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Price with optional compare-at (strikethrough). With a `variant` it shows
|
|
49
|
+
* that variant; otherwise the product's minimum price (prefixed with
|
|
50
|
+
* `fromLabel` when prices vary).
|
|
51
|
+
*/
|
|
52
|
+
declare function ProductPrice({ product, variant, fromLabel, compareAtLabel, locale, withoutTrailingZeros, ...rest }: ProductPriceProps): react.JSX.Element | null;
|
|
53
|
+
|
|
54
|
+
export { DEFAULT_IMAGE_WIDTHS as D, Image as I, Money as M, ProductPrice as P, type ImageLoader as a, type ImageProps as b, type MoneyProps as c, type ProductPriceProps as d, defaultImageLoader as e };
|
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
|
-
import { ReactNode, ComponentPropsWithoutRef,
|
|
3
|
-
import { StorefrontClient, Shop, StorefrontClientOptions, Cart, CartLineInput, CartLineMerchandise, CartLineUpdateInput, CartBuyerInput, AddressInput, DeliveryInput, DeliveryOptions,
|
|
2
|
+
import { ReactNode, ComponentPropsWithoutRef, ComponentType, FormEvent } from 'react';
|
|
3
|
+
import { StorefrontClient, Shop, StorefrontClientOptions, Cart, CartLineInput, CartLineMerchandise, CartLineUpdateInput, CartBuyerInput, AddressInput, DeliveryInput, DeliveryOptions, ProductVariant, Product, Image, Collection, Section, Theme, GeoPoint, ShopBranch, Money } from '@asteby/storefront';
|
|
4
|
+
export { D as DEFAULT_IMAGE_WIDTHS, I as Image, a as ImageLoader, b as ImageProps, M as Money, c as MoneyProps, P as ProductPrice, d as ProductPriceProps, e as defaultImageLoader } from './components-B5XhSH-m.cjs';
|
|
4
5
|
import { OpeningHours, GeoPoint as GeoPoint$1, OpenStatus as OpenStatus$1 } from '@asteby/storefront/geo';
|
|
5
6
|
|
|
6
7
|
type StorefrontContextValue = {
|
|
@@ -124,55 +125,6 @@ declare function useCart(): CartContextValue;
|
|
|
124
125
|
/** Cart context or `null` outside a provider. */
|
|
125
126
|
declare function useOptionalCart(): CartContextValue | null;
|
|
126
127
|
|
|
127
|
-
type MoneyProps<As extends ElementType = 'span'> = FormatMoneyOptions & {
|
|
128
|
-
data: Money$1;
|
|
129
|
-
/** Element to render (default `span`). */
|
|
130
|
-
as?: As;
|
|
131
|
-
/** Overrides the provider locale. */
|
|
132
|
-
locale?: string;
|
|
133
|
-
} & Omit<ComponentPropsWithoutRef<As>, 'children' | 'as'>;
|
|
134
|
-
/** Formats `Money` with the provider locale (or `locale`). */
|
|
135
|
-
declare function Money<As extends ElementType = 'span'>({ data, as, locale, withoutTrailingZeros, withoutCurrency, currencyDisplay, ...rest }: MoneyProps<As>): react.ReactElement<any, string | react.JSXElementConstructor<any>>;
|
|
136
|
-
declare const DEFAULT_IMAGE_WIDTHS: readonly [320, 480, 640, 768, 1024, 1280, 1600];
|
|
137
|
-
/** Builds the URL for one srcset width. */
|
|
138
|
-
type ImageLoader = (src: string, width: number, height?: number) => string;
|
|
139
|
-
/**
|
|
140
|
-
* Default loader: adds `?width=<w>` (the convention of most image CDNs and of
|
|
141
|
-
* the OPS image proxy). URLs that cannot be parsed are returned unchanged.
|
|
142
|
-
*/
|
|
143
|
-
declare const defaultImageLoader: ImageLoader;
|
|
144
|
-
type ImageProps = Omit<ComponentPropsWithoutRef<'img'>, 'src' | 'srcSet' | 'width' | 'height'> & {
|
|
145
|
-
data: Image$1;
|
|
146
|
-
/** `sizes` attribute (default `100vw`). */
|
|
147
|
-
sizes?: string;
|
|
148
|
-
/** Candidate widths for `srcset` (capped at the intrinsic width when known). */
|
|
149
|
-
widths?: readonly number[];
|
|
150
|
-
/** URL builder per width (default adds `?width=`). Pass `null` to disable srcset. */
|
|
151
|
-
loader?: ImageLoader | null;
|
|
152
|
-
/** Above-the-fold image: eager loading and `fetchpriority="high"`. */
|
|
153
|
-
priority?: boolean;
|
|
154
|
-
/** Forces an aspect ratio, e.g. `1/1` or `4/3`, used for width/height and srcset heights. */
|
|
155
|
-
aspectRatio?: string;
|
|
156
|
-
};
|
|
157
|
-
/** Responsive `<img>` with `srcset`, lazy by default, intrinsic size to avoid layout shift. */
|
|
158
|
-
declare function Image({ data, sizes, widths, loader, priority, aspectRatio, alt, loading, decoding, ...rest }: ImageProps): react.JSX.Element;
|
|
159
|
-
type ProductPriceProps = Omit<ComponentPropsWithoutRef<'div'>, 'children'> & {
|
|
160
|
-
product?: Pick<Product, 'price_range' | 'compare_at_price_range'> | null;
|
|
161
|
-
variant?: Pick<ProductVariant, 'price' | 'compare_at_price'> | null;
|
|
162
|
-
/** Prefix shown when the product has a price range and no variant is selected (default `Desde`). */
|
|
163
|
-
fromLabel?: ReactNode;
|
|
164
|
-
/** Accessible label for the compare-at price (default `Precio anterior`). */
|
|
165
|
-
compareAtLabel?: string;
|
|
166
|
-
locale?: string;
|
|
167
|
-
withoutTrailingZeros?: boolean;
|
|
168
|
-
};
|
|
169
|
-
/**
|
|
170
|
-
* Price with optional compare-at (strikethrough). With a `variant` it shows
|
|
171
|
-
* that variant; otherwise the product's minimum price (prefixed with
|
|
172
|
-
* `fromLabel` when prices vary).
|
|
173
|
-
*/
|
|
174
|
-
declare function ProductPrice({ product, variant, fromLabel, compareAtLabel, locale, withoutTrailingZeros, ...rest }: ProductPriceProps): react.JSX.Element | null;
|
|
175
|
-
|
|
176
128
|
type ProductOptionValueState = {
|
|
177
129
|
value: string;
|
|
178
130
|
/** Part of the current selection. */
|
|
@@ -285,7 +237,7 @@ type SeoMetaInput = {
|
|
|
285
237
|
description?: string | null;
|
|
286
238
|
/** Canonical absolute URL. */
|
|
287
239
|
url?: string | null;
|
|
288
|
-
image?: Image
|
|
240
|
+
image?: Image | string | null;
|
|
289
241
|
/** `og:type` (default `website`). */
|
|
290
242
|
type?: string;
|
|
291
243
|
siteName?: string | null;
|
|
@@ -665,7 +617,7 @@ declare function DirectionsLink({ location, provider, children, ...rest }: Direc
|
|
|
665
617
|
type PickupInfo<L extends ShopBranch = ShopBranch> = {
|
|
666
618
|
location: L;
|
|
667
619
|
/** `null` = free. Amount as sent by OPS; nothing is calculated here. */
|
|
668
|
-
fee: Money
|
|
620
|
+
fee: Money | null;
|
|
669
621
|
free: boolean;
|
|
670
622
|
/** Formatted `fee` (`null` when free). */
|
|
671
623
|
feeText: string | null;
|
|
@@ -703,4 +655,4 @@ type NearestLocationFormProps<L extends ShopBranch = ShopBranch> = {
|
|
|
703
655
|
*/
|
|
704
656
|
declare function NearestLocationForm<L extends ShopBranch = ShopBranch>({ locations, action, name, defaultValue, onSubmitPostalCode, onLocate, labels, children, ...rest }: NearestLocationFormProps<L>): react.JSX.Element | null;
|
|
705
657
|
|
|
706
|
-
export { AddToCartButton, type AddToCartButtonProps, type BreadcrumbItem, CART_COOKIE_NAME, type CartContextValue, type CartCookieOptions, type CartLineAddInput, CartProvider, type CartProviderProps, type CartStatus,
|
|
658
|
+
export { AddToCartButton, type AddToCartButtonProps, type BreadcrumbItem, CART_COOKIE_NAME, type CartContextValue, type CartCookieOptions, type CartLineAddInput, CartProvider, type CartProviderProps, type CartStatus, DirectionsLink, type DirectionsLinkProps, type FaqItem, type GeolocationErrorCode, type GeolocationFailure, type GeolocationPermission, type InferSectionProps, JsonLd, type JsonLdObject, type JsonLdProps, type LocalBusinessOptions, type LocationItemState, LocationList, type LocationListProps, LocationPicker, type LocationPickerProps, type MetaDescriptor, type NearbyLocation, NearestLocationForm, type NearestLocationFormLabels, type NearestLocationFormProps, OpenStatus, type OpenStatusLabels, type OpenStatusProps, type PickupInfo, PickupOption, type PickupOptionProps, type ProductOptionState, type ProductOptionValueState, type ProductOptionsState, SELECTED_LOCATION_PARAM, SELECTED_LOCATION_STORAGE_KEY, type SectionComponentProps, type SectionDefinition, type SectionPropError, type SectionPropKind, type SectionPropSchema, SectionRegistry, type SectionSchema, Sections, type SectionsProps, type SeoMetaInput, type StorefrontContextValue, StorefrontProvider, type StorefrontProviderProps, type ThemeCssOptions, ThemeStyle, type ThemeStyleProps, type UseGeolocationOptions, type UseGeolocationResult, type UseNearestLocationsOptions, type UseNearestLocationsResult, type UseProductOptionsConfig, type UseSelectedLocationOptions, type UseSelectedLocationResult, VariantSelector, type VariantSelectorProps, type VariantSelectorRenderProps, breadcrumbJsonLd, collectionJsonLd, collectionMeta, createSectionRegistry, defineSection, faqJsonLd, getCartIdFromCookie, isSafeCssValue, localBusinessJsonLd, openingHoursJsonLd, optimisticCart, organizationJsonLd, productJsonLd, productMeta, readCartCookie, readSelectedLocationId, resolveSectionProps, sectionJsonSchema, seoMeta, serializeCartCookie, serializeJsonLd, themeFontsHref, themeToCss, themeToCssVariables, toMerchandise, tokenName, useCart, useGeolocation, useNearestLocations, useOptionalCart, useOptionalStorefront, useProductOptions, useSelectedLocation, useStorefront, useStorefrontClient, writeCartCookie };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
|
-
import { ReactNode, ComponentPropsWithoutRef,
|
|
3
|
-
import { StorefrontClient, Shop, StorefrontClientOptions, Cart, CartLineInput, CartLineMerchandise, CartLineUpdateInput, CartBuyerInput, AddressInput, DeliveryInput, DeliveryOptions,
|
|
2
|
+
import { ReactNode, ComponentPropsWithoutRef, ComponentType, FormEvent } from 'react';
|
|
3
|
+
import { StorefrontClient, Shop, StorefrontClientOptions, Cart, CartLineInput, CartLineMerchandise, CartLineUpdateInput, CartBuyerInput, AddressInput, DeliveryInput, DeliveryOptions, ProductVariant, Product, Image, Collection, Section, Theme, GeoPoint, ShopBranch, Money } from '@asteby/storefront';
|
|
4
|
+
export { D as DEFAULT_IMAGE_WIDTHS, I as Image, a as ImageLoader, b as ImageProps, M as Money, c as MoneyProps, P as ProductPrice, d as ProductPriceProps, e as defaultImageLoader } from './components-B5XhSH-m.js';
|
|
4
5
|
import { OpeningHours, GeoPoint as GeoPoint$1, OpenStatus as OpenStatus$1 } from '@asteby/storefront/geo';
|
|
5
6
|
|
|
6
7
|
type StorefrontContextValue = {
|
|
@@ -124,55 +125,6 @@ declare function useCart(): CartContextValue;
|
|
|
124
125
|
/** Cart context or `null` outside a provider. */
|
|
125
126
|
declare function useOptionalCart(): CartContextValue | null;
|
|
126
127
|
|
|
127
|
-
type MoneyProps<As extends ElementType = 'span'> = FormatMoneyOptions & {
|
|
128
|
-
data: Money$1;
|
|
129
|
-
/** Element to render (default `span`). */
|
|
130
|
-
as?: As;
|
|
131
|
-
/** Overrides the provider locale. */
|
|
132
|
-
locale?: string;
|
|
133
|
-
} & Omit<ComponentPropsWithoutRef<As>, 'children' | 'as'>;
|
|
134
|
-
/** Formats `Money` with the provider locale (or `locale`). */
|
|
135
|
-
declare function Money<As extends ElementType = 'span'>({ data, as, locale, withoutTrailingZeros, withoutCurrency, currencyDisplay, ...rest }: MoneyProps<As>): react.ReactElement<any, string | react.JSXElementConstructor<any>>;
|
|
136
|
-
declare const DEFAULT_IMAGE_WIDTHS: readonly [320, 480, 640, 768, 1024, 1280, 1600];
|
|
137
|
-
/** Builds the URL for one srcset width. */
|
|
138
|
-
type ImageLoader = (src: string, width: number, height?: number) => string;
|
|
139
|
-
/**
|
|
140
|
-
* Default loader: adds `?width=<w>` (the convention of most image CDNs and of
|
|
141
|
-
* the OPS image proxy). URLs that cannot be parsed are returned unchanged.
|
|
142
|
-
*/
|
|
143
|
-
declare const defaultImageLoader: ImageLoader;
|
|
144
|
-
type ImageProps = Omit<ComponentPropsWithoutRef<'img'>, 'src' | 'srcSet' | 'width' | 'height'> & {
|
|
145
|
-
data: Image$1;
|
|
146
|
-
/** `sizes` attribute (default `100vw`). */
|
|
147
|
-
sizes?: string;
|
|
148
|
-
/** Candidate widths for `srcset` (capped at the intrinsic width when known). */
|
|
149
|
-
widths?: readonly number[];
|
|
150
|
-
/** URL builder per width (default adds `?width=`). Pass `null` to disable srcset. */
|
|
151
|
-
loader?: ImageLoader | null;
|
|
152
|
-
/** Above-the-fold image: eager loading and `fetchpriority="high"`. */
|
|
153
|
-
priority?: boolean;
|
|
154
|
-
/** Forces an aspect ratio, e.g. `1/1` or `4/3`, used for width/height and srcset heights. */
|
|
155
|
-
aspectRatio?: string;
|
|
156
|
-
};
|
|
157
|
-
/** Responsive `<img>` with `srcset`, lazy by default, intrinsic size to avoid layout shift. */
|
|
158
|
-
declare function Image({ data, sizes, widths, loader, priority, aspectRatio, alt, loading, decoding, ...rest }: ImageProps): react.JSX.Element;
|
|
159
|
-
type ProductPriceProps = Omit<ComponentPropsWithoutRef<'div'>, 'children'> & {
|
|
160
|
-
product?: Pick<Product, 'price_range' | 'compare_at_price_range'> | null;
|
|
161
|
-
variant?: Pick<ProductVariant, 'price' | 'compare_at_price'> | null;
|
|
162
|
-
/** Prefix shown when the product has a price range and no variant is selected (default `Desde`). */
|
|
163
|
-
fromLabel?: ReactNode;
|
|
164
|
-
/** Accessible label for the compare-at price (default `Precio anterior`). */
|
|
165
|
-
compareAtLabel?: string;
|
|
166
|
-
locale?: string;
|
|
167
|
-
withoutTrailingZeros?: boolean;
|
|
168
|
-
};
|
|
169
|
-
/**
|
|
170
|
-
* Price with optional compare-at (strikethrough). With a `variant` it shows
|
|
171
|
-
* that variant; otherwise the product's minimum price (prefixed with
|
|
172
|
-
* `fromLabel` when prices vary).
|
|
173
|
-
*/
|
|
174
|
-
declare function ProductPrice({ product, variant, fromLabel, compareAtLabel, locale, withoutTrailingZeros, ...rest }: ProductPriceProps): react.JSX.Element | null;
|
|
175
|
-
|
|
176
128
|
type ProductOptionValueState = {
|
|
177
129
|
value: string;
|
|
178
130
|
/** Part of the current selection. */
|
|
@@ -285,7 +237,7 @@ type SeoMetaInput = {
|
|
|
285
237
|
description?: string | null;
|
|
286
238
|
/** Canonical absolute URL. */
|
|
287
239
|
url?: string | null;
|
|
288
|
-
image?: Image
|
|
240
|
+
image?: Image | string | null;
|
|
289
241
|
/** `og:type` (default `website`). */
|
|
290
242
|
type?: string;
|
|
291
243
|
siteName?: string | null;
|
|
@@ -665,7 +617,7 @@ declare function DirectionsLink({ location, provider, children, ...rest }: Direc
|
|
|
665
617
|
type PickupInfo<L extends ShopBranch = ShopBranch> = {
|
|
666
618
|
location: L;
|
|
667
619
|
/** `null` = free. Amount as sent by OPS; nothing is calculated here. */
|
|
668
|
-
fee: Money
|
|
620
|
+
fee: Money | null;
|
|
669
621
|
free: boolean;
|
|
670
622
|
/** Formatted `fee` (`null` when free). */
|
|
671
623
|
feeText: string | null;
|
|
@@ -703,4 +655,4 @@ type NearestLocationFormProps<L extends ShopBranch = ShopBranch> = {
|
|
|
703
655
|
*/
|
|
704
656
|
declare function NearestLocationForm<L extends ShopBranch = ShopBranch>({ locations, action, name, defaultValue, onSubmitPostalCode, onLocate, labels, children, ...rest }: NearestLocationFormProps<L>): react.JSX.Element | null;
|
|
705
657
|
|
|
706
|
-
export { AddToCartButton, type AddToCartButtonProps, type BreadcrumbItem, CART_COOKIE_NAME, type CartContextValue, type CartCookieOptions, type CartLineAddInput, CartProvider, type CartProviderProps, type CartStatus,
|
|
658
|
+
export { AddToCartButton, type AddToCartButtonProps, type BreadcrumbItem, CART_COOKIE_NAME, type CartContextValue, type CartCookieOptions, type CartLineAddInput, CartProvider, type CartProviderProps, type CartStatus, DirectionsLink, type DirectionsLinkProps, type FaqItem, type GeolocationErrorCode, type GeolocationFailure, type GeolocationPermission, type InferSectionProps, JsonLd, type JsonLdObject, type JsonLdProps, type LocalBusinessOptions, type LocationItemState, LocationList, type LocationListProps, LocationPicker, type LocationPickerProps, type MetaDescriptor, type NearbyLocation, NearestLocationForm, type NearestLocationFormLabels, type NearestLocationFormProps, OpenStatus, type OpenStatusLabels, type OpenStatusProps, type PickupInfo, PickupOption, type PickupOptionProps, type ProductOptionState, type ProductOptionValueState, type ProductOptionsState, SELECTED_LOCATION_PARAM, SELECTED_LOCATION_STORAGE_KEY, type SectionComponentProps, type SectionDefinition, type SectionPropError, type SectionPropKind, type SectionPropSchema, SectionRegistry, type SectionSchema, Sections, type SectionsProps, type SeoMetaInput, type StorefrontContextValue, StorefrontProvider, type StorefrontProviderProps, type ThemeCssOptions, ThemeStyle, type ThemeStyleProps, type UseGeolocationOptions, type UseGeolocationResult, type UseNearestLocationsOptions, type UseNearestLocationsResult, type UseProductOptionsConfig, type UseSelectedLocationOptions, type UseSelectedLocationResult, VariantSelector, type VariantSelectorProps, type VariantSelectorRenderProps, breadcrumbJsonLd, collectionJsonLd, collectionMeta, createSectionRegistry, defineSection, faqJsonLd, getCartIdFromCookie, isSafeCssValue, localBusinessJsonLd, openingHoursJsonLd, optimisticCart, organizationJsonLd, productJsonLd, productMeta, readCartCookie, readSelectedLocationId, resolveSectionProps, sectionJsonSchema, seoMeta, serializeCartCookie, serializeJsonLd, themeFontsHref, themeToCss, themeToCssVariables, toMerchandise, tokenName, useCart, useGeolocation, useNearestLocations, useOptionalCart, useOptionalStorefront, useProductOptions, useSelectedLocation, useStorefront, useStorefrontClient, writeCartCookie };
|