@recipe-book/react 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +26 -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 +142 -155
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +729 -98
- package/dist/index.d.ts +729 -98
- package/dist/index.js +101 -128
- package/dist/index.js.map +1 -1
- package/package.json +27 -6
package/dist/index.cjs
CHANGED
|
@@ -66,12 +66,9 @@ __export(index_exports, {
|
|
|
66
66
|
});
|
|
67
67
|
module.exports = __toCommonJS(index_exports);
|
|
68
68
|
|
|
69
|
-
// src/parts/image.tsx
|
|
70
|
-
var import_react4 = require("react");
|
|
71
|
-
|
|
72
69
|
// src/context.tsx
|
|
73
70
|
var import_core3 = require("@recipe-book/core");
|
|
74
|
-
var
|
|
71
|
+
var import_react4 = require("react");
|
|
75
72
|
|
|
76
73
|
// src/labels.ts
|
|
77
74
|
var defaultLabels = {
|
|
@@ -85,9 +82,12 @@ var defaultLabels = {
|
|
|
85
82
|
to: "to"
|
|
86
83
|
};
|
|
87
84
|
|
|
85
|
+
// src/react.ts
|
|
86
|
+
var import_react = require("react");
|
|
87
|
+
|
|
88
88
|
// src/state/use-recipe-state.ts
|
|
89
89
|
var import_core2 = require("@recipe-book/core");
|
|
90
|
-
var
|
|
90
|
+
var import_react3 = require("react");
|
|
91
91
|
|
|
92
92
|
// src/is-parsed-recipe.ts
|
|
93
93
|
var import_core = require("@recipe-book/core");
|
|
@@ -128,46 +128,45 @@ function quote(text) {
|
|
|
128
128
|
}
|
|
129
129
|
|
|
130
130
|
// src/state/use-controllable-state.ts
|
|
131
|
-
var
|
|
132
|
-
function useControllableState({
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
onChange,
|
|
137
|
-
resetKey
|
|
138
|
-
}) {
|
|
139
|
-
const controlled = value !== void 0;
|
|
140
|
-
const [internal, setInternal] = (0, import_react.useState)(defaultValue);
|
|
141
|
-
const [internalResetKey, setInternalResetKey] = (0, import_react.useState)(resetKey);
|
|
131
|
+
var import_react2 = require("react");
|
|
132
|
+
function useControllableState(options) {
|
|
133
|
+
const { value, defaultValue, onChange, resetKey } = options;
|
|
134
|
+
const [internal, setInternal] = (0, import_react2.useState)(defaultValue);
|
|
135
|
+
const [internalResetKey, setInternalResetKey] = (0, import_react2.useState)(resetKey);
|
|
142
136
|
let uncontrolled = internal;
|
|
143
137
|
if (!Object.is(resetKey, internalResetKey)) {
|
|
144
138
|
setInternalResetKey(resetKey);
|
|
145
139
|
setInternal(defaultValue);
|
|
146
140
|
uncontrolled = defaultValue;
|
|
147
141
|
}
|
|
148
|
-
const current =
|
|
149
|
-
const latest = (0,
|
|
150
|
-
(0,
|
|
151
|
-
latest.current = {
|
|
142
|
+
const current = value === void 0 ? uncontrolled : value;
|
|
143
|
+
const latest = (0, import_react2.useRef)({ value, current, onChange });
|
|
144
|
+
(0, import_react2.useInsertionEffect)(() => {
|
|
145
|
+
latest.current = { value, current, onChange };
|
|
152
146
|
});
|
|
153
|
-
const setValue = (0,
|
|
154
|
-
const {
|
|
155
|
-
if (Object.is(next,
|
|
156
|
-
if (
|
|
157
|
-
latest.current.
|
|
147
|
+
const setValue = (0, import_react2.useCallback)((next) => {
|
|
148
|
+
const { value: value2, current: current2, onChange: onChange2 } = latest.current;
|
|
149
|
+
if (Object.is(next, current2)) return;
|
|
150
|
+
if (value2 === void 0) {
|
|
151
|
+
latest.current.current = next;
|
|
158
152
|
setInternal(next);
|
|
159
153
|
}
|
|
160
154
|
onChange2?.(next);
|
|
161
155
|
}, []);
|
|
162
156
|
if (process.env.NODE_ENV !== "production") {
|
|
163
|
-
|
|
157
|
+
const controlled = value !== void 0;
|
|
158
|
+
useModeWarnings(
|
|
159
|
+
options.prop,
|
|
160
|
+
controlled,
|
|
161
|
+
controlled && onChange === void 0
|
|
162
|
+
);
|
|
164
163
|
}
|
|
165
164
|
return [current, setValue];
|
|
166
165
|
}
|
|
167
166
|
function useModeWarnings(prop, controlled, readOnly) {
|
|
168
|
-
const initiallyControlled = (0,
|
|
169
|
-
const warned2 = (0,
|
|
170
|
-
(0,
|
|
167
|
+
const initiallyControlled = (0, import_react2.useRef)(controlled);
|
|
168
|
+
const warned2 = (0, import_react2.useRef)({ readOnly: false, modeSwitch: false });
|
|
169
|
+
(0, import_react2.useEffect)(() => {
|
|
171
170
|
const name = prop.charAt(0).toUpperCase() + prop.slice(1);
|
|
172
171
|
if (readOnly && !warned2.current.readOnly) {
|
|
173
172
|
warned2.current.readOnly = true;
|
|
@@ -189,11 +188,11 @@ function useModeWarnings(prop, controlled, readOnly) {
|
|
|
189
188
|
function useRecipeState(options) {
|
|
190
189
|
const { recipe } = options;
|
|
191
190
|
if (process.env.NODE_ENV !== "production") {
|
|
192
|
-
(0,
|
|
191
|
+
(0, import_react3.useMemo)(() => {
|
|
193
192
|
assertParsedRecipe(
|
|
194
193
|
recipe,
|
|
195
194
|
"useRecipeState()",
|
|
196
|
-
"Call parseRecipe() from @recipe-book/core and pass result.data."
|
|
195
|
+
"Call parseRecipe() from @recipe-book/react/core and pass result.data."
|
|
197
196
|
);
|
|
198
197
|
}, [recipe]);
|
|
199
198
|
}
|
|
@@ -227,7 +226,7 @@ function useRecipeState(options) {
|
|
|
227
226
|
system !== rawSystem && `Recipe Book: \`system\` must be "metric" or "us", received ${describe(rawSystem)}. Showing "${system}" instead.`
|
|
228
227
|
);
|
|
229
228
|
}
|
|
230
|
-
const setServings = (0,
|
|
229
|
+
const setServings = (0, import_react3.useCallback)(
|
|
231
230
|
(next) => {
|
|
232
231
|
if (isServingsFor(next, base)) {
|
|
233
232
|
updateServings(next);
|
|
@@ -239,7 +238,7 @@ function useRecipeState(options) {
|
|
|
239
238
|
},
|
|
240
239
|
[updateServings, base]
|
|
241
240
|
);
|
|
242
|
-
const setSystem = (0,
|
|
241
|
+
const setSystem = (0, import_react3.useCallback)(
|
|
243
242
|
(next) => {
|
|
244
243
|
if (isSystem(next)) {
|
|
245
244
|
updateSystem(next);
|
|
@@ -251,66 +250,64 @@ function useRecipeState(options) {
|
|
|
251
250
|
},
|
|
252
251
|
[updateSystem]
|
|
253
252
|
);
|
|
254
|
-
const steps = (0,
|
|
255
|
-
const
|
|
253
|
+
const steps = (0, import_react3.useMemo)(() => (0, import_core2.resolveRecipe)(recipe).steps, [recipe]);
|
|
254
|
+
const resolved = (0, import_react3.useMemo)(
|
|
256
255
|
() => (0, import_core2.resolveRecipe)(recipe, { servings, system }),
|
|
257
256
|
[recipe, servings, system]
|
|
258
257
|
);
|
|
259
|
-
return (0,
|
|
258
|
+
return (0, import_react3.useMemo)(
|
|
260
259
|
() => ({
|
|
261
260
|
recipe,
|
|
262
261
|
servings,
|
|
263
262
|
setServings,
|
|
264
|
-
scale,
|
|
263
|
+
scale: resolved.scale,
|
|
265
264
|
system,
|
|
266
265
|
setSystem,
|
|
267
|
-
canConvert,
|
|
268
|
-
ingredients,
|
|
266
|
+
canConvert: resolved.canConvert,
|
|
267
|
+
ingredients: resolved.ingredients,
|
|
269
268
|
steps
|
|
270
269
|
}),
|
|
271
|
-
[
|
|
272
|
-
recipe,
|
|
273
|
-
servings,
|
|
274
|
-
setServings,
|
|
275
|
-
scale,
|
|
276
|
-
system,
|
|
277
|
-
setSystem,
|
|
278
|
-
canConvert,
|
|
279
|
-
ingredients,
|
|
280
|
-
steps
|
|
281
|
-
]
|
|
270
|
+
[recipe, servings, setServings, resolved, system, setSystem, steps]
|
|
282
271
|
);
|
|
283
272
|
}
|
|
284
273
|
function useWarning(message) {
|
|
285
|
-
const warned2 = (0,
|
|
286
|
-
(0,
|
|
274
|
+
const warned2 = (0, import_react3.useRef)(false);
|
|
275
|
+
(0, import_react3.useEffect)(() => {
|
|
287
276
|
if (message !== warned2.current) {
|
|
288
277
|
warned2.current = message;
|
|
289
278
|
if (message) console.warn(message);
|
|
290
279
|
}
|
|
291
280
|
}, [message]);
|
|
292
281
|
}
|
|
293
|
-
function numberSteps(recipe) {
|
|
294
|
-
let number = 0;
|
|
295
|
-
return recipe.steps.map((section) => ({
|
|
296
|
-
...section,
|
|
297
|
-
items: section.items.map((step) => ({ ...step, number: ++number }))
|
|
298
|
-
}));
|
|
299
|
-
}
|
|
300
282
|
function isServings(value) {
|
|
301
283
|
return typeof value === "number" && Number.isFinite(value) && value > 0;
|
|
302
284
|
}
|
|
303
285
|
function servingsBase(recipe) {
|
|
304
286
|
return [recipe.servings?.amount, recipe.yield?.amount].find(isServings) ?? 1;
|
|
305
287
|
}
|
|
306
|
-
|
|
307
|
-
|
|
288
|
+
function servingsWindow(base) {
|
|
289
|
+
const [mantissa, exponent] = base.toExponential().split("e");
|
|
290
|
+
return [
|
|
291
|
+
Number(`${mantissa}e${Number(exponent) - 6}`),
|
|
292
|
+
Number(`${mantissa}e${Number(exponent) + 6}`)
|
|
293
|
+
];
|
|
294
|
+
}
|
|
308
295
|
function isServingsFor(value, base) {
|
|
309
|
-
|
|
296
|
+
const [min, max] = servingsWindow(base);
|
|
297
|
+
return isServings(value) && value >= min && value <= max;
|
|
310
298
|
}
|
|
311
299
|
function describeRange(base) {
|
|
312
|
-
const
|
|
313
|
-
return `a number from ${
|
|
300
|
+
const [min, max] = servingsWindow(base);
|
|
301
|
+
return `a number from ${roundInward(min, true)} to ${roundInward(max, false)} for this recipe`;
|
|
302
|
+
}
|
|
303
|
+
function roundInward(bound, up) {
|
|
304
|
+
const nearest = Number(bound.toPrecision(6));
|
|
305
|
+
if (up ? nearest >= bound : nearest <= bound) {
|
|
306
|
+
return nearest;
|
|
307
|
+
}
|
|
308
|
+
const [mantissa, exponent] = bound.toExponential().split("e");
|
|
309
|
+
const digits = Number(mantissa.replace(".", "").slice(0, 6));
|
|
310
|
+
return Number(`${up ? digits + 1 : digits}e${Number(exponent) - 5}`);
|
|
314
311
|
}
|
|
315
312
|
function isSystem(value) {
|
|
316
313
|
return value === "metric" || value === "us";
|
|
@@ -330,7 +327,7 @@ function describe(value) {
|
|
|
330
327
|
|
|
331
328
|
// src/context.tsx
|
|
332
329
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
333
|
-
var ConfigContext = /* @__PURE__ */ (0,
|
|
330
|
+
var ConfigContext = /* @__PURE__ */ (0, import_react.createContext)({
|
|
334
331
|
locale: "en-US",
|
|
335
332
|
labels: defaultLabels
|
|
336
333
|
});
|
|
@@ -339,7 +336,7 @@ function RecipeBookProvider({
|
|
|
339
336
|
...config
|
|
340
337
|
}) {
|
|
341
338
|
const { locale, labels, defaultSystem } = useConfig(config);
|
|
342
|
-
const value = (0,
|
|
339
|
+
const value = (0, import_react4.useMemo)(
|
|
343
340
|
() => ({ locale, labels, defaultSystem }),
|
|
344
341
|
[locale, labels, defaultSystem]
|
|
345
342
|
);
|
|
@@ -350,10 +347,10 @@ function useConfig({
|
|
|
350
347
|
labels,
|
|
351
348
|
defaultSystem
|
|
352
349
|
}) {
|
|
353
|
-
const outer = (0,
|
|
350
|
+
const outer = (0, import_react4.useContext)(ConfigContext);
|
|
354
351
|
return {
|
|
355
352
|
locale: locale ?? outer.locale,
|
|
356
|
-
labels: (0,
|
|
353
|
+
labels: (0, import_react4.useMemo)(
|
|
357
354
|
() => ({
|
|
358
355
|
...outer.labels,
|
|
359
356
|
...Object.fromEntries(
|
|
@@ -364,13 +361,13 @@ function useConfig({
|
|
|
364
361
|
}),
|
|
365
362
|
[outer.labels, labels]
|
|
366
363
|
),
|
|
367
|
-
defaultSystem:
|
|
364
|
+
defaultSystem: [defaultSystem, outer.defaultSystem].find(isSystem)
|
|
368
365
|
};
|
|
369
366
|
}
|
|
370
|
-
var RecipeDataContext = /* @__PURE__ */ (0,
|
|
371
|
-
var RecipeStateContext = /* @__PURE__ */ (0,
|
|
367
|
+
var RecipeDataContext = /* @__PURE__ */ (0, import_react.createContext)(null);
|
|
368
|
+
var RecipeStateContext = /* @__PURE__ */ (0, import_react.createContext)(null);
|
|
372
369
|
function useRequired(context, message) {
|
|
373
|
-
const value = (0,
|
|
370
|
+
const value = (0, import_react4.useContext)(context);
|
|
374
371
|
if (!value) {
|
|
375
372
|
throw new import_core3.RecipeBookError("missing_parent", message);
|
|
376
373
|
}
|
|
@@ -397,17 +394,14 @@ function useRecipe() {
|
|
|
397
394
|
|
|
398
395
|
// src/parts/image.tsx
|
|
399
396
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
400
|
-
var Image = /* @__PURE__ */ (0,
|
|
397
|
+
var Image = /* @__PURE__ */ (0, import_react.forwardRef)(function Image2({
|
|
401
398
|
as: Comp = "img",
|
|
402
399
|
src,
|
|
403
400
|
alt,
|
|
404
401
|
...props
|
|
405
402
|
}, ref) {
|
|
406
403
|
const { recipe } = useRecipeData("Recipe.Image");
|
|
407
|
-
|
|
408
|
-
return null;
|
|
409
|
-
}
|
|
410
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
404
|
+
return recipe.image !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
411
405
|
Comp,
|
|
412
406
|
{
|
|
413
407
|
...props,
|
|
@@ -420,16 +414,16 @@ var Image = /* @__PURE__ */ (0, import_react4.forwardRef)(function Image2({
|
|
|
420
414
|
});
|
|
421
415
|
|
|
422
416
|
// src/parts/ingredients.tsx
|
|
423
|
-
var
|
|
417
|
+
var import_react12 = require("react");
|
|
424
418
|
|
|
425
419
|
// src/slot.tsx
|
|
426
|
-
var
|
|
420
|
+
var import_react7 = require("react");
|
|
427
421
|
function resolveAsChild(part, tag, asChild, children, defaults) {
|
|
428
422
|
if (asChild) {
|
|
429
|
-
if ((0,
|
|
423
|
+
if ((0, import_react.isValidElement)(children) && children.type !== import_react.Fragment) {
|
|
430
424
|
return [
|
|
431
425
|
Slot,
|
|
432
|
-
isEmpty(children.props.children) ? (0,
|
|
426
|
+
isEmpty(children.props.children) ? (0, import_react.cloneElement)(children, void 0, defaults) : children
|
|
433
427
|
];
|
|
434
428
|
}
|
|
435
429
|
if (process.env.NODE_ENV !== "production" && !warned.has(part)) {
|
|
@@ -441,7 +435,7 @@ function resolveAsChild(part, tag, asChild, children, defaults) {
|
|
|
441
435
|
}
|
|
442
436
|
return [tag, isEmpty(children) ? defaults : children];
|
|
443
437
|
}
|
|
444
|
-
var Slot = /* @__PURE__ */ (0,
|
|
438
|
+
var Slot = /* @__PURE__ */ (0, import_react.forwardRef)(function Slot2({ children, ...props }, ref) {
|
|
445
439
|
const child = children;
|
|
446
440
|
const merged = { ...props, ...child.props };
|
|
447
441
|
for (const name in child.props) {
|
|
@@ -462,7 +456,7 @@ var Slot = /* @__PURE__ */ (0, import_react5.forwardRef)(function Slot2({ childr
|
|
|
462
456
|
}
|
|
463
457
|
}
|
|
464
458
|
const childRef = Object.getOwnPropertyDescriptor(child.props, "ref")?.value ?? child.ref;
|
|
465
|
-
merged.ref = (0,
|
|
459
|
+
merged.ref = (0, import_react7.useCallback)(
|
|
466
460
|
(node) => {
|
|
467
461
|
const refs = [ref, childRef];
|
|
468
462
|
const cleanups = refs.map((each) => setRef(each, node));
|
|
@@ -480,7 +474,7 @@ var Slot = /* @__PURE__ */ (0, import_react5.forwardRef)(function Slot2({ childr
|
|
|
480
474
|
},
|
|
481
475
|
[ref, childRef]
|
|
482
476
|
);
|
|
483
|
-
return (0,
|
|
477
|
+
return (0, import_react.cloneElement)(child, merged);
|
|
484
478
|
});
|
|
485
479
|
function setRef(ref, node) {
|
|
486
480
|
if (typeof ref === "function") {
|
|
@@ -493,7 +487,7 @@ function setRef(ref, node) {
|
|
|
493
487
|
}
|
|
494
488
|
var warned = /* @__PURE__ */ new Set();
|
|
495
489
|
function describeChildren(children) {
|
|
496
|
-
if ((0,
|
|
490
|
+
if ((0, import_react.isValidElement)(children)) {
|
|
497
491
|
return "a Fragment";
|
|
498
492
|
}
|
|
499
493
|
if (Array.isArray(children)) {
|
|
@@ -511,25 +505,26 @@ function isEmpty(children) {
|
|
|
511
505
|
|
|
512
506
|
// src/use-format-ingredient.ts
|
|
513
507
|
var import_core4 = require("@recipe-book/core");
|
|
514
|
-
var
|
|
508
|
+
var import_react9 = require("react");
|
|
515
509
|
function useFormatIngredient() {
|
|
516
510
|
const {
|
|
517
511
|
locale,
|
|
518
512
|
labels: { optional }
|
|
519
513
|
} = useRequired(
|
|
520
514
|
RecipeDataContext,
|
|
521
|
-
"useFormatIngredient() must be called inside <Recipe.Root>. To format ingredients without a Root, call formatIngredient() from @recipe-book/core."
|
|
515
|
+
"useFormatIngredient() must be called inside <Recipe.Root>. To format ingredients without a Root, call formatIngredient() from @recipe-book/react/core."
|
|
522
516
|
);
|
|
523
|
-
return (0,
|
|
517
|
+
return (0, import_react9.useCallback)(
|
|
524
518
|
(item) => formatLine(item, locale, optional),
|
|
525
519
|
[locale, optional]
|
|
526
520
|
);
|
|
527
521
|
}
|
|
528
522
|
function formatLine(item, locale, optional) {
|
|
529
523
|
const options = { locale };
|
|
524
|
+
const formatted = (0, import_core4.formatIngredient)(item, options);
|
|
530
525
|
const quantity = lineQuantity(item);
|
|
531
526
|
return {
|
|
532
|
-
...
|
|
527
|
+
...formatted,
|
|
533
528
|
quantityParts: quantity ? (0, import_core4.formatQuantityToParts)(quantity, options) : [],
|
|
534
529
|
...item.ingredient.optional && { optional }
|
|
535
530
|
};
|
|
@@ -539,10 +534,10 @@ function lineQuantity(item) {
|
|
|
539
534
|
}
|
|
540
535
|
|
|
541
536
|
// src/parts/sections.tsx
|
|
542
|
-
var
|
|
537
|
+
var import_react10 = require("react");
|
|
543
538
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
544
539
|
function renderKeyed(items, render) {
|
|
545
|
-
return items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
540
|
+
return items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react.Fragment, { children: render(item) }, item.id));
|
|
546
541
|
}
|
|
547
542
|
function SectionBlock({
|
|
548
543
|
kind,
|
|
@@ -550,21 +545,18 @@ function SectionBlock({
|
|
|
550
545
|
headingLevel,
|
|
551
546
|
children
|
|
552
547
|
}) {
|
|
553
|
-
const headingId = (0,
|
|
548
|
+
const headingId = (0, import_react10.useId)();
|
|
554
549
|
const marker = `data-recipe-${kind}-section`;
|
|
555
|
-
if (!title) {
|
|
556
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { ...{ [marker]: "" }, children });
|
|
557
|
-
}
|
|
558
550
|
const Heading = `h${headingLevel}`;
|
|
559
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { ...{ [marker]: "" }, "aria-labelledby": headingId, children: [
|
|
551
|
+
return title ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { ...{ [marker]: "" }, "aria-labelledby": headingId, children: [
|
|
560
552
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Heading, { id: headingId, children: title }),
|
|
561
553
|
children
|
|
562
|
-
] });
|
|
554
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { ...{ [marker]: "" }, children });
|
|
563
555
|
}
|
|
564
556
|
|
|
565
557
|
// src/parts/ingredients.tsx
|
|
566
558
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
567
|
-
var Ingredients = /* @__PURE__ */ (0,
|
|
559
|
+
var Ingredients = /* @__PURE__ */ (0, import_react.forwardRef)(
|
|
568
560
|
function Ingredients2({ headingLevel = 3, children, ...props }, ref) {
|
|
569
561
|
const { ingredients } = usePartState("Recipe.Ingredients");
|
|
570
562
|
const renderSection = children ?? ((section) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
@@ -579,21 +571,21 @@ var Ingredients = /* @__PURE__ */ (0, import_react8.forwardRef)(
|
|
|
579
571
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { ...props, "data-recipe-ingredients": "", ref, children: renderKeyed(ingredients, renderSection) });
|
|
580
572
|
}
|
|
581
573
|
);
|
|
582
|
-
var IngredientList = /* @__PURE__ */ (0,
|
|
574
|
+
var IngredientList = /* @__PURE__ */ (0, import_react.forwardRef)(
|
|
583
575
|
function IngredientList2({ section, children = (item) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Ingredient, { item }), ...props }, ref) {
|
|
584
576
|
const { ingredients } = usePartState("Recipe.IngredientList");
|
|
585
577
|
const items = section?.items ?? ingredients.flatMap((s) => s.items);
|
|
586
578
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("ul", { ...props, "data-recipe-ingredient-list": "", ref, children: renderKeyed(items, children) });
|
|
587
579
|
}
|
|
588
580
|
);
|
|
589
|
-
var LineContext = /* @__PURE__ */ (0,
|
|
590
|
-
var Ingredient = /* @__PURE__ */ (0,
|
|
581
|
+
var LineContext = /* @__PURE__ */ (0, import_react.createContext)(null);
|
|
582
|
+
var Ingredient = /* @__PURE__ */ (0, import_react.forwardRef)(
|
|
591
583
|
function Ingredient2({ item, asChild = false, children, ...props }, ref) {
|
|
592
584
|
const {
|
|
593
585
|
labels: { optional, to },
|
|
594
586
|
locale
|
|
595
587
|
} = useRecipeData("Recipe.Ingredient");
|
|
596
|
-
const line = (0,
|
|
588
|
+
const line = (0, import_react12.useMemo)(
|
|
597
589
|
() => ({ ...formatLine(item, locale, optional), to }),
|
|
598
590
|
[item, locale, optional, to]
|
|
599
591
|
);
|
|
@@ -642,12 +634,12 @@ function ingredientText(name, attribute, read) {
|
|
|
642
634
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Comp, { ...props, ...{ [attribute]: "" }, ref, children: Comp === "span" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
643
635
|
children,
|
|
644
636
|
text
|
|
645
|
-
] }) : (0,
|
|
637
|
+
] }) : (0, import_react.cloneElement)(child, void 0, child.props.children, text) });
|
|
646
638
|
}
|
|
647
639
|
if (process.env.NODE_ENV !== "production") {
|
|
648
640
|
Object.defineProperty(IngredientText, "name", { value: name });
|
|
649
641
|
}
|
|
650
|
-
return (0,
|
|
642
|
+
return (0, import_react.forwardRef)(IngredientText);
|
|
651
643
|
}
|
|
652
644
|
var IngredientQuantity = /* @__PURE__ */ ingredientText(
|
|
653
645
|
"IngredientQuantity",
|
|
@@ -701,9 +693,9 @@ var IngredientOptional = /* @__PURE__ */ ingredientText(
|
|
|
701
693
|
|
|
702
694
|
// src/parts/json-ld.tsx
|
|
703
695
|
var import_schema_org = require("@recipe-book/core/schema-org");
|
|
704
|
-
var
|
|
696
|
+
var import_react14 = require("react");
|
|
705
697
|
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
706
|
-
var JsonLd = /* @__PURE__ */ (0,
|
|
698
|
+
var JsonLd = /* @__PURE__ */ (0, import_react.forwardRef)(
|
|
707
699
|
function JsonLd2({
|
|
708
700
|
servings,
|
|
709
701
|
system,
|
|
@@ -715,12 +707,12 @@ var JsonLd = /* @__PURE__ */ (0, import_react9.forwardRef)(
|
|
|
715
707
|
...props
|
|
716
708
|
}, ref) {
|
|
717
709
|
const { recipe } = useRecipeData("Recipe.JsonLd");
|
|
718
|
-
const
|
|
710
|
+
const result = (0, import_react14.useMemo)(
|
|
719
711
|
() => (0, import_schema_org.toJsonLd)(recipe, { servings, system, url, extra }),
|
|
720
712
|
[recipe, servings, system, url, extra]
|
|
721
713
|
);
|
|
722
714
|
if (process.env.NODE_ENV !== "production") {
|
|
723
|
-
useWarningsReport(recipe.name, warnings);
|
|
715
|
+
useWarningsReport(recipe.name, result.warnings);
|
|
724
716
|
}
|
|
725
717
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
726
718
|
"script",
|
|
@@ -729,7 +721,7 @@ var JsonLd = /* @__PURE__ */ (0, import_react9.forwardRef)(
|
|
|
729
721
|
type: "application/ld+json",
|
|
730
722
|
"data-recipe-json-ld": "",
|
|
731
723
|
dangerouslySetInnerHTML: {
|
|
732
|
-
__html: JSON.stringify(data).replace(/</g, "\\u003c")
|
|
724
|
+
__html: JSON.stringify(result.data).replace(/</g, "\\u003c")
|
|
733
725
|
},
|
|
734
726
|
ref
|
|
735
727
|
}
|
|
@@ -737,8 +729,8 @@ var JsonLd = /* @__PURE__ */ (0, import_react9.forwardRef)(
|
|
|
737
729
|
}
|
|
738
730
|
);
|
|
739
731
|
function useWarningsReport(name, warnings) {
|
|
740
|
-
const reported = (0,
|
|
741
|
-
(0,
|
|
732
|
+
const reported = (0, import_react14.useRef)(void 0);
|
|
733
|
+
(0, import_react14.useEffect)(() => {
|
|
742
734
|
const key = JSON.stringify(warnings);
|
|
743
735
|
const count = warnings.length;
|
|
744
736
|
if (count > 0 && key !== reported.current) {
|
|
@@ -752,7 +744,7 @@ function useWarningsReport(name, warnings) {
|
|
|
752
744
|
}
|
|
753
745
|
|
|
754
746
|
// src/parts/root.tsx
|
|
755
|
-
var
|
|
747
|
+
var import_react16 = require("react");
|
|
756
748
|
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
757
749
|
function Root({
|
|
758
750
|
recipe,
|
|
@@ -761,14 +753,14 @@ function Root({
|
|
|
761
753
|
children,
|
|
762
754
|
...options
|
|
763
755
|
}) {
|
|
764
|
-
const result = (0,
|
|
756
|
+
const result = (0, import_react16.useMemo)(() => {
|
|
765
757
|
if (parse !== void 0) {
|
|
766
758
|
return parse(recipe);
|
|
767
759
|
}
|
|
768
760
|
assertParsedRecipe(
|
|
769
761
|
recipe,
|
|
770
762
|
"<Recipe.Root>",
|
|
771
|
-
"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."
|
|
763
|
+
"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."
|
|
772
764
|
);
|
|
773
765
|
return { success: true, data: recipe, warnings: [] };
|
|
774
766
|
}, [parse, recipe]);
|
|
@@ -783,23 +775,23 @@ function Root({
|
|
|
783
775
|
function RecipeProvider({ children, ...options }) {
|
|
784
776
|
const { locale, labels, defaultSystem } = useConfig(options);
|
|
785
777
|
const state = useRecipeState({ ...options, defaultSystem });
|
|
786
|
-
const [temperatures, setTemperatures] = (0,
|
|
787
|
-
const reportTemperature = (0,
|
|
778
|
+
const [temperatures, setTemperatures] = (0, import_react16.useState)(0);
|
|
779
|
+
const reportTemperature = (0, import_react16.useCallback)(() => {
|
|
788
780
|
setTemperatures((count) => count + 1);
|
|
789
781
|
return () => setTemperatures((count) => count - 1);
|
|
790
782
|
}, []);
|
|
791
783
|
const canConvert = state.canConvert || temperatures > 0;
|
|
792
|
-
const value = (0,
|
|
784
|
+
const value = (0, import_react16.useMemo)(() => ({ ...state, canConvert }), [state, canConvert]);
|
|
793
785
|
const { recipe, steps } = state;
|
|
794
|
-
const data = (0,
|
|
786
|
+
const data = (0, import_react16.useMemo)(
|
|
795
787
|
() => ({ recipe, steps, labels, locale, reportTemperature }),
|
|
796
788
|
[recipe, steps, labels, locale, reportTemperature]
|
|
797
789
|
);
|
|
798
790
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(RecipeDataContext.Provider, { value: data, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(RecipeStateContext.Provider, { value, children }) });
|
|
799
791
|
}
|
|
800
792
|
function useParseReport(result) {
|
|
801
|
-
const reported = (0,
|
|
802
|
-
(0,
|
|
793
|
+
const reported = (0, import_react16.useRef)(void 0);
|
|
794
|
+
(0, import_react16.useEffect)(() => {
|
|
803
795
|
const key = result.success ? result.warnings.length > 0 ? `warnings ${JSON.stringify(result.warnings)}` : void 0 : `error ${JSON.stringify([result.error.message, result.error.issues])}`;
|
|
804
796
|
if (key === reported.current) {
|
|
805
797
|
return;
|
|
@@ -822,7 +814,7 @@ function useParseReport(result) {
|
|
|
822
814
|
|
|
823
815
|
// src/parts/servings.tsx
|
|
824
816
|
var import_core5 = require("@recipe-book/core");
|
|
825
|
-
var
|
|
817
|
+
var import_react17 = require("react");
|
|
826
818
|
|
|
827
819
|
// src/compose-event-handlers.ts
|
|
828
820
|
function composeEventHandlers(theirs, ours) {
|
|
@@ -836,7 +828,7 @@ function composeEventHandlers(theirs, ours) {
|
|
|
836
828
|
|
|
837
829
|
// src/parts/servings.tsx
|
|
838
830
|
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
839
|
-
var ServingsSelect = /* @__PURE__ */ (0,
|
|
831
|
+
var ServingsSelect = /* @__PURE__ */ (0, import_react.forwardRef)(
|
|
840
832
|
function ServingsSelect2({ options, "aria-label": ariaLabel, onChange, ...props }, ref) {
|
|
841
833
|
const { recipe, labels, locale } = useRecipeData("Recipe.ServingsSelect");
|
|
842
834
|
const { servings, setServings } = usePartState("Recipe.ServingsSelect");
|
|
@@ -864,7 +856,7 @@ var ServingsSelect = /* @__PURE__ */ (0, import_react11.forwardRef)(
|
|
|
864
856
|
);
|
|
865
857
|
}
|
|
866
858
|
);
|
|
867
|
-
var ServingsInput = /* @__PURE__ */ (0,
|
|
859
|
+
var ServingsInput = /* @__PURE__ */ (0, import_react.forwardRef)(
|
|
868
860
|
function ServingsInput2({
|
|
869
861
|
min = 1,
|
|
870
862
|
max,
|
|
@@ -878,7 +870,7 @@ var ServingsInput = /* @__PURE__ */ (0, import_react11.forwardRef)(
|
|
|
878
870
|
const { recipe, labels } = useRecipeData("Recipe.ServingsInput");
|
|
879
871
|
const { servings, setServings } = usePartState("Recipe.ServingsInput");
|
|
880
872
|
const base = servingsBase(recipe);
|
|
881
|
-
const [draft, setDraft] = (0,
|
|
873
|
+
const [draft, setDraft] = (0, import_react17.useState)({ text: String(servings), servings });
|
|
882
874
|
if (draft.servings !== servings) {
|
|
883
875
|
setDraft({
|
|
884
876
|
text: Number(draft.text) === servings ? draft.text : String(servings),
|
|
@@ -944,12 +936,11 @@ function optionText(choice, { servings, yield: makes }, base, labels, locale) {
|
|
|
944
936
|
|
|
945
937
|
// src/parts/step-text.tsx
|
|
946
938
|
var import_core6 = require("@recipe-book/core");
|
|
947
|
-
var
|
|
939
|
+
var import_react20 = require("react");
|
|
948
940
|
|
|
949
941
|
// src/parts/steps.tsx
|
|
950
|
-
var import_react12 = require("react");
|
|
951
942
|
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
952
|
-
var Steps = /* @__PURE__ */ (0,
|
|
943
|
+
var Steps = /* @__PURE__ */ (0, import_react.forwardRef)(function Steps2({ headingLevel = 3, children, ...props }, ref) {
|
|
953
944
|
const { steps } = useRecipeData("Recipe.Steps");
|
|
954
945
|
const renderSection = children ?? ((section) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
955
946
|
SectionBlock,
|
|
@@ -962,7 +953,7 @@ var Steps = /* @__PURE__ */ (0, import_react12.forwardRef)(function Steps2({ hea
|
|
|
962
953
|
));
|
|
963
954
|
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { ...props, "data-recipe-steps": "", ref, children: renderKeyed(steps, renderSection) });
|
|
964
955
|
});
|
|
965
|
-
var StepList = /* @__PURE__ */ (0,
|
|
956
|
+
var StepList = /* @__PURE__ */ (0, import_react.forwardRef)(
|
|
966
957
|
function StepList2({ section, children = (step) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Step, { item: step }), start, ...props }, ref) {
|
|
967
958
|
const { steps } = useRecipeData("Recipe.StepList");
|
|
968
959
|
const items = section?.items ?? steps.flatMap((s) => s.items);
|
|
@@ -978,8 +969,8 @@ var StepList = /* @__PURE__ */ (0, import_react12.forwardRef)(
|
|
|
978
969
|
);
|
|
979
970
|
}
|
|
980
971
|
);
|
|
981
|
-
var StepContext = /* @__PURE__ */ (0,
|
|
982
|
-
var Step = /* @__PURE__ */ (0,
|
|
972
|
+
var StepContext = /* @__PURE__ */ (0, import_react.createContext)(null);
|
|
973
|
+
var Step = /* @__PURE__ */ (0, import_react.forwardRef)(function Step2({ item, asChild = false, children, ...props }, ref) {
|
|
983
974
|
useRecipeData("Recipe.Step");
|
|
984
975
|
const [Comp, content] = resolveAsChild(
|
|
985
976
|
"Recipe.Step",
|
|
@@ -994,7 +985,7 @@ var Step = /* @__PURE__ */ (0, import_react12.forwardRef)(function Step2({ item,
|
|
|
994
985
|
);
|
|
995
986
|
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(StepContext.Provider, { value: item, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Comp, { ...props, "data-recipe-step": "", ref, children: content }) });
|
|
996
987
|
});
|
|
997
|
-
var StepName = /* @__PURE__ */ (0,
|
|
988
|
+
var StepName = /* @__PURE__ */ (0, import_react.forwardRef)(
|
|
998
989
|
function StepName2(props, ref) {
|
|
999
990
|
const step = useRequired(
|
|
1000
991
|
StepContext,
|
|
@@ -1006,13 +997,13 @@ var StepName = /* @__PURE__ */ (0, import_react12.forwardRef)(
|
|
|
1006
997
|
|
|
1007
998
|
// src/parts/step-text.tsx
|
|
1008
999
|
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
1009
|
-
var StepText = /* @__PURE__ */ (0,
|
|
1000
|
+
var StepText = /* @__PURE__ */ (0, import_react.forwardRef)(
|
|
1010
1001
|
function StepText2(props, ref) {
|
|
1011
1002
|
const step = useRequired(
|
|
1012
1003
|
StepContext,
|
|
1013
1004
|
"<Recipe.StepText> must be rendered inside <Recipe.Step>."
|
|
1014
1005
|
);
|
|
1015
|
-
const segments = (0,
|
|
1006
|
+
const segments = (0, import_react20.useMemo)(() => (0, import_core6.segmentStepText)(step.text), [step.text]);
|
|
1016
1007
|
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { ...props, "data-recipe-step-text": "", ref, children: segments.map(
|
|
1017
1008
|
(segment, index) => segment.type === "temperature" ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Temperature, { segment }, index) : (
|
|
1018
1009
|
// Core may add segment types in a minor release; show those as authored.
|
|
@@ -1025,44 +1016,39 @@ function Temperature({ segment }) {
|
|
|
1025
1016
|
const { labels, locale, reportTemperature } = useRecipeData("Recipe.StepText");
|
|
1026
1017
|
const unit = usePartState("Recipe.StepText").system === "us" ? "F" : "C";
|
|
1027
1018
|
const readings = [segment, ...segment.alternatives];
|
|
1028
|
-
(0,
|
|
1029
|
-
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { "data-recipe-temperature": "", children: [false, true].
|
|
1019
|
+
(0, import_react20.useEffect)(reportTemperature, [reportTemperature]);
|
|
1020
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { "data-recipe-temperature": "", children: [false, true].map((fan) => {
|
|
1030
1021
|
const kind = readings.filter((reading2) => reading2.fan === fan);
|
|
1031
1022
|
const reading = kind.find((each) => each.temperature.unit === unit) ?? kind[0];
|
|
1032
|
-
return reading
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
rounding: reading.temperature.unit === unit ? "none" : void 0
|
|
1038
|
-
}
|
|
1039
|
-
) + (fan && labels.fan ? ` ${labels.fan}` : "")
|
|
1040
|
-
] : [];
|
|
1041
|
-
}).join(" / ") });
|
|
1023
|
+
return reading && (0, import_core6.formatTemperature)((0, import_core6.convertTemperature)(reading.temperature, unit), {
|
|
1024
|
+
locale,
|
|
1025
|
+
rounding: reading.temperature.unit === unit ? "none" : void 0
|
|
1026
|
+
}) + (fan && labels.fan ? ` ${labels.fan}` : "");
|
|
1027
|
+
}).filter(Boolean).join(" / ") });
|
|
1042
1028
|
}
|
|
1043
1029
|
|
|
1044
1030
|
// src/parts/system-toggle.tsx
|
|
1045
|
-
var
|
|
1031
|
+
var import_react22 = require("react");
|
|
1046
1032
|
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
1047
|
-
var ToggleContext = /* @__PURE__ */ (0,
|
|
1033
|
+
var ToggleContext = /* @__PURE__ */ (0, import_react.createContext)(
|
|
1048
1034
|
null
|
|
1049
1035
|
);
|
|
1050
|
-
var SystemToggle = /* @__PURE__ */ (0,
|
|
1036
|
+
var SystemToggle = /* @__PURE__ */ (0, import_react.forwardRef)(
|
|
1051
1037
|
function SystemToggle2({ asChild = false, "aria-label": ariaLabel, children, ...props }, ref) {
|
|
1052
1038
|
const { labels } = useRecipeData("Recipe.SystemToggle");
|
|
1053
1039
|
const { system, setSystem, canConvert } = usePartState(
|
|
1054
1040
|
"Recipe.SystemToggle"
|
|
1055
1041
|
);
|
|
1056
1042
|
const disabled = !canConvert;
|
|
1057
|
-
const [offers, setOffers] = (0,
|
|
1058
|
-
const [chosen, choose] = (0,
|
|
1059
|
-
const offer = (0,
|
|
1043
|
+
const [offers, setOffers] = (0, import_react22.useState)([]);
|
|
1044
|
+
const [chosen, choose] = (0, import_react22.useState)();
|
|
1045
|
+
const offer = (0, import_react22.useCallback)((id, value) => {
|
|
1060
1046
|
const entry = { id, value };
|
|
1061
1047
|
setOffers((current) => [...current, entry]);
|
|
1062
1048
|
return () => setOffers((current) => current.filter((other) => other !== entry));
|
|
1063
1049
|
}, []);
|
|
1064
1050
|
const tabStop = (offers.find((entry) => entry.value === system && entry.id === chosen) ?? offers.find((entry) => entry.value === system) ?? offers[0])?.id;
|
|
1065
|
-
const context = (0,
|
|
1051
|
+
const context = (0, import_react22.useMemo)(
|
|
1066
1052
|
() => ({ system, setSystem, disabled, tabStop, offer, choose }),
|
|
1067
1053
|
[system, setSystem, disabled, tabStop, offer]
|
|
1068
1054
|
);
|
|
@@ -1091,7 +1077,7 @@ var SystemToggle = /* @__PURE__ */ (0, import_react14.forwardRef)(
|
|
|
1091
1077
|
) });
|
|
1092
1078
|
}
|
|
1093
1079
|
);
|
|
1094
|
-
var SystemOption = /* @__PURE__ */ (0,
|
|
1080
|
+
var SystemOption = /* @__PURE__ */ (0, import_react.forwardRef)(
|
|
1095
1081
|
function SystemOption2({
|
|
1096
1082
|
value,
|
|
1097
1083
|
asChild = false,
|
|
@@ -1114,10 +1100,10 @@ var SystemOption = /* @__PURE__ */ (0, import_react14.forwardRef)(
|
|
|
1114
1100
|
"<Recipe.SystemOption> must be rendered inside <Recipe.SystemToggle>."
|
|
1115
1101
|
);
|
|
1116
1102
|
const { labels } = useRecipeData("Recipe.SystemOption");
|
|
1117
|
-
const id = (0,
|
|
1103
|
+
const id = (0, import_react22.useId)();
|
|
1118
1104
|
const disabled = groupDisabled || ownDisabled;
|
|
1119
1105
|
const checked = value === system;
|
|
1120
|
-
(0,
|
|
1106
|
+
(0, import_react22.useEffect)(
|
|
1121
1107
|
() => disabled ? void 0 : offer(id, value),
|
|
1122
1108
|
[disabled, offer, id, value]
|
|
1123
1109
|
);
|
|
@@ -1132,6 +1118,7 @@ var SystemOption = /* @__PURE__ */ (0, import_react14.forwardRef)(
|
|
|
1132
1118
|
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1133
1119
|
Comp,
|
|
1134
1120
|
{
|
|
1121
|
+
autoComplete: "off",
|
|
1135
1122
|
...props,
|
|
1136
1123
|
type: type ?? "button",
|
|
1137
1124
|
role: "radio",
|