@recipe-book/react 0.1.0 → 0.1.2
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 +76 -0
- package/README.md +6 -4
- 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 +204 -166
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +744 -109
- package/dist/index.d.ts +744 -109
- package/dist/index.js +164 -140
- package/dist/index.js.map +1 -1
- package/package.json +27 -6
package/dist/index.js
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
// src/parts/image.tsx
|
|
4
|
-
import {
|
|
5
|
-
forwardRef
|
|
6
|
-
} from "react";
|
|
7
|
-
|
|
8
3
|
// src/context.tsx
|
|
9
4
|
import { RecipeBookError as RecipeBookError2 } from "@recipe-book/core";
|
|
10
5
|
import {
|
|
11
|
-
createContext,
|
|
12
6
|
useContext,
|
|
13
7
|
useMemo as useMemo2
|
|
14
8
|
} from "react";
|
|
15
9
|
|
|
10
|
+
// src/display-name.ts
|
|
11
|
+
function setDisplayName(component, name) {
|
|
12
|
+
const target = component;
|
|
13
|
+
target.displayName = name;
|
|
14
|
+
Object.defineProperty(target.render ?? component, "name", { value: name });
|
|
15
|
+
}
|
|
16
|
+
|
|
16
17
|
// src/labels.ts
|
|
17
18
|
var defaultLabels = {
|
|
18
19
|
servings: "Servings",
|
|
@@ -25,6 +26,15 @@ var defaultLabels = {
|
|
|
25
26
|
to: "to"
|
|
26
27
|
};
|
|
27
28
|
|
|
29
|
+
// src/react.ts
|
|
30
|
+
import {
|
|
31
|
+
cloneElement,
|
|
32
|
+
createContext,
|
|
33
|
+
forwardRef,
|
|
34
|
+
Fragment,
|
|
35
|
+
isValidElement
|
|
36
|
+
} from "react";
|
|
37
|
+
|
|
28
38
|
// src/state/use-recipe-state.ts
|
|
29
39
|
import {
|
|
30
40
|
resolveRecipe
|
|
@@ -77,14 +87,8 @@ import {
|
|
|
77
87
|
useRef,
|
|
78
88
|
useState
|
|
79
89
|
} from "react";
|
|
80
|
-
function useControllableState({
|
|
81
|
-
|
|
82
|
-
value,
|
|
83
|
-
defaultValue,
|
|
84
|
-
onChange,
|
|
85
|
-
resetKey
|
|
86
|
-
}) {
|
|
87
|
-
const controlled = value !== void 0;
|
|
90
|
+
function useControllableState(options) {
|
|
91
|
+
const { value, defaultValue, onChange, resetKey } = options;
|
|
88
92
|
const [internal, setInternal] = useState(defaultValue);
|
|
89
93
|
const [internalResetKey, setInternalResetKey] = useState(resetKey);
|
|
90
94
|
let uncontrolled = internal;
|
|
@@ -93,22 +97,27 @@ function useControllableState({
|
|
|
93
97
|
setInternal(defaultValue);
|
|
94
98
|
uncontrolled = defaultValue;
|
|
95
99
|
}
|
|
96
|
-
const current =
|
|
97
|
-
const latest = useRef({
|
|
100
|
+
const current = value === void 0 ? uncontrolled : value;
|
|
101
|
+
const latest = useRef({ value, current, onChange });
|
|
98
102
|
useInsertionEffect(() => {
|
|
99
|
-
latest.current = {
|
|
103
|
+
latest.current = { value, current, onChange };
|
|
100
104
|
});
|
|
101
105
|
const setValue = useCallback((next) => {
|
|
102
|
-
const {
|
|
103
|
-
if (Object.is(next,
|
|
104
|
-
if (
|
|
105
|
-
latest.current.
|
|
106
|
+
const { value: value2, current: current2, onChange: onChange2 } = latest.current;
|
|
107
|
+
if (Object.is(next, current2)) return;
|
|
108
|
+
if (value2 === void 0) {
|
|
109
|
+
latest.current.current = next;
|
|
106
110
|
setInternal(next);
|
|
107
111
|
}
|
|
108
112
|
onChange2?.(next);
|
|
109
113
|
}, []);
|
|
110
114
|
if (process.env.NODE_ENV !== "production") {
|
|
111
|
-
|
|
115
|
+
const controlled = value !== void 0;
|
|
116
|
+
useModeWarnings(
|
|
117
|
+
options.prop,
|
|
118
|
+
controlled,
|
|
119
|
+
controlled && onChange === void 0
|
|
120
|
+
);
|
|
112
121
|
}
|
|
113
122
|
return [current, setValue];
|
|
114
123
|
}
|
|
@@ -141,7 +150,7 @@ function useRecipeState(options) {
|
|
|
141
150
|
assertParsedRecipe(
|
|
142
151
|
recipe,
|
|
143
152
|
"useRecipeState()",
|
|
144
|
-
"Call parseRecipe() from @recipe-book/core and pass result.data."
|
|
153
|
+
"Call parseRecipe() from @recipe-book/react/core and pass result.data."
|
|
145
154
|
);
|
|
146
155
|
}, [recipe]);
|
|
147
156
|
}
|
|
@@ -199,8 +208,8 @@ function useRecipeState(options) {
|
|
|
199
208
|
},
|
|
200
209
|
[updateSystem]
|
|
201
210
|
);
|
|
202
|
-
const steps = useMemo(() =>
|
|
203
|
-
const
|
|
211
|
+
const steps = useMemo(() => resolveRecipe(recipe).steps, [recipe]);
|
|
212
|
+
const resolved = useMemo(
|
|
204
213
|
() => resolveRecipe(recipe, { servings, system }),
|
|
205
214
|
[recipe, servings, system]
|
|
206
215
|
);
|
|
@@ -209,24 +218,14 @@ function useRecipeState(options) {
|
|
|
209
218
|
recipe,
|
|
210
219
|
servings,
|
|
211
220
|
setServings,
|
|
212
|
-
scale,
|
|
221
|
+
scale: resolved.scale,
|
|
213
222
|
system,
|
|
214
223
|
setSystem,
|
|
215
|
-
canConvert,
|
|
216
|
-
ingredients,
|
|
224
|
+
canConvert: resolved.canConvert,
|
|
225
|
+
ingredients: resolved.ingredients,
|
|
217
226
|
steps
|
|
218
227
|
}),
|
|
219
|
-
[
|
|
220
|
-
recipe,
|
|
221
|
-
servings,
|
|
222
|
-
setServings,
|
|
223
|
-
scale,
|
|
224
|
-
system,
|
|
225
|
-
setSystem,
|
|
226
|
-
canConvert,
|
|
227
|
-
ingredients,
|
|
228
|
-
steps
|
|
229
|
-
]
|
|
228
|
+
[recipe, servings, setServings, resolved, system, setSystem, steps]
|
|
230
229
|
);
|
|
231
230
|
}
|
|
232
231
|
function useWarning(message) {
|
|
@@ -238,27 +237,35 @@ function useWarning(message) {
|
|
|
238
237
|
}
|
|
239
238
|
}, [message]);
|
|
240
239
|
}
|
|
241
|
-
function numberSteps(recipe) {
|
|
242
|
-
let number = 0;
|
|
243
|
-
return recipe.steps.map((section) => ({
|
|
244
|
-
...section,
|
|
245
|
-
items: section.items.map((step) => ({ ...step, number: ++number }))
|
|
246
|
-
}));
|
|
247
|
-
}
|
|
248
240
|
function isServings(value) {
|
|
249
241
|
return typeof value === "number" && Number.isFinite(value) && value > 0;
|
|
250
242
|
}
|
|
251
243
|
function servingsBase(recipe) {
|
|
252
244
|
return [recipe.servings?.amount, recipe.yield?.amount].find(isServings) ?? 1;
|
|
253
245
|
}
|
|
254
|
-
|
|
255
|
-
|
|
246
|
+
function servingsWindow(base) {
|
|
247
|
+
const [mantissa, exponent] = base.toExponential().split("e");
|
|
248
|
+
return [
|
|
249
|
+
Number(`${mantissa}e${Number(exponent) - 6}`),
|
|
250
|
+
Number(`${mantissa}e${Number(exponent) + 6}`)
|
|
251
|
+
];
|
|
252
|
+
}
|
|
256
253
|
function isServingsFor(value, base) {
|
|
257
|
-
|
|
254
|
+
const [min, max] = servingsWindow(base);
|
|
255
|
+
return isServings(value) && value >= min && value <= max;
|
|
258
256
|
}
|
|
259
257
|
function describeRange(base) {
|
|
260
|
-
const
|
|
261
|
-
return `a number from ${
|
|
258
|
+
const [min, max] = servingsWindow(base);
|
|
259
|
+
return `a number from ${roundInward(min, true)} to ${roundInward(max, false)} for this recipe`;
|
|
260
|
+
}
|
|
261
|
+
function roundInward(bound, up) {
|
|
262
|
+
const nearest = Number(bound.toPrecision(6));
|
|
263
|
+
if (up ? nearest >= bound : nearest <= bound) {
|
|
264
|
+
return nearest;
|
|
265
|
+
}
|
|
266
|
+
const [mantissa, exponent] = bound.toExponential().split("e");
|
|
267
|
+
const digits = Number(mantissa.replace(".", "").slice(0, 6));
|
|
268
|
+
return Number(`${up ? digits + 1 : digits}e${Number(exponent) - 5}`);
|
|
262
269
|
}
|
|
263
270
|
function isSystem(value) {
|
|
264
271
|
return value === "metric" || value === "us";
|
|
@@ -312,7 +319,7 @@ function useConfig({
|
|
|
312
319
|
}),
|
|
313
320
|
[outer.labels, labels]
|
|
314
321
|
),
|
|
315
|
-
defaultSystem:
|
|
322
|
+
defaultSystem: [defaultSystem, outer.defaultSystem].find(isSystem)
|
|
316
323
|
};
|
|
317
324
|
}
|
|
318
325
|
var RecipeDataContext = /* @__PURE__ */ createContext(null);
|
|
@@ -342,6 +349,9 @@ function useRecipe() {
|
|
|
342
349
|
"useRecipe() must be called inside <Recipe.Root>. To use recipe state without a Root, call useRecipeState()."
|
|
343
350
|
);
|
|
344
351
|
}
|
|
352
|
+
if (process.env.NODE_ENV !== "production") {
|
|
353
|
+
setDisplayName(RecipeBookProvider, "Recipe.RecipeBookProvider");
|
|
354
|
+
}
|
|
345
355
|
|
|
346
356
|
// src/parts/image.tsx
|
|
347
357
|
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
@@ -352,10 +362,7 @@ var Image = /* @__PURE__ */ forwardRef(function Image2({
|
|
|
352
362
|
...props
|
|
353
363
|
}, ref) {
|
|
354
364
|
const { recipe } = useRecipeData("Recipe.Image");
|
|
355
|
-
|
|
356
|
-
return null;
|
|
357
|
-
}
|
|
358
|
-
return /* @__PURE__ */ jsx2(
|
|
365
|
+
return recipe.image !== void 0 && /* @__PURE__ */ jsx2(
|
|
359
366
|
Comp,
|
|
360
367
|
{
|
|
361
368
|
...props,
|
|
@@ -366,23 +373,17 @@ var Image = /* @__PURE__ */ forwardRef(function Image2({
|
|
|
366
373
|
}
|
|
367
374
|
);
|
|
368
375
|
});
|
|
376
|
+
if (process.env.NODE_ENV !== "production") {
|
|
377
|
+
setDisplayName(Image, "Recipe.Image");
|
|
378
|
+
}
|
|
369
379
|
|
|
370
380
|
// src/parts/ingredients.tsx
|
|
371
381
|
import {
|
|
372
|
-
cloneElement as cloneElement2,
|
|
373
|
-
createContext as createContext2,
|
|
374
|
-
forwardRef as forwardRef3,
|
|
375
382
|
useMemo as useMemo3
|
|
376
383
|
} from "react";
|
|
377
384
|
|
|
378
385
|
// src/slot.tsx
|
|
379
|
-
import {
|
|
380
|
-
cloneElement,
|
|
381
|
-
forwardRef as forwardRef2,
|
|
382
|
-
Fragment,
|
|
383
|
-
isValidElement,
|
|
384
|
-
useCallback as useCallback3
|
|
385
|
-
} from "react";
|
|
386
|
+
import { useCallback as useCallback3 } from "react";
|
|
386
387
|
function resolveAsChild(part, tag, asChild, children, defaults) {
|
|
387
388
|
if (asChild) {
|
|
388
389
|
if (isValidElement(children) && children.type !== Fragment) {
|
|
@@ -400,7 +401,7 @@ function resolveAsChild(part, tag, asChild, children, defaults) {
|
|
|
400
401
|
}
|
|
401
402
|
return [tag, isEmpty(children) ? defaults : children];
|
|
402
403
|
}
|
|
403
|
-
var Slot = /* @__PURE__ */
|
|
404
|
+
var Slot = /* @__PURE__ */ forwardRef(function Slot2({ children, ...props }, ref) {
|
|
404
405
|
const child = children;
|
|
405
406
|
const merged = { ...props, ...child.props };
|
|
406
407
|
for (const name in child.props) {
|
|
@@ -421,7 +422,7 @@ var Slot = /* @__PURE__ */ forwardRef2(function Slot2({ children, ...props }, re
|
|
|
421
422
|
}
|
|
422
423
|
}
|
|
423
424
|
const childRef = Object.getOwnPropertyDescriptor(child.props, "ref")?.value ?? child.ref;
|
|
424
|
-
|
|
425
|
+
const mergedRef = useCallback3(
|
|
425
426
|
(node) => {
|
|
426
427
|
const refs = [ref, childRef];
|
|
427
428
|
const cleanups = refs.map((each) => setRef(each, node));
|
|
@@ -439,6 +440,9 @@ var Slot = /* @__PURE__ */ forwardRef2(function Slot2({ children, ...props }, re
|
|
|
439
440
|
},
|
|
440
441
|
[ref, childRef]
|
|
441
442
|
);
|
|
443
|
+
if (ref != null) {
|
|
444
|
+
merged.ref = mergedRef;
|
|
445
|
+
}
|
|
442
446
|
return cloneElement(child, merged);
|
|
443
447
|
});
|
|
444
448
|
function setRef(ref, node) {
|
|
@@ -467,6 +471,9 @@ function describeChildren(children) {
|
|
|
467
471
|
function isEmpty(children) {
|
|
468
472
|
return children == null || typeof children === "boolean";
|
|
469
473
|
}
|
|
474
|
+
if (process.env.NODE_ENV !== "production") {
|
|
475
|
+
setDisplayName(Slot, "Slot");
|
|
476
|
+
}
|
|
470
477
|
|
|
471
478
|
// src/use-format-ingredient.ts
|
|
472
479
|
import {
|
|
@@ -480,7 +487,7 @@ function useFormatIngredient() {
|
|
|
480
487
|
labels: { optional }
|
|
481
488
|
} = useRequired(
|
|
482
489
|
RecipeDataContext,
|
|
483
|
-
"useFormatIngredient() must be called inside <Recipe.Root>. To format ingredients without a Root, call formatIngredient() from @recipe-book/core."
|
|
490
|
+
"useFormatIngredient() must be called inside <Recipe.Root>. To format ingredients without a Root, call formatIngredient() from @recipe-book/react/core."
|
|
484
491
|
);
|
|
485
492
|
return useCallback4(
|
|
486
493
|
(item) => formatLine(item, locale, optional),
|
|
@@ -489,9 +496,10 @@ function useFormatIngredient() {
|
|
|
489
496
|
}
|
|
490
497
|
function formatLine(item, locale, optional) {
|
|
491
498
|
const options = { locale };
|
|
499
|
+
const formatted = formatIngredient(item, options);
|
|
492
500
|
const quantity = lineQuantity(item);
|
|
493
501
|
return {
|
|
494
|
-
...
|
|
502
|
+
...formatted,
|
|
495
503
|
quantityParts: quantity ? formatQuantityToParts(quantity, options) : [],
|
|
496
504
|
...item.ingredient.optional && { optional }
|
|
497
505
|
};
|
|
@@ -501,10 +509,10 @@ function lineQuantity(item) {
|
|
|
501
509
|
}
|
|
502
510
|
|
|
503
511
|
// src/parts/sections.tsx
|
|
504
|
-
import {
|
|
512
|
+
import { useId } from "react";
|
|
505
513
|
import { jsx as jsx3, jsxs } from "react/jsx-runtime";
|
|
506
514
|
function renderKeyed(items, render) {
|
|
507
|
-
return items.map((item) => /* @__PURE__ */ jsx3(
|
|
515
|
+
return items.map((item) => /* @__PURE__ */ jsx3(Fragment, { children: render(item) }, item.id));
|
|
508
516
|
}
|
|
509
517
|
function SectionBlock({
|
|
510
518
|
kind,
|
|
@@ -514,19 +522,16 @@ function SectionBlock({
|
|
|
514
522
|
}) {
|
|
515
523
|
const headingId = useId();
|
|
516
524
|
const marker = `data-recipe-${kind}-section`;
|
|
517
|
-
if (!title) {
|
|
518
|
-
return /* @__PURE__ */ jsx3("div", { ...{ [marker]: "" }, children });
|
|
519
|
-
}
|
|
520
525
|
const Heading = `h${headingLevel}`;
|
|
521
|
-
return /* @__PURE__ */ jsxs("section", { ...{ [marker]: "" }, "aria-labelledby": headingId, children: [
|
|
526
|
+
return title ? /* @__PURE__ */ jsxs("section", { ...{ [marker]: "" }, "aria-labelledby": headingId, children: [
|
|
522
527
|
/* @__PURE__ */ jsx3(Heading, { id: headingId, children: title }),
|
|
523
528
|
children
|
|
524
|
-
] });
|
|
529
|
+
] }) : /* @__PURE__ */ jsx3("div", { ...{ [marker]: "" }, children });
|
|
525
530
|
}
|
|
526
531
|
|
|
527
532
|
// src/parts/ingredients.tsx
|
|
528
|
-
import { Fragment as
|
|
529
|
-
var Ingredients = /* @__PURE__ */
|
|
533
|
+
import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
534
|
+
var Ingredients = /* @__PURE__ */ forwardRef(
|
|
530
535
|
function Ingredients2({ headingLevel = 3, children, ...props }, ref) {
|
|
531
536
|
const { ingredients } = usePartState("Recipe.Ingredients");
|
|
532
537
|
const renderSection = children ?? ((section) => /* @__PURE__ */ jsx4(
|
|
@@ -541,15 +546,15 @@ var Ingredients = /* @__PURE__ */ forwardRef3(
|
|
|
541
546
|
return /* @__PURE__ */ jsx4("div", { ...props, "data-recipe-ingredients": "", ref, children: renderKeyed(ingredients, renderSection) });
|
|
542
547
|
}
|
|
543
548
|
);
|
|
544
|
-
var IngredientList = /* @__PURE__ */
|
|
549
|
+
var IngredientList = /* @__PURE__ */ forwardRef(
|
|
545
550
|
function IngredientList2({ section, children = (item) => /* @__PURE__ */ jsx4(Ingredient, { item }), ...props }, ref) {
|
|
546
551
|
const { ingredients } = usePartState("Recipe.IngredientList");
|
|
547
552
|
const items = section?.items ?? ingredients.flatMap((s) => s.items);
|
|
548
553
|
return /* @__PURE__ */ jsx4("ul", { ...props, "data-recipe-ingredient-list": "", ref, children: renderKeyed(items, children) });
|
|
549
554
|
}
|
|
550
555
|
);
|
|
551
|
-
var LineContext = /* @__PURE__ */
|
|
552
|
-
var Ingredient = /* @__PURE__ */
|
|
556
|
+
var LineContext = /* @__PURE__ */ createContext(null);
|
|
557
|
+
var Ingredient = /* @__PURE__ */ forwardRef(
|
|
553
558
|
function Ingredient2({ item, asChild = false, children, ...props }, ref) {
|
|
554
559
|
const {
|
|
555
560
|
labels: { optional, to },
|
|
@@ -565,7 +570,7 @@ var Ingredient = /* @__PURE__ */ forwardRef3(
|
|
|
565
570
|
"li",
|
|
566
571
|
asChild,
|
|
567
572
|
children,
|
|
568
|
-
/* @__PURE__ */ jsxs2(
|
|
573
|
+
/* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
569
574
|
/* @__PURE__ */ jsx4(IngredientQuantity, {}),
|
|
570
575
|
quantity && (quantity.unit === void 0 ? "\xA0" : " "),
|
|
571
576
|
/* @__PURE__ */ jsx4(IngredientName, {}),
|
|
@@ -601,15 +606,12 @@ function ingredientText(name, attribute, read) {
|
|
|
601
606
|
return null;
|
|
602
607
|
}
|
|
603
608
|
const [Comp, child] = resolveAsChild(part, "span", asChild, children, null);
|
|
604
|
-
return /* @__PURE__ */ jsx4(Comp, { ...props, ...{ [attribute]: "" }, ref, children: Comp === "span" ? /* @__PURE__ */ jsxs2(
|
|
609
|
+
return /* @__PURE__ */ jsx4(Comp, { ...props, ...{ [attribute]: "" }, ref, children: Comp === "span" ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
605
610
|
children,
|
|
606
611
|
text
|
|
607
|
-
] }) :
|
|
608
|
-
}
|
|
609
|
-
if (process.env.NODE_ENV !== "production") {
|
|
610
|
-
Object.defineProperty(IngredientText, "name", { value: name });
|
|
612
|
+
] }) : cloneElement(child, void 0, child.props.children, text) });
|
|
611
613
|
}
|
|
612
|
-
return
|
|
614
|
+
return forwardRef(IngredientText);
|
|
613
615
|
}
|
|
614
616
|
var IngredientQuantity = /* @__PURE__ */ ingredientText(
|
|
615
617
|
"IngredientQuantity",
|
|
@@ -637,7 +639,7 @@ function renderQuantity(parts, to) {
|
|
|
637
639
|
if (!separator) {
|
|
638
640
|
return join(parts);
|
|
639
641
|
}
|
|
640
|
-
return /* @__PURE__ */ jsxs2(
|
|
642
|
+
return /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
641
643
|
join(parts.slice(0, dash)),
|
|
642
644
|
/* @__PURE__ */ jsx4("span", { "data-recipe-range-separator": "", "aria-hidden": "true", children: separator.value }),
|
|
643
645
|
/* @__PURE__ */ jsx4("span", { style: hiddenStyle, children: ` ${to} ` }),
|
|
@@ -660,17 +662,25 @@ var IngredientOptional = /* @__PURE__ */ ingredientText(
|
|
|
660
662
|
// An empty label shows only the part's own children, such as an icon.
|
|
661
663
|
({ optional }, children) => optional === "" && isEmpty(children) ? void 0 : optional
|
|
662
664
|
);
|
|
665
|
+
if (process.env.NODE_ENV !== "production") {
|
|
666
|
+
setDisplayName(Ingredients, "Recipe.Ingredients");
|
|
667
|
+
setDisplayName(IngredientList, "Recipe.IngredientList");
|
|
668
|
+
setDisplayName(Ingredient, "Recipe.Ingredient");
|
|
669
|
+
setDisplayName(IngredientQuantity, "Recipe.IngredientQuantity");
|
|
670
|
+
setDisplayName(IngredientName, "Recipe.IngredientName");
|
|
671
|
+
setDisplayName(IngredientNote, "Recipe.IngredientNote");
|
|
672
|
+
setDisplayName(IngredientOptional, "Recipe.IngredientOptional");
|
|
673
|
+
}
|
|
663
674
|
|
|
664
675
|
// src/parts/json-ld.tsx
|
|
665
676
|
import { toJsonLd } from "@recipe-book/core/schema-org";
|
|
666
677
|
import {
|
|
667
|
-
forwardRef as forwardRef4,
|
|
668
678
|
useEffect as useEffect3,
|
|
669
679
|
useMemo as useMemo4,
|
|
670
680
|
useRef as useRef3
|
|
671
681
|
} from "react";
|
|
672
682
|
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
673
|
-
var JsonLd = /* @__PURE__ */
|
|
683
|
+
var JsonLd = /* @__PURE__ */ forwardRef(
|
|
674
684
|
function JsonLd2({
|
|
675
685
|
servings,
|
|
676
686
|
system,
|
|
@@ -682,12 +692,12 @@ var JsonLd = /* @__PURE__ */ forwardRef4(
|
|
|
682
692
|
...props
|
|
683
693
|
}, ref) {
|
|
684
694
|
const { recipe } = useRecipeData("Recipe.JsonLd");
|
|
685
|
-
const
|
|
695
|
+
const result = useMemo4(
|
|
686
696
|
() => toJsonLd(recipe, { servings, system, url, extra }),
|
|
687
697
|
[recipe, servings, system, url, extra]
|
|
688
698
|
);
|
|
689
699
|
if (process.env.NODE_ENV !== "production") {
|
|
690
|
-
useWarningsReport(recipe.name, warnings);
|
|
700
|
+
useWarningsReport(recipe.name, result.warnings);
|
|
691
701
|
}
|
|
692
702
|
return /* @__PURE__ */ jsx5(
|
|
693
703
|
"script",
|
|
@@ -696,7 +706,7 @@ var JsonLd = /* @__PURE__ */ forwardRef4(
|
|
|
696
706
|
type: "application/ld+json",
|
|
697
707
|
"data-recipe-json-ld": "",
|
|
698
708
|
dangerouslySetInnerHTML: {
|
|
699
|
-
__html: JSON.stringify(data).replace(/</g, "\\u003c")
|
|
709
|
+
__html: JSON.stringify(result.data).replace(/</g, "\\u003c")
|
|
700
710
|
},
|
|
701
711
|
ref
|
|
702
712
|
}
|
|
@@ -717,6 +727,9 @@ function useWarningsReport(name, warnings) {
|
|
|
717
727
|
reported.current = key;
|
|
718
728
|
}, [name, warnings]);
|
|
719
729
|
}
|
|
730
|
+
if (process.env.NODE_ENV !== "production") {
|
|
731
|
+
setDisplayName(JsonLd, "Recipe.JsonLd");
|
|
732
|
+
}
|
|
720
733
|
|
|
721
734
|
// src/parts/root.tsx
|
|
722
735
|
import {
|
|
@@ -726,7 +739,7 @@ import {
|
|
|
726
739
|
useRef as useRef4,
|
|
727
740
|
useState as useState2
|
|
728
741
|
} from "react";
|
|
729
|
-
import { Fragment as
|
|
742
|
+
import { Fragment as Fragment3, jsx as jsx6 } from "react/jsx-runtime";
|
|
730
743
|
function Root({
|
|
731
744
|
recipe,
|
|
732
745
|
parse,
|
|
@@ -741,7 +754,7 @@ function Root({
|
|
|
741
754
|
assertParsedRecipe(
|
|
742
755
|
recipe,
|
|
743
756
|
"<Recipe.Root>",
|
|
744
|
-
"Call parseRecipe() from @recipe-book/core on the server, in a loader, or at build time and pass result.data, or pass parse={parseRecipe} to parse it in the browser."
|
|
757
|
+
"Call parseRecipe() from @recipe-book/react/core on the server, in a loader, or at build time and pass result.data, or pass parse={parseRecipe} to parse it in the browser."
|
|
745
758
|
);
|
|
746
759
|
return { success: true, data: recipe, warnings: [] };
|
|
747
760
|
}, [parse, recipe]);
|
|
@@ -749,7 +762,7 @@ function Root({
|
|
|
749
762
|
useParseReport(result);
|
|
750
763
|
}
|
|
751
764
|
if (!result.success) {
|
|
752
|
-
return /* @__PURE__ */ jsx6(
|
|
765
|
+
return /* @__PURE__ */ jsx6(Fragment3, { children: fallback });
|
|
753
766
|
}
|
|
754
767
|
return /* @__PURE__ */ jsx6(RecipeProvider, { ...options, recipe: result.data, children });
|
|
755
768
|
}
|
|
@@ -784,7 +797,7 @@ function useParseReport(result) {
|
|
|
784
797
|
if (result.success) {
|
|
785
798
|
const count = result.warnings.length;
|
|
786
799
|
console.warn(
|
|
787
|
-
`Recipe Book: ${quote(result.data.name)} has ${count} ${count === 1 ? "warning" : "warnings"}. It still renders
|
|
800
|
+
`Recipe Book: ${quote(result.data.name)} has ${count} ${count === 1 ? "warning" : "warnings"}. It still renders. https://recipe-book.siraj.page/errors/#issue-codes gives the fix for each warning's code.`,
|
|
788
801
|
result.warnings
|
|
789
802
|
);
|
|
790
803
|
} else {
|
|
@@ -792,6 +805,9 @@ function useParseReport(result) {
|
|
|
792
805
|
}
|
|
793
806
|
}, [result]);
|
|
794
807
|
}
|
|
808
|
+
if (process.env.NODE_ENV !== "production") {
|
|
809
|
+
setDisplayName(Root, "Recipe.Root");
|
|
810
|
+
}
|
|
795
811
|
|
|
796
812
|
// src/parts/servings.tsx
|
|
797
813
|
import {
|
|
@@ -799,7 +815,6 @@ import {
|
|
|
799
815
|
formatYield
|
|
800
816
|
} from "@recipe-book/core";
|
|
801
817
|
import {
|
|
802
|
-
forwardRef as forwardRef5,
|
|
803
818
|
useState as useState3
|
|
804
819
|
} from "react";
|
|
805
820
|
|
|
@@ -815,7 +830,7 @@ function composeEventHandlers(theirs, ours) {
|
|
|
815
830
|
|
|
816
831
|
// src/parts/servings.tsx
|
|
817
832
|
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
818
|
-
var ServingsSelect = /* @__PURE__ */
|
|
833
|
+
var ServingsSelect = /* @__PURE__ */ forwardRef(
|
|
819
834
|
function ServingsSelect2({ options, "aria-label": ariaLabel, onChange, ...props }, ref) {
|
|
820
835
|
const { recipe, labels, locale } = useRecipeData("Recipe.ServingsSelect");
|
|
821
836
|
const { servings, setServings } = usePartState("Recipe.ServingsSelect");
|
|
@@ -843,7 +858,7 @@ var ServingsSelect = /* @__PURE__ */ forwardRef5(
|
|
|
843
858
|
);
|
|
844
859
|
}
|
|
845
860
|
);
|
|
846
|
-
var ServingsInput = /* @__PURE__ */
|
|
861
|
+
var ServingsInput = /* @__PURE__ */ forwardRef(
|
|
847
862
|
function ServingsInput2({
|
|
848
863
|
min = 1,
|
|
849
864
|
max,
|
|
@@ -920,6 +935,10 @@ function optionText(choice, { servings, yield: makes }, base, labels, locale) {
|
|
|
920
935
|
}
|
|
921
936
|
return `${formatServings({ amount: choice }, format)}\xD7`;
|
|
922
937
|
}
|
|
938
|
+
if (process.env.NODE_ENV !== "production") {
|
|
939
|
+
setDisplayName(ServingsSelect, "Recipe.ServingsSelect");
|
|
940
|
+
setDisplayName(ServingsInput, "Recipe.ServingsInput");
|
|
941
|
+
}
|
|
923
942
|
|
|
924
943
|
// src/parts/step-text.tsx
|
|
925
944
|
import {
|
|
@@ -928,18 +947,13 @@ import {
|
|
|
928
947
|
segmentStepText
|
|
929
948
|
} from "@recipe-book/core";
|
|
930
949
|
import {
|
|
931
|
-
forwardRef as forwardRef7,
|
|
932
950
|
useEffect as useEffect5,
|
|
933
951
|
useMemo as useMemo6
|
|
934
952
|
} from "react";
|
|
935
953
|
|
|
936
954
|
// src/parts/steps.tsx
|
|
937
|
-
import {
|
|
938
|
-
|
|
939
|
-
forwardRef as forwardRef6
|
|
940
|
-
} from "react";
|
|
941
|
-
import { Fragment as Fragment5, jsx as jsx8, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
942
|
-
var Steps = /* @__PURE__ */ forwardRef6(function Steps2({ headingLevel = 3, children, ...props }, ref) {
|
|
955
|
+
import { Fragment as Fragment4, jsx as jsx8, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
956
|
+
var Steps = /* @__PURE__ */ forwardRef(function Steps2({ headingLevel = 3, children, ...props }, ref) {
|
|
943
957
|
const { steps } = useRecipeData("Recipe.Steps");
|
|
944
958
|
const renderSection = children ?? ((section) => /* @__PURE__ */ jsx8(
|
|
945
959
|
SectionBlock,
|
|
@@ -952,7 +966,7 @@ var Steps = /* @__PURE__ */ forwardRef6(function Steps2({ headingLevel = 3, chil
|
|
|
952
966
|
));
|
|
953
967
|
return /* @__PURE__ */ jsx8("div", { ...props, "data-recipe-steps": "", ref, children: renderKeyed(steps, renderSection) });
|
|
954
968
|
});
|
|
955
|
-
var StepList = /* @__PURE__ */
|
|
969
|
+
var StepList = /* @__PURE__ */ forwardRef(
|
|
956
970
|
function StepList2({ section, children = (step) => /* @__PURE__ */ jsx8(Step, { item: step }), start, ...props }, ref) {
|
|
957
971
|
const { steps } = useRecipeData("Recipe.StepList");
|
|
958
972
|
const items = section?.items ?? steps.flatMap((s) => s.items);
|
|
@@ -968,15 +982,15 @@ var StepList = /* @__PURE__ */ forwardRef6(
|
|
|
968
982
|
);
|
|
969
983
|
}
|
|
970
984
|
);
|
|
971
|
-
var StepContext = /* @__PURE__ */
|
|
972
|
-
var Step = /* @__PURE__ */
|
|
985
|
+
var StepContext = /* @__PURE__ */ createContext(null);
|
|
986
|
+
var Step = /* @__PURE__ */ forwardRef(function Step2({ item, asChild = false, children, ...props }, ref) {
|
|
973
987
|
useRecipeData("Recipe.Step");
|
|
974
988
|
const [Comp, content] = resolveAsChild(
|
|
975
989
|
"Recipe.Step",
|
|
976
990
|
"li",
|
|
977
991
|
asChild,
|
|
978
992
|
children,
|
|
979
|
-
/* @__PURE__ */ jsxs3(
|
|
993
|
+
/* @__PURE__ */ jsxs3(Fragment4, { children: [
|
|
980
994
|
/* @__PURE__ */ jsx8(StepName, {}),
|
|
981
995
|
item.name !== void 0 && " ",
|
|
982
996
|
item.text
|
|
@@ -984,19 +998,25 @@ var Step = /* @__PURE__ */ forwardRef6(function Step2({ item, asChild = false, c
|
|
|
984
998
|
);
|
|
985
999
|
return /* @__PURE__ */ jsx8(StepContext.Provider, { value: item, children: /* @__PURE__ */ jsx8(Comp, { ...props, "data-recipe-step": "", ref, children: content }) });
|
|
986
1000
|
});
|
|
987
|
-
var StepName = /* @__PURE__ */
|
|
1001
|
+
var StepName = /* @__PURE__ */ forwardRef(
|
|
988
1002
|
function StepName2(props, ref) {
|
|
989
1003
|
const step = useRequired(
|
|
990
1004
|
StepContext,
|
|
991
1005
|
"<Recipe.StepName> must be rendered inside <Recipe.Step>."
|
|
992
1006
|
);
|
|
993
|
-
return step.name
|
|
1007
|
+
return step.name !== void 0 && /* @__PURE__ */ jsx8("b", { ...props, "data-recipe-name": "", ref, children: step.name });
|
|
994
1008
|
}
|
|
995
1009
|
);
|
|
1010
|
+
if (process.env.NODE_ENV !== "production") {
|
|
1011
|
+
setDisplayName(Steps, "Recipe.Steps");
|
|
1012
|
+
setDisplayName(StepList, "Recipe.StepList");
|
|
1013
|
+
setDisplayName(Step, "Recipe.Step");
|
|
1014
|
+
setDisplayName(StepName, "Recipe.StepName");
|
|
1015
|
+
}
|
|
996
1016
|
|
|
997
1017
|
// src/parts/step-text.tsx
|
|
998
1018
|
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
999
|
-
var StepText = /* @__PURE__ */
|
|
1019
|
+
var StepText = /* @__PURE__ */ forwardRef(
|
|
1000
1020
|
function StepText2(props, ref) {
|
|
1001
1021
|
const step = useRequired(
|
|
1002
1022
|
StepContext,
|
|
@@ -1016,36 +1036,32 @@ function Temperature({ segment }) {
|
|
|
1016
1036
|
const unit = usePartState("Recipe.StepText").system === "us" ? "F" : "C";
|
|
1017
1037
|
const readings = [segment, ...segment.alternatives];
|
|
1018
1038
|
useEffect5(reportTemperature, [reportTemperature]);
|
|
1019
|
-
return /* @__PURE__ */ jsx9("span", { "data-recipe-temperature": "", children: [false, true].
|
|
1039
|
+
return /* @__PURE__ */ jsx9("span", { "data-recipe-temperature": "", children: [false, true].map((fan) => {
|
|
1020
1040
|
const kind = readings.filter((reading2) => reading2.fan === fan);
|
|
1021
1041
|
const reading = kind.find((each) => each.temperature.unit === unit) ?? kind[0];
|
|
1022
|
-
return reading
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
] : [];
|
|
1031
|
-
}).join(" / ") });
|
|
1042
|
+
return reading && formatTemperature(convertTemperature(reading.temperature, unit), {
|
|
1043
|
+
locale,
|
|
1044
|
+
rounding: reading.temperature.unit === unit ? "none" : void 0
|
|
1045
|
+
}) + (fan && labels.fan ? ` ${labels.fan}` : "");
|
|
1046
|
+
}).filter(Boolean).join(" / ") });
|
|
1047
|
+
}
|
|
1048
|
+
if (process.env.NODE_ENV !== "production") {
|
|
1049
|
+
setDisplayName(StepText, "Recipe.StepText");
|
|
1032
1050
|
}
|
|
1033
1051
|
|
|
1034
1052
|
// src/parts/system-toggle.tsx
|
|
1035
1053
|
import {
|
|
1036
|
-
createContext as createContext4,
|
|
1037
|
-
forwardRef as forwardRef8,
|
|
1038
1054
|
useCallback as useCallback6,
|
|
1039
1055
|
useEffect as useEffect6,
|
|
1040
1056
|
useId as useId2,
|
|
1041
1057
|
useMemo as useMemo7,
|
|
1042
1058
|
useState as useState4
|
|
1043
1059
|
} from "react";
|
|
1044
|
-
import { Fragment as
|
|
1045
|
-
var ToggleContext = /* @__PURE__ */
|
|
1060
|
+
import { Fragment as Fragment5, jsx as jsx10, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1061
|
+
var ToggleContext = /* @__PURE__ */ createContext(
|
|
1046
1062
|
null
|
|
1047
1063
|
);
|
|
1048
|
-
var SystemToggle = /* @__PURE__ */
|
|
1064
|
+
var SystemToggle = /* @__PURE__ */ forwardRef(
|
|
1049
1065
|
function SystemToggle2({ asChild = false, "aria-label": ariaLabel, children, ...props }, ref) {
|
|
1050
1066
|
const { labels } = useRecipeData("Recipe.SystemToggle");
|
|
1051
1067
|
const { system, setSystem, canConvert } = usePartState(
|
|
@@ -1069,7 +1085,7 @@ var SystemToggle = /* @__PURE__ */ forwardRef8(
|
|
|
1069
1085
|
"div",
|
|
1070
1086
|
asChild,
|
|
1071
1087
|
children,
|
|
1072
|
-
/* @__PURE__ */ jsxs4(
|
|
1088
|
+
/* @__PURE__ */ jsxs4(Fragment5, { children: [
|
|
1073
1089
|
/* @__PURE__ */ jsx10(SystemOption, { value: "metric" }),
|
|
1074
1090
|
/* @__PURE__ */ jsx10(SystemOption, { value: "us" })
|
|
1075
1091
|
] })
|
|
@@ -1089,7 +1105,7 @@ var SystemToggle = /* @__PURE__ */ forwardRef8(
|
|
|
1089
1105
|
) });
|
|
1090
1106
|
}
|
|
1091
1107
|
);
|
|
1092
|
-
var SystemOption = /* @__PURE__ */
|
|
1108
|
+
var SystemOption = /* @__PURE__ */ forwardRef(
|
|
1093
1109
|
function SystemOption2({
|
|
1094
1110
|
value,
|
|
1095
1111
|
asChild = false,
|
|
@@ -1130,6 +1146,7 @@ var SystemOption = /* @__PURE__ */ forwardRef8(
|
|
|
1130
1146
|
return /* @__PURE__ */ jsx10(
|
|
1131
1147
|
Comp,
|
|
1132
1148
|
{
|
|
1149
|
+
autoComplete: "off",
|
|
1133
1150
|
...props,
|
|
1134
1151
|
type: type ?? "button",
|
|
1135
1152
|
role: "radio",
|
|
@@ -1156,6 +1173,10 @@ function moveOnArrowKey(event) {
|
|
|
1156
1173
|
if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) {
|
|
1157
1174
|
return;
|
|
1158
1175
|
}
|
|
1176
|
+
const group = event.currentTarget.closest("[data-recipe-system-toggle]");
|
|
1177
|
+
if (group === null) {
|
|
1178
|
+
return;
|
|
1179
|
+
}
|
|
1159
1180
|
const { key } = event;
|
|
1160
1181
|
let step;
|
|
1161
1182
|
if (key === "ArrowDown") {
|
|
@@ -1163,17 +1184,16 @@ function moveOnArrowKey(event) {
|
|
|
1163
1184
|
} else if (key === "ArrowUp") {
|
|
1164
1185
|
step = -1;
|
|
1165
1186
|
} else if (key === "ArrowRight") {
|
|
1166
|
-
step = isRtl(
|
|
1187
|
+
step = isRtl(group) ? -1 : 1;
|
|
1167
1188
|
} else if (key === "ArrowLeft") {
|
|
1168
|
-
step = isRtl(
|
|
1189
|
+
step = isRtl(group) ? 1 : -1;
|
|
1169
1190
|
} else {
|
|
1170
1191
|
return;
|
|
1171
1192
|
}
|
|
1172
|
-
const group = event.currentTarget.closest("[data-recipe-system-toggle]");
|
|
1173
1193
|
const options = Array.from(
|
|
1174
|
-
group
|
|
1194
|
+
group.querySelectorAll(
|
|
1175
1195
|
"[data-recipe-system-option]:not([data-disabled])"
|
|
1176
|
-
)
|
|
1196
|
+
)
|
|
1177
1197
|
);
|
|
1178
1198
|
const index = options.indexOf(event.currentTarget);
|
|
1179
1199
|
if (index === -1) {
|
|
@@ -1185,7 +1205,11 @@ function moveOnArrowKey(event) {
|
|
|
1185
1205
|
next?.click();
|
|
1186
1206
|
}
|
|
1187
1207
|
function isRtl(element) {
|
|
1188
|
-
return element.
|
|
1208
|
+
return getComputedStyle(element).direction === "rtl";
|
|
1209
|
+
}
|
|
1210
|
+
if (process.env.NODE_ENV !== "production") {
|
|
1211
|
+
setDisplayName(SystemToggle, "Recipe.SystemToggle");
|
|
1212
|
+
setDisplayName(SystemOption, "Recipe.SystemOption");
|
|
1189
1213
|
}
|
|
1190
1214
|
export {
|
|
1191
1215
|
Image,
|