@terrafirmagreg-team/recipe 0.1.0 → 1.2.0

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 (240) hide show
  1. package/package.json +16 -16
  2. package/src/components/button-copy.tsx +1 -0
  3. package/src/components/cards/card/index.tsx +5 -3
  4. package/src/components/cards/card/scene.tsx +4 -2
  5. package/src/components/cards/card/strip.tsx +4 -2
  6. package/src/components/cards/card/text.tsx +2 -1
  7. package/src/components/cards/card/tips.tsx +1 -0
  8. package/src/components/cards/default-item.tsx +6 -2
  9. package/src/components/cards/glare-filter.tsx +1 -0
  10. package/src/components/cards/paged-card.tsx +1 -0
  11. package/src/components/cards/slot-hitbox.tsx +4 -2
  12. package/src/components/cards/strip-card/buttons.tsx +7 -2
  13. package/src/components/cards/strip-card/index.tsx +3 -1
  14. package/src/components/cards/strip-card/member-cell.tsx +4 -2
  15. package/src/components/cards/strip-card/sprite.tsx +1 -0
  16. package/src/components/embed-card.tsx +44 -0
  17. package/src/components/mdx/recipe.tsx +34 -16
  18. package/src/components/tool-list.tsx +1 -0
  19. package/src/{lib/tree.ts → components/tree.tsx} +20 -12
  20. package/src/components/views/alloy/index.tsx +14 -7
  21. package/src/components/views/alloy/list.tsx +3 -2
  22. package/src/components/views/alloy/mix/index.tsx +1 -0
  23. package/src/components/views/alloy/mix/ratio.tsx +7 -6
  24. package/src/components/views/alloy/mix/rows.tsx +6 -7
  25. package/src/components/views/alloy/mix/status.tsx +8 -7
  26. package/src/components/views/alloy/mix/total.tsx +13 -12
  27. package/src/components/views/alloy/range-bar.tsx +2 -1
  28. package/src/components/views/alloy/stack-bar.tsx +4 -2
  29. package/src/components/views/browser/axis-switcher.tsx +13 -12
  30. package/src/components/views/browser/card-grid.tsx +2 -1
  31. package/src/components/views/browser/favorite-button.tsx +2 -1
  32. package/src/components/views/browser/frame.tsx +3 -2
  33. package/src/components/views/browser/index.tsx +20 -2
  34. package/src/components/views/browser/item-panel/index.tsx +11 -9
  35. package/src/components/views/browser/item-panel/skeleton.tsx +1 -0
  36. package/src/components/views/browser/item-panel-grid/cell.tsx +5 -3
  37. package/src/components/views/browser/item-panel-grid/favorite-cell.tsx +4 -2
  38. package/src/components/views/browser/item-panel-grid/index.tsx +4 -2
  39. package/src/components/views/browser/item-view/index.tsx +7 -12
  40. package/src/components/views/browser/item-view/tags.tsx +7 -5
  41. package/src/components/views/browser/item-view-header.tsx +10 -9
  42. package/src/components/views/browser/pane-tabs.tsx +1 -0
  43. package/src/components/views/browser/place-header.tsx +4 -3
  44. package/src/components/views/browser/query-controls.tsx +3 -1
  45. package/src/components/views/browser/recipe-item-header.tsx +5 -4
  46. package/src/components/views/browser/settings.tsx +4 -3
  47. package/src/components/views/browser/toolbar.tsx +3 -2
  48. package/src/components/views/browser/type-tabs.tsx +5 -3
  49. package/src/components/views/browser/type-view.tsx +7 -12
  50. package/src/components/views/browser/workstation-rail.tsx +4 -3
  51. package/src/components/views/calc/calculator/actions.tsx +4 -14
  52. package/src/components/views/calc/calculator/help.tsx +69 -28
  53. package/src/components/views/calc/calculator/index.tsx +34 -82
  54. package/src/components/views/calc/dot-overlay.tsx +1 -0
  55. package/src/components/views/calc/edge.tsx +134 -32
  56. package/src/components/views/calc/flow/index.tsx +92 -54
  57. package/src/components/views/calc/flow/picker-dialogs.tsx +84 -6
  58. package/src/components/views/calc/flow/toolbar.tsx +9 -21
  59. package/src/components/views/calc/flow/view-menu.tsx +16 -120
  60. package/src/components/views/calc/member-picker.tsx +8 -6
  61. package/src/components/views/calc/node-card/actions.tsx +28 -106
  62. package/src/components/views/calc/node-card/badges.tsx +10 -28
  63. package/src/components/views/calc/node-card/chips.tsx +8 -40
  64. package/src/components/views/calc/node-card/far.tsx +13 -65
  65. package/src/components/views/calc/node-card/full.tsx +133 -83
  66. package/src/components/views/calc/node-card/index.tsx +1 -0
  67. package/src/components/views/calc/node-card/menu.tsx +93 -22
  68. package/src/components/views/calc/node-card/port-cells.tsx +186 -0
  69. package/src/components/views/calc/node-card/port-rails.tsx +251 -0
  70. package/src/components/views/calc/node-card/ports.tsx +86 -0
  71. package/src/components/views/calc/recipe-picker/body.tsx +17 -14
  72. package/src/components/views/calc/recipe-picker/footer.tsx +5 -3
  73. package/src/components/views/calc/recipe-picker/index.tsx +5 -0
  74. package/src/components/views/calc/sidebar.tsx +19 -10
  75. package/src/components/views/calc/trees/icon-picker.tsx +3 -2
  76. package/src/components/views/calc/trees/index.tsx +5 -4
  77. package/src/components/views/calc/trees/label.tsx +6 -4
  78. package/src/components/views/calc/trees/rows.tsx +6 -5
  79. package/src/components/views/forge/gui.tsx +2 -1
  80. package/src/components/views/forge/index.tsx +14 -7
  81. package/src/components/views/forge/list.tsx +3 -2
  82. package/src/components/views/forge/workbench/controls.tsx +13 -6
  83. package/src/components/views/forge/workbench/index.tsx +3 -2
  84. package/src/components/views/forge/workbench/panel.tsx +1 -0
  85. package/src/components/views/forge/workbench/ruler.tsx +5 -4
  86. package/src/components/views/forge/workbench/status.tsx +6 -5
  87. package/src/components/views/forge/workbench/tape.tsx +5 -4
  88. package/src/hooks/alloy/use-fluid-colors.ts +12 -9
  89. package/src/hooks/alloy/use-mix-state.ts +3 -2
  90. package/src/hooks/calc/flow/use-engage.ts +129 -0
  91. package/src/hooks/calc/flow/use-handlers.ts +192 -0
  92. package/src/hooks/calc/flow/use-layout.ts +105 -0
  93. package/src/hooks/calc/flow/{mount.ts → use-mount.ts} +1 -0
  94. package/src/hooks/calc/flow/{nodes.ts → use-nodes.ts} +46 -37
  95. package/src/hooks/calc/flow/use-pickers.ts +57 -0
  96. package/src/hooks/calc/flow/{viewport.ts → use-viewport.ts} +13 -26
  97. package/src/hooks/calc/flow/{window.ts → use-window.ts} +1 -0
  98. package/src/hooks/calc/use-actions.ts +208 -229
  99. package/src/hooks/calc/use-amounts.ts +23 -60
  100. package/src/hooks/calc/use-data.ts +106 -192
  101. package/src/hooks/calc/use-defaults.ts +4 -2
  102. package/src/hooks/calc/use-far-mode.ts +1 -0
  103. package/src/hooks/calc/use-focus.ts +8 -7
  104. package/src/hooks/calc/use-maps.ts +1 -0
  105. package/src/hooks/calc/use-reset.ts +1 -0
  106. package/src/hooks/calc/use-resolver.ts +32 -196
  107. package/src/hooks/calc/use-session.ts +1 -0
  108. package/src/hooks/calc/use-share.ts +5 -2
  109. package/src/hooks/calc/use-storage.ts +5 -4
  110. package/src/hooks/calc/use-tier.ts +1 -0
  111. package/src/hooks/calc/use-view-mode.ts +1 -0
  112. package/src/hooks/calc/use-worker.ts +56 -121
  113. package/src/hooks/forge/use-anvil-gui.ts +4 -2
  114. package/src/hooks/forge/use-forge-state.ts +1 -0
  115. package/src/hooks/forge/use-ruler.ts +1 -0
  116. package/src/hooks/use-add-to-calc.ts +23 -19
  117. package/src/hooks/use-categories-by-id.ts +18 -0
  118. package/src/hooks/use-favorite-hotkey.ts +1 -0
  119. package/src/hooks/use-favorites.ts +1 -0
  120. package/src/hooks/use-group-outlines.ts +1 -0
  121. package/src/hooks/use-hide-unused.ts +2 -1
  122. package/src/hooks/use-index.ts +6 -2
  123. package/src/hooks/use-item-feeds.ts +3 -1
  124. package/src/hooks/use-item-pane.ts +6 -4
  125. package/src/hooks/use-item-press.ts +27 -23
  126. package/src/hooks/use-item-tag-groups.ts +4 -2
  127. package/src/hooks/use-item-tooltips.ts +3 -1
  128. package/src/hooks/use-left-sidebar-tree.ts +11 -3
  129. package/src/hooks/use-mod-names.ts +4 -2
  130. package/src/hooks/use-mount-limit.ts +1 -0
  131. package/src/hooks/use-panel-cells.ts +3 -1
  132. package/src/hooks/use-panel-page.ts +9 -6
  133. package/src/hooks/use-panel-tabs.ts +2 -1
  134. package/src/hooks/use-query.ts +8 -6
  135. package/src/hooks/use-session.ts +6 -2
  136. package/src/hooks/use-sidebar-group.ts +3 -7
  137. package/src/hooks/use-tag-members.ts +3 -1
  138. package/src/hooks/use-tool-recipes.ts +1 -0
  139. package/src/hooks/use-type-filter.ts +1 -0
  140. package/src/lib/alloy/mix.ts +1 -0
  141. package/src/lib/alloy/parse.ts +1 -0
  142. package/src/lib/calc/defaults.ts +6 -4
  143. package/src/lib/calc/flow.ts +143 -107
  144. package/src/lib/calc/focus.ts +1 -0
  145. package/src/lib/calc/meta.ts +3 -1
  146. package/src/lib/calc/pack.ts +47 -154
  147. package/src/lib/calc/ports.ts +43 -0
  148. package/src/lib/calc/resolve.ts +6 -38
  149. package/src/lib/calc/route/buckets.ts +1 -0
  150. package/src/lib/calc/route/geometry.ts +13 -24
  151. package/src/lib/calc/route/index.ts +1 -0
  152. package/src/lib/calc/route/polyline.ts +3 -3
  153. package/src/lib/calc/route/router.ts +181 -57
  154. package/src/lib/calc/scheme.ts +226 -0
  155. package/src/lib/calc/storage/entry.ts +27 -19
  156. package/src/lib/calc/storage/index.ts +2 -0
  157. package/src/lib/calc/storage/keys.ts +4 -8
  158. package/src/lib/calc/storage/store.ts +11 -36
  159. package/src/lib/calc/tree/index.ts +2 -16
  160. package/src/lib/calc/tree/materials.ts +1 -0
  161. package/src/lib/calc/tree/recipe.ts +1 -0
  162. package/src/lib/calc/tree/share.ts +86 -149
  163. package/src/lib/calc/worker/api.ts +3 -11
  164. package/src/lib/calc/worker/fetch.ts +1 -0
  165. package/src/lib/calc/worker/flush.ts +7 -20
  166. package/src/lib/calc/worker/index.ts +1 -1
  167. package/src/lib/calc/worker/protocol.ts +16 -13
  168. package/src/lib/calc/worker/resolve.ts +32 -84
  169. package/src/lib/calc/worker/state.ts +5 -6
  170. package/src/{components/cards/card/model.ts → lib/card-model.ts} +1 -0
  171. package/src/lib/client/recipe-categories.ts +11 -93
  172. package/src/lib/client/recipe.ts +13 -11
  173. package/src/lib/client-index/catalog.ts +33 -27
  174. package/src/lib/client-index/chrome.ts +30 -30
  175. package/src/lib/client-index/index.ts +1 -0
  176. package/src/lib/client-index/registry.ts +70 -59
  177. package/src/lib/client-index/rows.ts +63 -57
  178. package/src/lib/client-index/tooltips.ts +28 -34
  179. package/src/lib/config.ts +2 -1
  180. package/src/lib/data/category/dto.ts +4 -3
  181. package/src/lib/data/category/load.ts +9 -8
  182. package/src/lib/data/category/parse.ts +4 -3
  183. package/src/lib/data/dto.ts +4 -3
  184. package/src/lib/data/grid.ts +2 -1
  185. package/src/lib/data/parse/entry.ts +3 -2
  186. package/src/lib/data/parse/index.ts +1 -0
  187. package/src/lib/data/parse/layout.ts +5 -2
  188. package/src/lib/data/parse/slots.ts +3 -2
  189. package/src/lib/data/parse/widgets.ts +3 -2
  190. package/src/lib/data/scene.ts +1 -1
  191. package/src/lib/data/slot-io.ts +1 -0
  192. package/src/lib/dump.ts +4 -3
  193. package/src/lib/embed.ts +22 -0
  194. package/src/lib/favorite-hover.ts +1 -0
  195. package/src/lib/fluid-outputs.ts +10 -12
  196. package/src/lib/forge/actions.ts +2 -1
  197. package/src/lib/forge/data.ts +2 -1
  198. package/src/lib/forge/solve.ts +1 -0
  199. package/src/lib/group.ts +1 -0
  200. package/src/lib/index-store.ts +15 -9
  201. package/src/lib/links.ts +15 -9
  202. package/src/lib/lookup.ts +10 -8
  203. package/src/lib/panel-outline.ts +1 -0
  204. package/src/lib/panel.ts +3 -2
  205. package/src/lib/preview.ts +12 -8
  206. package/src/lib/recipe-slots.ts +1 -0
  207. package/src/lib/search.ts +1 -0
  208. package/src/lib/sidebar.ts +1 -0
  209. package/src/lib/used-items.ts +1 -0
  210. package/src/locales/en_us.json +170 -226
  211. package/src/locales/ru_ru.json +170 -226
  212. package/src/locales.ts +1 -0
  213. package/src/types/alloy.ts +1 -0
  214. package/src/{hooks/calc/flow/props.ts → types/calc-flow-props.ts} +18 -14
  215. package/src/types/calc.ts +41 -44
  216. package/src/types/forge.ts +1 -0
  217. package/src/types/index.ts +4 -2
  218. package/styles/calc.css +308 -47
  219. package/src/components/cards/fit-card.tsx +0 -26
  220. package/src/components/views/calc/target.tsx +0 -271
  221. package/src/hooks/calc/flow/engage.ts +0 -89
  222. package/src/hooks/calc/flow/handlers.ts +0 -115
  223. package/src/hooks/calc/flow/layout.ts +0 -149
  224. package/src/hooks/calc/flow/pickers.ts +0 -50
  225. package/src/hooks/calc/use-calc-fill.ts +0 -91
  226. package/src/hooks/calc/use-density.ts +0 -28
  227. package/src/hooks/calc/use-derived.ts +0 -258
  228. package/src/hooks/calc/use-direction.ts +0 -23
  229. package/src/hooks/calc/use-edge-style.ts +0 -40
  230. package/src/hooks/calc/use-fill.ts +0 -213
  231. package/src/lib/alloy/alloy.test.ts +0 -186
  232. package/src/lib/calc/tree/build.ts +0 -196
  233. package/src/lib/calc/tree/context.ts +0 -42
  234. package/src/lib/calc/tree/goal.ts +0 -64
  235. package/src/lib/calc/tree/ideal.ts +0 -36
  236. package/src/lib/calc/tree/pick.ts +0 -68
  237. package/src/lib/calc/tree/tree.test.ts +0 -169
  238. package/src/lib/calc/worker/fill.ts +0 -123
  239. package/src/lib/client-index/cache.ts +0 -13
  240. package/src/lib/forge/forge.test.ts +0 -123
@@ -26,7 +26,7 @@ export function RatioPanel({
26
26
  <div className="space-y-1.5 rounded-md border border-dashed px-3 py-2 text-sm">
27
27
  <div className="flex items-center gap-2">
28
28
  <span className="text-xs text-muted-foreground">
29
- {t('recipe.alloy.ratio_ingots')}
29
+ {t('Recipe ratio in ingots', { note: 'recipe.alloy.ratio_ingots' })}
30
30
  </span>
31
31
  <span className="ms-auto flex shrink-0 items-center gap-1.5">
32
32
  {[2, 4, 8].map((mult) => {
@@ -40,7 +40,7 @@ export function RatioPanel({
40
40
  <Button
41
41
  variant="outline"
42
42
  size="xs"
43
- aria-label={`${t('recipe.alloy.hint.mult')}: ${text}`}
43
+ aria-label={`${t('Apply the recipe ratio multiplied', { note: 'recipe.alloy.hint.mult' })}: ${text}`}
44
44
  onClick={() => applyRatioMix(mult)}
45
45
  />
46
46
  }
@@ -61,9 +61,9 @@ export function RatioPanel({
61
61
  />
62
62
  }
63
63
  >
64
- {t('recipe.alloy.apply')}
64
+ {t('Apply', { note: 'recipe.alloy.apply' })}
65
65
  </TooltipTrigger>
66
- <TooltipContent>{t('recipe.alloy.hint.apply')}</TooltipContent>
66
+ <TooltipContent>{t('Fill fields with the recipe ratio in whole ingots', { note: 'recipe.alloy.hint.apply' })}</TooltipContent>
67
67
  </Tooltip>
68
68
  </span>
69
69
  </div>
@@ -84,10 +84,11 @@ export function RatioPanel({
84
84
  </span>
85
85
  ))}
86
86
  <span className="tabular-nums text-muted-foreground">
87
- → {ratioMix.total.toLocaleString()} {t('recipe.alloy.unit.ingot')} (
88
- {(ratioMix.total * INGOT_MB).toLocaleString()} {t('recipe.alloy.unit.mb')})
87
+ → {ratioMix.total.toLocaleString()} {t('ing.', { note: 'recipe.alloy.unit.ingot' })} (
88
+ {(ratioMix.total * INGOT_MB).toLocaleString()} {t('mB', { note: 'recipe.alloy.unit.mb' })})
89
89
  </span>
90
90
  </div>
91
91
  </div>
92
92
  );
93
93
  }
94
+
@@ -8,7 +8,7 @@ import { IconButton } from '@terrafirmagreg-team/ui/components/blocks/button/ico
8
8
  import { minShareMix } from '@terrafirmagreg-team/recipe/lib/alloy/mix';
9
9
  import { AlloyRangeBar } from '@terrafirmagreg-team/recipe/components/views/alloy/range-bar';
10
10
  import { Check, Minus, Plus, TrendingDown, X } from 'lucide-react';
11
- import { cn } from 'cn';
11
+ import { cn } from '@terrafirmagreg-team/ui/lib/utils/cn';
12
12
  import type { AlloyComponent } from '@terrafirmagreg-team/recipe/types/alloy';
13
13
  import type { MixState } from '@terrafirmagreg-team/recipe/hooks/alloy/use-mix-state';
14
14
 
@@ -78,7 +78,7 @@ export function MixRows({
78
78
  max={range.max}
79
79
  value={row?.percent ?? 0}
80
80
  color={colors[i]}
81
- label={`${t('recipe.alloy.range_allowed')}: ${formatPercent(
81
+ label={`${t('Allowed window', { note: 'recipe.alloy.range_allowed' })}: ${formatPercent(
82
82
  range.min,
83
83
  )}–${formatPercent(range.max)}%`}
84
84
  />
@@ -90,7 +90,7 @@ export function MixRows({
90
90
  <Button
91
91
  variant="outline"
92
92
  size="icon-xs"
93
- aria-label={`${t('recipe.alloy.step.down')} ${name(slot.id)}`}
93
+ aria-label={`${t('Remove 1', { note: 'recipe.alloy.step.down' })} ${name(slot.id)}`}
94
94
  onClick={() => stepInput(i, -1)}
95
95
  >
96
96
  <Minus />
@@ -113,7 +113,7 @@ export function MixRows({
113
113
  <Button
114
114
  variant="outline"
115
115
  size="icon-xs"
116
- aria-label={`${t('recipe.alloy.step.up')} ${name(slot.id)}`}
116
+ aria-label={`${t('Add 1', { note: 'recipe.alloy.step.up' })} ${name(slot.id)}`}
117
117
  onClick={() => stepInput(i, 1)}
118
118
  >
119
119
  <Plus />
@@ -123,9 +123,7 @@ export function MixRows({
123
123
  </span>
124
124
  {range ? (
125
125
  <IconButton
126
- label={`${t('recipe.alloy.economize')} ${name(slot.id)} — ${t(
127
- 'recipe.alloy.hint.economize',
128
- )}`}
126
+ label={`${t('Minimize', { note: 'recipe.alloy.economize' })} ${name(slot.id)}: ${t('Set this metal to the lower bound of its range; others keep the recipe ratio', { note: 'recipe.alloy.hint.economize' })}`}
129
127
  size="icon-xs"
130
128
  disabled={!econ}
131
129
  onClick={() =>
@@ -144,3 +142,4 @@ export function MixRows({
144
142
  </ul>
145
143
  );
146
144
  }
145
+
@@ -43,11 +43,11 @@ export function MixStatus({ state }: { state: MixState }) {
43
43
  className="flex flex-wrap items-center gap-3 rounded-md border bg-muted/40 px-3 py-2"
44
44
  >
45
45
  <Badge variant={mix.valid ? 'default' : 'destructive'}>
46
- {mix.valid ? t('recipe.alloy.valid') : t('recipe.alloy.invalid')}
46
+ {mix.valid ? t('Valid alloy', { note: 'recipe.alloy.valid' }) : t('Outside allowed ranges', { note: 'recipe.alloy.invalid' })}
47
47
  </Badge>
48
48
  <span className="flex flex-wrap items-baseline gap-x-3">
49
49
  <span className="text-sm text-muted-foreground tabular-nums">
50
- {t('recipe.alloy.total_in')}: {format(mix.total)} {unitLabel}
50
+ {t('Total', { note: 'recipe.alloy.total_in' })}: {format(mix.total)} {unitLabel}
51
51
  </span>
52
52
  <span className="flex items-center gap-1.5 text-sm tabular-nums font-medium">
53
53
  <span className="text-muted-foreground">→</span>
@@ -61,7 +61,7 @@ export function MixStatus({ state }: { state: MixState }) {
61
61
  tooltip={false}
62
62
  />
63
63
  ) : (
64
- t('recipe.alloy.result')
64
+ t('Alloy', { note: 'recipe.alloy.result' })
65
65
  )}
66
66
  <span className="font-normal text-muted-foreground">
67
67
  {format(mix.output)} {unitLabel}
@@ -70,7 +70,7 @@ export function MixStatus({ state }: { state: MixState }) {
70
70
  </span>
71
71
  <span className="ms-auto flex flex-wrap items-center gap-2">
72
72
  <IconButton
73
- label={`${t('recipe.alloy.fix')} — ${t('recipe.alloy.hint.fix')}`}
73
+ label={`${t('Top up to minimum', { note: 'recipe.alloy.fix' })}: ${t('Add just enough metal to bring every share into its range', { note: 'recipe.alloy.hint.fix' })}`}
74
74
  disabled={!fix || mix.valid}
75
75
  onClick={() =>
76
76
  fix &&
@@ -83,7 +83,7 @@ export function MixStatus({ state }: { state: MixState }) {
83
83
  </IconButton>
84
84
  {needsSnap ? (
85
85
  <IconButton
86
- label={`${t('recipe.alloy.snap_ingots')} — ${t('recipe.alloy.hint.snap')}`}
86
+ label={`${t('Snap to whole ingots', { note: 'recipe.alloy.snap_ingots' })}: ${t('Round each metal to whole ingots, staying inside the ranges', { note: 'recipe.alloy.hint.snap' })}`}
87
87
  disabled={!snapped}
88
88
  onClick={() =>
89
89
  snapped && setInputs(snapped.map((value) => trim(value / factor)))
@@ -95,7 +95,7 @@ export function MixStatus({ state }: { state: MixState }) {
95
95
  <span className="size-7 shrink-0" aria-hidden />
96
96
  )}
97
97
  <IconButton
98
- label={`${t('recipe.alloy.reset')} — ${t('recipe.alloy.hint.reset')}`}
98
+ label={`${t('Reset to recipe ratio', { note: 'recipe.alloy.reset' })}: ${t('Restore the recipe-ratio mix', { note: 'recipe.alloy.hint.reset' })}`}
99
99
  onClick={() =>
100
100
  fill(
101
101
  Number.isFinite(totalNumber)
@@ -108,7 +108,7 @@ export function MixStatus({ state }: { state: MixState }) {
108
108
  >
109
109
  <RotateCcw className="size-3.5" />
110
110
  </IconButton>
111
- <IconButton label={t('recipe.alloy.copy_mix')} onClick={onCopy}>
111
+ <IconButton label={t('Copy the mix as text', { note: 'recipe.alloy.copy_mix' })} onClick={onCopy}>
112
112
  {copied ? (
113
113
  <Check className="size-3.5 text-green-600 dark:text-green-400" />
114
114
  ) : (
@@ -119,3 +119,4 @@ export function MixStatus({ state }: { state: MixState }) {
119
119
  </div>
120
120
  );
121
121
  }
122
+
@@ -45,12 +45,12 @@ export function MixTotal({
45
45
  <div className="flex flex-wrap items-end gap-2">
46
46
  <label className="flex w-44 flex-col gap-1 text-xs text-muted-foreground">
47
47
  <span className="flex items-baseline justify-between gap-2">
48
- {t('recipe.alloy.total')}
48
+ {t('Target total', { note: 'recipe.alloy.total' })}
49
49
  {unit === 'ingot' ? (
50
50
  <span className="tabular-nums text-muted-foreground/70">
51
51
  {Number.isFinite(totalNumber)
52
- ? `= ${format(totalNumber * INGOT_MB)} ${t('recipe.alloy.unit.mb')}`
53
- : `×${INGOT_MB} ${t('recipe.alloy.unit.mb')}`}
52
+ ? `= ${format(totalNumber * INGOT_MB)} ${t('mB', { note: 'recipe.alloy.unit.mb' })}`
53
+ : `×${INGOT_MB} ${t('mB', { note: 'recipe.alloy.unit.mb' })}`}
54
54
  </span>
55
55
  ) : null}
56
56
  </span>
@@ -69,11 +69,11 @@ export function MixTotal({
69
69
  />
70
70
  }
71
71
  />
72
- <TooltipContent>{t('recipe.alloy.hint.scale')}</TooltipContent>
72
+ <TooltipContent>{t('Scales the current mix to this total as you type', { note: 'recipe.alloy.hint.scale' })}</TooltipContent>
73
73
  </Tooltip>
74
74
  {totalInvalid ? (
75
75
  <span className="text-[11px] text-destructive">
76
- {t('recipe.alloy.invalid_total')}
76
+ {t('Enter a positive total amount.', { note: 'recipe.alloy.invalid_total' })}
77
77
  </span>
78
78
  ) : null}
79
79
  </label>
@@ -86,23 +86,23 @@ export function MixTotal({
86
86
  variant="outline"
87
87
  size="sm"
88
88
  spacing={0}
89
- aria-label={t('recipe.alloy.units')}
89
+ aria-label={t('units', { note: 'recipe.alloy.units' })}
90
90
  >
91
91
  <Tooltip>
92
92
  <TooltipTrigger render={<ToggleGroupItem value="mb" />}>
93
- {t('recipe.alloy.unit.mb')}
93
+ {t('mB', { note: 'recipe.alloy.unit.mb' })}
94
94
  </TooltipTrigger>
95
- <TooltipContent>{t('recipe.alloy.hint.mb')}</TooltipContent>
95
+ <TooltipContent>{t('Millibuckets (mB)', { note: 'recipe.alloy.hint.mb' })}</TooltipContent>
96
96
  </Tooltip>
97
97
  <Tooltip>
98
98
  <TooltipTrigger render={<ToggleGroupItem value="ingot" />}>
99
- {t('recipe.alloy.unit.ingot')}
99
+ {t('ing.', { note: 'recipe.alloy.unit.ingot' })}
100
100
  </TooltipTrigger>
101
- <TooltipContent>{t('recipe.alloy.hint.ingot')}</TooltipContent>
101
+ <TooltipContent>{t('Ingots: 1 ingot = 144 mB', { note: 'recipe.alloy.hint.ingot' })}</TooltipContent>
102
102
  </Tooltip>
103
103
  </ToggleGroup>
104
104
  <IconButton
105
- label={`${t('recipe.alloy.fill')} — ${t('recipe.alloy.hint.fill')}`}
105
+ label={`${t('Fill by recipe', { note: 'recipe.alloy.fill' })}: ${t('Split the target total between metals by the recipe ratio', { note: 'recipe.alloy.hint.fill' })}`}
106
106
  disabled={!suggestAmounts(components, totalNumber)}
107
107
  onClick={() => fill(totalNumber)}
108
108
  >
@@ -111,7 +111,7 @@ export function MixTotal({
111
111
  </div>
112
112
  <div
113
113
  role="group"
114
- aria-label={t('recipe.alloy.presets')}
114
+ aria-label={t('Quick totals', { note: 'recipe.alloy.presets' })}
115
115
  className="flex flex-wrap gap-1.5"
116
116
  >
117
117
  {presets.map((value) => (
@@ -129,3 +129,4 @@ export function MixTotal({
129
129
  </>
130
130
  );
131
131
  }
132
+
@@ -5,7 +5,7 @@ import {
5
5
  TooltipContent,
6
6
  TooltipTrigger,
7
7
  } from '@terrafirmagreg-team/ui/components/ui/tooltip';
8
- import { cn } from 'cn';
8
+ import { cn } from '@terrafirmagreg-team/ui/lib/utils/cn';
9
9
 
10
10
  export function AlloyRangeBar({
11
11
  min,
@@ -62,3 +62,4 @@ export function AlloyRangeBar({
62
62
  </Tooltip>
63
63
  );
64
64
  }
65
+
@@ -1,7 +1,8 @@
1
1
  'use client';
2
+ import type { DatasetRef } from '@terrafirmagreg-team/sites/location';
2
3
 
3
4
  import { useMemo } from 'react';
4
- import { cn } from 'cn';
5
+ import { cn } from '@terrafirmagreg-team/ui/lib/utils/cn';
5
6
  import { useFluidColors } from '@terrafirmagreg-team/recipe/hooks/alloy/use-fluid-colors';
6
7
  import type { AlloyComponent, AlloyMixRow } from '@terrafirmagreg-team/recipe/types/alloy';
7
8
 
@@ -63,7 +64,7 @@ export function AlloyMiniBar({
63
64
  components,
64
65
  className,
65
66
  }: {
66
- dataset: string;
67
+ dataset: DatasetRef;
67
68
  components: readonly AlloyComponent[];
68
69
  className?: string;
69
70
  }) {
@@ -84,3 +85,4 @@ export function AlloyMiniBar({
84
85
  />
85
86
  );
86
87
  }
88
+
@@ -4,50 +4,51 @@ import { usePathname } from 'next/navigation';
4
4
  import { Anvil, Calculator, FlaskConical, Shapes } from 'lucide-react';
5
5
  import { useTranslations } from '@terrafirmagreg-team/translate/hooks/use-translations';
6
6
  import { useResolvedLang } from '@terrafirmagreg-team/translate/hooks/use-resolved-lang';
7
- import { useLocationSearch } from '@terrafirmagreg-team/ui/hooks/page/use-location-search';
7
+ import { useLocationSearchParams } from '@terrafirmagreg-team/ui/hooks/page/use-location-search';
8
8
  import { recipePlaceFromParams } from '@terrafirmagreg-team/recipe/lib/links';
9
9
  import { recipeCalcHref, recipeHref } from '@terrafirmagreg-team/recipe/lib/links';
10
- import { parseSectionLocation } from '@terrafirmagreg-team/kit/lib/location';
10
+ import { parseSectionLocation } from '@terrafirmagreg-team/sites/location';
11
11
  import { Switcher } from '@terrafirmagreg-team/ui/components/blocks/nav/switcher';
12
12
 
13
13
  export function RecipeAxisSwitcher() {
14
14
  const t = useTranslations();
15
- const { dataset } = parseSectionLocation(usePathname());
15
+ const { dataset: datasetId } = parseSectionLocation(usePathname());
16
16
  const lang = useResolvedLang();
17
- const axis = recipePlaceFromParams(
18
- new URLSearchParams(useLocationSearch()),
19
- ).kind;
20
- if (!dataset) return null;
17
+ const params = useLocationSearchParams();
18
+ const axis = recipePlaceFromParams(params).kind;
19
+ const dataset = { id: datasetId ?? '', version: params.get('version') ?? undefined };
20
+ if (!datasetId) return null;
21
21
  return (
22
22
  <Switcher
23
23
  options={[
24
24
  {
25
25
  value: 'type',
26
- title: t('recipe.axis_type'),
26
+ title: t('Categories', { note: 'recipe.axis_type' }),
27
27
  icon: <Shapes className="size-4" />,
28
28
  url: recipeHref(dataset, lang),
29
29
  },
30
30
  {
31
31
  value: 'calc',
32
- title: t('recipe.calculator'),
32
+ title: t('Calculator', { note: 'recipe.calculator' }),
33
33
  icon: <Calculator className="size-4" />,
34
34
  url: recipeCalcHref(dataset, lang),
35
35
  },
36
36
  {
37
37
  value: 'forge',
38
- title: t('recipe.forge.title'),
38
+ title: t('Forging', { note: 'recipe.forge.title' }),
39
39
  icon: <Anvil className="size-4" />,
40
40
  url: recipeHref(dataset, lang, { tool: 'forge' }),
41
41
  },
42
42
  {
43
43
  value: 'alloy',
44
- title: t('recipe.alloy.title'),
44
+ title: t('Alloys', { note: 'recipe.alloy.title' }),
45
45
  icon: <FlaskConical className="size-4" />,
46
46
  url: recipeHref(dataset, lang, { tool: 'alloy' }),
47
47
  },
48
48
  ]}
49
49
  selected={axis ?? 'type'}
50
- placeholder={t('recipe.axis_type')}
50
+ placeholder={t('Categories', { note: 'recipe.axis_type' })}
51
51
  />
52
52
  );
53
53
  }
54
+
@@ -173,7 +173,7 @@ function RecipeGridCard({
173
173
  onFail={() => setFailed(true)}
174
174
  />
175
175
  ) : (
176
- <EmptyState variant="empty">{t('recipe.no_image')}</EmptyState>
176
+ <EmptyState variant="empty">{t('No recipe image in dump.', { note: 'recipe.no_image' })}</EmptyState>
177
177
  )
178
178
  ) : src && !failed ? (
179
179
  // eslint-disable-next-line @next/next/no-img-element -- dump asset
@@ -272,3 +272,4 @@ export function RecipeCardGrid({
272
272
  </div>
273
273
  );
274
274
  }
275
+
@@ -22,7 +22,7 @@ export function FavoriteButton({
22
22
  const t = useTranslations();
23
23
  const text =
24
24
  label ??
25
- (active ? t('recipe.remove_favorite') : t('recipe.add_favorite'));
25
+ (active ? t('Remove from favorites', { note: 'recipe.remove_favorite' }) : t('Add to favorites', { note: 'recipe.add_favorite' }));
26
26
  return (
27
27
  <Hint label={text}>
28
28
  <Toggle
@@ -43,3 +43,4 @@ export function FavoriteButton({
43
43
  </Hint>
44
44
  );
45
45
  }
46
+
@@ -81,7 +81,7 @@ export function RecipeFrame({
81
81
  pages={list.pages}
82
82
  to={list.to}
83
83
  total={list.total}
84
- label={t('recipe.page_of')}
84
+ label={t('{page}/{pages}', { note: 'recipe.page_of' })}
85
85
  className="pt-2"
86
86
  onPage={onPageChange}
87
87
  />
@@ -92,7 +92,7 @@ export function RecipeFrame({
92
92
  params={{ ...session.nav, id: undefined }}
93
93
  query={session.query}
94
94
  list={list}
95
- label={t('recipe.page_of')}
95
+ label={t('{page}/{pages}', { note: 'recipe.page_of' })}
96
96
  className="pt-2"
97
97
  />
98
98
  )
@@ -109,3 +109,4 @@ export function RecipeFrame({
109
109
  </div>
110
110
  );
111
111
  }
112
+
@@ -18,11 +18,28 @@ import { ItemRow } from '@terrafirmagreg-team/ui/components/blocks/list/row';
18
18
  import { Skeleton } from '@terrafirmagreg-team/ui/components/ui/skeleton';
19
19
  import { EntryProvider } from '@terrafirmagreg-team/game/hooks/use-entry-context';
20
20
  import { cn } from '@terrafirmagreg-team/ui/lib/utils/cn';
21
+ import type { Lang } from '@terrafirmagreg-team/translate/types/locale';
21
22
  import type { RecipePageData } from '@terrafirmagreg-team/recipe/types';
22
23
 
23
- export function RecipeBrowser({ page }: { page: RecipePageData }) {
24
+ export function RecipeBrowser({
25
+ dataset: id,
26
+ datasetTitle,
27
+ lang,
28
+ versions,
29
+ }: {
30
+ dataset: string;
31
+ datasetTitle: string;
32
+ lang: Lang;
33
+ versions?: readonly string[];
34
+ }) {
35
+ const page: RecipePageData = {
36
+ title: datasetTitle,
37
+ dataset: { id },
38
+ lang,
39
+ versions: versions as string[] | undefined,
40
+ };
24
41
  const session = useRecipeSession(page);
25
- const { dataset, lang, item, fluid, names } = session;
42
+ const { dataset, item, fluid, names } = session;
26
43
  const focusId = item ?? fluid;
27
44
 
28
45
  const focusTitle = focusId
@@ -94,3 +111,4 @@ export function RecipeBrowser({ page }: { page: RecipePageData }) {
94
111
  </EntryProvider>
95
112
  );
96
113
  }
114
+
@@ -1,4 +1,5 @@
1
1
  'use client';
2
+ import type { DatasetRef } from '@terrafirmagreg-team/sites/location';
2
3
 
3
4
  import {
4
5
  memo,
@@ -19,7 +20,7 @@ import { type ItemPanelMode } from '@terrafirmagreg-team/recipe/lib/panel';
19
20
  import { recipeHref } from '@terrafirmagreg-team/recipe/lib/links';
20
21
  import { replaceUrlState } from '@terrafirmagreg-team/ui/lib/utils/history';
21
22
  import { favoriteHover } from '@terrafirmagreg-team/recipe/lib/favorite-hover';
22
- import { IconTabs } from '@terrafirmagreg-team/game/components/entry/icon/tabs';
23
+ import { IconPager } from '@terrafirmagreg-team/ui/components/blocks/page/pager';
23
24
  import { FavoriteButton } from '@terrafirmagreg-team/recipe/components/views/browser/favorite-button';
24
25
  import { ItemPanelGrid } from '@terrafirmagreg-team/recipe/components/views/browser/item-panel-grid';
25
26
  import { RecipeSettings } from '@terrafirmagreg-team/recipe/components/views/browser/settings';
@@ -53,7 +54,7 @@ export const ItemPanel = memo(function ItemPanel({
53
54
  nav,
54
55
  className,
55
56
  }: {
56
- dataset: string;
57
+ dataset: DatasetRef;
57
58
  lang: Lang;
58
59
  index: RecipeCompactIndex | null;
59
60
  indexLoading: boolean;
@@ -141,10 +142,10 @@ export const ItemPanel = memo(function ItemPanel({
141
142
  body = (
142
143
  <EmptyState variant="empty">
143
144
  {mode === 'fav'
144
- ? t('recipe.favorites_empty')
145
+ ? t('No favorites yet.', { note: 'recipe.favorites_empty' })
145
146
  : hideUnused && !query.trim()
146
- ? t('recipe.hide_unused_empty')
147
- : t('recipe.empty_items')}
147
+ ? t('No items match with Hide unused enabled. Turn it off to browse the full catalog.', { note: 'recipe.hide_unused_empty' })
148
+ : t('No matching items.', { note: 'recipe.empty_items' })}
148
149
  </EmptyState>
149
150
  );
150
151
  } else {
@@ -171,7 +172,7 @@ export const ItemPanel = memo(function ItemPanel({
171
172
 
172
173
  return (
173
174
  <div className={cn('not-prose flex min-h-0 flex-col gap-2', className)}>
174
- <IconTabs
175
+ <IconPager
175
176
  value={mode === 'fav' ? 'fav' : (tab ?? '')}
176
177
  options={tabOptions}
177
178
  onChange={(id) => {
@@ -184,13 +185,13 @@ export const ItemPanel = memo(function ItemPanel({
184
185
  pages={list.pages}
185
186
  to={list.to}
186
187
  total={list.total}
187
- label={t('recipe.page_of')}
188
+ label={t('{page}/{pages}', { note: 'recipe.page_of' })}
188
189
  onPage={setPanelPage}
189
190
  leading={
190
191
  <FavoriteButton
191
192
  variant="outline"
192
193
  active={mode === 'fav'}
193
- label={t('recipe.favorites')}
194
+ label={t('Favorites', { note: 'recipe.favorites' })}
194
195
  onToggle={() => {
195
196
  setPanelPage(0);
196
197
  setMode(mode === 'fav' ? 'all' : 'fav');
@@ -218,10 +219,11 @@ export const ItemPanel = memo(function ItemPanel({
218
219
  setPanelPage(0);
219
220
  setQuery(next);
220
221
  }}
221
- placeholder={t('recipe.search')}
222
+ placeholder={t('Search items', { note: 'recipe.search' })}
222
223
  className="w-full"
223
224
  />
224
225
  </div>
225
226
  </div>
226
227
  );
227
228
  });
229
+
@@ -23,3 +23,4 @@ export function PanelSkeleton({ cols, rows }: { cols: number; rows: number }) {
23
23
  </ul>
24
24
  );
25
25
  }
26
+
@@ -1,12 +1,13 @@
1
1
  'use client';
2
+ import type { DatasetRef } from '@terrafirmagreg-team/sites/location';
2
3
 
3
4
  import type { ReactNode } from 'react';
4
5
  import { Minus, Plus, Star } from 'lucide-react';
5
6
  import { Entry } from '@terrafirmagreg-team/game/components/entry/entry';
6
7
  import { EntryGroup } from '@terrafirmagreg-team/game/components/entry/group';
7
8
  import { CopyIdMenu } from '@terrafirmagreg-team/game/components/entry/copy-id-menu';
8
- import { parseStackId } from '@terrafirmagreg-team/game/lib/dump/contract/ref';
9
- import { formatNbt } from '@terrafirmagreg-team/game/lib/snbt';
9
+ import { parseStackId } from '@terrafirmagreg-team/dump/lib/dump/contract/ref';
10
+ import { formatNbt } from '@terrafirmagreg-team/dump/lib/snbt';
10
11
  import { recipeItemName } from '@terrafirmagreg-team/recipe/lib/client-index';
11
12
  import { Badge } from '@terrafirmagreg-team/ui/components/ui/badge';
12
13
  import { Hint } from '@terrafirmagreg-team/ui/components/blocks/tooltip/hint';
@@ -72,7 +73,7 @@ export function PanelCell({
72
73
  onToggleGroup,
73
74
  }: {
74
75
  cell: ItemPanelCell;
75
- dataset: string;
76
+ dataset: DatasetRef;
76
77
  lang: Lang;
77
78
  names: Record<string, Record<string, string>>;
78
79
  nav: RecipeHrefOpts;
@@ -174,3 +175,4 @@ export function PanelCell({
174
175
  </li>
175
176
  );
176
177
  }
178
+
@@ -1,4 +1,5 @@
1
1
  'use client';
2
+ import type { DatasetRef } from '@terrafirmagreg-team/sites/location';
2
3
 
3
4
  import Link from 'next/link';
4
5
  import { Entry } from '@terrafirmagreg-team/game/components/entry/entry';
@@ -16,7 +17,7 @@ import {
16
17
  } from '@terrafirmagreg-team/ui/components/ui/tooltip';
17
18
  import { Badge } from '@terrafirmagreg-team/ui/components/ui/badge';
18
19
  import type { Lang } from '@terrafirmagreg-team/translate/types/locale';
19
- import type { ReferenceKind } from '@terrafirmagreg-team/game/lib/dump/contract/ref';
20
+ import type { ReferenceKind } from '@terrafirmagreg-team/dump/lib/dump/contract/ref';
20
21
  import type { RecipeFavorite, RecipeHrefOpts } from '@terrafirmagreg-team/recipe/types';
21
22
 
22
23
  const TAG_SEGMENT_KIND: Record<string, ReferenceKind> = {
@@ -40,7 +41,7 @@ export function RecipeFavoriteCell({
40
41
  nav,
41
42
  fav,
42
43
  }: {
43
- dataset: string;
44
+ dataset: DatasetRef;
44
45
  lang: Lang;
45
46
  names: Record<string, Record<string, string>>;
46
47
  nav: RecipeHrefOpts;
@@ -125,3 +126,4 @@ export function RecipeFavoriteCell({
125
126
  </Tooltip>
126
127
  );
127
128
  }
129
+
@@ -1,4 +1,5 @@
1
1
  'use client';
2
+ import type { DatasetRef } from '@terrafirmagreg-team/sites/location';
2
3
 
3
4
  import { memo } from 'react';
4
5
  import { useTranslations } from '@terrafirmagreg-team/translate/hooks/use-translations';
@@ -30,7 +31,7 @@ export const ItemPanelGrid = memo(function ItemPanelGrid({
30
31
  cells: ItemPanelCell[];
31
32
 
32
33
  resetKey: unknown;
33
- dataset: string;
34
+ dataset: DatasetRef;
34
35
  lang: Lang;
35
36
  names: Record<string, Record<string, string>>;
36
37
  nav: RecipeHrefOpts;
@@ -43,7 +44,7 @@ export const ItemPanelGrid = memo(function ItemPanelGrid({
43
44
  draggableStacks?: boolean;
44
45
  }) {
45
46
  const t = useTranslations();
46
- const expandLabel = t('recipe.expand');
47
+ const expandLabel = t('Expand', { note: 'recipe.expand' });
47
48
  const limit = useMountLimit(cells.length, resetKey);
48
49
  const shown = limit >= cells.length ? cells : cells.slice(0, limit);
49
50
  const { gridRef, outlines } = useGroupOutlines(shown, cols, rows);
@@ -101,3 +102,4 @@ export const ItemPanelGrid = memo(function ItemPanelGrid({
101
102
  </ul>
102
103
  );
103
104
  });
105
+
@@ -12,6 +12,7 @@ import { RecipeTypeTabs } from '@terrafirmagreg-team/recipe/components/views/bro
12
12
  import { WorkstationRail } from '@terrafirmagreg-team/recipe/components/views/browser/workstation-rail';
13
13
  import { PaneTabs } from '@terrafirmagreg-team/recipe/components/views/browser/pane-tabs';
14
14
  import { useFitPages } from '@terrafirmagreg-team/ui/hooks/page/use-fit-pages';
15
+ import { useCategoriesById } from '@terrafirmagreg-team/recipe/hooks/use-categories-by-id';
15
16
  import { useTypeFilter } from '@terrafirmagreg-team/recipe/hooks/use-type-filter';
16
17
  import { useFavorites } from '@terrafirmagreg-team/recipe/hooks/use-favorites';
17
18
  import { recipeItemName } from '@terrafirmagreg-team/recipe/lib/client-index';
@@ -24,12 +25,11 @@ import { ItemTagGroups } from '@terrafirmagreg-team/recipe/components/views/brow
24
25
  import { useItemPane } from '@terrafirmagreg-team/recipe/hooks/use-item-pane';
25
26
  import { useAddToCalc } from '@terrafirmagreg-team/recipe/hooks/use-add-to-calc';
26
27
  import { recipeHref } from '@terrafirmagreg-team/recipe/lib/links';
27
- import { parseStackId, stackIdFromRef } from '@terrafirmagreg-team/game/lib/dump/contract/ref';
28
- import type { TaggedReference } from '@terrafirmagreg-team/game/lib/dump/contract/ref';
29
- import { customStackName } from '@terrafirmagreg-team/game/lib/dump/assets/lang/names';
28
+ import { parseStackId, stackIdFromRef } from '@terrafirmagreg-team/dump/lib/dump/contract/ref';
29
+ import type { TaggedReference } from '@terrafirmagreg-team/dump/lib/dump/contract/ref';
30
+ import { customStackName } from '@terrafirmagreg-team/dump/lib/dump/assets/lang/names';
30
31
  import { replaceUrlState } from '@terrafirmagreg-team/ui/lib/utils/history';
31
32
  import type {
32
- RecipeCategory,
33
33
  RecipeSession,
34
34
  } from '@terrafirmagreg-team/recipe/types';
35
35
 
@@ -56,13 +56,7 @@ export function ItemView({ session }: { session: RecipeSession }) {
56
56
 
57
57
  const boxRef = useRef<HTMLDivElement | null>(null);
58
58
 
59
- const categoriesById = useMemo(
60
- () =>
61
- new Map<string, RecipeCategory>(
62
- (index?.categories ?? []).map((row) => [row.id, row]),
63
- ),
64
- [index],
65
- );
59
+ const categoriesById = useCategoriesById(index);
66
60
 
67
61
  const feeds = useItemFeeds({ dataset, index, indexLoading, item, kind });
68
62
  const { recipes, uses } = feeds;
@@ -182,10 +176,11 @@ export function ItemView({ session }: { session: RecipeSession }) {
182
176
  maxH={list.box.h}
183
177
  maxW={list.box.w}
184
178
  loading={feeds.pending}
185
- empty={t('recipe.empty_type')}
179
+ empty={t('No recipes of this type.', { note: 'recipe.empty_type' })}
186
180
  onSwipe={onSwipe}
187
181
  />
188
182
  )}
189
183
  </RecipeFrame>
190
184
  );
191
185
  }
186
+