@recipe-book/react 0.1.1 → 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/dist/index.d.cts CHANGED
@@ -222,7 +222,7 @@ type RecipeState = {
222
222
  * its ingredients at those settings, and its numbered steps.
223
223
  *
224
224
  * @example
225
- * import type { Recipe as ParsedRecipe } from '@recipe-book/react/core'
225
+ * import type { ParsedRecipe } from '@recipe-book/react/core'
226
226
  * import * as Recipe from '@recipe-book/react'
227
227
  *
228
228
  * function ServingsSummary({ recipe }: { recipe: ParsedRecipe }) {
@@ -344,7 +344,8 @@ type RecipeIngredientProps = Omit<ComponentPropsWithoutRef<'li'>, 'dangerouslySe
344
344
  item: IngredientItem;
345
345
  /**
346
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
347
+ * instead of an `<li>`. Render an `<li>` or a component that renders one, so
348
+ * the list keeps its items. A prop on the child wins, except that the line's
348
349
  * `tabIndex` wins, `className`s join, `style` merges key by key with the
349
350
  * child winning, both event handlers run (the child's first), and both refs
350
351
  * are set. The child's own children replace the line's, so an empty child
@@ -1059,7 +1060,8 @@ type RecipeStepProps = Omit<ComponentPropsWithoutRef<'li'>, 'dangerouslySetInner
1059
1060
  item: StepItem;
1060
1061
  /**
1061
1062
  * 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
+ * instead of an `<li>`. Render an `<li>` or a component that renders one, so
1064
+ * the list keeps its items. A prop on the child wins, except that the step's
1063
1065
  * `tabIndex` wins, `className`s join, `style` merges key by key with the
1064
1066
  * child winning, both event handlers run (the child's first), and both refs
1065
1067
  * are set. The child's own children replace the step's, so an empty child
@@ -1185,15 +1187,17 @@ type RecipeSystemOptionProps = Omit<ComponentPropsWithoutRef<'button'>, 'value'
1185
1187
  autoComplete?: string | undefined;
1186
1188
  /**
1187
1189
  * 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.
1190
+ * `<motion.button layout />`, instead of a `<button>`. Render a `<button>` or
1191
+ * a component that renders one, so Space and Enter check it, and a disabled
1192
+ * option reads as disabled to screen readers and doesn't take focus on a
1193
+ * click. A prop on the child wins, except that the option's `tabIndex` wins,
1194
+ * `className`s join, `style` merges key by key with the child winning, both
1195
+ * event handlers run (the child's first), and both refs are set. The option
1196
+ * sets `tabIndex` to keep one radio in the tab order once React hydrates the
1197
+ * page; before that, every enabled checked option is in it. The child's own
1198
+ * children replace the option's, so an empty child gets the system's label.
1199
+ * With anything but one element child, it renders its own `<button>`, with a
1200
+ * warning in development.
1197
1201
  *
1198
1202
  * @defaultValue `false`
1199
1203
  *
package/dist/index.d.ts CHANGED
@@ -222,7 +222,7 @@ type RecipeState = {
222
222
  * its ingredients at those settings, and its numbered steps.
223
223
  *
224
224
  * @example
225
- * import type { Recipe as ParsedRecipe } from '@recipe-book/react/core'
225
+ * import type { ParsedRecipe } from '@recipe-book/react/core'
226
226
  * import * as Recipe from '@recipe-book/react'
227
227
  *
228
228
  * function ServingsSummary({ recipe }: { recipe: ParsedRecipe }) {
@@ -344,7 +344,8 @@ type RecipeIngredientProps = Omit<ComponentPropsWithoutRef<'li'>, 'dangerouslySe
344
344
  item: IngredientItem;
345
345
  /**
346
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
347
+ * instead of an `<li>`. Render an `<li>` or a component that renders one, so
348
+ * the list keeps its items. A prop on the child wins, except that the line's
348
349
  * `tabIndex` wins, `className`s join, `style` merges key by key with the
349
350
  * child winning, both event handlers run (the child's first), and both refs
350
351
  * are set. The child's own children replace the line's, so an empty child
@@ -1059,7 +1060,8 @@ type RecipeStepProps = Omit<ComponentPropsWithoutRef<'li'>, 'dangerouslySetInner
1059
1060
  item: StepItem;
1060
1061
  /**
1061
1062
  * 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
+ * instead of an `<li>`. Render an `<li>` or a component that renders one, so
1064
+ * the list keeps its items. A prop on the child wins, except that the step's
1063
1065
  * `tabIndex` wins, `className`s join, `style` merges key by key with the
1064
1066
  * child winning, both event handlers run (the child's first), and both refs
1065
1067
  * are set. The child's own children replace the step's, so an empty child
@@ -1185,15 +1187,17 @@ type RecipeSystemOptionProps = Omit<ComponentPropsWithoutRef<'button'>, 'value'
1185
1187
  autoComplete?: string | undefined;
1186
1188
  /**
1187
1189
  * 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.
1190
+ * `<motion.button layout />`, instead of a `<button>`. Render a `<button>` or
1191
+ * a component that renders one, so Space and Enter check it, and a disabled
1192
+ * option reads as disabled to screen readers and doesn't take focus on a
1193
+ * click. A prop on the child wins, except that the option's `tabIndex` wins,
1194
+ * `className`s join, `style` merges key by key with the child winning, both
1195
+ * event handlers run (the child's first), and both refs are set. The option
1196
+ * sets `tabIndex` to keep one radio in the tab order once React hydrates the
1197
+ * page; before that, every enabled checked option is in it. The child's own
1198
+ * children replace the option's, so an empty child gets the system's label.
1199
+ * With anything but one element child, it renders its own `<button>`, with a
1200
+ * warning in development.
1197
1201
  *
1198
1202
  * @defaultValue `false`
1199
1203
  *
package/dist/index.js CHANGED
@@ -7,6 +7,13 @@ import {
7
7
  useMemo as useMemo2
8
8
  } from "react";
9
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
+
10
17
  // src/labels.ts
11
18
  var defaultLabels = {
12
19
  servings: "Servings",
@@ -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";
@@ -363,6 +373,9 @@ var Image = /* @__PURE__ */ forwardRef(function Image2({
363
373
  }
364
374
  );
365
375
  });
376
+ if (process.env.NODE_ENV !== "production") {
377
+ setDisplayName(Image, "Recipe.Image");
378
+ }
366
379
 
367
380
  // src/parts/ingredients.tsx
368
381
  import {
@@ -409,7 +422,7 @@ var Slot = /* @__PURE__ */ forwardRef(function Slot2({ children, ...props }, ref
409
422
  }
410
423
  }
411
424
  const childRef = Object.getOwnPropertyDescriptor(child.props, "ref")?.value ?? child.ref;
412
- merged.ref = useCallback3(
425
+ const mergedRef = useCallback3(
413
426
  (node) => {
414
427
  const refs = [ref, childRef];
415
428
  const cleanups = refs.map((each) => setRef(each, node));
@@ -427,6 +440,9 @@ var Slot = /* @__PURE__ */ forwardRef(function Slot2({ children, ...props }, ref
427
440
  },
428
441
  [ref, childRef]
429
442
  );
443
+ if (ref != null) {
444
+ merged.ref = mergedRef;
445
+ }
430
446
  return cloneElement(child, merged);
431
447
  });
432
448
  function setRef(ref, node) {
@@ -455,6 +471,9 @@ function describeChildren(children) {
455
471
  function isEmpty(children) {
456
472
  return children == null || typeof children === "boolean";
457
473
  }
474
+ if (process.env.NODE_ENV !== "production") {
475
+ setDisplayName(Slot, "Slot");
476
+ }
458
477
 
459
478
  // src/use-format-ingredient.ts
460
479
  import {
@@ -592,9 +611,6 @@ function ingredientText(name, attribute, read) {
592
611
  text
593
612
  ] }) : cloneElement(child, void 0, child.props.children, text) });
594
613
  }
595
- if (process.env.NODE_ENV !== "production") {
596
- Object.defineProperty(IngredientText, "name", { value: name });
597
- }
598
614
  return forwardRef(IngredientText);
599
615
  }
600
616
  var IngredientQuantity = /* @__PURE__ */ ingredientText(
@@ -646,6 +662,15 @@ var IngredientOptional = /* @__PURE__ */ ingredientText(
646
662
  // An empty label shows only the part's own children, such as an icon.
647
663
  ({ optional }, children) => optional === "" && isEmpty(children) ? void 0 : optional
648
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
+ }
649
674
 
650
675
  // src/parts/json-ld.tsx
651
676
  import { toJsonLd } from "@recipe-book/core/schema-org";
@@ -702,6 +727,9 @@ function useWarningsReport(name, warnings) {
702
727
  reported.current = key;
703
728
  }, [name, warnings]);
704
729
  }
730
+ if (process.env.NODE_ENV !== "production") {
731
+ setDisplayName(JsonLd, "Recipe.JsonLd");
732
+ }
705
733
 
706
734
  // src/parts/root.tsx
707
735
  import {
@@ -769,7 +797,7 @@ function useParseReport(result) {
769
797
  if (result.success) {
770
798
  const count = result.warnings.length;
771
799
  console.warn(
772
- `Recipe Book: ${quote(result.data.name)} has ${count} ${count === 1 ? "warning" : "warnings"}. It still renders, but a warning can mean a misspelled field.`,
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.`,
773
801
  result.warnings
774
802
  );
775
803
  } else {
@@ -777,6 +805,9 @@ function useParseReport(result) {
777
805
  }
778
806
  }, [result]);
779
807
  }
808
+ if (process.env.NODE_ENV !== "production") {
809
+ setDisplayName(Root, "Recipe.Root");
810
+ }
780
811
 
781
812
  // src/parts/servings.tsx
782
813
  import {
@@ -904,6 +935,10 @@ function optionText(choice, { servings, yield: makes }, base, labels, locale) {
904
935
  }
905
936
  return `${formatServings({ amount: choice }, format)}\xD7`;
906
937
  }
938
+ if (process.env.NODE_ENV !== "production") {
939
+ setDisplayName(ServingsSelect, "Recipe.ServingsSelect");
940
+ setDisplayName(ServingsInput, "Recipe.ServingsInput");
941
+ }
907
942
 
908
943
  // src/parts/step-text.tsx
909
944
  import {
@@ -969,9 +1004,15 @@ var StepName = /* @__PURE__ */ forwardRef(
969
1004
  StepContext,
970
1005
  "<Recipe.StepName> must be rendered inside <Recipe.Step>."
971
1006
  );
972
- return step.name === void 0 ? null : /* @__PURE__ */ jsx8("b", { ...props, "data-recipe-name": "", ref, children: step.name });
1007
+ return step.name !== void 0 && /* @__PURE__ */ jsx8("b", { ...props, "data-recipe-name": "", ref, children: step.name });
973
1008
  }
974
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
+ }
975
1016
 
976
1017
  // src/parts/step-text.tsx
977
1018
  import { jsx as jsx9 } from "react/jsx-runtime";
@@ -1004,6 +1045,9 @@ function Temperature({ segment }) {
1004
1045
  }) + (fan && labels.fan ? ` ${labels.fan}` : "");
1005
1046
  }).filter(Boolean).join(" / ") });
1006
1047
  }
1048
+ if (process.env.NODE_ENV !== "production") {
1049
+ setDisplayName(StepText, "Recipe.StepText");
1050
+ }
1007
1051
 
1008
1052
  // src/parts/system-toggle.tsx
1009
1053
  import {
@@ -1129,6 +1173,10 @@ function moveOnArrowKey(event) {
1129
1173
  if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) {
1130
1174
  return;
1131
1175
  }
1176
+ const group = event.currentTarget.closest("[data-recipe-system-toggle]");
1177
+ if (group === null) {
1178
+ return;
1179
+ }
1132
1180
  const { key } = event;
1133
1181
  let step;
1134
1182
  if (key === "ArrowDown") {
@@ -1136,17 +1184,16 @@ function moveOnArrowKey(event) {
1136
1184
  } else if (key === "ArrowUp") {
1137
1185
  step = -1;
1138
1186
  } else if (key === "ArrowRight") {
1139
- step = isRtl(event.currentTarget) ? -1 : 1;
1187
+ step = isRtl(group) ? -1 : 1;
1140
1188
  } else if (key === "ArrowLeft") {
1141
- step = isRtl(event.currentTarget) ? 1 : -1;
1189
+ step = isRtl(group) ? 1 : -1;
1142
1190
  } else {
1143
1191
  return;
1144
1192
  }
1145
- const group = event.currentTarget.closest("[data-recipe-system-toggle]");
1146
1193
  const options = Array.from(
1147
- group?.querySelectorAll(
1194
+ group.querySelectorAll(
1148
1195
  "[data-recipe-system-option]:not([data-disabled])"
1149
- ) ?? []
1196
+ )
1150
1197
  );
1151
1198
  const index = options.indexOf(event.currentTarget);
1152
1199
  if (index === -1) {
@@ -1158,7 +1205,11 @@ function moveOnArrowKey(event) {
1158
1205
  next?.click();
1159
1206
  }
1160
1207
  function isRtl(element) {
1161
- return element.closest("[dir]")?.getAttribute("dir")?.toLowerCase() === "rtl";
1208
+ return getComputedStyle(element).direction === "rtl";
1209
+ }
1210
+ if (process.env.NODE_ENV !== "production") {
1211
+ setDisplayName(SystemToggle, "Recipe.SystemToggle");
1212
+ setDisplayName(SystemOption, "Recipe.SystemOption");
1162
1213
  }
1163
1214
  export {
1164
1215
  Image,