@recipe-book/react 0.0.3 → 0.1.1
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/CHANGELOG.md +36 -0
- package/LICENSE +21 -0
- package/README.md +48 -15
- package/core/package.json +5 -0
- package/core/schema-org/package.json +5 -0
- package/dist/core/schema-org.cjs +25 -0
- package/dist/core/schema-org.cjs.map +1 -0
- package/dist/core/schema-org.d.cts +1 -0
- package/dist/core/schema-org.d.ts +1 -0
- package/dist/core/schema-org.js +3 -0
- package/dist/core/schema-org.js.map +1 -0
- package/dist/core.cjs +25 -0
- package/dist/core.cjs.map +1 -0
- package/dist/core.d.cts +1 -0
- package/dist/core.d.ts +1 -0
- package/dist/core.js +3 -0
- package/dist/core.js.map +1 -0
- package/dist/index.cjs +1224 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1276 -0
- package/dist/index.d.ts +1276 -10
- package/dist/index.js +1207 -2
- package/dist/index.js.map +1 -0
- package/package.json +71 -15
- package/dist/chunk-2S2Z4HLL.mjs +0 -46
- package/dist/chunk-2VMRVR3X.mjs +0 -1
- package/dist/chunk-36H6LM2B.mjs +0 -14
- package/dist/chunk-4IWVZEXX.mjs +0 -20
- package/dist/chunk-4XBZKTOL.mjs +0 -1
- package/dist/chunk-6AGILC25.mjs +0 -20
- package/dist/chunk-6AXGEB5P.mjs +0 -14
- package/dist/chunk-6JEDN4VR.mjs +0 -20
- package/dist/chunk-6KLLMLNF.mjs +0 -33
- package/dist/chunk-6LTLY5K7.mjs +0 -20
- package/dist/chunk-6RA4EVIO.mjs +0 -46
- package/dist/chunk-75DF3E6L.mjs +0 -50
- package/dist/chunk-7BWMULSB.mjs +0 -55
- package/dist/chunk-7PPB3PM6.mjs +0 -40
- package/dist/chunk-7SBP7DC5.mjs +0 -42
- package/dist/chunk-7XJBP24U.mjs +0 -20
- package/dist/chunk-A5JAKCMG.mjs +0 -44
- package/dist/chunk-ATOAYKI3.mjs +0 -26
- package/dist/chunk-B5IXKKFC.mjs +0 -38
- package/dist/chunk-BEMMFA52.mjs +0 -49
- package/dist/chunk-BOG5DA6M.mjs +0 -38
- package/dist/chunk-BW4DYFBO.mjs +0 -36
- package/dist/chunk-CDQFOSWR.mjs +0 -34
- package/dist/chunk-CRQVP6PW.mjs +0 -20
- package/dist/chunk-CY27OHOG.mjs +0 -1
- package/dist/chunk-DACFJWGN.mjs +0 -14
- package/dist/chunk-DE5GUZKO.mjs +0 -46
- package/dist/chunk-DNZAFS5G.mjs +0 -48
- package/dist/chunk-DS3O5PAR.mjs +0 -20
- package/dist/chunk-ENGJXHYU.mjs +0 -42
- package/dist/chunk-FIFGRJKD.mjs +0 -26
- package/dist/chunk-FWOMIZEF.mjs +0 -46
- package/dist/chunk-G7XD4VBW.mjs +0 -44
- package/dist/chunk-GBU6MVZL.mjs +0 -14
- package/dist/chunk-GM5F7IUT.mjs +0 -2
- package/dist/chunk-GSGRXRJP.mjs +0 -38
- package/dist/chunk-GZRNU24M.mjs +0 -46
- package/dist/chunk-HNDXCSZY.mjs +0 -44
- package/dist/chunk-HXTUDCO2.mjs +0 -49
- package/dist/chunk-I5TR6PEA.mjs +0 -0
- package/dist/chunk-IXRYSEMS.mjs +0 -30
- package/dist/chunk-J5Q2Z2JG.mjs +0 -38
- package/dist/chunk-JBAAWEV6.mjs +0 -1
- package/dist/chunk-JCPPNN26.mjs +0 -44
- package/dist/chunk-JR3OTSZB.mjs +0 -32
- package/dist/chunk-JWS5RTU3.mjs +0 -46
- package/dist/chunk-K6EZ773Q.mjs +0 -26
- package/dist/chunk-KNXMYQVO.mjs +0 -36
- package/dist/chunk-KRUZ7OA7.mjs +0 -44
- package/dist/chunk-KXCIJBR6.mjs +0 -14
- package/dist/chunk-M5D3UUZF.mjs +0 -19
- package/dist/chunk-MASAOP7L.mjs +0 -55
- package/dist/chunk-MGBEDCLT.mjs +0 -34
- package/dist/chunk-MKBCBPVR.mjs +0 -53
- package/dist/chunk-N53TONLF.mjs +0 -39
- package/dist/chunk-NYDGFRPM.mjs +0 -46
- package/dist/chunk-OPOABKD6.mjs +0 -23
- package/dist/chunk-OX6ITS5C.mjs +0 -20
- package/dist/chunk-PAAVW47I.mjs +0 -50
- package/dist/chunk-PAF5HSSV.mjs +0 -53
- package/dist/chunk-PBENQR7Y.mjs +0 -1
- package/dist/chunk-PH3LQIHZ.mjs +0 -26
- package/dist/chunk-PIB3RAOO.mjs +0 -24
- package/dist/chunk-PIXLJD7Y.mjs +0 -37
- package/dist/chunk-PTS3BZHK.mjs +0 -1
- package/dist/chunk-Q6I5J3IJ.mjs +0 -1
- package/dist/chunk-QOCKR2HO.mjs +0 -1
- package/dist/chunk-QOZCSS3B.mjs +0 -44
- package/dist/chunk-QSFPUODQ.mjs +0 -34
- package/dist/chunk-RY7QUBJI.mjs +0 -34
- package/dist/chunk-RZJRUG2I.mjs +0 -55
- package/dist/chunk-S3GGSQB5.mjs +0 -1
- package/dist/chunk-S3HRT5Z5.mjs +0 -14
- package/dist/chunk-SB7HBCCZ.mjs +0 -49
- package/dist/chunk-SEXTT3NJ.mjs +0 -25
- package/dist/chunk-SKEQCOPX.mjs +0 -43
- package/dist/chunk-TLBRVWD2.mjs +0 -1
- package/dist/chunk-TOOCHDUY.mjs +0 -36
- package/dist/chunk-TSKANLT4.mjs +0 -37
- package/dist/chunk-UAMZEZUI.mjs +0 -36
- package/dist/chunk-UQJ4XNWN.mjs +0 -26
- package/dist/chunk-VDSUUXCH.mjs +0 -34
- package/dist/chunk-VO7RY2ZK.mjs +0 -44
- package/dist/chunk-WJKDFBJ2.mjs +0 -34
- package/dist/chunk-WTC7PY7U.mjs +0 -54
- package/dist/chunk-WXDV7CMB.mjs +0 -14
- package/dist/chunk-X5FG3X6T.mjs +0 -1
- package/dist/chunk-X66DY4AZ.mjs +0 -1
- package/dist/chunk-XXSJXKWQ.mjs +0 -44
- package/dist/chunk-YZMVAQQG.mjs +0 -1
- package/dist/chunk-ZCXPZU7W.mjs +0 -20
- package/dist/chunk-ZJ4PNVYO.mjs +0 -52
- package/dist/chunk-ZU4QJLEY.mjs +0 -53
- package/dist/components/ingredients/ingredients-list.d.mts +0 -13
- package/dist/components/ingredients/ingredients-list.d.ts +0 -13
- package/dist/components/ingredients/ingredients-list.js +0 -2
- package/dist/components/ingredients/ingredients-list.mjs +0 -1
- package/dist/components/instructions/instruction-list.d.mts +0 -13
- package/dist/components/instructions/instruction-list.d.ts +0 -13
- package/dist/components/instructions/instruction-list.js +0 -1
- package/dist/components/instructions/instruction-list.mjs +0 -1
- package/dist/components/layouts/layout-default.d.mts +0 -7
- package/dist/components/layouts/layout-default.d.ts +0 -7
- package/dist/components/layouts/layout-default.js +0 -1
- package/dist/components/layouts/layout-default.mjs +0 -1
- package/dist/components/layouts/layout-types.d.mts +0 -8
- package/dist/components/layouts/layout-types.d.ts +0 -8
- package/dist/components/layouts/layout-types.js +0 -1
- package/dist/components/layouts/layout-types.mjs +0 -0
- package/dist/components/measurement-select.d.mts +0 -13
- package/dist/components/measurement-select.d.ts +0 -13
- package/dist/components/measurement-select.js +0 -1
- package/dist/components/measurement-select.mjs +0 -1
- package/dist/components/root.d.mts +0 -13
- package/dist/components/root.d.ts +0 -13
- package/dist/components/root.js +0 -1
- package/dist/components/root.mjs +0 -1
- package/dist/components/servings-select.d.mts +0 -11
- package/dist/components/servings-select.d.ts +0 -11
- package/dist/components/servings-select.js +0 -1
- package/dist/components/servings-select.mjs +0 -1
- package/dist/components/thumbnail.d.mts +0 -18
- package/dist/components/thumbnail.d.ts +0 -18
- package/dist/components/thumbnail.js +0 -1
- package/dist/components/thumbnail.mjs +0 -1
- package/dist/global-context.d.mts +0 -29
- package/dist/global-context.d.ts +0 -29
- package/dist/global-context.js +0 -1
- package/dist/global-context.mjs +0 -1
- package/dist/hooks/use-controllable.d.mts +0 -15
- package/dist/hooks/use-controllable.d.ts +0 -15
- package/dist/hooks/use-controllable.js +0 -1
- package/dist/hooks/use-controllable.mjs +0 -1
- package/dist/index.d.mts +0 -10
- package/dist/index.mjs +0 -1
- package/dist/recipe-context.d.mts +0 -29
- package/dist/recipe-context.d.ts +0 -29
- package/dist/recipe-context.js +0 -1
- package/dist/recipe-context.mjs +0 -1
- package/dist/types-from-core.d.mts +0 -1
- package/dist/types-from-core.d.ts +0 -1
- package/dist/types-from-core.js +0 -1
- package/dist/types-from-core.mjs +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,1276 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
import { ElementType, ComponentPropsWithoutRef, Ref, ComponentRef, ReactNode, ForwardRefExoticComponent, RefAttributes, JSX } from 'react';
|
|
2
|
+
import { ResolvedIngredient, Recipe, System, Step as Step$1, ParseResult, FormattedIngredient, QuantityPart } from '@recipe-book/core';
|
|
3
|
+
import { ToJsonLdOptions } from '@recipe-book/core/schema-org';
|
|
4
|
+
|
|
5
|
+
/** What `<Recipe.Image>` passes to `as`: a string `src` and `alt`. */
|
|
6
|
+
type ImageAttributes = {
|
|
7
|
+
src: string;
|
|
8
|
+
alt: string;
|
|
9
|
+
};
|
|
10
|
+
/** The type error for an `as` component whose `src` and `alt` props don't take a string. */
|
|
11
|
+
type NotAnImageComponent = 'Recipe.Image: as must be a component whose src and alt props take a string';
|
|
12
|
+
/** `C` when its `src` and `alt` props take a string, else `NotAnImageComponent`. */
|
|
13
|
+
type ImageComponent<C extends ElementType> = 'src' | 'alt' extends keyof ComponentPropsWithoutRef<C> ? ImageAttributes extends Pick<ComponentPropsWithoutRef<C>, 'src' | 'alt'> ? C : NotAnImageComponent : NotAnImageComponent;
|
|
14
|
+
/**
|
|
15
|
+
* The props of `<Recipe.Image>`: those of `C` without its `ref`, with `src`
|
|
16
|
+
* and `alt` optional, plus `as`. `C` defaults to `'img'`. Use it to type a
|
|
17
|
+
* wrapper that takes what `<Recipe.Image as={C}>` takes.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* import NextImage from 'next/image'
|
|
21
|
+
*
|
|
22
|
+
* function Hero(props: Recipe.RecipeImageProps<typeof NextImage>) {
|
|
23
|
+
* return <Recipe.Image {...props} as={NextImage} className="hero" />
|
|
24
|
+
* }
|
|
25
|
+
*
|
|
26
|
+
* @see https://recipe-book.siraj.page/reference/react/image/#type-a-wrapper
|
|
27
|
+
*/
|
|
28
|
+
type RecipeImageProps<C extends ElementType = 'img'> = {
|
|
29
|
+
/**
|
|
30
|
+
* The component to render instead of `<img>`, such as `next/image`. It
|
|
31
|
+
* gets `src`, `alt`, `data-recipe-image` and the ref, and `Recipe.Image`
|
|
32
|
+
* takes its props. Its `src` and `alt` must take strings, and its other
|
|
33
|
+
* required props are required on `Recipe.Image`. From a Server Component,
|
|
34
|
+
* pass a Client Component: one whose module starts with `'use client'`, as
|
|
35
|
+
* `next/image`'s does.
|
|
36
|
+
*
|
|
37
|
+
* @defaultValue `'img'`
|
|
38
|
+
*
|
|
39
|
+
* @see https://recipe-book.siraj.page/reference/react/image/#render-another-component
|
|
40
|
+
*/
|
|
41
|
+
as?: ImageComponent<C> | undefined;
|
|
42
|
+
} & Omit<ComponentPropsWithoutRef<C>, 'as' | 'src' | 'alt'> & {
|
|
43
|
+
/**
|
|
44
|
+
* Replaces the recipe's `image`, such as with a CDN URL. Nothing renders
|
|
45
|
+
* when the recipe has no `image`, even with `src`. With `as`, it takes
|
|
46
|
+
* that component's `src` type, such as `string | StaticImport` for
|
|
47
|
+
* `next/image`.
|
|
48
|
+
*
|
|
49
|
+
* @defaultValue The recipe's `image`.
|
|
50
|
+
*
|
|
51
|
+
* @see https://recipe-book.siraj.page/reference/react/image/#image
|
|
52
|
+
*/
|
|
53
|
+
src?: (ComponentPropsWithoutRef<C> extends {
|
|
54
|
+
src?: infer S;
|
|
55
|
+
} ? S : never) | undefined;
|
|
56
|
+
/**
|
|
57
|
+
* The alt text. Pass `''` for a decorative image.
|
|
58
|
+
*
|
|
59
|
+
* @defaultValue The recipe's `name`.
|
|
60
|
+
*
|
|
61
|
+
* @see https://recipe-book.siraj.page/reference/react/image/#decorative-images
|
|
62
|
+
*/
|
|
63
|
+
alt?: string | undefined;
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* The recipe's image, as an `<img>` or the component passed to `as`, or
|
|
67
|
+
* nothing when the recipe has none. `src` defaults to the recipe's image and
|
|
68
|
+
* `alt` to its name; pass `alt=""` when the image is decorative. Other props
|
|
69
|
+
* pass through, and it always sets `data-recipe-image`.
|
|
70
|
+
*
|
|
71
|
+
* `Recipe.Image` takes `as`, not `asChild`, so a component such as
|
|
72
|
+
* `next/image` gets `src` and `alt` from the recipe and still has its
|
|
73
|
+
* required props checked.
|
|
74
|
+
*
|
|
75
|
+
* @throws {RecipeBookError} `missing_parent` outside a `<Recipe.Root>`.
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* import NextImage from 'next/image'
|
|
79
|
+
*
|
|
80
|
+
* function RecipeHero() {
|
|
81
|
+
* return <Recipe.Image as={NextImage} width={1200} height={800} />
|
|
82
|
+
* }
|
|
83
|
+
*
|
|
84
|
+
* @see https://recipe-book.siraj.page/reference/react/image/
|
|
85
|
+
*/
|
|
86
|
+
declare const Image: <C extends ElementType = "img">(props: RecipeImageProps<C> & {
|
|
87
|
+
/**
|
|
88
|
+
* Set to the `<img>`, or passed to the `as` component. Left unset when the recipe has no image.
|
|
89
|
+
*
|
|
90
|
+
* @see https://recipe-book.siraj.page/reference/react/image/#image
|
|
91
|
+
*/
|
|
92
|
+
ref?: Ref<ComponentRef<C>> | undefined;
|
|
93
|
+
}) => ReactNode;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* What `useRecipeState()` takes. The state props of `<Recipe.Root>` are the
|
|
97
|
+
* same.
|
|
98
|
+
*
|
|
99
|
+
* @see https://recipe-book.siraj.page/reference/react/hooks/#recipestateoptions
|
|
100
|
+
*/
|
|
101
|
+
type RecipeStateOptions = {
|
|
102
|
+
/** A parsed recipe, as returned by `parseRecipe` in `@recipe-book/react/core`. */
|
|
103
|
+
recipe: Recipe;
|
|
104
|
+
/**
|
|
105
|
+
* The number of servings to show. Passing it makes servings controlled. A
|
|
106
|
+
* number outside the servings window shows `defaultServings` instead, with a
|
|
107
|
+
* warning in development.
|
|
108
|
+
*
|
|
109
|
+
* @see https://recipe-book.siraj.page/reference/react/root/#controlled-and-uncontrolled-state
|
|
110
|
+
*/
|
|
111
|
+
servings?: number | undefined;
|
|
112
|
+
/**
|
|
113
|
+
* Starting servings when uncontrolled. A number outside the servings window
|
|
114
|
+
* falls back to the scaling base, with a warning in development.
|
|
115
|
+
*
|
|
116
|
+
* @defaultValue The recipe's scaling base: its servings, then its yield,
|
|
117
|
+
* then 1.
|
|
118
|
+
* @see https://recipe-book.siraj.page/reference/react/root/#scaling-base
|
|
119
|
+
*/
|
|
120
|
+
defaultServings?: number | undefined;
|
|
121
|
+
/**
|
|
122
|
+
* Called when `setServings` accepts a number other than the current one,
|
|
123
|
+
* whether or not servings are controlled. While a controlled `servings` is
|
|
124
|
+
* outside the range `setServings` accepts, passing it the number shown calls
|
|
125
|
+
* this too.
|
|
126
|
+
*/
|
|
127
|
+
onServingsChange?: ((servings: number) => void) | undefined;
|
|
128
|
+
/** The measurement system to show. Passing it makes the system controlled. */
|
|
129
|
+
system?: System | undefined;
|
|
130
|
+
/** Starting system when uncontrolled; defaults to the system the recipe was written in, then `'metric'`. */
|
|
131
|
+
defaultSystem?: System | undefined;
|
|
132
|
+
/**
|
|
133
|
+
* Called when `setSystem` accepts a system other than the current one,
|
|
134
|
+
* whether or not it's controlled. While a controlled `system` is neither
|
|
135
|
+
* `'metric'` nor `'us'`, passing `setSystem` the system shown calls this too.
|
|
136
|
+
*/
|
|
137
|
+
onSystemChange?: ((system: System) => void) | undefined;
|
|
138
|
+
};
|
|
139
|
+
/**
|
|
140
|
+
* An ingredient scaled to the servings and expressed in the display
|
|
141
|
+
* system, unrounded and unformatted. Render its text with the ingredient
|
|
142
|
+
* sub-parts inside `<Recipe.Ingredient>`, or format it with
|
|
143
|
+
* `useFormatIngredient()`.
|
|
144
|
+
*/
|
|
145
|
+
type IngredientItem = ResolvedIngredient;
|
|
146
|
+
/** A step with its position, counted from 1 across sections. */
|
|
147
|
+
type StepItem = Step$1 & {
|
|
148
|
+
/** The step's position, counted from 1 across sections. */
|
|
149
|
+
number: number;
|
|
150
|
+
};
|
|
151
|
+
/**
|
|
152
|
+
* A section of a recipe's ingredients or steps. Untitled sections have no
|
|
153
|
+
* `title`.
|
|
154
|
+
*
|
|
155
|
+
* @see https://recipe-book.siraj.page/reference/react/hooks/#recipesection
|
|
156
|
+
*/
|
|
157
|
+
type RecipeSection<T> = {
|
|
158
|
+
/** The section's id from the recipe. */
|
|
159
|
+
id: string;
|
|
160
|
+
/** The section's title from the recipe. */
|
|
161
|
+
title?: string | undefined;
|
|
162
|
+
/** The ingredients or steps in the section. */
|
|
163
|
+
items: T[];
|
|
164
|
+
};
|
|
165
|
+
/**
|
|
166
|
+
* What `useRecipe()` and `useRecipeState()` return.
|
|
167
|
+
*
|
|
168
|
+
* @see https://recipe-book.siraj.page/reference/react/hooks/#recipestate
|
|
169
|
+
*/
|
|
170
|
+
type RecipeState = {
|
|
171
|
+
/** The parsed recipe. */
|
|
172
|
+
recipe: Recipe;
|
|
173
|
+
/** The number of servings shown. For a recipe with a yield but no servings, it counts in the yield's unit. */
|
|
174
|
+
servings: number;
|
|
175
|
+
/**
|
|
176
|
+
* Calls `onServingsChange` with a number other than the current one, and
|
|
177
|
+
* changes the servings unless controlled. Ignores a number outside the
|
|
178
|
+
* servings window, from a millionth to a million times the scaling base
|
|
179
|
+
* including both ends, and warns about it in development. While a
|
|
180
|
+
* controlled `servings` is outside that window, passing the number shown
|
|
181
|
+
* calls `onServingsChange` too.
|
|
182
|
+
*
|
|
183
|
+
* @see https://recipe-book.siraj.page/reference/react/root/#servings-window
|
|
184
|
+
*/
|
|
185
|
+
setServings: (servings: number) => void;
|
|
186
|
+
/** From `resolveRecipe`: `servings` divided by the recipe's servings amount, else its yield amount, else 1. */
|
|
187
|
+
scale: number;
|
|
188
|
+
/** The display system. */
|
|
189
|
+
system: System;
|
|
190
|
+
/**
|
|
191
|
+
* Calls `onSystemChange` with a system other than the current one, and
|
|
192
|
+
* changes the system unless controlled; ignores anything but `'metric'` and
|
|
193
|
+
* `'us'`. While a controlled `system` is neither, passing the system shown
|
|
194
|
+
* calls `onSystemChange` too.
|
|
195
|
+
*/
|
|
196
|
+
setSystem: (system: System) => void;
|
|
197
|
+
/**
|
|
198
|
+
* True when an ingredient's quantity has a unit that belongs to only one
|
|
199
|
+
* system. Under `<Recipe.Root>`, a `Recipe.StepText` that shows a
|
|
200
|
+
* temperature also counts once it mounts, which is after the server render.
|
|
201
|
+
* This hook alone reads ingredients only.
|
|
202
|
+
*/
|
|
203
|
+
canConvert: boolean;
|
|
204
|
+
/** From `resolveRecipe`: each section's ingredients at `servings`, in `system`. */
|
|
205
|
+
ingredients: RecipeSection<IngredientItem>[];
|
|
206
|
+
/** The recipe's steps in their sections, numbered from 1 across sections. */
|
|
207
|
+
steps: RecipeSection<StepItem>[];
|
|
208
|
+
};
|
|
209
|
+
/**
|
|
210
|
+
* Headless recipe state: servings, the display system, and data derived from
|
|
211
|
+
* them. Needs no provider and renders nothing. `<Recipe.Root>` is built on it.
|
|
212
|
+
*
|
|
213
|
+
* Each piece of state is controlled when its value is defined (`servings`,
|
|
214
|
+
* `system`) and uncontrolled otherwise. Uncontrolled state resets when
|
|
215
|
+
* `recipe.id` changes.
|
|
216
|
+
*
|
|
217
|
+
* @throws {RecipeBookError} `invalid_argument` in development when `recipe`
|
|
218
|
+
* isn't a parsed recipe.
|
|
219
|
+
*
|
|
220
|
+
* @param options - The recipe and its state.
|
|
221
|
+
* @returns The recipe, its servings and display system with their setters,
|
|
222
|
+
* its ingredients at those settings, and its numbered steps.
|
|
223
|
+
*
|
|
224
|
+
* @example
|
|
225
|
+
* import type { Recipe as ParsedRecipe } from '@recipe-book/react/core'
|
|
226
|
+
* import * as Recipe from '@recipe-book/react'
|
|
227
|
+
*
|
|
228
|
+
* function ServingsSummary({ recipe }: { recipe: ParsedRecipe }) {
|
|
229
|
+
* const { servings, scale } = Recipe.useRecipeState({
|
|
230
|
+
* recipe,
|
|
231
|
+
* defaultServings: 8,
|
|
232
|
+
* })
|
|
233
|
+
* return <p>{`Serves ${servings}, scaled ×${scale}`}</p>
|
|
234
|
+
* }
|
|
235
|
+
*
|
|
236
|
+
* @see https://recipe-book.siraj.page/reference/react/hooks/#userecipestate
|
|
237
|
+
*/
|
|
238
|
+
declare function useRecipeState(options: RecipeStateOptions): RecipeState;
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* The heading levels `<Recipe.Ingredients>` and `<Recipe.Steps>` take as
|
|
242
|
+
* `headingLevel` for section titles; level 1 belongs to the page's title.
|
|
243
|
+
* Both default to 3, for sections under an `<h2>` such as "Ingredients". Pass
|
|
244
|
+
* the level below your own heading to keep the outline in order.
|
|
245
|
+
*
|
|
246
|
+
* @see https://recipe-book.siraj.page/reference/react/ingredients/#recipeheadinglevel
|
|
247
|
+
*/
|
|
248
|
+
type RecipeHeadingLevel = 2 | 3 | 4 | 5 | 6;
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Attributes for the wrapping `<div>` other than `dangerouslySetInnerHTML`,
|
|
252
|
+
* plus `headingLevel`; `children` renders each section.
|
|
253
|
+
*
|
|
254
|
+
* @see https://recipe-book.siraj.page/reference/react/ingredients/#ingredients
|
|
255
|
+
*/
|
|
256
|
+
type RecipeIngredientsProps = Omit<ComponentPropsWithoutRef<'div'>, 'children' | 'dangerouslySetInnerHTML'> & {
|
|
257
|
+
/**
|
|
258
|
+
* Heading level of section titles in the default rendering. Defaults to 3,
|
|
259
|
+
* for ingredients under an `<h2>` such as "Ingredients".
|
|
260
|
+
*
|
|
261
|
+
* @defaultValue `3`
|
|
262
|
+
* @see https://recipe-book.siraj.page/guides/make-a-recipe-accessible/#set-heading-levels
|
|
263
|
+
*/
|
|
264
|
+
headingLevel?: RecipeHeadingLevel | undefined;
|
|
265
|
+
/**
|
|
266
|
+
* Renders each section instead of the default. Each result is keyed for
|
|
267
|
+
* you, so return one element or a fragment; an array's items need their own
|
|
268
|
+
* keys, as anywhere in React.
|
|
269
|
+
*
|
|
270
|
+
* @defaultValue A `<section>` named by the section's heading, or a `<div>`
|
|
271
|
+
* for an untitled section, around a `<Recipe.IngredientList>` of its
|
|
272
|
+
* ingredients.
|
|
273
|
+
* @see https://recipe-book.siraj.page/reference/react/ingredients/#render-your-own-sections
|
|
274
|
+
*/
|
|
275
|
+
children?: ((section: RecipeSection<IngredientItem>) => ReactNode) | undefined;
|
|
276
|
+
};
|
|
277
|
+
/**
|
|
278
|
+
* The recipe's ingredients at the current servings and display system, one
|
|
279
|
+
* block per section. A titled section renders as a `<section>` named by its
|
|
280
|
+
* heading, then a `<Recipe.IngredientList>`.
|
|
281
|
+
*
|
|
282
|
+
* @throws {RecipeBookError} `missing_parent` outside a `<Recipe.Root>`.
|
|
283
|
+
* @throws {RecipeBookError} `invalid_argument` from the `<Recipe.Ingredient>`
|
|
284
|
+
* it renders for each item by default, when Root's `locale` isn't a language
|
|
285
|
+
* tag that `Intl` accepts, such as `'en_US'`.
|
|
286
|
+
*
|
|
287
|
+
* @example
|
|
288
|
+
* <Recipe.Root recipe={recipe}>
|
|
289
|
+
* <h2>Ingredients</h2>
|
|
290
|
+
* <Recipe.Ingredients />
|
|
291
|
+
* </Recipe.Root>
|
|
292
|
+
*
|
|
293
|
+
* @see https://recipe-book.siraj.page/reference/react/ingredients/#ingredients
|
|
294
|
+
*/
|
|
295
|
+
declare const Ingredients: ForwardRefExoticComponent<RecipeIngredientsProps & RefAttributes<HTMLDivElement>>;
|
|
296
|
+
/**
|
|
297
|
+
* Attributes for the `<ul>` other than `dangerouslySetInnerHTML`, plus the
|
|
298
|
+
* `section` to list; `children` renders each ingredient.
|
|
299
|
+
*
|
|
300
|
+
* @see https://recipe-book.siraj.page/reference/react/ingredients/#ingredientlist
|
|
301
|
+
*/
|
|
302
|
+
type RecipeIngredientListProps = Omit<ComponentPropsWithoutRef<'ul'>, 'children' | 'dangerouslySetInnerHTML'> & {
|
|
303
|
+
/** The section to list. Defaults to every ingredient in the recipe. */
|
|
304
|
+
section?: RecipeSection<IngredientItem> | undefined;
|
|
305
|
+
/**
|
|
306
|
+
* Renders each ingredient instead of `<Recipe.Ingredient>`. Each result is
|
|
307
|
+
* keyed for you, so return one element or a fragment; an array's items need
|
|
308
|
+
* their own keys, as anywhere in React.
|
|
309
|
+
*
|
|
310
|
+
* @defaultValue `(item) => <Recipe.Ingredient item={item} />`
|
|
311
|
+
* @see https://recipe-book.siraj.page/reference/react/ingredients/#render-your-own-ingredients
|
|
312
|
+
*/
|
|
313
|
+
children?: ((item: IngredientItem) => ReactNode) | undefined;
|
|
314
|
+
};
|
|
315
|
+
/**
|
|
316
|
+
* An unordered list of ingredients, one `<Recipe.Ingredient>` each unless
|
|
317
|
+
* `children` renders them.
|
|
318
|
+
*
|
|
319
|
+
* @throws {RecipeBookError} `missing_parent` outside a `<Recipe.Root>`.
|
|
320
|
+
* @throws {RecipeBookError} `invalid_argument` from the `<Recipe.Ingredient>`
|
|
321
|
+
* it renders for each item by default, when Root's `locale` isn't a language
|
|
322
|
+
* tag that `Intl` accepts, such as `'en_US'`.
|
|
323
|
+
*
|
|
324
|
+
* @example
|
|
325
|
+
* <Recipe.IngredientList>
|
|
326
|
+
* {(item) => (
|
|
327
|
+
* <Recipe.Ingredient item={item}>
|
|
328
|
+
* <Recipe.IngredientName /> <Recipe.IngredientQuantity />
|
|
329
|
+
* </Recipe.Ingredient>
|
|
330
|
+
* )}
|
|
331
|
+
* </Recipe.IngredientList>
|
|
332
|
+
*
|
|
333
|
+
* @see https://recipe-book.siraj.page/reference/react/ingredients/#ingredientlist
|
|
334
|
+
*/
|
|
335
|
+
declare const IngredientList: ForwardRefExoticComponent<RecipeIngredientListProps & RefAttributes<HTMLUListElement>>;
|
|
336
|
+
/**
|
|
337
|
+
* Attributes for the `<li>` other than `dangerouslySetInnerHTML`, plus the
|
|
338
|
+
* `item` to render and `asChild`.
|
|
339
|
+
*
|
|
340
|
+
* @see https://recipe-book.siraj.page/reference/react/ingredients/#ingredient
|
|
341
|
+
*/
|
|
342
|
+
type RecipeIngredientProps = Omit<ComponentPropsWithoutRef<'li'>, 'dangerouslySetInnerHTML'> & {
|
|
343
|
+
/** The ingredient to render, such as one that `<Recipe.IngredientList>` passes to its `children`. */
|
|
344
|
+
item: IngredientItem;
|
|
345
|
+
/**
|
|
346
|
+
* Renders the line as its one element child, such as `<motion.li layout />`,
|
|
347
|
+
* instead of an `<li>`. A prop on the child wins, except that the line's
|
|
348
|
+
* `tabIndex` wins, `className`s join, `style` merges key by key with the
|
|
349
|
+
* child winning, both event handlers run (the child's first), and both refs
|
|
350
|
+
* are set. The child's own children replace the line's, so an empty child
|
|
351
|
+
* gets the default line. With anything but one element child, it renders
|
|
352
|
+
* its own `<li>`, with a warning in development.
|
|
353
|
+
*
|
|
354
|
+
* @defaultValue `false`
|
|
355
|
+
* @see https://recipe-book.siraj.page/reference/react/ingredients/#render-your-own-element
|
|
356
|
+
*/
|
|
357
|
+
asChild?: boolean | undefined;
|
|
358
|
+
};
|
|
359
|
+
/**
|
|
360
|
+
* One ingredient line, formatted with the nearest Root's locale and labels.
|
|
361
|
+
* Default children are `<Recipe.IngredientQuantity>`,
|
|
362
|
+
* `<Recipe.IngredientName>`, and `<Recipe.IngredientNote>`, joined as in
|
|
363
|
+
* `formatIngredient`'s `text`, then `<Recipe.IngredientOptional>` after a
|
|
364
|
+
* space. Custom children can use the same sub-parts, which render this line's
|
|
365
|
+
* text.
|
|
366
|
+
*
|
|
367
|
+
* `data-origin` tells where the quantity comes from: `authored`, `equivalent`,
|
|
368
|
+
* or `converted` into the display system. Unquantified lines have
|
|
369
|
+
* `data-unquantified` instead. Optional ingredients have `data-optional`.
|
|
370
|
+
*
|
|
371
|
+
* @throws {RecipeBookError} `missing_parent` outside a `<Recipe.Root>`.
|
|
372
|
+
* @throws {RecipeBookError} `invalid_argument` when Root's `locale` isn't a
|
|
373
|
+
* language tag that `Intl` accepts, such as `'en_US'`; when `item` isn't
|
|
374
|
+
* `{ ingredient, quantity? }`, such as an authored ingredient; or when an
|
|
375
|
+
* `item` you build has an amount that isn't a finite number greater than 0
|
|
376
|
+
* or a range of them, or a range whose `min` isn't less than its `max`.
|
|
377
|
+
* @throws {RecipeBookError} `unknown_unit` when the item's unit isn't a unit
|
|
378
|
+
* ID.
|
|
379
|
+
*
|
|
380
|
+
* @example
|
|
381
|
+
* <Recipe.Ingredient item={item} className="flex gap-2">
|
|
382
|
+
* <Recipe.IngredientQuantity className="w-24 tabular-nums" />
|
|
383
|
+
* <Recipe.IngredientName />
|
|
384
|
+
* <Recipe.IngredientNote className="text-stone-500" />
|
|
385
|
+
* </Recipe.Ingredient>
|
|
386
|
+
*
|
|
387
|
+
* @see https://recipe-book.siraj.page/reference/react/ingredients/#ingredient
|
|
388
|
+
*/
|
|
389
|
+
declare const Ingredient: ForwardRefExoticComponent<RecipeIngredientProps & RefAttributes<HTMLLIElement>>;
|
|
390
|
+
/** Attributes for an ingredient sub-part's `<span>`, plus `asChild`; `children` go before its text. */
|
|
391
|
+
type IngredientTextProps = Omit<ComponentPropsWithoutRef<'span'>, 'dangerouslySetInnerHTML'> & {
|
|
392
|
+
/**
|
|
393
|
+
* Renders as its one element child, such as `<a href={url} />`, instead of a
|
|
394
|
+
* `<span>`, with the text after the child's own children. A prop on the
|
|
395
|
+
* child wins, except that the part's `tabIndex` wins, `className`s join,
|
|
396
|
+
* `style` merges key by key with the child winning, both event handlers run
|
|
397
|
+
* (the child's first), and both refs are set. With anything but one element
|
|
398
|
+
* child, it renders its own `<span>`, with a warning in development.
|
|
399
|
+
*/
|
|
400
|
+
asChild?: boolean | undefined;
|
|
401
|
+
};
|
|
402
|
+
/** Attributes for the `<span>`, plus `asChild`; `children` go before the quantity. */
|
|
403
|
+
type RecipeIngredientQuantityProps = IngredientTextProps;
|
|
404
|
+
/**
|
|
405
|
+
* The nearest `<Recipe.Ingredient>`'s formatted quantity, or nothing for an
|
|
406
|
+
* unquantified line. A range's dash is hidden from screen readers, which hear
|
|
407
|
+
* `labels.to` instead: "2 to 3 tbsp". Children come before the quantity.
|
|
408
|
+
*
|
|
409
|
+
* @example
|
|
410
|
+
* <Recipe.IngredientQuantity>
|
|
411
|
+
* {item.origin === 'converted' && '≈ '}
|
|
412
|
+
* </Recipe.IngredientQuantity>
|
|
413
|
+
*
|
|
414
|
+
* @throws {RecipeBookError} `missing_parent` outside a `<Recipe.Ingredient>`.
|
|
415
|
+
*
|
|
416
|
+
* @see https://recipe-book.siraj.page/reference/react/ingredients/#ingredientquantity
|
|
417
|
+
*/
|
|
418
|
+
declare const IngredientQuantity: ForwardRefExoticComponent<RecipeIngredientQuantityProps & RefAttributes<HTMLSpanElement>>;
|
|
419
|
+
/** Attributes for the `<span>`, plus `asChild`; `children` go before the name. */
|
|
420
|
+
type RecipeIngredientNameProps = IngredientTextProps;
|
|
421
|
+
/**
|
|
422
|
+
* The nearest `<Recipe.Ingredient>`'s name, or its `plural` after a bare
|
|
423
|
+
* count that takes the plural, as in "2 eggs". Children come before the name.
|
|
424
|
+
*
|
|
425
|
+
* @example
|
|
426
|
+
* // The name goes inside the link.
|
|
427
|
+
* <Recipe.IngredientName asChild>
|
|
428
|
+
* <a href={`/glossary/${item.id}`} />
|
|
429
|
+
* </Recipe.IngredientName>
|
|
430
|
+
*
|
|
431
|
+
* @throws {RecipeBookError} `missing_parent` outside a `<Recipe.Ingredient>`.
|
|
432
|
+
*
|
|
433
|
+
* @see https://recipe-book.siraj.page/reference/react/ingredients/#ingredientname
|
|
434
|
+
*/
|
|
435
|
+
declare const IngredientName: ForwardRefExoticComponent<RecipeIngredientNameProps & RefAttributes<HTMLSpanElement>>;
|
|
436
|
+
/** Attributes for the `<span>`, plus `asChild`; `children` go before the note. */
|
|
437
|
+
type RecipeIngredientNoteProps = IngredientTextProps;
|
|
438
|
+
/**
|
|
439
|
+
* The nearest `<Recipe.Ingredient>`'s note, such as "sifted", or nothing when
|
|
440
|
+
* it has none. Children come before the note.
|
|
441
|
+
*
|
|
442
|
+
* @example
|
|
443
|
+
* <Recipe.IngredientNote className="text-stone-500" />
|
|
444
|
+
*
|
|
445
|
+
* @throws {RecipeBookError} `missing_parent` outside a `<Recipe.Ingredient>`.
|
|
446
|
+
*
|
|
447
|
+
* @see https://recipe-book.siraj.page/reference/react/ingredients/#ingredientnote
|
|
448
|
+
*/
|
|
449
|
+
declare const IngredientNote: ForwardRefExoticComponent<RecipeIngredientNoteProps & RefAttributes<HTMLSpanElement>>;
|
|
450
|
+
/** Attributes for the `<span>`, plus `asChild`; `children` go before the label. */
|
|
451
|
+
type RecipeIngredientOptionalProps = IngredientTextProps;
|
|
452
|
+
/**
|
|
453
|
+
* `labels.optional`, "(optional)" by default, when the nearest
|
|
454
|
+
* `<Recipe.Ingredient>` is optional; nothing otherwise. It's text, so screen
|
|
455
|
+
* readers read it with the line. Children come before the label.
|
|
456
|
+
*
|
|
457
|
+
* @example
|
|
458
|
+
* <Recipe.IngredientOptional className="text-stone-500" />
|
|
459
|
+
*
|
|
460
|
+
* @throws {RecipeBookError} `missing_parent` outside a `<Recipe.Ingredient>`.
|
|
461
|
+
*
|
|
462
|
+
* @see https://recipe-book.siraj.page/reference/react/ingredients/#ingredientoptional
|
|
463
|
+
*/
|
|
464
|
+
declare const IngredientOptional: ForwardRefExoticComponent<RecipeIngredientOptionalProps & RefAttributes<HTMLSpanElement>>;
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* The props of `<Recipe.JsonLd>`: `toJsonLd`'s `servings`, `system`, `url`
|
|
468
|
+
* and `extra`, passed to it as they are, plus the `<script>`'s attributes but
|
|
469
|
+
* `type`, `src` and its content, which `<Recipe.JsonLd>` sets.
|
|
470
|
+
*
|
|
471
|
+
* @see https://recipe-book.siraj.page/reference/react/json-ld/#jsonld
|
|
472
|
+
*/
|
|
473
|
+
type RecipeJsonLdProps = {
|
|
474
|
+
/**
|
|
475
|
+
* Writes the recipe at this many servings, as `resolveRecipe` scales it.
|
|
476
|
+
* The Root's servings don't change it.
|
|
477
|
+
*
|
|
478
|
+
* @defaultValue The recipe's own servings, unscaled.
|
|
479
|
+
*
|
|
480
|
+
* @see https://recipe-book.siraj.page/reference/react/json-ld/#jsonld
|
|
481
|
+
*/
|
|
482
|
+
servings?: ToJsonLdOptions['servings'];
|
|
483
|
+
/**
|
|
484
|
+
* Writes quantities in this measurement system. The Root's system doesn't
|
|
485
|
+
* change it.
|
|
486
|
+
*
|
|
487
|
+
* @defaultValue `recipe.system`, then `'metric'`.
|
|
488
|
+
*
|
|
489
|
+
* @see https://recipe-book.siraj.page/reference/react/json-ld/#jsonld
|
|
490
|
+
*/
|
|
491
|
+
system?: ToJsonLdOptions['system'];
|
|
492
|
+
/**
|
|
493
|
+
* The recipe page's URL. Each step gets it as `url`, with the step's id,
|
|
494
|
+
* percent-encoded, as the fragment; without it, steps have no `url`.
|
|
495
|
+
* `<Recipe.Step>` renders no `id`, so pass it the step's `id` for the
|
|
496
|
+
* fragment to point at it.
|
|
497
|
+
*
|
|
498
|
+
* @see https://recipe-book.siraj.page/reference/react/json-ld/#step-ids
|
|
499
|
+
*/
|
|
500
|
+
url?: ToJsonLdOptions['url'];
|
|
501
|
+
/**
|
|
502
|
+
* schema.org fields the recipe doesn't model, such as `author`,
|
|
503
|
+
* `datePublished`, or `keywords`, written as you pass them. A field
|
|
504
|
+
* `toJsonLd` writes from the recipe wins; `@context` and `@type` are always
|
|
505
|
+
* its own. A field that is `undefined` is left out, so
|
|
506
|
+
* `{ image: maybeImage }` adds an image only when there is one, and an
|
|
507
|
+
* `image` here stops the missing-image warning. A field `toJsonLd` writes
|
|
508
|
+
* from a recipe takes the type `SchemaOrgRecipe` gives it here too, so an
|
|
509
|
+
* `image` is a URL. Pass the `extra` that `fromJsonLd` returned to write them
|
|
510
|
+
* back.
|
|
511
|
+
*
|
|
512
|
+
* @example
|
|
513
|
+
* <Recipe.JsonLd
|
|
514
|
+
* url="https://example.com/pancakes"
|
|
515
|
+
* extra={{ author: { '@type': 'Person', name: 'Ada Lovelace' } }}
|
|
516
|
+
* />
|
|
517
|
+
*
|
|
518
|
+
* @see https://recipe-book.siraj.page/reference/react/json-ld/#jsonld
|
|
519
|
+
*/
|
|
520
|
+
extra?: ToJsonLdOptions['extra'];
|
|
521
|
+
} & Omit<ComponentPropsWithoutRef<'script'>, 'type' | 'children' | 'dangerouslySetInnerHTML' | 'src'>;
|
|
522
|
+
/**
|
|
523
|
+
* The recipe as schema.org Recipe JSON-LD, for search engines' recipe results,
|
|
524
|
+
* in a `<script type="application/ld+json">` with `<` escaped as `\u003c`.
|
|
525
|
+
* Writes the recipe as authored: at its own servings and in `recipe.system`,
|
|
526
|
+
* else metric, unless `servings` or `system` say otherwise. Root's current
|
|
527
|
+
* servings and system don't change it. The text is in English. Other props
|
|
528
|
+
* pass to the `<script>`, and it always sets `data-recipe-json-ld`.
|
|
529
|
+
*
|
|
530
|
+
* In development, logs to the browser console the warnings that `toJsonLd`
|
|
531
|
+
* returns, such as for a missing `image`, unless the previous render had the
|
|
532
|
+
* same ones in the same order. Nothing logs where it renders only on the
|
|
533
|
+
* server, such as in an Astro page without a `client:` directive.
|
|
534
|
+
*
|
|
535
|
+
* @throws {RecipeBookError} `missing_parent` outside a `<Recipe.Root>`.
|
|
536
|
+
*
|
|
537
|
+
* @example
|
|
538
|
+
* // app/pancakes/page.tsx, a Server Component: no 'use client' needed
|
|
539
|
+
* export default function Page() {
|
|
540
|
+
* return (
|
|
541
|
+
* <Recipe.Root recipe={recipe}>
|
|
542
|
+
* <Recipe.JsonLd url="https://example.com/pancakes" />
|
|
543
|
+
* </Recipe.Root>
|
|
544
|
+
* )
|
|
545
|
+
* }
|
|
546
|
+
*
|
|
547
|
+
* @see https://recipe-book.siraj.page/reference/react/json-ld/
|
|
548
|
+
*/
|
|
549
|
+
declare const JsonLd: ForwardRefExoticComponent<RecipeJsonLdProps & RefAttributes<HTMLScriptElement>>;
|
|
550
|
+
|
|
551
|
+
/**
|
|
552
|
+
* Built-in text that parts render or announce. Override any of it with the
|
|
553
|
+
* `labels` prop on `<Recipe.Root>` or `<RecipeBookProvider>`.
|
|
554
|
+
*
|
|
555
|
+
* A new key is additive: labels that leave it out keep its English default,
|
|
556
|
+
* and a label pack checked with `satisfies RecipeLabels` gets a compile error
|
|
557
|
+
* naming the new key.
|
|
558
|
+
*
|
|
559
|
+
* @example
|
|
560
|
+
* const spanish = {
|
|
561
|
+
* servings: 'Raciones',
|
|
562
|
+
* servingUnit: { one: 'ración', other: 'raciones' },
|
|
563
|
+
* system: 'Sistema de medida',
|
|
564
|
+
* metric: 'Métrico',
|
|
565
|
+
* us: 'EE. UU.',
|
|
566
|
+
* fan: 'con ventilador',
|
|
567
|
+
* optional: '(opcional)',
|
|
568
|
+
* to: 'a',
|
|
569
|
+
* } satisfies Recipe.RecipeLabels
|
|
570
|
+
*
|
|
571
|
+
* <Recipe.RecipeBookProvider locale="es-ES" labels={spanish}>
|
|
572
|
+
* {children}
|
|
573
|
+
* </Recipe.RecipeBookProvider>
|
|
574
|
+
*
|
|
575
|
+
* @see https://recipe-book.siraj.page/reference/react/provider/
|
|
576
|
+
*/
|
|
577
|
+
type RecipeLabels = {
|
|
578
|
+
/**
|
|
579
|
+
* Accessible name of `<Recipe.ServingsSelect>` and `<Recipe.ServingsInput>`,
|
|
580
|
+
* unless they get an `aria-label` or `aria-labelledby`. Defaults to
|
|
581
|
+
* `'Servings'`.
|
|
582
|
+
*
|
|
583
|
+
* @see https://recipe-book.siraj.page/reference/react/provider/
|
|
584
|
+
*/
|
|
585
|
+
servings: string;
|
|
586
|
+
/**
|
|
587
|
+
* Unit for the servings count: "1 serving", "4 servings".
|
|
588
|
+
* `<Recipe.ServingsSelect>` words each option with it, for a recipe with
|
|
589
|
+
* `servings`. Defaults to `{ one: 'serving', other: 'servings' }`.
|
|
590
|
+
*
|
|
591
|
+
* @see https://recipe-book.siraj.page/reference/react/provider/
|
|
592
|
+
*/
|
|
593
|
+
servingUnit: {
|
|
594
|
+
/** Follows 1 and a fraction below 1: "1 serving", "½ serving". */
|
|
595
|
+
one: string;
|
|
596
|
+
/** Follows decimals and any other number: "0.3 servings", "4 servings". */
|
|
597
|
+
other: string;
|
|
598
|
+
};
|
|
599
|
+
/**
|
|
600
|
+
* Accessible name of `<Recipe.SystemToggle>`, unless it gets an
|
|
601
|
+
* `aria-label` or `aria-labelledby`. Defaults to `'Measurement system'`.
|
|
602
|
+
*
|
|
603
|
+
* @see https://recipe-book.siraj.page/reference/react/provider/
|
|
604
|
+
*/
|
|
605
|
+
system: string;
|
|
606
|
+
/**
|
|
607
|
+
* Name of the metric system, shown by a `<Recipe.SystemOption>` for
|
|
608
|
+
* `'metric'` that has no children, or an empty `asChild` child. Defaults to
|
|
609
|
+
* `'Metric'`.
|
|
610
|
+
*
|
|
611
|
+
* @see https://recipe-book.siraj.page/reference/react/provider/
|
|
612
|
+
*/
|
|
613
|
+
metric: string;
|
|
614
|
+
/**
|
|
615
|
+
* Name of the US system, shown by a `<Recipe.SystemOption>` for `'us'` that
|
|
616
|
+
* has no children, or an empty `asChild` child. Defaults to `'US'`.
|
|
617
|
+
*
|
|
618
|
+
* @see https://recipe-book.siraj.page/reference/react/provider/
|
|
619
|
+
*/
|
|
620
|
+
us: string;
|
|
621
|
+
/**
|
|
622
|
+
* Marker after a fan-oven temperature in `<Recipe.StepText>`: "160 °C fan".
|
|
623
|
+
* An empty string leaves it out. Defaults to `'fan'`.
|
|
624
|
+
*
|
|
625
|
+
* @see https://recipe-book.siraj.page/reference/react/provider/
|
|
626
|
+
*/
|
|
627
|
+
fan: string;
|
|
628
|
+
/**
|
|
629
|
+
* Marker after an optional ingredient, shown as is, punctuation included.
|
|
630
|
+
* `<Recipe.IngredientOptional>` renders it, and the function from
|
|
631
|
+
* `useFormatIngredient()` returns it as `optional`. Defaults to
|
|
632
|
+
* `'(optional)'`.
|
|
633
|
+
*
|
|
634
|
+
* @see https://recipe-book.siraj.page/reference/react/provider/
|
|
635
|
+
*/
|
|
636
|
+
optional: string;
|
|
637
|
+
/**
|
|
638
|
+
* Spoken between the ends of a range, "2 to 3 tbsp". Screen readers only:
|
|
639
|
+
* `<Recipe.IngredientQuantity>` keeps the visible dash, "2–3 tbsp".
|
|
640
|
+
* Defaults to `'to'`.
|
|
641
|
+
*
|
|
642
|
+
* @see https://recipe-book.siraj.page/reference/react/provider/
|
|
643
|
+
*/
|
|
644
|
+
to: string;
|
|
645
|
+
};
|
|
646
|
+
|
|
647
|
+
/** The locale, labels, and starting system that `RecipeBookProvider` and `<Recipe.Root>` take. */
|
|
648
|
+
type RecipeBookConfig = {
|
|
649
|
+
/**
|
|
650
|
+
* A language tag that `Intl` accepts, such as `'de-DE'`, for formatting
|
|
651
|
+
* numbers. With a tag it rejects, such as `'en_US'`, formatting a number
|
|
652
|
+
* throws `invalid_argument`.
|
|
653
|
+
*
|
|
654
|
+
* @defaultValue The outer provider's `locale`, then `'en-US'`.
|
|
655
|
+
*
|
|
656
|
+
* @see https://recipe-book.siraj.page/reference/react/provider/#recipebookprovider
|
|
657
|
+
* @see https://recipe-book.siraj.page/reference/react/root/#root
|
|
658
|
+
*/
|
|
659
|
+
locale?: string | undefined;
|
|
660
|
+
/**
|
|
661
|
+
* Built-in text to override. A key you leave out keeps the outer provider's
|
|
662
|
+
* value, then its English default. Pass an object that keeps its identity
|
|
663
|
+
* between renders: an equal but new one re-renders most parts.
|
|
664
|
+
*
|
|
665
|
+
* @see https://recipe-book.siraj.page/reference/react/provider/
|
|
666
|
+
* @see https://recipe-book.siraj.page/reference/react/root/
|
|
667
|
+
*/
|
|
668
|
+
labels?: RecipeLabelOverrides | undefined;
|
|
669
|
+
/**
|
|
670
|
+
* The measurement system a Root starts in, unless its `system` is
|
|
671
|
+
* controlled. Defaults to the outer provider's, then the system its recipe
|
|
672
|
+
* was written in, then `'metric'`. A value other than `'metric'` or `'us'`
|
|
673
|
+
* counts as missing.
|
|
674
|
+
*
|
|
675
|
+
* @see https://recipe-book.siraj.page/reference/react/provider/#recipebookprovider
|
|
676
|
+
* @see https://recipe-book.siraj.page/reference/react/root/#root
|
|
677
|
+
*/
|
|
678
|
+
defaultSystem?: System | undefined;
|
|
679
|
+
};
|
|
680
|
+
/**
|
|
681
|
+
* Built-in text to override, for the `labels` prop of `RecipeBookProvider` and
|
|
682
|
+
* `<Recipe.Root>`.
|
|
683
|
+
*
|
|
684
|
+
* Any keys of `RecipeLabels`. A value replaces the whole key, so `servingUnit`
|
|
685
|
+
* needs both `one` and `other`.
|
|
686
|
+
*
|
|
687
|
+
* @example
|
|
688
|
+
* // At module scope, so it keeps its identity between renders.
|
|
689
|
+
* const labels = {
|
|
690
|
+
* servings: 'Portions',
|
|
691
|
+
* servingUnit: { one: 'portion', other: 'portions' },
|
|
692
|
+
* } satisfies Recipe.RecipeLabelOverrides
|
|
693
|
+
*
|
|
694
|
+
* <Recipe.Root recipe={recipe} labels={labels}>
|
|
695
|
+
* <Recipe.ServingsSelect />
|
|
696
|
+
* </Recipe.Root>
|
|
697
|
+
*
|
|
698
|
+
* @see https://recipe-book.siraj.page/reference/react/provider/#recipelabeloverrides
|
|
699
|
+
*/
|
|
700
|
+
type RecipeLabelOverrides = {
|
|
701
|
+
[Key in keyof RecipeLabels]?: RecipeLabels[Key] | undefined;
|
|
702
|
+
};
|
|
703
|
+
/**
|
|
704
|
+
* Props of `RecipeBookProvider`: defaults for every Root below it, plus
|
|
705
|
+
* `children`.
|
|
706
|
+
*
|
|
707
|
+
* @example
|
|
708
|
+
* export function AppProvider(props: Recipe.RecipeBookProviderProps) {
|
|
709
|
+
* return <Recipe.RecipeBookProvider locale="en-GB" {...props} />
|
|
710
|
+
* }
|
|
711
|
+
*
|
|
712
|
+
* @see https://recipe-book.siraj.page/reference/react/provider/#recipebookprovider
|
|
713
|
+
*/
|
|
714
|
+
type RecipeBookProviderProps = RecipeBookConfig & {
|
|
715
|
+
/**
|
|
716
|
+
* The part of the app that uses these defaults.
|
|
717
|
+
*
|
|
718
|
+
* @see https://recipe-book.siraj.page/reference/react/provider/#recipebookprovider
|
|
719
|
+
*/
|
|
720
|
+
children?: ReactNode;
|
|
721
|
+
};
|
|
722
|
+
/**
|
|
723
|
+
* App-wide defaults for every `<Recipe.Root>` below it. Takes only data, so it
|
|
724
|
+
* can wrap a layout rendered as a Server Component. Nested providers override
|
|
725
|
+
* the outer one key by key.
|
|
726
|
+
*
|
|
727
|
+
* @example
|
|
728
|
+
* // app/layout.tsx
|
|
729
|
+
* <Recipe.RecipeBookProvider defaultSystem="metric">
|
|
730
|
+
* {children}
|
|
731
|
+
* </Recipe.RecipeBookProvider>
|
|
732
|
+
*
|
|
733
|
+
* @see https://recipe-book.siraj.page/reference/react/provider/#recipebookprovider
|
|
734
|
+
*/
|
|
735
|
+
declare function RecipeBookProvider({ children, ...config }: RecipeBookProviderProps): JSX.Element;
|
|
736
|
+
/**
|
|
737
|
+
* The state of the nearest `<Recipe.Root>`: the recipe, servings, and
|
|
738
|
+
* measurement system, with their setters.
|
|
739
|
+
*
|
|
740
|
+
* @returns The Root's `RecipeState`: `recipe`, `servings`, `scale`, `system`,
|
|
741
|
+
* `canConvert`, `ingredients` and `steps` as the Root shows them, and the
|
|
742
|
+
* `setServings` and `setSystem` that change them.
|
|
743
|
+
*
|
|
744
|
+
* @throws {RecipeBookError} `missing_parent` outside a Root.
|
|
745
|
+
*
|
|
746
|
+
* @example
|
|
747
|
+
* function SystemSwitch() {
|
|
748
|
+
* const { system, setSystem, canConvert } = Recipe.useRecipe()
|
|
749
|
+
* if (!canConvert) return null
|
|
750
|
+
* return (
|
|
751
|
+
* <button onClick={() => setSystem(system === 'us' ? 'metric' : 'us')}>
|
|
752
|
+
* {system === 'us' ? 'Show metric' : 'Show US'}
|
|
753
|
+
* </button>
|
|
754
|
+
* )
|
|
755
|
+
* }
|
|
756
|
+
*
|
|
757
|
+
* @see https://recipe-book.siraj.page/reference/react/hooks/#userecipe
|
|
758
|
+
*/
|
|
759
|
+
declare function useRecipe(): RecipeState;
|
|
760
|
+
|
|
761
|
+
/**
|
|
762
|
+
* The props of `<Recipe.Root>`, a union: a parsed `recipe`, or raw data with
|
|
763
|
+
* `parse`. To wrap `Root`, intersect (`RecipeRootProps & { … }`) or
|
|
764
|
+
* destructure it, rather than `Omit<RecipeRootProps, …>`, which doesn't
|
|
765
|
+
* type-check against a union.
|
|
766
|
+
*
|
|
767
|
+
* @see https://recipe-book.siraj.page/reference/react/root/#root
|
|
768
|
+
* @see https://recipe-book.siraj.page/reference/react/root/#wrap-root
|
|
769
|
+
*/
|
|
770
|
+
type RecipeRootProps = RecipeBookConfig & Omit<RecipeStateOptions, 'recipe' | 'defaultSystem'> & {
|
|
771
|
+
/** The parts and components that read the recipe's state. */
|
|
772
|
+
children?: ReactNode;
|
|
773
|
+
} & ({
|
|
774
|
+
/**
|
|
775
|
+
* A parsed recipe. Call `parseRecipe` from `@recipe-book/react/core`
|
|
776
|
+
* on the server, in a loader, or at build time, and pass
|
|
777
|
+
* `result.data`.
|
|
778
|
+
*/
|
|
779
|
+
recipe: Recipe;
|
|
780
|
+
/** Only with recipe data to parse. A parsed recipe takes no `parse`. */
|
|
781
|
+
parse?: undefined;
|
|
782
|
+
/** Only with `parse`. A parsed recipe always renders. */
|
|
783
|
+
fallback?: undefined;
|
|
784
|
+
} | {
|
|
785
|
+
/** Recipe data for `parse` to validate and normalize. */
|
|
786
|
+
recipe: unknown;
|
|
787
|
+
/**
|
|
788
|
+
* Parses `recipe` in the browser. Pass `parseRecipe` from
|
|
789
|
+
* `@recipe-book/react/core`; only apps that do download the parser.
|
|
790
|
+
*
|
|
791
|
+
* A function, so it can only be passed from a Client Component. Pass a
|
|
792
|
+
* stable function such as `parseRecipe` itself: an inline arrow
|
|
793
|
+
* parses again on every render.
|
|
794
|
+
*/
|
|
795
|
+
parse: (input: unknown) => ParseResult<Recipe>;
|
|
796
|
+
/**
|
|
797
|
+
* Rendered instead of `children` when `parse` rejects `recipe`.
|
|
798
|
+
*
|
|
799
|
+
* @defaultValue `null`
|
|
800
|
+
* @see https://recipe-book.siraj.page/reference/react/root/#parse-in-the-browser
|
|
801
|
+
*/
|
|
802
|
+
fallback?: ReactNode;
|
|
803
|
+
});
|
|
804
|
+
/**
|
|
805
|
+
* Provides a recipe's state to the parts inside. Renders no element of its own.
|
|
806
|
+
*
|
|
807
|
+
* Takes a parsed recipe. To parse recipe data in the browser instead, pass
|
|
808
|
+
* `parse={parseRecipe}`: an invalid recipe then renders `fallback`, and in
|
|
809
|
+
* development a result's validation error or warnings are logged to the
|
|
810
|
+
* browser console unless the previous result had the same ones in the same
|
|
811
|
+
* order.
|
|
812
|
+
*
|
|
813
|
+
* @throws {RecipeBookError} `invalid_argument` when `recipe` isn't a parsed
|
|
814
|
+
* recipe and there is no `parse`.
|
|
815
|
+
*
|
|
816
|
+
* @example
|
|
817
|
+
* <Recipe.Root recipe={recipe} defaultServings={8}>
|
|
818
|
+
* <Recipe.Image />
|
|
819
|
+
* <Recipe.Ingredients />
|
|
820
|
+
* <Recipe.Steps />
|
|
821
|
+
* </Recipe.Root>
|
|
822
|
+
*
|
|
823
|
+
* @see https://recipe-book.siraj.page/reference/react/root/
|
|
824
|
+
*/
|
|
825
|
+
declare function Root({ recipe, parse, fallback, children, ...options }: RecipeRootProps): JSX.Element;
|
|
826
|
+
|
|
827
|
+
/**
|
|
828
|
+
* The props of `<Recipe.ServingsSelect>`: the `<select>`'s attributes, plus
|
|
829
|
+
* the `options` to offer. It sets the value and the options itself, so it
|
|
830
|
+
* doesn't take `value`, `defaultValue`, `multiple`, `children` or
|
|
831
|
+
* `dangerouslySetInnerHTML`.
|
|
832
|
+
*
|
|
833
|
+
* @see https://recipe-book.siraj.page/reference/react/servings/#servingsselect
|
|
834
|
+
*/
|
|
835
|
+
type RecipeServingsSelectProps = Omit<ComponentPropsWithoutRef<'select'>, 'value' | 'defaultValue' | 'multiple' | 'children' | 'dangerouslySetInnerHTML'> & {
|
|
836
|
+
/**
|
|
837
|
+
* Servings to offer, shown in ascending order. A number outside the
|
|
838
|
+
* servings window is left out.
|
|
839
|
+
*
|
|
840
|
+
* @defaultValue ½×, 1×, 2×, and 3× the recipe's scaling base (its servings
|
|
841
|
+
* amount, else its yield amount, else 1), each rounded to a whole number of
|
|
842
|
+
* at least 1.
|
|
843
|
+
*
|
|
844
|
+
* @see https://recipe-book.siraj.page/reference/react/servings/#servingsselect
|
|
845
|
+
* @see https://recipe-book.siraj.page/reference/react/root/#servings-window
|
|
846
|
+
*/
|
|
847
|
+
options?: readonly number[] | undefined;
|
|
848
|
+
};
|
|
849
|
+
/**
|
|
850
|
+
* A `<select>` of servings. Options read "4 servings" when the recipe has
|
|
851
|
+
* servings, "24 cookies" in the yield's word when it has only a yield, and
|
|
852
|
+
* "2×" when it has neither. Their values are always servings. The current
|
|
853
|
+
* servings are always an option, so a value set elsewhere still shows.
|
|
854
|
+
*
|
|
855
|
+
* Its accessible name defaults to the `servings` label. An `aria-label` you
|
|
856
|
+
* pass replaces it and `aria-labelledby` outranks it. To name the select with
|
|
857
|
+
* a `<label>`, pass `aria-label=""`.
|
|
858
|
+
*
|
|
859
|
+
* It sets `autoComplete="off"`, so when going back reloads the page, the
|
|
860
|
+
* browser doesn't restore an earlier choice over the Root's servings. An
|
|
861
|
+
* `autoComplete` you pass wins.
|
|
862
|
+
*
|
|
863
|
+
* @throws {RecipeBookError} `missing_parent` outside a `<Recipe.Root>`, and
|
|
864
|
+
* `invalid_argument` when the Root's `locale` isn't a language tag that
|
|
865
|
+
* `Intl` accepts, such as `'en_US'`.
|
|
866
|
+
*
|
|
867
|
+
* @example
|
|
868
|
+
* <Recipe.Root recipe={recipe}>
|
|
869
|
+
* <Recipe.ServingsSelect options={[2, 4, 6, 8]} />
|
|
870
|
+
* </Recipe.Root>
|
|
871
|
+
*
|
|
872
|
+
* @see https://recipe-book.siraj.page/reference/react/servings/#servingsselect
|
|
873
|
+
*/
|
|
874
|
+
declare const ServingsSelect: ForwardRefExoticComponent<RecipeServingsSelectProps & RefAttributes<HTMLSelectElement>>;
|
|
875
|
+
/**
|
|
876
|
+
* The props of `<Recipe.ServingsInput>`: the `<input type="number">`'s
|
|
877
|
+
* attributes, with `min`, `max` and `step` as numbers. It sets the type and
|
|
878
|
+
* the value, which follows the Root's servings, so it doesn't take `type`,
|
|
879
|
+
* `value` or `defaultValue`.
|
|
880
|
+
*
|
|
881
|
+
* @see https://recipe-book.siraj.page/reference/react/servings/#servingsinput
|
|
882
|
+
*/
|
|
883
|
+
type RecipeServingsInputProps = Omit<ComponentPropsWithoutRef<'input'>, 'type' | 'value' | 'defaultValue' | 'min' | 'max' | 'step'> & {
|
|
884
|
+
/**
|
|
885
|
+
* The fewest servings that can be entered, set as the `min` attribute. The
|
|
886
|
+
* `step` grid counts from it.
|
|
887
|
+
*
|
|
888
|
+
* @defaultValue `1`
|
|
889
|
+
*
|
|
890
|
+
* @see https://recipe-book.siraj.page/reference/react/servings/#servingsinput
|
|
891
|
+
*/
|
|
892
|
+
min?: number | undefined;
|
|
893
|
+
/**
|
|
894
|
+
* The most servings that can be entered, set as the `max` attribute.
|
|
895
|
+
* Without it, there's no `max` attribute, and the input accepts numbers up
|
|
896
|
+
* to the top of the servings window.
|
|
897
|
+
*
|
|
898
|
+
* @see https://recipe-book.siraj.page/reference/react/servings/#servingsinput
|
|
899
|
+
* @see https://recipe-book.siraj.page/reference/react/root/#servings-window
|
|
900
|
+
*/
|
|
901
|
+
max?: number | undefined;
|
|
902
|
+
/**
|
|
903
|
+
* How far the arrows move the value, and the grid, counted from `min`, that
|
|
904
|
+
* an entered value must be on. `'any'` allows any value. A `step` that
|
|
905
|
+
* isn't a number above 0 counts as 1, as in the browser.
|
|
906
|
+
*
|
|
907
|
+
* @defaultValue `1`, the browser's step for an input without a `step`
|
|
908
|
+
* attribute
|
|
909
|
+
*
|
|
910
|
+
* @see https://recipe-book.siraj.page/reference/react/servings/#the-step-grid
|
|
911
|
+
*/
|
|
912
|
+
step?: number | 'any' | undefined;
|
|
913
|
+
};
|
|
914
|
+
/**
|
|
915
|
+
* A number input for servings. Each valid value commits as it's typed. An
|
|
916
|
+
* empty or out-of-range entry, text that isn't a number yet, or a number off
|
|
917
|
+
* the `step` grid stays a draft, and leaving the input shows the current
|
|
918
|
+
* servings again. Servings the recipe can't be scaled to count as out of
|
|
919
|
+
* range, so typing them logs no warning.
|
|
920
|
+
*
|
|
921
|
+
* Its accessible name and `autoComplete` follow the same rules as
|
|
922
|
+
* `<Recipe.ServingsSelect>`. `inputMode` defaults to `'numeric'` when `min`
|
|
923
|
+
* and the step are whole numbers, as with the defaults of 1, and to
|
|
924
|
+
* `'decimal'` otherwise, including with `step="any"`.
|
|
925
|
+
*
|
|
926
|
+
* @throws {RecipeBookError} `missing_parent` outside a `<Recipe.Root>`.
|
|
927
|
+
*
|
|
928
|
+
* @example
|
|
929
|
+
* <Recipe.Root recipe={recipe}>
|
|
930
|
+
* <Recipe.ServingsInput max={48} />
|
|
931
|
+
* </Recipe.Root>
|
|
932
|
+
*
|
|
933
|
+
* @see https://recipe-book.siraj.page/reference/react/servings/#servingsinput
|
|
934
|
+
*/
|
|
935
|
+
declare const ServingsInput: ForwardRefExoticComponent<RecipeServingsInputProps & RefAttributes<HTMLInputElement>>;
|
|
936
|
+
|
|
937
|
+
/**
|
|
938
|
+
* Attributes for the `<span>`; it renders the step's text, so no `children` or
|
|
939
|
+
* `dangerouslySetInnerHTML`.
|
|
940
|
+
*
|
|
941
|
+
* @see https://recipe-book.siraj.page/reference/react/steps/#steptext
|
|
942
|
+
*/
|
|
943
|
+
type RecipeStepTextProps = Omit<ComponentPropsWithoutRef<'span'>, 'children' | 'dangerouslySetInnerHTML'>;
|
|
944
|
+
/**
|
|
945
|
+
* The nearest `<Recipe.Step>`'s text, with each temperature shown in Root's
|
|
946
|
+
* display system: °C for metric, °F for US. A reading the author wrote in that
|
|
947
|
+
* unit keeps its value as written, such as 56.5 °C. A converted one is in
|
|
948
|
+
* whole degrees, because step text doesn't say whether it's an oven setting or
|
|
949
|
+
* a food temperature. A setting the author already wrote in both units isn't
|
|
950
|
+
* converted again, and a fan-oven setting is followed by `labels.fan`. A gas
|
|
951
|
+
* mark that follows a temperature as another way to give the same setting, as
|
|
952
|
+
* in `190C/170C fan/gas 5` or `200°C (gas mark 6)`, is left out. Everything
|
|
953
|
+
* else, including a gas mark on its own or before a temperature, is shown as
|
|
954
|
+
* authored. Each temperature is a `<span data-recipe-temperature>`. When
|
|
955
|
+
* `segmentStepText` pairs a conventional setting with a fan one, the
|
|
956
|
+
* conventional one shows first and the fan one after a slash, as in
|
|
957
|
+
* `200 °C / 180 °C fan`.
|
|
958
|
+
*
|
|
959
|
+
* @throws {RecipeBookError} `missing_parent` outside a `<Recipe.Step>`.
|
|
960
|
+
* @throws {RecipeBookError} `invalid_argument` for a step with a temperature
|
|
961
|
+
* when Root's `locale` isn't a language tag that `Intl` accepts, such as
|
|
962
|
+
* `'en_US'`.
|
|
963
|
+
*
|
|
964
|
+
* @example
|
|
965
|
+
* <Recipe.Step item={step}>
|
|
966
|
+
* <Recipe.StepName /> <Recipe.StepText />
|
|
967
|
+
* </Recipe.Step>
|
|
968
|
+
*
|
|
969
|
+
* @see https://recipe-book.siraj.page/reference/react/steps/#steptext
|
|
970
|
+
*/
|
|
971
|
+
declare const StepText: ForwardRefExoticComponent<RecipeStepTextProps & RefAttributes<HTMLSpanElement>>;
|
|
972
|
+
|
|
973
|
+
/**
|
|
974
|
+
* Attributes for the wrapping `<div>` other than `dangerouslySetInnerHTML`,
|
|
975
|
+
* plus `headingLevel`; `children` renders each section.
|
|
976
|
+
*
|
|
977
|
+
* @see https://recipe-book.siraj.page/reference/react/steps/#steps
|
|
978
|
+
*/
|
|
979
|
+
type RecipeStepsProps = Omit<ComponentPropsWithoutRef<'div'>, 'children' | 'dangerouslySetInnerHTML'> & {
|
|
980
|
+
/**
|
|
981
|
+
* Heading level of section titles in the default rendering. Defaults to 3,
|
|
982
|
+
* for steps under an `<h2>` such as "Method".
|
|
983
|
+
*
|
|
984
|
+
* @defaultValue `3`
|
|
985
|
+
* @see https://recipe-book.siraj.page/guides/make-a-recipe-accessible/#set-heading-levels
|
|
986
|
+
*/
|
|
987
|
+
headingLevel?: RecipeHeadingLevel | undefined;
|
|
988
|
+
/**
|
|
989
|
+
* Renders each section instead of the default. Each result is keyed for
|
|
990
|
+
* you, so return one element or a fragment; an array's items need their own
|
|
991
|
+
* keys, as anywhere in React.
|
|
992
|
+
*
|
|
993
|
+
* @defaultValue A `<section>` named by the section's heading, or a `<div>`
|
|
994
|
+
* for an untitled section, around a `<Recipe.StepList>` of its steps.
|
|
995
|
+
* @see https://recipe-book.siraj.page/reference/react/steps/#render-your-own-sections
|
|
996
|
+
*/
|
|
997
|
+
children?: ((section: RecipeSection<StepItem>) => ReactNode) | undefined;
|
|
998
|
+
};
|
|
999
|
+
/**
|
|
1000
|
+
* The recipe's steps, one block per section. A titled section renders as a
|
|
1001
|
+
* `<section>` named by its heading, then a `<Recipe.StepList>`.
|
|
1002
|
+
*
|
|
1003
|
+
* @throws {RecipeBookError} `missing_parent` outside a `<Recipe.Root>`.
|
|
1004
|
+
*
|
|
1005
|
+
* @example
|
|
1006
|
+
* <Recipe.Root recipe={recipe}>
|
|
1007
|
+
* <h2>Method</h2>
|
|
1008
|
+
* <Recipe.Steps />
|
|
1009
|
+
* </Recipe.Root>
|
|
1010
|
+
*
|
|
1011
|
+
* @see https://recipe-book.siraj.page/reference/react/steps/#steps
|
|
1012
|
+
*/
|
|
1013
|
+
declare const Steps: ForwardRefExoticComponent<RecipeStepsProps & RefAttributes<HTMLDivElement>>;
|
|
1014
|
+
/**
|
|
1015
|
+
* Attributes for the `<ol>` other than `dangerouslySetInnerHTML`, plus the
|
|
1016
|
+
* `section` to list; `children` renders each step.
|
|
1017
|
+
*
|
|
1018
|
+
* @see https://recipe-book.siraj.page/reference/react/steps/#steplist
|
|
1019
|
+
*/
|
|
1020
|
+
type RecipeStepListProps = Omit<ComponentPropsWithoutRef<'ol'>, 'children' | 'dangerouslySetInnerHTML'> & {
|
|
1021
|
+
/** The section to list. Defaults to every step in the recipe. */
|
|
1022
|
+
section?: RecipeSection<StepItem> | undefined;
|
|
1023
|
+
/**
|
|
1024
|
+
* Renders each step instead of `<Recipe.Step>`. Each result is keyed for
|
|
1025
|
+
* you, so return one element or a fragment; an array's items need their own
|
|
1026
|
+
* keys, as anywhere in React.
|
|
1027
|
+
*
|
|
1028
|
+
* @defaultValue `(step) => <Recipe.Step item={step} />`
|
|
1029
|
+
* @see https://recipe-book.siraj.page/reference/react/steps/#render-your-own-steps
|
|
1030
|
+
*/
|
|
1031
|
+
children?: ((step: StepItem) => ReactNode) | undefined;
|
|
1032
|
+
};
|
|
1033
|
+
/**
|
|
1034
|
+
* An ordered list of steps. `start` defaults to the first step's number, so
|
|
1035
|
+
* numbering continues across sections.
|
|
1036
|
+
*
|
|
1037
|
+
* @throws {RecipeBookError} `missing_parent` outside a `<Recipe.Root>`.
|
|
1038
|
+
*
|
|
1039
|
+
* @example
|
|
1040
|
+
* <Recipe.StepList>
|
|
1041
|
+
* {(step) => (
|
|
1042
|
+
* <Recipe.Step item={step}>
|
|
1043
|
+
* <Recipe.StepName /> <Recipe.StepText />
|
|
1044
|
+
* </Recipe.Step>
|
|
1045
|
+
* )}
|
|
1046
|
+
* </Recipe.StepList>
|
|
1047
|
+
*
|
|
1048
|
+
* @see https://recipe-book.siraj.page/reference/react/steps/#steplist
|
|
1049
|
+
*/
|
|
1050
|
+
declare const StepList: ForwardRefExoticComponent<RecipeStepListProps & RefAttributes<HTMLOListElement>>;
|
|
1051
|
+
/**
|
|
1052
|
+
* Attributes for the `<li>` other than `dangerouslySetInnerHTML`, plus the
|
|
1053
|
+
* `item` to render and `asChild`.
|
|
1054
|
+
*
|
|
1055
|
+
* @see https://recipe-book.siraj.page/reference/react/steps/#step
|
|
1056
|
+
*/
|
|
1057
|
+
type RecipeStepProps = Omit<ComponentPropsWithoutRef<'li'>, 'dangerouslySetInnerHTML'> & {
|
|
1058
|
+
/** The step to render, with its number. */
|
|
1059
|
+
item: StepItem;
|
|
1060
|
+
/**
|
|
1061
|
+
* Renders the step as its one element child, such as `<motion.li layout />`,
|
|
1062
|
+
* instead of an `<li>`. A prop on the child wins, except that the step's
|
|
1063
|
+
* `tabIndex` wins, `className`s join, `style` merges key by key with the
|
|
1064
|
+
* child winning, both event handlers run (the child's first), and both refs
|
|
1065
|
+
* are set. The child's own children replace the step's, so an empty child
|
|
1066
|
+
* gets the name and text. With anything but one element child, it renders
|
|
1067
|
+
* its own `<li>`, with a warning in development.
|
|
1068
|
+
*
|
|
1069
|
+
* @defaultValue `false`
|
|
1070
|
+
* @see https://recipe-book.siraj.page/reference/react/steps/#render-your-own-element
|
|
1071
|
+
*/
|
|
1072
|
+
asChild?: boolean | undefined;
|
|
1073
|
+
};
|
|
1074
|
+
/**
|
|
1075
|
+
* One step. Default children are `<Recipe.StepName>`, then a space if the
|
|
1076
|
+
* step has a name, then its text as authored. Custom children can use
|
|
1077
|
+
* `<Recipe.StepName>` and `<Recipe.StepText>` to read like the default, with
|
|
1078
|
+
* temperatures in Root's display system.
|
|
1079
|
+
*
|
|
1080
|
+
* @example
|
|
1081
|
+
* <Recipe.Step item={step}>
|
|
1082
|
+
* <Recipe.StepName /> <Recipe.StepText />
|
|
1083
|
+
* </Recipe.Step>
|
|
1084
|
+
*
|
|
1085
|
+
* @throws {RecipeBookError} `missing_parent` outside a `<Recipe.Root>`.
|
|
1086
|
+
*
|
|
1087
|
+
* @see https://recipe-book.siraj.page/reference/react/steps/#step
|
|
1088
|
+
*/
|
|
1089
|
+
declare const Step: ForwardRefExoticComponent<RecipeStepProps & RefAttributes<HTMLLIElement>>;
|
|
1090
|
+
/**
|
|
1091
|
+
* Attributes for the `<b>`; it renders the step's name, so no `children` or
|
|
1092
|
+
* `dangerouslySetInnerHTML`.
|
|
1093
|
+
*
|
|
1094
|
+
* @see https://recipe-book.siraj.page/reference/react/steps/#stepname
|
|
1095
|
+
*/
|
|
1096
|
+
type RecipeStepNameProps = Omit<ComponentPropsWithoutRef<'b'>, 'children' | 'dangerouslySetInnerHTML'>;
|
|
1097
|
+
/**
|
|
1098
|
+
* The nearest `<Recipe.Step>`'s name in a `<b data-recipe-name>`, or nothing
|
|
1099
|
+
* when the step has none.
|
|
1100
|
+
*
|
|
1101
|
+
* @throws {RecipeBookError} `missing_parent` outside a `<Recipe.Step>`.
|
|
1102
|
+
*
|
|
1103
|
+
* @see https://recipe-book.siraj.page/reference/react/steps/#stepname
|
|
1104
|
+
*/
|
|
1105
|
+
declare const StepName: ForwardRefExoticComponent<RecipeStepNameProps & RefAttributes<HTMLElement>>;
|
|
1106
|
+
|
|
1107
|
+
/**
|
|
1108
|
+
* The props of `<Recipe.SystemToggle>`: the radio group's `<div>` attributes,
|
|
1109
|
+
* plus `asChild`. It sets `role` and renders its own content, so it doesn't
|
|
1110
|
+
* take `role` or `dangerouslySetInnerHTML`.
|
|
1111
|
+
*
|
|
1112
|
+
* The group sets `aria-disabled` and its data attributes at runtime, over any
|
|
1113
|
+
* you pass, so `aria-disabled` is there only while the toggle is disabled. An
|
|
1114
|
+
* `asChild` child's own `role`, `aria-disabled` and data attributes still
|
|
1115
|
+
* win.
|
|
1116
|
+
*
|
|
1117
|
+
* @see https://recipe-book.siraj.page/reference/react/system-toggle/#systemtoggle
|
|
1118
|
+
*/
|
|
1119
|
+
type RecipeSystemToggleProps = Omit<ComponentPropsWithoutRef<'div'>, 'role' | 'dangerouslySetInnerHTML'> & {
|
|
1120
|
+
/**
|
|
1121
|
+
* Renders the radio group as its one element child, such as
|
|
1122
|
+
* `<motion.div layout />`, instead of a `<div>`. A prop on the child wins,
|
|
1123
|
+
* except that the group's `tabIndex` wins, `className`s join, `style` merges
|
|
1124
|
+
* key by key with the child winning, both event handlers run (the child's
|
|
1125
|
+
* first), and both refs are set. The child's own children replace the
|
|
1126
|
+
* group's, so an empty child gets the metric and US options. With anything
|
|
1127
|
+
* but one element child, it renders its own `<div>`, with a warning in
|
|
1128
|
+
* development.
|
|
1129
|
+
*
|
|
1130
|
+
* @defaultValue `false`
|
|
1131
|
+
*
|
|
1132
|
+
* @see https://recipe-book.siraj.page/reference/react/system-toggle/#render-your-own-elements
|
|
1133
|
+
*/
|
|
1134
|
+
asChild?: boolean | undefined;
|
|
1135
|
+
};
|
|
1136
|
+
/**
|
|
1137
|
+
* Switches the Root's measurement system. A radio group whose default options
|
|
1138
|
+
* are metric and US. Disabled when there's nothing to convert: no ingredient
|
|
1139
|
+
* has a unit that belongs to only one system, and no `Recipe.StepText` in the
|
|
1140
|
+
* Root shows a temperature. A `StepText` counts once it mounts, so for a
|
|
1141
|
+
* recipe whose only temperatures are in its steps, the toggle enables after
|
|
1142
|
+
* hydration.
|
|
1143
|
+
*
|
|
1144
|
+
* Its accessible name defaults to the `system` label, unless you pass
|
|
1145
|
+
* `aria-label` or `aria-labelledby`.
|
|
1146
|
+
*
|
|
1147
|
+
* @throws {RecipeBookError} `missing_parent` outside a `<Recipe.Root>`.
|
|
1148
|
+
*
|
|
1149
|
+
* @example
|
|
1150
|
+
* <Recipe.Root recipe={recipe}>
|
|
1151
|
+
* <Recipe.SystemToggle className="units" />
|
|
1152
|
+
* </Recipe.Root>
|
|
1153
|
+
*
|
|
1154
|
+
* @see https://recipe-book.siraj.page/reference/react/system-toggle/#systemtoggle
|
|
1155
|
+
*/
|
|
1156
|
+
declare const SystemToggle: ForwardRefExoticComponent<RecipeSystemToggleProps & RefAttributes<HTMLDivElement>>;
|
|
1157
|
+
/**
|
|
1158
|
+
* The props of `<Recipe.SystemOption>`: the radio's `<button>` attributes,
|
|
1159
|
+
* with `value` the system it selects, plus `asChild`. It sets `role` and
|
|
1160
|
+
* `tabIndex` and renders its own content, so it doesn't take them or
|
|
1161
|
+
* `dangerouslySetInnerHTML`.
|
|
1162
|
+
*
|
|
1163
|
+
* The option sets `aria-checked` and its data attributes at runtime, over any
|
|
1164
|
+
* you pass. An `asChild` child's own `role`, `aria-checked` and data
|
|
1165
|
+
* attributes still win.
|
|
1166
|
+
*
|
|
1167
|
+
* @see https://recipe-book.siraj.page/reference/react/system-toggle/#systemoption
|
|
1168
|
+
*/
|
|
1169
|
+
type RecipeSystemOptionProps = Omit<ComponentPropsWithoutRef<'button'>, 'value' | 'role' | 'tabIndex' | 'dangerouslySetInnerHTML'> & {
|
|
1170
|
+
/**
|
|
1171
|
+
* The system this option selects: `'metric'` or `'us'`.
|
|
1172
|
+
*
|
|
1173
|
+
* @see https://recipe-book.siraj.page/reference/react/system-toggle/#systemoption
|
|
1174
|
+
*/
|
|
1175
|
+
value: System;
|
|
1176
|
+
/**
|
|
1177
|
+
* The button's `autocomplete` attribute. Off by default, so when going back
|
|
1178
|
+
* reloads the page, Firefox doesn't re-enable an option that the server
|
|
1179
|
+
* rendered disabled and the page enabled later.
|
|
1180
|
+
*
|
|
1181
|
+
* @defaultValue `'off'`
|
|
1182
|
+
*
|
|
1183
|
+
* @see https://recipe-book.siraj.page/reference/react/system-toggle/#systemoption
|
|
1184
|
+
*/
|
|
1185
|
+
autoComplete?: string | undefined;
|
|
1186
|
+
/**
|
|
1187
|
+
* Renders the radio as its one element child, such as
|
|
1188
|
+
* `<motion.button layout />`, instead of a `<button>`. A prop on the child
|
|
1189
|
+
* wins, except that the option's `tabIndex` wins, `className`s join, `style`
|
|
1190
|
+
* merges key by key with the child winning, both event handlers run (the
|
|
1191
|
+
* child's first), and both refs are set. The option sets `tabIndex` to keep
|
|
1192
|
+
* one radio in the tab order once React hydrates the page; before that,
|
|
1193
|
+
* every enabled checked option is in it. The child's own children replace
|
|
1194
|
+
* the option's, so an empty child gets the system's label. With anything but
|
|
1195
|
+
* one element child, it renders its own `<button>`, with a warning in
|
|
1196
|
+
* development.
|
|
1197
|
+
*
|
|
1198
|
+
* @defaultValue `false`
|
|
1199
|
+
*
|
|
1200
|
+
* @see https://recipe-book.siraj.page/reference/react/system-toggle/#render-your-own-elements
|
|
1201
|
+
*/
|
|
1202
|
+
asChild?: boolean | undefined;
|
|
1203
|
+
};
|
|
1204
|
+
/**
|
|
1205
|
+
* One option of a `<Recipe.SystemToggle>`. Checked when its `value` is the
|
|
1206
|
+
* Root's system; a click sets the Root's system to `value`. Children default
|
|
1207
|
+
* to the system's label. Its `type` defaults to `'button'`, so it doesn't
|
|
1208
|
+
* submit a form. It's disabled while the toggle is, even with
|
|
1209
|
+
* `disabled={false}`.
|
|
1210
|
+
*
|
|
1211
|
+
* It sets `autoComplete="off"`, so when going back reloads the page, Firefox
|
|
1212
|
+
* doesn't re-enable an option that the server rendered disabled and the page
|
|
1213
|
+
* enabled later. An `autoComplete` you pass wins.
|
|
1214
|
+
*
|
|
1215
|
+
* @throws {RecipeBookError} `missing_parent` outside a
|
|
1216
|
+
* `<Recipe.SystemToggle>`.
|
|
1217
|
+
*
|
|
1218
|
+
* @example
|
|
1219
|
+
* <Recipe.SystemToggle>
|
|
1220
|
+
* <Recipe.SystemOption value="us">Cups and spoons</Recipe.SystemOption>
|
|
1221
|
+
* <Recipe.SystemOption value="metric">
|
|
1222
|
+
* Grams and milliliters
|
|
1223
|
+
* </Recipe.SystemOption>
|
|
1224
|
+
* </Recipe.SystemToggle>
|
|
1225
|
+
*
|
|
1226
|
+
* @see https://recipe-book.siraj.page/reference/react/system-toggle/#systemoption
|
|
1227
|
+
*/
|
|
1228
|
+
declare const SystemOption: ForwardRefExoticComponent<RecipeSystemOptionProps & RefAttributes<HTMLButtonElement>>;
|
|
1229
|
+
|
|
1230
|
+
/** An ingredient formatted with the nearest Root's locale and labels. */
|
|
1231
|
+
type FormattedIngredientItem = FormattedIngredient & {
|
|
1232
|
+
/** The quantity from `formatQuantityToParts`. Empty for an unquantified line. */
|
|
1233
|
+
quantityParts: QuantityPart[];
|
|
1234
|
+
/** `labels.optional`, set only for an optional ingredient. `text` never includes it. */
|
|
1235
|
+
optional?: string | undefined;
|
|
1236
|
+
};
|
|
1237
|
+
/**
|
|
1238
|
+
* Formats ingredient lines as `<Recipe.Ingredient>` does, with the nearest
|
|
1239
|
+
* Root's locale and labels: for markup without the ingredient parts, and for
|
|
1240
|
+
* renderers without a DOM. Returns the same function until the locale or
|
|
1241
|
+
* `labels.optional` changes.
|
|
1242
|
+
*
|
|
1243
|
+
* Without a Root, call `formatIngredient` from `@recipe-book/react/core`.
|
|
1244
|
+
*
|
|
1245
|
+
* @throws {RecipeBookError} `missing_parent` outside a Root.
|
|
1246
|
+
*
|
|
1247
|
+
* @returns A function that formats one of the state's ingredient items into
|
|
1248
|
+
* the pieces `<Recipe.Ingredient>` renders. It throws `invalid_argument`
|
|
1249
|
+
* when Root's `locale` isn't a language tag that `Intl` accepts, such as
|
|
1250
|
+
* `'en_US'`, the item isn't `{ ingredient, quantity? }`, or it has an amount
|
|
1251
|
+
* that `formatQuantity` rejects, and `unknown_unit` when the item's unit
|
|
1252
|
+
* isn't a unit ID.
|
|
1253
|
+
*
|
|
1254
|
+
* @example
|
|
1255
|
+
* function CopyIngredients() {
|
|
1256
|
+
* const { ingredients } = Recipe.useRecipe()
|
|
1257
|
+
* const format = Recipe.useFormatIngredient()
|
|
1258
|
+
* const lines = ingredients
|
|
1259
|
+
* .flatMap((section) => section.items)
|
|
1260
|
+
* .map((item) => {
|
|
1261
|
+
* const line = format(item)
|
|
1262
|
+
* return line.optional ? `${line.text} ${line.optional}` : line.text
|
|
1263
|
+
* })
|
|
1264
|
+
* return (
|
|
1265
|
+
* <button onClick={() => navigator.clipboard.writeText(lines.join('\n'))}>
|
|
1266
|
+
* Copy ingredients
|
|
1267
|
+
* </button>
|
|
1268
|
+
* )
|
|
1269
|
+
* }
|
|
1270
|
+
*
|
|
1271
|
+
* @see https://recipe-book.siraj.page/reference/react/hooks/#useformatingredient
|
|
1272
|
+
*/
|
|
1273
|
+
declare function useFormatIngredient(): (item: IngredientItem) => FormattedIngredientItem;
|
|
1274
|
+
|
|
1275
|
+
export { Image, Ingredient, IngredientList, IngredientName, IngredientNote, IngredientOptional, IngredientQuantity, Ingredients, JsonLd, RecipeBookProvider, Image as RecipeImage, Ingredient as RecipeIngredient, IngredientList as RecipeIngredientList, IngredientName as RecipeIngredientName, IngredientNote as RecipeIngredientNote, IngredientOptional as RecipeIngredientOptional, IngredientQuantity as RecipeIngredientQuantity, Ingredients as RecipeIngredients, JsonLd as RecipeJsonLd, Root as RecipeRoot, ServingsInput as RecipeServingsInput, ServingsSelect as RecipeServingsSelect, Step as RecipeStep, StepList as RecipeStepList, StepName as RecipeStepName, StepText as RecipeStepText, Steps as RecipeSteps, SystemOption as RecipeSystemOption, SystemToggle as RecipeSystemToggle, Root, ServingsInput, ServingsSelect, Step, StepList, StepName, StepText, Steps, SystemOption, SystemToggle, useFormatIngredient, useRecipe, useRecipeState };
|
|
1276
|
+
export type { FormattedIngredientItem, IngredientItem, RecipeBookProviderProps, RecipeHeadingLevel, RecipeImageProps, RecipeIngredientListProps, RecipeIngredientNameProps, RecipeIngredientNoteProps, RecipeIngredientOptionalProps, RecipeIngredientProps, RecipeIngredientQuantityProps, RecipeIngredientsProps, RecipeJsonLdProps, RecipeLabelOverrides, RecipeLabels, RecipeRootProps, RecipeSection, RecipeServingsInputProps, RecipeServingsSelectProps, RecipeState, RecipeStateOptions, RecipeStepListProps, RecipeStepNameProps, RecipeStepProps, RecipeStepTextProps, RecipeStepsProps, RecipeSystemOptionProps, RecipeSystemToggleProps, StepItem };
|