@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.
- package/package.json +16 -16
- package/src/components/button-copy.tsx +1 -0
- package/src/components/cards/card/index.tsx +5 -3
- package/src/components/cards/card/scene.tsx +4 -2
- package/src/components/cards/card/strip.tsx +4 -2
- package/src/components/cards/card/text.tsx +2 -1
- package/src/components/cards/card/tips.tsx +1 -0
- package/src/components/cards/default-item.tsx +6 -2
- package/src/components/cards/glare-filter.tsx +1 -0
- package/src/components/cards/paged-card.tsx +1 -0
- package/src/components/cards/slot-hitbox.tsx +4 -2
- package/src/components/cards/strip-card/buttons.tsx +7 -2
- package/src/components/cards/strip-card/index.tsx +3 -1
- package/src/components/cards/strip-card/member-cell.tsx +4 -2
- package/src/components/cards/strip-card/sprite.tsx +1 -0
- package/src/components/embed-card.tsx +44 -0
- package/src/components/mdx/recipe.tsx +34 -16
- package/src/components/tool-list.tsx +1 -0
- package/src/{lib/tree.ts → components/tree.tsx} +20 -12
- package/src/components/views/alloy/index.tsx +14 -7
- package/src/components/views/alloy/list.tsx +3 -2
- package/src/components/views/alloy/mix/index.tsx +1 -0
- package/src/components/views/alloy/mix/ratio.tsx +7 -6
- package/src/components/views/alloy/mix/rows.tsx +6 -7
- package/src/components/views/alloy/mix/status.tsx +8 -7
- package/src/components/views/alloy/mix/total.tsx +13 -12
- package/src/components/views/alloy/range-bar.tsx +2 -1
- package/src/components/views/alloy/stack-bar.tsx +4 -2
- package/src/components/views/browser/axis-switcher.tsx +13 -12
- package/src/components/views/browser/card-grid.tsx +2 -1
- package/src/components/views/browser/favorite-button.tsx +2 -1
- package/src/components/views/browser/frame.tsx +3 -2
- package/src/components/views/browser/index.tsx +20 -2
- package/src/components/views/browser/item-panel/index.tsx +11 -9
- package/src/components/views/browser/item-panel/skeleton.tsx +1 -0
- package/src/components/views/browser/item-panel-grid/cell.tsx +5 -3
- package/src/components/views/browser/item-panel-grid/favorite-cell.tsx +4 -2
- package/src/components/views/browser/item-panel-grid/index.tsx +4 -2
- package/src/components/views/browser/item-view/index.tsx +7 -12
- package/src/components/views/browser/item-view/tags.tsx +7 -5
- package/src/components/views/browser/item-view-header.tsx +10 -9
- package/src/components/views/browser/pane-tabs.tsx +1 -0
- package/src/components/views/browser/place-header.tsx +4 -3
- package/src/components/views/browser/query-controls.tsx +3 -1
- package/src/components/views/browser/recipe-item-header.tsx +5 -4
- package/src/components/views/browser/settings.tsx +4 -3
- package/src/components/views/browser/toolbar.tsx +3 -2
- package/src/components/views/browser/type-tabs.tsx +5 -3
- package/src/components/views/browser/type-view.tsx +7 -12
- package/src/components/views/browser/workstation-rail.tsx +4 -3
- package/src/components/views/calc/calculator/actions.tsx +4 -14
- package/src/components/views/calc/calculator/help.tsx +69 -28
- package/src/components/views/calc/calculator/index.tsx +34 -82
- package/src/components/views/calc/dot-overlay.tsx +1 -0
- package/src/components/views/calc/edge.tsx +134 -32
- package/src/components/views/calc/flow/index.tsx +92 -54
- package/src/components/views/calc/flow/picker-dialogs.tsx +84 -6
- package/src/components/views/calc/flow/toolbar.tsx +9 -21
- package/src/components/views/calc/flow/view-menu.tsx +16 -120
- package/src/components/views/calc/member-picker.tsx +8 -6
- package/src/components/views/calc/node-card/actions.tsx +28 -106
- package/src/components/views/calc/node-card/badges.tsx +10 -28
- package/src/components/views/calc/node-card/chips.tsx +8 -40
- package/src/components/views/calc/node-card/far.tsx +13 -65
- package/src/components/views/calc/node-card/full.tsx +133 -83
- package/src/components/views/calc/node-card/index.tsx +1 -0
- package/src/components/views/calc/node-card/menu.tsx +93 -22
- package/src/components/views/calc/node-card/port-cells.tsx +186 -0
- package/src/components/views/calc/node-card/port-rails.tsx +251 -0
- package/src/components/views/calc/node-card/ports.tsx +86 -0
- package/src/components/views/calc/recipe-picker/body.tsx +17 -14
- package/src/components/views/calc/recipe-picker/footer.tsx +5 -3
- package/src/components/views/calc/recipe-picker/index.tsx +5 -0
- package/src/components/views/calc/sidebar.tsx +19 -10
- package/src/components/views/calc/trees/icon-picker.tsx +3 -2
- package/src/components/views/calc/trees/index.tsx +5 -4
- package/src/components/views/calc/trees/label.tsx +6 -4
- package/src/components/views/calc/trees/rows.tsx +6 -5
- package/src/components/views/forge/gui.tsx +2 -1
- package/src/components/views/forge/index.tsx +14 -7
- package/src/components/views/forge/list.tsx +3 -2
- package/src/components/views/forge/workbench/controls.tsx +13 -6
- package/src/components/views/forge/workbench/index.tsx +3 -2
- package/src/components/views/forge/workbench/panel.tsx +1 -0
- package/src/components/views/forge/workbench/ruler.tsx +5 -4
- package/src/components/views/forge/workbench/status.tsx +6 -5
- package/src/components/views/forge/workbench/tape.tsx +5 -4
- package/src/hooks/alloy/use-fluid-colors.ts +12 -9
- package/src/hooks/alloy/use-mix-state.ts +3 -2
- package/src/hooks/calc/flow/use-engage.ts +129 -0
- package/src/hooks/calc/flow/use-handlers.ts +192 -0
- package/src/hooks/calc/flow/use-layout.ts +105 -0
- package/src/hooks/calc/flow/{mount.ts → use-mount.ts} +1 -0
- package/src/hooks/calc/flow/{nodes.ts → use-nodes.ts} +46 -37
- package/src/hooks/calc/flow/use-pickers.ts +57 -0
- package/src/hooks/calc/flow/{viewport.ts → use-viewport.ts} +13 -26
- package/src/hooks/calc/flow/{window.ts → use-window.ts} +1 -0
- package/src/hooks/calc/use-actions.ts +208 -229
- package/src/hooks/calc/use-amounts.ts +23 -60
- package/src/hooks/calc/use-data.ts +106 -192
- package/src/hooks/calc/use-defaults.ts +4 -2
- package/src/hooks/calc/use-far-mode.ts +1 -0
- package/src/hooks/calc/use-focus.ts +8 -7
- package/src/hooks/calc/use-maps.ts +1 -0
- package/src/hooks/calc/use-reset.ts +1 -0
- package/src/hooks/calc/use-resolver.ts +32 -196
- package/src/hooks/calc/use-session.ts +1 -0
- package/src/hooks/calc/use-share.ts +5 -2
- package/src/hooks/calc/use-storage.ts +5 -4
- package/src/hooks/calc/use-tier.ts +1 -0
- package/src/hooks/calc/use-view-mode.ts +1 -0
- package/src/hooks/calc/use-worker.ts +56 -121
- package/src/hooks/forge/use-anvil-gui.ts +4 -2
- package/src/hooks/forge/use-forge-state.ts +1 -0
- package/src/hooks/forge/use-ruler.ts +1 -0
- package/src/hooks/use-add-to-calc.ts +23 -19
- package/src/hooks/use-categories-by-id.ts +18 -0
- package/src/hooks/use-favorite-hotkey.ts +1 -0
- package/src/hooks/use-favorites.ts +1 -0
- package/src/hooks/use-group-outlines.ts +1 -0
- package/src/hooks/use-hide-unused.ts +2 -1
- package/src/hooks/use-index.ts +6 -2
- package/src/hooks/use-item-feeds.ts +3 -1
- package/src/hooks/use-item-pane.ts +6 -4
- package/src/hooks/use-item-press.ts +27 -23
- package/src/hooks/use-item-tag-groups.ts +4 -2
- package/src/hooks/use-item-tooltips.ts +3 -1
- package/src/hooks/use-left-sidebar-tree.ts +11 -3
- package/src/hooks/use-mod-names.ts +4 -2
- package/src/hooks/use-mount-limit.ts +1 -0
- package/src/hooks/use-panel-cells.ts +3 -1
- package/src/hooks/use-panel-page.ts +9 -6
- package/src/hooks/use-panel-tabs.ts +2 -1
- package/src/hooks/use-query.ts +8 -6
- package/src/hooks/use-session.ts +6 -2
- package/src/hooks/use-sidebar-group.ts +3 -7
- package/src/hooks/use-tag-members.ts +3 -1
- package/src/hooks/use-tool-recipes.ts +1 -0
- package/src/hooks/use-type-filter.ts +1 -0
- package/src/lib/alloy/mix.ts +1 -0
- package/src/lib/alloy/parse.ts +1 -0
- package/src/lib/calc/defaults.ts +6 -4
- package/src/lib/calc/flow.ts +143 -107
- package/src/lib/calc/focus.ts +1 -0
- package/src/lib/calc/meta.ts +3 -1
- package/src/lib/calc/pack.ts +47 -154
- package/src/lib/calc/ports.ts +43 -0
- package/src/lib/calc/resolve.ts +6 -38
- package/src/lib/calc/route/buckets.ts +1 -0
- package/src/lib/calc/route/geometry.ts +13 -24
- package/src/lib/calc/route/index.ts +1 -0
- package/src/lib/calc/route/polyline.ts +3 -3
- package/src/lib/calc/route/router.ts +181 -57
- package/src/lib/calc/scheme.ts +226 -0
- package/src/lib/calc/storage/entry.ts +27 -19
- package/src/lib/calc/storage/index.ts +2 -0
- package/src/lib/calc/storage/keys.ts +4 -8
- package/src/lib/calc/storage/store.ts +11 -36
- package/src/lib/calc/tree/index.ts +2 -16
- package/src/lib/calc/tree/materials.ts +1 -0
- package/src/lib/calc/tree/recipe.ts +1 -0
- package/src/lib/calc/tree/share.ts +86 -149
- package/src/lib/calc/worker/api.ts +3 -11
- package/src/lib/calc/worker/fetch.ts +1 -0
- package/src/lib/calc/worker/flush.ts +7 -20
- package/src/lib/calc/worker/index.ts +1 -1
- package/src/lib/calc/worker/protocol.ts +16 -13
- package/src/lib/calc/worker/resolve.ts +32 -84
- package/src/lib/calc/worker/state.ts +5 -6
- package/src/{components/cards/card/model.ts → lib/card-model.ts} +1 -0
- package/src/lib/client/recipe-categories.ts +11 -93
- package/src/lib/client/recipe.ts +13 -11
- package/src/lib/client-index/catalog.ts +33 -27
- package/src/lib/client-index/chrome.ts +30 -30
- package/src/lib/client-index/index.ts +1 -0
- package/src/lib/client-index/registry.ts +70 -59
- package/src/lib/client-index/rows.ts +63 -57
- package/src/lib/client-index/tooltips.ts +28 -34
- package/src/lib/config.ts +2 -1
- package/src/lib/data/category/dto.ts +4 -3
- package/src/lib/data/category/load.ts +9 -8
- package/src/lib/data/category/parse.ts +4 -3
- package/src/lib/data/dto.ts +4 -3
- package/src/lib/data/grid.ts +2 -1
- package/src/lib/data/parse/entry.ts +3 -2
- package/src/lib/data/parse/index.ts +1 -0
- package/src/lib/data/parse/layout.ts +5 -2
- package/src/lib/data/parse/slots.ts +3 -2
- package/src/lib/data/parse/widgets.ts +3 -2
- package/src/lib/data/scene.ts +1 -1
- package/src/lib/data/slot-io.ts +1 -0
- package/src/lib/dump.ts +4 -3
- package/src/lib/embed.ts +22 -0
- package/src/lib/favorite-hover.ts +1 -0
- package/src/lib/fluid-outputs.ts +10 -12
- package/src/lib/forge/actions.ts +2 -1
- package/src/lib/forge/data.ts +2 -1
- package/src/lib/forge/solve.ts +1 -0
- package/src/lib/group.ts +1 -0
- package/src/lib/index-store.ts +15 -9
- package/src/lib/links.ts +15 -9
- package/src/lib/lookup.ts +10 -8
- package/src/lib/panel-outline.ts +1 -0
- package/src/lib/panel.ts +3 -2
- package/src/lib/preview.ts +12 -8
- package/src/lib/recipe-slots.ts +1 -0
- package/src/lib/search.ts +1 -0
- package/src/lib/sidebar.ts +1 -0
- package/src/lib/used-items.ts +1 -0
- package/src/locales/en_us.json +170 -226
- package/src/locales/ru_ru.json +170 -226
- package/src/locales.ts +1 -0
- package/src/types/alloy.ts +1 -0
- package/src/{hooks/calc/flow/props.ts → types/calc-flow-props.ts} +18 -14
- package/src/types/calc.ts +41 -44
- package/src/types/forge.ts +1 -0
- package/src/types/index.ts +4 -2
- package/styles/calc.css +308 -47
- package/src/components/cards/fit-card.tsx +0 -26
- package/src/components/views/calc/target.tsx +0 -271
- package/src/hooks/calc/flow/engage.ts +0 -89
- package/src/hooks/calc/flow/handlers.ts +0 -115
- package/src/hooks/calc/flow/layout.ts +0 -149
- package/src/hooks/calc/flow/pickers.ts +0 -50
- package/src/hooks/calc/use-calc-fill.ts +0 -91
- package/src/hooks/calc/use-density.ts +0 -28
- package/src/hooks/calc/use-derived.ts +0 -258
- package/src/hooks/calc/use-direction.ts +0 -23
- package/src/hooks/calc/use-edge-style.ts +0 -40
- package/src/hooks/calc/use-fill.ts +0 -213
- package/src/lib/alloy/alloy.test.ts +0 -186
- package/src/lib/calc/tree/build.ts +0 -196
- package/src/lib/calc/tree/context.ts +0 -42
- package/src/lib/calc/tree/goal.ts +0 -64
- package/src/lib/calc/tree/ideal.ts +0 -36
- package/src/lib/calc/tree/pick.ts +0 -68
- package/src/lib/calc/tree/tree.test.ts +0 -169
- package/src/lib/calc/worker/fill.ts +0 -123
- package/src/lib/client-index/cache.ts +0 -13
- 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)}
|
|
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')}
|
|
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')}
|
|
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')}
|
|
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')}
|
|
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:
|
|
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 {
|
|
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/
|
|
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
|
|
18
|
-
|
|
19
|
-
)
|
|
20
|
-
if (!
|
|
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({
|
|
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,
|
|
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 {
|
|
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:
|
|
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
|
-
<
|
|
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
|
+
|
|
@@ -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/
|
|
9
|
-
import { formatNbt } from '@terrafirmagreg-team/
|
|
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:
|
|
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/
|
|
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:
|
|
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:
|
|
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/
|
|
28
|
-
import type { TaggedReference } from '@terrafirmagreg-team/
|
|
29
|
-
import { customStackName } from '@terrafirmagreg-team/
|
|
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 =
|
|
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
|
+
|