@asteby/storefront-react 0.2.0 → 0.4.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,262 @@
1
+ import * as react from 'react';
2
+ import { SVGProps, ReactNode, CSSProperties, ComponentType } from 'react';
3
+ import { Product, ProductVariant, Image } from '@asteby/storefront';
4
+ import { BuiltinMockupData, MockupProduct, MockupVariant, GenericMockupData, PartMockupData, SupplementMockupData, TireMockupData, MockupKind } from '@asteby/storefront/mockup';
5
+ export { BUILTIN_MOCKUP_KINDS, BuiltinMockupData, BuiltinMockupKind, DEFAULT_MOCKUP_KIND_RULES, GenericMockupData, MOCKUP_KIND_ATTRIBUTES, MOCKUP_TEXT_LIMITS, MockupDataMap, MockupKind, MockupKindRule, MockupProduct, MockupVariant, PartMockupData, ResolveMockupKindOptions, SupplementMockupData, SupplementShape, TireMockupData, cleanMockupText, genericMockupData, mockupDataFromProduct, mockupMonogram, partMockupData, resolveMockupKind, supplementMockupData, tireMockupData } from '@asteby/storefront/mockup';
6
+ import { b as ImageProps } from './components-B5XhSH-m.js';
7
+
8
+ /** Side of the square viewBox every mockup draws in. */
9
+ declare const MOCKUP_SIZE = 400;
10
+ /**
11
+ * Theme tokens. Each mockup reads `--mockup-*` (set them in the store CSS),
12
+ * falls back to the store theme (`--color-muted`, `--color-primary`... as
13
+ * emitted by `ThemeStyle`) and finally to neutral greys that follow
14
+ * `color-scheme` through `light-dark()`. No brand colors live here.
15
+ */
16
+ declare const MOCKUP_TOKENS: {
17
+ readonly bg: "var(--mockup-bg, var(--color-muted, light-dark(#f4f4f5, #27272a)))";
18
+ readonly surface: "var(--mockup-surface, light-dark(#3f3f46, #0a0a0a))";
19
+ readonly 'surface-ink': "var(--mockup-surface-ink, light-dark(#e4e4e7, #a1a1aa))";
20
+ readonly label: "var(--mockup-label, var(--color-background, light-dark(#ffffff, #18181b)))";
21
+ readonly 'label-ink': "var(--mockup-label-ink, var(--color-foreground, light-dark(#18181b, #fafafa)))";
22
+ readonly ink: "var(--mockup-ink, var(--color-foreground, light-dark(#18181b, #fafafa)))";
23
+ readonly muted: "var(--mockup-muted, var(--color-muted-foreground, light-dark(#71717a, #a1a1aa)))";
24
+ readonly accent: "var(--mockup-accent, var(--color-primary, light-dark(#52525b, #d4d4d8)))";
25
+ readonly 'accent-ink': "var(--mockup-accent-ink, var(--color-primary-foreground, light-dark(#ffffff, #18181b)))";
26
+ };
27
+ type MockupTone = keyof typeof MOCKUP_TOKENS;
28
+ /** `style` that paints an element with a token: `<rect style={tone('accent')} />`. */
29
+ declare function tone(t: MockupTone, prop?: 'fill' | 'stroke'): CSSProperties;
30
+ /** Monospace stack for part numbers and sizes (`--mockup-font-mono`). */
31
+ declare const MOCKUP_MONO = "var(--mockup-font-mono, var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace))";
32
+ /**
33
+ * Greedy word wrap by characters; the last allowed line ends in `…` when text
34
+ * is cut. Words longer than `wordMax` (default `maxChars`) are cut with `…`; a
35
+ * word between `maxChars` and `wordMax` keeps a line of its own, so the caller
36
+ * can shrink the font to fit it (`fitMockupFontSize`) instead of cutting it.
37
+ */
38
+ declare function wrapMockupText(text: string | null | undefined, maxChars: number, maxLines: number, wordMax?: number): string[];
39
+ /** Longest word (in characters) that still fits `width` at font size `min` (glyph width `ratio` em). */
40
+ declare function mockupWordMax(width: number, min: number, ratio?: number): number;
41
+ /** Font size so the longest line fits `width` (approximate glyph width `ratio` em). */
42
+ declare function fitMockupFontSize(lines: readonly string[], width: number, max: number, min?: number, ratio?: number): number;
43
+ type MockupTextProps = Omit<SVGProps<SVGTextElement>, 'children'> & {
44
+ lines: readonly string[];
45
+ x: number;
46
+ y: number;
47
+ size: number;
48
+ lineHeight?: number;
49
+ tone?: MockupTone;
50
+ weight?: number;
51
+ anchor?: 'start' | 'middle' | 'end';
52
+ mono?: boolean;
53
+ };
54
+ /** Multi-line `<text>`; `y` is the baseline of the first line. */
55
+ declare function MockupText({ lines, x, y, size, lineHeight, tone: t, weight, anchor, mono, style, ...rest }: MockupTextProps): react.JSX.Element | null;
56
+ type MockupFrameProps = Omit<SVGProps<SVGSVGElement>, 'children' | 'role' | 'ref'> & {
57
+ /** Accessible name (`aria-label` and `<title>`). */
58
+ label: string;
59
+ /** Hide from assistive tech (the product name is already next to it). */
60
+ decorative?: boolean;
61
+ /** Written to `data-mockup` for styling and tests. */
62
+ kind?: string;
63
+ children?: ReactNode;
64
+ };
65
+ /**
66
+ * The `<svg>` shell shared by every mockup: square viewBox, token variables,
67
+ * background, `role="img"` with an accessible name that says it is an
68
+ * illustration. Use it in custom renderers to get the same contract.
69
+ */
70
+ declare function MockupFrame({ label, decorative, kind, children, style, width, height, ...rest }: MockupFrameProps): react.JSX.Element;
71
+
72
+ /** Interface words used by the built-in mockups (generic UI text, not store copy). */
73
+ type MockupLabels = {
74
+ /** Prefix of every accessible name, so a mockup is never announced as a photo. */
75
+ illustration: string;
76
+ size: string;
77
+ partNumber: string;
78
+ oem: string;
79
+ fits: string;
80
+ flavor: string;
81
+ /** Unit after a numeric `servings` attribute. */
82
+ servings: string;
83
+ lightTruck: string;
84
+ runFlat: string;
85
+ };
86
+ declare const DEFAULT_MOCKUP_LABELS: MockupLabels;
87
+ /** Accessible name for built-in data: "Ilustración de referencia: <title>, <key spec>". */
88
+ declare function describeMockup(data: Partial<BuiltinMockupData> & {
89
+ title?: string | null;
90
+ }, labels?: MockupLabels): string;
91
+
92
+ /** Props every mockup component receives. Spread the rest on `<MockupFrame>`. */
93
+ type MockupComponentProps<D = unknown> = Omit<MockupFrameProps, 'label' | 'kind' | 'children'> & {
94
+ data: D;
95
+ /** Accessible name already built (prefixed with `labels.illustration`). */
96
+ label: string;
97
+ labels: MockupLabels;
98
+ };
99
+ type MockupComponent<D = unknown> = ComponentType<MockupComponentProps<D>>;
100
+ /** A registered mockup: how to draw it and, optionally, how to read its data from a product. */
101
+ type MockupRenderer<D = any> = {
102
+ component: MockupComponent<D>;
103
+ /** Product → data. Default: the built-in extractor for the kind (generic data for custom kinds). */
104
+ fromProduct?: (product: MockupProduct, variant?: MockupVariant | null) => D;
105
+ /** Data → accessible name. Default: `describeMockup`. */
106
+ describe?: (data: D, labels: MockupLabels) => string;
107
+ };
108
+
109
+ /** Closed box with the product monogram, the brand on the box and the name below. */
110
+ declare function GenericMockup({ data, label, labels: _labels, ...rest }: MockupComponentProps<GenericMockupData>): react.JSX.Element;
111
+
112
+ /** Hang tag ("ficha") with the part number in a band, the name and the compatibility. */
113
+ declare function PartMockup({ data, label, labels, ...rest }: MockupComponentProps<PartMockupData>): react.JSX.Element;
114
+
115
+ /** Tub, bottle or bag with a label: brand, product name, flavor and presentation. */
116
+ declare function SupplementMockup({ data, label, labels, ...rest }: MockupComponentProps<SupplementMockupData>): react.JSX.Element;
117
+
118
+ /** Tire seen from the side (tread blocks on the edge) with the size in big digits. Shows only what the data has. */
119
+ declare function TireMockup({ data, label, labels, ...rest }: MockupComponentProps<TireMockupData>): react.JSX.Element;
120
+
121
+ /** A renderer, or just its component (data then comes from the built-in extractor). */
122
+ type MockupRendererInput<D = any> = MockupRenderer<D> | MockupComponent<D>;
123
+ /** A resolved renderer: every hook filled in. */
124
+ type ResolvedMockupRenderer<D = any> = Required<MockupRenderer<D>>;
125
+ type MockupRegistry = {
126
+ /** Adds or replaces a kind. Returns the registry (chainable). */
127
+ register<D>(kind: MockupKind, renderer: MockupRendererInput<D>): MockupRegistry;
128
+ get(kind: MockupKind): ResolvedMockupRenderer | undefined;
129
+ has(kind: MockupKind): boolean;
130
+ kinds(): MockupKind[];
131
+ /** New registry with these entries plus the overrides (the original is untouched). */
132
+ extend(overrides?: Partial<Record<MockupKind, MockupRendererInput>>): MockupRegistry;
133
+ };
134
+ /** A registry of mockup kinds. Pass `BUILTIN_MOCKUPS` (or a subset) to start from the base ones. */
135
+ declare function createMockupRegistry(initial?: Partial<Record<MockupKind, MockupRendererInput>>): MockupRegistry;
136
+ /** The four base mockups. */
137
+ declare const BUILTIN_MOCKUPS: {
138
+ tire: typeof TireMockup;
139
+ part: typeof PartMockup;
140
+ supplement: typeof SupplementMockup;
141
+ generic: typeof GenericMockup;
142
+ };
143
+ /** Registry used when no `MockupProvider`/`registry` prop is given. */
144
+ declare const defaultMockupRegistry: MockupRegistry;
145
+ /**
146
+ * Registers a kind in the default registry (call it once at module scope, e.g.
147
+ * in `app/root.tsx`). For an isolated registry use `createMockupRegistry` + `MockupProvider`.
148
+ */
149
+ declare function registerMockup<D>(kind: MockupKind, renderer: MockupRendererInput<D>): MockupRegistry;
150
+ /**
151
+ * Store-level kind resolver. Receives the default guess; return a kind to
152
+ * override it, or `null`/`undefined` to keep the default.
153
+ */
154
+ type ResolveMockupKind = (product: MockupProduct, defaultKind: MockupKind) => MockupKind | null | undefined;
155
+ type MockupConfig = {
156
+ registry: MockupRegistry;
157
+ resolveKind?: ResolveMockupKind | undefined;
158
+ labels: MockupLabels;
159
+ };
160
+ type MockupProviderProps = {
161
+ registry?: MockupRegistry;
162
+ resolveKind?: ResolveMockupKind;
163
+ labels?: Partial<MockupLabels>;
164
+ children?: ReactNode;
165
+ };
166
+ /** Per-store mockup configuration (registry, kind resolver, labels) for every `ProductImage` below. */
167
+ declare function MockupProvider({ registry, resolveKind, labels, children }: MockupProviderProps): react.JSX.Element;
168
+ /** Current mockup configuration (defaults when there is no provider). */
169
+ declare function useMockupConfig(): MockupConfig;
170
+
171
+ type SvgPassThrough = Omit<MockupFrameProps, 'label' | 'kind' | 'children'>;
172
+ type ProductMockupProps<D = unknown> = SvgPassThrough & {
173
+ kind: MockupKind;
174
+ data: D;
175
+ /** Accessible name override (still prefixed with `labels.illustration`). */
176
+ label?: string;
177
+ labels?: Partial<MockupLabels>;
178
+ registry?: MockupRegistry;
179
+ };
180
+ /**
181
+ * Draws the mockup registered for `kind` with already extracted `data`
182
+ * (e.g. from `mockupDataFromProduct`). Unknown kinds fall back to `generic`;
183
+ * returns `null` when the registry has neither.
184
+ */
185
+ declare function ProductMockup<D>({ kind, data, label, labels: labelOverrides, registry: registryProp, ...svg }: ProductMockupProps<D>): react.JSX.Element | null;
186
+ /** Product fields `ProductImage` reads: the mockup fields plus the images. */
187
+ type ProductImageProduct = MockupProduct & Partial<Pick<Product, 'featured_image' | 'images'>>;
188
+ type ProductImageProps = Omit<ImageProps, 'data'> & {
189
+ product: ProductImageProduct;
190
+ /** Selected variant: its image wins; its options (flavor, presentation) feed the mockup. */
191
+ variant?: (MockupVariant & Partial<Pick<ProductVariant, 'image'>>) | null;
192
+ /** Explicit image (e.g. a gallery slide). `null` forces the mockup. */
193
+ image?: Image | null;
194
+ /** Forces a mockup kind (skips resolution). */
195
+ kind?: MockupKind;
196
+ resolveKind?: ResolveMockupKind;
197
+ registry?: MockupRegistry;
198
+ labels?: Partial<MockupLabels>;
199
+ };
200
+ /**
201
+ * The product's image from OPS (responsive `Image`: `alt`, intrinsic size,
202
+ * `priority` for LCP) or, when it has none, the mockup for its kind. Kind:
203
+ * `kind` prop → `resolveKind` (prop, then `MockupProvider`) → `resolveMockupKind`.
204
+ *
205
+ * The mockup's accessible name always says it is an illustration; `alt=""`
206
+ * makes it decorative (`aria-hidden`), like an empty `alt` on an image.
207
+ */
208
+ declare function ProductImage({ product, variant, image, kind: kindProp, resolveKind: resolveProp, registry: registryProp, labels: labelOverrides, alt, className, style, id, ...imageProps }: ProductImageProps): react.JSX.Element | null;
209
+
210
+ /**
211
+ * One store mockup, in one file: which products it claims, what it reads from
212
+ * them and how it draws. Every field but `kind` and `render` is optional.
213
+ */
214
+ type MockupDefinition<D = any> = {
215
+ /** Kind name (`supplement`, `tire`, `casco-moto`). Reusing a base kind replaces it. */
216
+ kind: MockupKind;
217
+ /**
218
+ * Claims a product for this kind. Checked in list order, before the SDK's
219
+ * guess (`guess`: `mockup_kind` attribute, tire/part attributes, words in
220
+ * type/category/tags). Omit it to rely on the guess or on `mockup_kind`.
221
+ */
222
+ match?: (product: MockupProduct, guess: MockupKind) => boolean;
223
+ /** Product (+ selected variant) → data for `render`. Default: the base extractor of the kind (generic data for new kinds). Never prices. */
224
+ data?: (product: MockupProduct, variant?: MockupVariant | null) => D;
225
+ /** Data → accessible name (prefix it with `labels.illustration`). Default: `describeMockup`. */
226
+ describe?: (data: D, labels: MockupLabels) => string;
227
+ /** The drawing: a component that returns a `<MockupFrame>` (or a base one: `SupplementMockup`…). */
228
+ render: MockupComponent<D>;
229
+ };
230
+ /** Typed, checked definition of a store mockup (throws on an invalid kind or a missing `render`). */
231
+ declare function defineMockup<D = any>(definition: MockupDefinition<D>): MockupDefinition<D>;
232
+ type CreateStoreMockupsOptions = {
233
+ /**
234
+ * Starting registry: `builtin` (default) keeps tire, part, supplement and
235
+ * generic for the kinds the store does not define; `none` starts empty (keep
236
+ * a `generic` among your definitions); or pass a registry to extend.
237
+ */
238
+ base?: 'builtin' | 'none' | MockupRegistry;
239
+ /** Interface words (`illustration`, `servings`…) for every mockup. */
240
+ labels?: Partial<MockupLabels>;
241
+ };
242
+ /** What `<MockupProvider {...storeMockups}>` takes. */
243
+ type StoreMockups = {
244
+ registry: MockupRegistry;
245
+ resolveKind: ResolveMockupKind;
246
+ labels?: Partial<MockupLabels>;
247
+ /** Kinds defined by the store, in order. */
248
+ kinds: MockupKind[];
249
+ };
250
+ /**
251
+ * Builds the store's mockup setup from its definitions: a registry (base
252
+ * mockups + the store's, the store's win) and a `resolveKind` that asks each
253
+ * `match` in order and otherwise keeps the SDK's guess.
254
+ *
255
+ * ```tsx
256
+ * export const storeMockups = createStoreMockups([supplement, accessory])
257
+ * <MockupProvider {...storeMockups}>…</MockupProvider>
258
+ * ```
259
+ */
260
+ declare function createStoreMockups(definitions: readonly MockupDefinition[], options?: CreateStoreMockupsOptions): StoreMockups;
261
+
262
+ export { BUILTIN_MOCKUPS, type CreateStoreMockupsOptions, DEFAULT_MOCKUP_LABELS, GenericMockup, MOCKUP_MONO, MOCKUP_SIZE, MOCKUP_TOKENS, type MockupComponent, type MockupComponentProps, type MockupConfig, type MockupDefinition, MockupFrame, type MockupFrameProps, type MockupLabels, MockupProvider, type MockupProviderProps, type MockupRegistry, type MockupRenderer, type MockupRendererInput, MockupText, type MockupTextProps, type MockupTone, PartMockup, ProductImage, type ProductImageProduct, type ProductImageProps, ProductMockup, type ProductMockupProps, type ResolveMockupKind, type ResolvedMockupRenderer, type StoreMockups, SupplementMockup, TireMockup, createMockupRegistry, createStoreMockups, defaultMockupRegistry, defineMockup, describeMockup, fitMockupFontSize, mockupWordMax, registerMockup, tone, useMockupConfig, wrapMockupText };