@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.
Files changed (167) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/LICENSE +21 -0
  3. package/README.md +48 -15
  4. package/core/package.json +5 -0
  5. package/core/schema-org/package.json +5 -0
  6. package/dist/core/schema-org.cjs +25 -0
  7. package/dist/core/schema-org.cjs.map +1 -0
  8. package/dist/core/schema-org.d.cts +1 -0
  9. package/dist/core/schema-org.d.ts +1 -0
  10. package/dist/core/schema-org.js +3 -0
  11. package/dist/core/schema-org.js.map +1 -0
  12. package/dist/core.cjs +25 -0
  13. package/dist/core.cjs.map +1 -0
  14. package/dist/core.d.cts +1 -0
  15. package/dist/core.d.ts +1 -0
  16. package/dist/core.js +3 -0
  17. package/dist/core.js.map +1 -0
  18. package/dist/index.cjs +1224 -0
  19. package/dist/index.cjs.map +1 -0
  20. package/dist/index.d.cts +1276 -0
  21. package/dist/index.d.ts +1276 -10
  22. package/dist/index.js +1207 -2
  23. package/dist/index.js.map +1 -0
  24. package/package.json +71 -15
  25. package/dist/chunk-2S2Z4HLL.mjs +0 -46
  26. package/dist/chunk-2VMRVR3X.mjs +0 -1
  27. package/dist/chunk-36H6LM2B.mjs +0 -14
  28. package/dist/chunk-4IWVZEXX.mjs +0 -20
  29. package/dist/chunk-4XBZKTOL.mjs +0 -1
  30. package/dist/chunk-6AGILC25.mjs +0 -20
  31. package/dist/chunk-6AXGEB5P.mjs +0 -14
  32. package/dist/chunk-6JEDN4VR.mjs +0 -20
  33. package/dist/chunk-6KLLMLNF.mjs +0 -33
  34. package/dist/chunk-6LTLY5K7.mjs +0 -20
  35. package/dist/chunk-6RA4EVIO.mjs +0 -46
  36. package/dist/chunk-75DF3E6L.mjs +0 -50
  37. package/dist/chunk-7BWMULSB.mjs +0 -55
  38. package/dist/chunk-7PPB3PM6.mjs +0 -40
  39. package/dist/chunk-7SBP7DC5.mjs +0 -42
  40. package/dist/chunk-7XJBP24U.mjs +0 -20
  41. package/dist/chunk-A5JAKCMG.mjs +0 -44
  42. package/dist/chunk-ATOAYKI3.mjs +0 -26
  43. package/dist/chunk-B5IXKKFC.mjs +0 -38
  44. package/dist/chunk-BEMMFA52.mjs +0 -49
  45. package/dist/chunk-BOG5DA6M.mjs +0 -38
  46. package/dist/chunk-BW4DYFBO.mjs +0 -36
  47. package/dist/chunk-CDQFOSWR.mjs +0 -34
  48. package/dist/chunk-CRQVP6PW.mjs +0 -20
  49. package/dist/chunk-CY27OHOG.mjs +0 -1
  50. package/dist/chunk-DACFJWGN.mjs +0 -14
  51. package/dist/chunk-DE5GUZKO.mjs +0 -46
  52. package/dist/chunk-DNZAFS5G.mjs +0 -48
  53. package/dist/chunk-DS3O5PAR.mjs +0 -20
  54. package/dist/chunk-ENGJXHYU.mjs +0 -42
  55. package/dist/chunk-FIFGRJKD.mjs +0 -26
  56. package/dist/chunk-FWOMIZEF.mjs +0 -46
  57. package/dist/chunk-G7XD4VBW.mjs +0 -44
  58. package/dist/chunk-GBU6MVZL.mjs +0 -14
  59. package/dist/chunk-GM5F7IUT.mjs +0 -2
  60. package/dist/chunk-GSGRXRJP.mjs +0 -38
  61. package/dist/chunk-GZRNU24M.mjs +0 -46
  62. package/dist/chunk-HNDXCSZY.mjs +0 -44
  63. package/dist/chunk-HXTUDCO2.mjs +0 -49
  64. package/dist/chunk-I5TR6PEA.mjs +0 -0
  65. package/dist/chunk-IXRYSEMS.mjs +0 -30
  66. package/dist/chunk-J5Q2Z2JG.mjs +0 -38
  67. package/dist/chunk-JBAAWEV6.mjs +0 -1
  68. package/dist/chunk-JCPPNN26.mjs +0 -44
  69. package/dist/chunk-JR3OTSZB.mjs +0 -32
  70. package/dist/chunk-JWS5RTU3.mjs +0 -46
  71. package/dist/chunk-K6EZ773Q.mjs +0 -26
  72. package/dist/chunk-KNXMYQVO.mjs +0 -36
  73. package/dist/chunk-KRUZ7OA7.mjs +0 -44
  74. package/dist/chunk-KXCIJBR6.mjs +0 -14
  75. package/dist/chunk-M5D3UUZF.mjs +0 -19
  76. package/dist/chunk-MASAOP7L.mjs +0 -55
  77. package/dist/chunk-MGBEDCLT.mjs +0 -34
  78. package/dist/chunk-MKBCBPVR.mjs +0 -53
  79. package/dist/chunk-N53TONLF.mjs +0 -39
  80. package/dist/chunk-NYDGFRPM.mjs +0 -46
  81. package/dist/chunk-OPOABKD6.mjs +0 -23
  82. package/dist/chunk-OX6ITS5C.mjs +0 -20
  83. package/dist/chunk-PAAVW47I.mjs +0 -50
  84. package/dist/chunk-PAF5HSSV.mjs +0 -53
  85. package/dist/chunk-PBENQR7Y.mjs +0 -1
  86. package/dist/chunk-PH3LQIHZ.mjs +0 -26
  87. package/dist/chunk-PIB3RAOO.mjs +0 -24
  88. package/dist/chunk-PIXLJD7Y.mjs +0 -37
  89. package/dist/chunk-PTS3BZHK.mjs +0 -1
  90. package/dist/chunk-Q6I5J3IJ.mjs +0 -1
  91. package/dist/chunk-QOCKR2HO.mjs +0 -1
  92. package/dist/chunk-QOZCSS3B.mjs +0 -44
  93. package/dist/chunk-QSFPUODQ.mjs +0 -34
  94. package/dist/chunk-RY7QUBJI.mjs +0 -34
  95. package/dist/chunk-RZJRUG2I.mjs +0 -55
  96. package/dist/chunk-S3GGSQB5.mjs +0 -1
  97. package/dist/chunk-S3HRT5Z5.mjs +0 -14
  98. package/dist/chunk-SB7HBCCZ.mjs +0 -49
  99. package/dist/chunk-SEXTT3NJ.mjs +0 -25
  100. package/dist/chunk-SKEQCOPX.mjs +0 -43
  101. package/dist/chunk-TLBRVWD2.mjs +0 -1
  102. package/dist/chunk-TOOCHDUY.mjs +0 -36
  103. package/dist/chunk-TSKANLT4.mjs +0 -37
  104. package/dist/chunk-UAMZEZUI.mjs +0 -36
  105. package/dist/chunk-UQJ4XNWN.mjs +0 -26
  106. package/dist/chunk-VDSUUXCH.mjs +0 -34
  107. package/dist/chunk-VO7RY2ZK.mjs +0 -44
  108. package/dist/chunk-WJKDFBJ2.mjs +0 -34
  109. package/dist/chunk-WTC7PY7U.mjs +0 -54
  110. package/dist/chunk-WXDV7CMB.mjs +0 -14
  111. package/dist/chunk-X5FG3X6T.mjs +0 -1
  112. package/dist/chunk-X66DY4AZ.mjs +0 -1
  113. package/dist/chunk-XXSJXKWQ.mjs +0 -44
  114. package/dist/chunk-YZMVAQQG.mjs +0 -1
  115. package/dist/chunk-ZCXPZU7W.mjs +0 -20
  116. package/dist/chunk-ZJ4PNVYO.mjs +0 -52
  117. package/dist/chunk-ZU4QJLEY.mjs +0 -53
  118. package/dist/components/ingredients/ingredients-list.d.mts +0 -13
  119. package/dist/components/ingredients/ingredients-list.d.ts +0 -13
  120. package/dist/components/ingredients/ingredients-list.js +0 -2
  121. package/dist/components/ingredients/ingredients-list.mjs +0 -1
  122. package/dist/components/instructions/instruction-list.d.mts +0 -13
  123. package/dist/components/instructions/instruction-list.d.ts +0 -13
  124. package/dist/components/instructions/instruction-list.js +0 -1
  125. package/dist/components/instructions/instruction-list.mjs +0 -1
  126. package/dist/components/layouts/layout-default.d.mts +0 -7
  127. package/dist/components/layouts/layout-default.d.ts +0 -7
  128. package/dist/components/layouts/layout-default.js +0 -1
  129. package/dist/components/layouts/layout-default.mjs +0 -1
  130. package/dist/components/layouts/layout-types.d.mts +0 -8
  131. package/dist/components/layouts/layout-types.d.ts +0 -8
  132. package/dist/components/layouts/layout-types.js +0 -1
  133. package/dist/components/layouts/layout-types.mjs +0 -0
  134. package/dist/components/measurement-select.d.mts +0 -13
  135. package/dist/components/measurement-select.d.ts +0 -13
  136. package/dist/components/measurement-select.js +0 -1
  137. package/dist/components/measurement-select.mjs +0 -1
  138. package/dist/components/root.d.mts +0 -13
  139. package/dist/components/root.d.ts +0 -13
  140. package/dist/components/root.js +0 -1
  141. package/dist/components/root.mjs +0 -1
  142. package/dist/components/servings-select.d.mts +0 -11
  143. package/dist/components/servings-select.d.ts +0 -11
  144. package/dist/components/servings-select.js +0 -1
  145. package/dist/components/servings-select.mjs +0 -1
  146. package/dist/components/thumbnail.d.mts +0 -18
  147. package/dist/components/thumbnail.d.ts +0 -18
  148. package/dist/components/thumbnail.js +0 -1
  149. package/dist/components/thumbnail.mjs +0 -1
  150. package/dist/global-context.d.mts +0 -29
  151. package/dist/global-context.d.ts +0 -29
  152. package/dist/global-context.js +0 -1
  153. package/dist/global-context.mjs +0 -1
  154. package/dist/hooks/use-controllable.d.mts +0 -15
  155. package/dist/hooks/use-controllable.d.ts +0 -15
  156. package/dist/hooks/use-controllable.js +0 -1
  157. package/dist/hooks/use-controllable.mjs +0 -1
  158. package/dist/index.d.mts +0 -10
  159. package/dist/index.mjs +0 -1
  160. package/dist/recipe-context.d.mts +0 -29
  161. package/dist/recipe-context.d.ts +0 -29
  162. package/dist/recipe-context.js +0 -1
  163. package/dist/recipe-context.mjs +0 -1
  164. package/dist/types-from-core.d.mts +0 -1
  165. package/dist/types-from-core.d.ts +0 -1
  166. package/dist/types-from-core.js +0 -1
  167. package/dist/types-from-core.mjs +0 -1
@@ -0,0 +1,1276 @@
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 };