@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
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
|
-
Handle,
|
|
5
|
-
Position,
|
|
6
4
|
type NodeProps,
|
|
7
5
|
} from '@terrafirmagreg-team/ui/lib/canvas/xyflow';
|
|
8
6
|
import { ListFilter } from 'lucide-react';
|
|
@@ -20,40 +18,19 @@ import { recipeTitle } from '@terrafirmagreg-team/recipe/lib/data/parse';
|
|
|
20
18
|
import { cn } from '@terrafirmagreg-team/ui/lib/utils/cn';
|
|
21
19
|
import type { CalcFlowNode } from '@terrafirmagreg-team/recipe/lib/calc/flow';
|
|
22
20
|
import { CORNER_BUTTON } from './actions';
|
|
21
|
+
import { CardHandles } from './ports';
|
|
23
22
|
|
|
24
23
|
export function CalcHiddenCard({ data }: NodeProps<CalcFlowNode>) {
|
|
25
|
-
const { direction } = data;
|
|
26
|
-
const srcPos = direction === 'horizontal' ? Position.Left : Position.Top;
|
|
27
|
-
const tgtPos =
|
|
28
|
-
direction === 'horizontal' ? Position.Right : Position.Bottom;
|
|
29
24
|
return (
|
|
30
25
|
<div data-calc-card className="relative h-full w-full">
|
|
31
|
-
<
|
|
32
|
-
type="source"
|
|
33
|
-
position={srcPos}
|
|
34
|
-
isConnectable={false}
|
|
35
|
-
className="calc-port"
|
|
36
|
-
/>
|
|
37
|
-
<Handle
|
|
38
|
-
type="target"
|
|
39
|
-
position={tgtPos}
|
|
40
|
-
isConnectable={false}
|
|
41
|
-
className="calc-port"
|
|
42
|
-
/>
|
|
26
|
+
<CardHandles node={data.node} interactive={false} />
|
|
43
27
|
<Skeleton className="size-full rounded-md" />
|
|
44
28
|
</div>
|
|
45
29
|
);
|
|
46
30
|
}
|
|
47
31
|
|
|
48
32
|
export function CalcFarCard({ data, selected }: NodeProps<CalcFlowNode>) {
|
|
49
|
-
const {
|
|
50
|
-
node,
|
|
51
|
-
dataset,
|
|
52
|
-
mode,
|
|
53
|
-
direction,
|
|
54
|
-
recipeBody,
|
|
55
|
-
onRequestPicker,
|
|
56
|
-
} = data;
|
|
33
|
+
const { node, dataset, mode, recipeBody, onRequestPicker } = data;
|
|
57
34
|
const t = useTranslations();
|
|
58
35
|
const session = useCalcSession();
|
|
59
36
|
const lang = session?.lang ?? 'en_us';
|
|
@@ -69,14 +46,10 @@ export function CalcFarCard({ data, selected }: NodeProps<CalcFlowNode>) {
|
|
|
69
46
|
node.recipe != null || node.availableRecipes.length > 0;
|
|
70
47
|
const stateCls = cn(
|
|
71
48
|
node.cycle && 'border-red-500/70',
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
!node.cycle && !node.catalyst && node.recipe && 'border-primary/60',
|
|
49
|
+
!node.cycle && node.recipe && 'border-primary/60',
|
|
50
|
+
!node.recipe && 'border-dashed border-muted-foreground/50',
|
|
75
51
|
selected && 'ring-2 ring-primary/70',
|
|
76
52
|
);
|
|
77
|
-
const srcPos = direction === 'horizontal' ? Position.Left : Position.Top;
|
|
78
|
-
const tgtPos =
|
|
79
|
-
direction === 'horizontal' ? Position.Right : Position.Bottom;
|
|
80
53
|
return (
|
|
81
54
|
<div
|
|
82
55
|
data-calc-card
|
|
@@ -85,22 +58,11 @@ export function CalcFarCard({ data, selected }: NodeProps<CalcFlowNode>) {
|
|
|
85
58
|
stateCls,
|
|
86
59
|
)}
|
|
87
60
|
>
|
|
88
|
-
<
|
|
89
|
-
type="source"
|
|
90
|
-
position={srcPos}
|
|
91
|
-
isConnectable={false}
|
|
92
|
-
className="calc-port"
|
|
93
|
-
/>
|
|
94
|
-
<Handle
|
|
95
|
-
type="target"
|
|
96
|
-
position={tgtPos}
|
|
97
|
-
isConnectable={false}
|
|
98
|
-
className="calc-port"
|
|
99
|
-
/>
|
|
61
|
+
<CardHandles node={node} interactive={false} />
|
|
100
62
|
<div className="flex min-w-0 items-center gap-1.5">
|
|
101
63
|
<span className="size-4 shrink-0 rounded-sm border border-border bg-muted/40" />
|
|
102
64
|
<span className="min-w-0 flex-1 truncate">
|
|
103
|
-
<StackCount count={node.
|
|
65
|
+
<StackCount count={node.produced} /> {name}
|
|
104
66
|
</span>
|
|
105
67
|
</div>
|
|
106
68
|
{mode === 'detailed' && body && src ? (
|
|
@@ -124,7 +86,7 @@ export function CalcFarCard({ data, selected }: NodeProps<CalcFlowNode>) {
|
|
|
124
86
|
{pickable ? (
|
|
125
87
|
<button
|
|
126
88
|
type="button"
|
|
127
|
-
aria-label={t('recipe.calc.select')}
|
|
89
|
+
aria-label={t('Choose recipe', { note: 'recipe.calc.select' })}
|
|
128
90
|
onClick={(event) => {
|
|
129
91
|
event.stopPropagation();
|
|
130
92
|
onRequestPicker(node);
|
|
@@ -139,17 +101,13 @@ export function CalcFarCard({ data, selected }: NodeProps<CalcFlowNode>) {
|
|
|
139
101
|
}
|
|
140
102
|
|
|
141
103
|
export function CalcDotCard({ data, selected }: NodeProps<CalcFlowNode>) {
|
|
142
|
-
const { node
|
|
104
|
+
const { node } = data;
|
|
143
105
|
const stateCls = cn(
|
|
144
106
|
node.cycle && 'border-red-500/70',
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
!node.cycle && !node.catalyst && node.recipe && 'border-primary/60',
|
|
107
|
+
!node.cycle && node.recipe && 'border-primary/60',
|
|
108
|
+
!node.recipe && 'border-dashed border-muted-foreground/50',
|
|
148
109
|
selected && 'ring-2 ring-primary/70',
|
|
149
110
|
);
|
|
150
|
-
const srcPos = direction === 'horizontal' ? Position.Left : Position.Top;
|
|
151
|
-
const tgtPos =
|
|
152
|
-
direction === 'horizontal' ? Position.Right : Position.Bottom;
|
|
153
111
|
return (
|
|
154
112
|
<div
|
|
155
113
|
data-calc-card
|
|
@@ -158,18 +116,8 @@ export function CalcDotCard({ data, selected }: NodeProps<CalcFlowNode>) {
|
|
|
158
116
|
stateCls,
|
|
159
117
|
)}
|
|
160
118
|
>
|
|
161
|
-
<
|
|
162
|
-
type="source"
|
|
163
|
-
position={srcPos}
|
|
164
|
-
isConnectable={false}
|
|
165
|
-
className="calc-port"
|
|
166
|
-
/>
|
|
167
|
-
<Handle
|
|
168
|
-
type="target"
|
|
169
|
-
position={tgtPos}
|
|
170
|
-
isConnectable={false}
|
|
171
|
-
className="calc-port"
|
|
172
|
-
/>
|
|
119
|
+
<CardHandles node={node} interactive={false} />
|
|
173
120
|
</div>
|
|
174
121
|
);
|
|
175
122
|
}
|
|
123
|
+
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { memo, useEffect, useState } from 'react';
|
|
4
|
+
import { Minus, Plus } from 'lucide-react';
|
|
4
5
|
import {
|
|
5
|
-
|
|
6
|
-
Position,
|
|
6
|
+
useUpdateNodeInternals,
|
|
7
7
|
type NodeProps,
|
|
8
8
|
} from '@terrafirmagreg-team/ui/lib/canvas/xyflow';
|
|
9
9
|
import { useTranslations } from '@terrafirmagreg-team/translate/hooks/use-translations';
|
|
@@ -30,10 +30,12 @@ import {
|
|
|
30
30
|
import { recipeTitle } from '@terrafirmagreg-team/recipe/lib/data/parse';
|
|
31
31
|
import { cn } from '@terrafirmagreg-team/ui/lib/utils/cn';
|
|
32
32
|
import { CALC_NODE_W } from '@terrafirmagreg-team/recipe/lib/calc/flow';
|
|
33
|
+
import { railSpans } from '@terrafirmagreg-team/recipe/lib/calc/ports';
|
|
33
34
|
import type { CalcFlowNode } from '@terrafirmagreg-team/recipe/lib/calc/flow';
|
|
34
35
|
import { NodeBadges } from './badges';
|
|
35
|
-
import {
|
|
36
|
+
import { NodeChips } from './chips';
|
|
36
37
|
import { NodeActions } from './actions';
|
|
38
|
+
import { PortRailIn, PortRailOut } from './port-rails';
|
|
37
39
|
import { NodeContextMenu, NodeHoverContent } from './menu';
|
|
38
40
|
|
|
39
41
|
export const CalcNodeCardFull = memo(function CalcNodeCardFull({
|
|
@@ -45,10 +47,10 @@ export const CalcNodeCardFull = memo(function CalcNodeCardFull({
|
|
|
45
47
|
node,
|
|
46
48
|
dataset,
|
|
47
49
|
mode,
|
|
48
|
-
direction,
|
|
49
50
|
recipeBody,
|
|
50
51
|
onRequestPicker,
|
|
51
52
|
onRequestMemberPicker,
|
|
53
|
+
onCrafts,
|
|
52
54
|
} = data;
|
|
53
55
|
const t = useTranslations();
|
|
54
56
|
const session = useCalcSession();
|
|
@@ -103,72 +105,56 @@ export const CalcNodeCardFull = memo(function CalcNodeCardFull({
|
|
|
103
105
|
}, [staged, bodyReady]);
|
|
104
106
|
const cardOn = card && (!staged || bodyReady);
|
|
105
107
|
|
|
108
|
+
useEffect(
|
|
109
|
+
() => () => {
|
|
110
|
+
railSpans.delete(id);
|
|
111
|
+
},
|
|
112
|
+
[id],
|
|
113
|
+
);
|
|
114
|
+
|
|
106
115
|
const skeleton =
|
|
107
116
|
mode === 'detailed' && node.recipe != null && !cardOn;
|
|
108
117
|
const stateCls = cn(
|
|
109
118
|
node.cycle && 'border-red-500/70',
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
!node.cycle && !node.catalyst && node.recipe && 'border-primary/60',
|
|
119
|
+
!node.cycle && node.recipe && 'border-primary/60',
|
|
120
|
+
!node.recipe && 'border-dashed border-muted-foreground/50',
|
|
113
121
|
selected && 'ring-2 ring-primary/70',
|
|
114
122
|
);
|
|
115
123
|
|
|
116
|
-
const srcPos = direction === 'horizontal' ? Position.Left : Position.Top;
|
|
117
|
-
const tgtPos = direction === 'horizontal' ? Position.Right : Position.Bottom;
|
|
118
|
-
|
|
119
124
|
const interactive = tier === 'near';
|
|
120
|
-
const
|
|
125
|
+
const updateNodeInternals = useUpdateNodeInternals();
|
|
126
|
+
useEffect(() => {
|
|
127
|
+
updateNodeInternals(id);
|
|
128
|
+
}, [
|
|
129
|
+
id,
|
|
130
|
+
updateNodeInternals,
|
|
131
|
+
mode,
|
|
132
|
+
interactive,
|
|
133
|
+
node.recipe?.recipeId,
|
|
134
|
+
node.inputs.length,
|
|
135
|
+
node.outputs.length,
|
|
136
|
+
]);
|
|
137
|
+
const innerContent = (
|
|
121
138
|
<div
|
|
122
|
-
data-calc-card
|
|
123
139
|
className={cn(
|
|
124
|
-
'
|
|
125
|
-
'
|
|
126
|
-
mode === 'mini' ? 'items-center px-1.5 py-1' : 'px-2 py-1',
|
|
127
|
-
stateCls,
|
|
140
|
+
'flex min-w-0 flex-1 flex-col justify-center gap-0.5 px-2 py-1',
|
|
141
|
+
mode === 'mini' ? 'items-center px-1.5' : '',
|
|
128
142
|
)}
|
|
129
143
|
>
|
|
130
|
-
<Handle
|
|
131
|
-
type="source"
|
|
132
|
-
position={srcPos}
|
|
133
|
-
isConnectable={false}
|
|
134
|
-
className="calc-port"
|
|
135
|
-
/>
|
|
136
|
-
<Handle
|
|
137
|
-
type="target"
|
|
138
|
-
position={tgtPos}
|
|
139
|
-
isConnectable={false}
|
|
140
|
-
className="calc-port"
|
|
141
|
-
/>
|
|
142
144
|
{mode === 'mini' ? (
|
|
143
|
-
<div className="flex w-
|
|
144
|
-
<
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
}
|
|
157
|
-
centerClassName="py-0.5"
|
|
158
|
-
>
|
|
159
|
-
<Entry
|
|
160
|
-
id={node.materialId}
|
|
161
|
-
kind={node.kind}
|
|
162
|
-
dataset={dataset}
|
|
163
|
-
lang={lang}
|
|
164
|
-
langMap={langMap}
|
|
165
|
-
name={name}
|
|
166
|
-
size="lg"
|
|
167
|
-
href={false}
|
|
168
|
-
tooltip={false}
|
|
169
|
-
badge={<StackCount count={node.amount} />}
|
|
170
|
-
/>
|
|
171
|
-
</CycleChip>
|
|
145
|
+
<div className="mx-3 flex w-auto flex-col items-center gap-0.5">
|
|
146
|
+
<Entry
|
|
147
|
+
id={node.materialId}
|
|
148
|
+
kind={node.kind}
|
|
149
|
+
dataset={dataset}
|
|
150
|
+
lang={lang}
|
|
151
|
+
langMap={langMap}
|
|
152
|
+
name={name}
|
|
153
|
+
size="lg"
|
|
154
|
+
href={false}
|
|
155
|
+
tooltip="adaptive"
|
|
156
|
+
badge={<StackCount count={node.produced} />}
|
|
157
|
+
/>
|
|
172
158
|
<span className="w-full truncate px-0.5 text-center text-[9px] leading-tight text-muted-foreground">
|
|
173
159
|
{name}
|
|
174
160
|
</span>
|
|
@@ -187,7 +173,7 @@ export const CalcNodeCardFull = memo(function CalcNodeCardFull({
|
|
|
187
173
|
</div>
|
|
188
174
|
) : (
|
|
189
175
|
<>
|
|
190
|
-
<div className="flex min-w-0 items-center gap-1.5">
|
|
176
|
+
<div className="mx-1 flex min-w-0 items-center gap-1.5">
|
|
191
177
|
<Entry
|
|
192
178
|
id={node.materialId}
|
|
193
179
|
kind={node.kind}
|
|
@@ -197,23 +183,57 @@ export const CalcNodeCardFull = memo(function CalcNodeCardFull({
|
|
|
197
183
|
size="lg"
|
|
198
184
|
labeled
|
|
199
185
|
href={false}
|
|
200
|
-
tooltip=
|
|
201
|
-
badge={<StackCount count={node.
|
|
186
|
+
tooltip="adaptive"
|
|
187
|
+
badge={<StackCount count={node.produced} />}
|
|
202
188
|
className="min-w-0 flex-1 justify-start truncate"
|
|
203
189
|
/>
|
|
190
|
+
<NodeChips
|
|
191
|
+
node={node}
|
|
192
|
+
mini={false}
|
|
193
|
+
name={name}
|
|
194
|
+
category={category}
|
|
195
|
+
hasAlternatives={hasAlternatives}
|
|
196
|
+
dataset={dataset}
|
|
197
|
+
lang={lang}
|
|
198
|
+
langMap={langMap}
|
|
199
|
+
onRequestPicker={onRequestPicker}
|
|
200
|
+
onRequestMemberPicker={onRequestMemberPicker}
|
|
201
|
+
/>
|
|
202
|
+
</div>
|
|
203
|
+
<div className="mx-1 flex min-w-0 items-center gap-1">
|
|
204
|
+
{interactive ? (
|
|
205
|
+
<span className="nodrag ml-auto flex shrink-0 items-center gap-0.5">
|
|
206
|
+
<button
|
|
207
|
+
type="button"
|
|
208
|
+
aria-label={t('Fewer crafts', { note: 'recipe.calc.crafts.down' })}
|
|
209
|
+
className="grid size-4 place-items-center rounded border border-border bg-background text-muted-foreground hover:text-foreground"
|
|
210
|
+
onClick={(e) => {
|
|
211
|
+
e.stopPropagation();
|
|
212
|
+
onCrafts(id, Math.max(1, node.crafts - 1));
|
|
213
|
+
}}
|
|
214
|
+
>
|
|
215
|
+
<Minus className="size-2.5" />
|
|
216
|
+
</button>
|
|
217
|
+
<span
|
|
218
|
+
className="min-w-6 text-center tabular-nums"
|
|
219
|
+
title={t('Crafts', { note: 'recipe.calc.crafts.title' })}
|
|
220
|
+
>
|
|
221
|
+
{node.crafts}
|
|
222
|
+
</span>
|
|
223
|
+
<button
|
|
224
|
+
type="button"
|
|
225
|
+
aria-label={t('More crafts', { note: 'recipe.calc.crafts.up' })}
|
|
226
|
+
className="grid size-4 place-items-center rounded border border-border bg-background text-muted-foreground hover:text-foreground"
|
|
227
|
+
onClick={(e) => {
|
|
228
|
+
e.stopPropagation();
|
|
229
|
+
onCrafts(id, node.crafts + 1);
|
|
230
|
+
}}
|
|
231
|
+
>
|
|
232
|
+
<Plus className="size-2.5" />
|
|
233
|
+
</button>
|
|
234
|
+
</span>
|
|
235
|
+
) : null}
|
|
204
236
|
</div>
|
|
205
|
-
<NodeChips
|
|
206
|
-
node={node}
|
|
207
|
-
mini={false}
|
|
208
|
-
name={name}
|
|
209
|
-
category={category}
|
|
210
|
-
hasAlternatives={hasAlternatives}
|
|
211
|
-
dataset={dataset}
|
|
212
|
-
lang={lang}
|
|
213
|
-
langMap={langMap}
|
|
214
|
-
onRequestPicker={onRequestPicker}
|
|
215
|
-
onRequestMemberPicker={onRequestMemberPicker}
|
|
216
|
-
/>
|
|
217
237
|
</>
|
|
218
238
|
)}
|
|
219
239
|
{cardOn && body && src ? (
|
|
@@ -231,7 +251,7 @@ export const CalcNodeCardFull = memo(function CalcNodeCardFull({
|
|
|
231
251
|
naturalW={body.w}
|
|
232
252
|
naturalH={body.h}
|
|
233
253
|
interactive={false}
|
|
234
|
-
slotTooltip={interactive ? '
|
|
254
|
+
slotTooltip={interactive ? 'adaptive' : 'none'}
|
|
235
255
|
eager
|
|
236
256
|
onFail={() => setImgFail(true)}
|
|
237
257
|
/>
|
|
@@ -246,13 +266,44 @@ export const CalcNodeCardFull = memo(function CalcNodeCardFull({
|
|
|
246
266
|
}
|
|
247
267
|
/>
|
|
248
268
|
) : null}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
269
|
+
</div>
|
|
270
|
+
);
|
|
271
|
+
const hoverBody =
|
|
272
|
+
interactive && hoverCard ? (
|
|
273
|
+
<HoverCardTrigger render={innerContent} />
|
|
274
|
+
) : (
|
|
275
|
+
innerContent
|
|
276
|
+
);
|
|
277
|
+
const cardBody = (
|
|
278
|
+
<div
|
|
279
|
+
data-calc-card
|
|
280
|
+
className={cn(
|
|
281
|
+
'relative flex h-full w-full select-none flex-col text-xs outline-none',
|
|
282
|
+
'rounded-md border bg-card',
|
|
283
|
+
stateCls,
|
|
284
|
+
)}
|
|
285
|
+
>
|
|
286
|
+
<PortRailIn
|
|
287
|
+
node={node}
|
|
288
|
+
data={data}
|
|
289
|
+
dataset={dataset}
|
|
290
|
+
lang={lang}
|
|
291
|
+
langMap={langMap}
|
|
292
|
+
names={names}
|
|
293
|
+
connectable={interactive}
|
|
294
|
+
/>
|
|
295
|
+
{hoverBody}
|
|
296
|
+
<PortRailOut
|
|
297
|
+
node={node}
|
|
298
|
+
data={data}
|
|
299
|
+
dataset={dataset}
|
|
300
|
+
lang={lang}
|
|
301
|
+
langMap={langMap}
|
|
302
|
+
names={names}
|
|
303
|
+
connectable={interactive}
|
|
304
|
+
onOpen={() => onRequestPicker(node)}
|
|
305
|
+
/>
|
|
306
|
+
{interactive ? <NodeActions data={data} nodeId={id} /> : null}
|
|
256
307
|
<NodeBadges node={node} />
|
|
257
308
|
</div>
|
|
258
309
|
);
|
|
@@ -260,9 +311,7 @@ export const CalcNodeCardFull = memo(function CalcNodeCardFull({
|
|
|
260
311
|
return (
|
|
261
312
|
<HoverCard>
|
|
262
313
|
<ContextMenu>
|
|
263
|
-
<
|
|
264
|
-
render={<ContextMenuTrigger render={cardBody} />}
|
|
265
|
-
/>
|
|
314
|
+
<ContextMenuTrigger render={cardBody} />
|
|
266
315
|
<NodeContextMenu data={data} lang={lang} langMap={langMap} />
|
|
267
316
|
</ContextMenu>
|
|
268
317
|
{hoverCard ? (
|
|
@@ -280,3 +329,4 @@ export const CalcNodeCardFull = memo(function CalcNodeCardFull({
|
|
|
280
329
|
</HoverCard>
|
|
281
330
|
);
|
|
282
331
|
});
|
|
332
|
+
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use client';
|
|
2
|
+
import type { DatasetRef } from '@terrafirmagreg-team/sites/location';
|
|
2
3
|
|
|
3
4
|
import {
|
|
4
5
|
ExternalLink,
|
|
5
6
|
ListFilter,
|
|
6
|
-
Package,
|
|
7
7
|
Pin,
|
|
8
8
|
PinOff,
|
|
9
9
|
Plus,
|
|
@@ -24,6 +24,7 @@ import { Entry } from '@terrafirmagreg-team/game/components/entry/entry';
|
|
|
24
24
|
import { PagedCard } from '@terrafirmagreg-team/recipe/components/cards/paged-card';
|
|
25
25
|
import { recipeTitle } from '@terrafirmagreg-team/recipe/lib/data/parse';
|
|
26
26
|
import type { CalcFlowData } from '@terrafirmagreg-team/recipe/lib/calc/flow';
|
|
27
|
+
import type { CalcKind } from '@terrafirmagreg-team/recipe/types/calc';
|
|
27
28
|
import type { Recipe } from '@terrafirmagreg-team/recipe/lib/data/dto';
|
|
28
29
|
import type { RecipeCategory } from '@terrafirmagreg-team/recipe/types';
|
|
29
30
|
|
|
@@ -39,10 +40,9 @@ export function NodeContextMenu({
|
|
|
39
40
|
const {
|
|
40
41
|
node,
|
|
41
42
|
dataset,
|
|
42
|
-
|
|
43
|
-
onAddStock,
|
|
43
|
+
onAddCard,
|
|
44
44
|
onOpenItem,
|
|
45
|
-
|
|
45
|
+
onSelectRecipe,
|
|
46
46
|
onRequestPicker,
|
|
47
47
|
onRequestMemberPicker,
|
|
48
48
|
recipeDefaults,
|
|
@@ -70,24 +70,17 @@ export function NodeContextMenu({
|
|
|
70
70
|
<ContextMenuSeparator />
|
|
71
71
|
<ContextMenuItem
|
|
72
72
|
className="whitespace-nowrap"
|
|
73
|
-
onClick={() =>
|
|
73
|
+
onClick={() => onAddCard(node.materialId, node.kind)}
|
|
74
74
|
>
|
|
75
75
|
<Target />
|
|
76
|
-
{t('recipe.calc.
|
|
77
|
-
</ContextMenuItem>
|
|
78
|
-
<ContextMenuItem
|
|
79
|
-
className="whitespace-nowrap"
|
|
80
|
-
onClick={() => onAddStock(node.materialId, node.kind)}
|
|
81
|
-
>
|
|
82
|
-
<Package />
|
|
83
|
-
{t('recipe.calc.add.stock')}
|
|
76
|
+
{t('Add card', { note: 'recipe.calc.add.goal' })}
|
|
84
77
|
</ContextMenuItem>
|
|
85
78
|
<ContextMenuItem
|
|
86
79
|
className="whitespace-nowrap"
|
|
87
80
|
onClick={() => onOpenItem(node.materialId, node.kind)}
|
|
88
81
|
>
|
|
89
82
|
<ExternalLink />
|
|
90
|
-
{t('recipe.calc.open.item')}
|
|
83
|
+
{t('Open item page', { note: 'recipe.calc.open.item' })}
|
|
91
84
|
</ContextMenuItem>
|
|
92
85
|
{node.recipe ? (
|
|
93
86
|
<ContextMenuItem
|
|
@@ -104,32 +97,32 @@ export function NodeContextMenu({
|
|
|
104
97
|
{recipeDefaults[node.materialId] === node.recipe.recipeId ? (
|
|
105
98
|
<>
|
|
106
99
|
<PinOff />
|
|
107
|
-
{t('recipe.calc.clear.default')}
|
|
100
|
+
{t('Unpin default recipe', { note: 'recipe.calc.clear.default' })}
|
|
108
101
|
</>
|
|
109
102
|
) : (
|
|
110
103
|
<>
|
|
111
104
|
<Pin />
|
|
112
|
-
{t('recipe.calc.set_default')}
|
|
105
|
+
{t('Pin as default recipe', { note: 'recipe.calc.set_default' })}
|
|
113
106
|
</>
|
|
114
107
|
)}
|
|
115
108
|
</ContextMenuItem>
|
|
116
109
|
) : null}
|
|
117
|
-
{node.recipe
|
|
110
|
+
{node.recipe ? (
|
|
118
111
|
<ContextMenuItem
|
|
119
112
|
className="whitespace-nowrap"
|
|
120
|
-
onClick={() =>
|
|
113
|
+
onClick={() => onSelectRecipe(node.id, null)}
|
|
121
114
|
>
|
|
122
115
|
<Undo2 />
|
|
123
|
-
{t('recipe.calc.remove.recipe')}
|
|
116
|
+
{t('Remove recipe', { note: 'recipe.calc.remove.recipe' })}
|
|
124
117
|
</ContextMenuItem>
|
|
125
118
|
) : null}
|
|
126
|
-
{node.
|
|
119
|
+
{!node.recipe && node.availableRecipes.length > 0 ? (
|
|
127
120
|
<ContextMenuItem
|
|
128
121
|
className="whitespace-nowrap"
|
|
129
122
|
onClick={() => onRequestPicker(node)}
|
|
130
123
|
>
|
|
131
124
|
<Plus />
|
|
132
|
-
{t('recipe.calc.pick.title')}
|
|
125
|
+
{t('Pick a recipe', { note: 'recipe.calc.pick.title' })}
|
|
133
126
|
</ContextMenuItem>
|
|
134
127
|
) : null}
|
|
135
128
|
{node.tagId && members && members.length > 1 ? (
|
|
@@ -138,9 +131,86 @@ export function NodeContextMenu({
|
|
|
138
131
|
onClick={() => onRequestMemberPicker(node)}
|
|
139
132
|
>
|
|
140
133
|
<ListFilter />
|
|
141
|
-
{t('recipe.calc.member.title')}
|
|
134
|
+
{t('Choose tag member', { note: 'recipe.calc.member.title' })}
|
|
135
|
+
</ContextMenuItem>
|
|
136
|
+
) : null}
|
|
137
|
+
</ContextMenuContent>
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export function PortContextMenu({
|
|
142
|
+
data,
|
|
143
|
+
node,
|
|
144
|
+
input,
|
|
145
|
+
out,
|
|
146
|
+
id,
|
|
147
|
+
kind,
|
|
148
|
+
dataset,
|
|
149
|
+
lang,
|
|
150
|
+
langMap,
|
|
151
|
+
}: {
|
|
152
|
+
data: CalcFlowData;
|
|
153
|
+
node: CalcFlowData['node'];
|
|
154
|
+
input?: number;
|
|
155
|
+
out?: number;
|
|
156
|
+
id: string;
|
|
157
|
+
kind: CalcKind;
|
|
158
|
+
dataset: DatasetRef;
|
|
159
|
+
lang: string;
|
|
160
|
+
langMap?: Record<string, string>;
|
|
161
|
+
}) {
|
|
162
|
+
const { onAddCard, onOpenItem, onRequestPicker, onRequestSupply } = data;
|
|
163
|
+
const t = useTranslations();
|
|
164
|
+
return (
|
|
165
|
+
<ContextMenuContent>
|
|
166
|
+
<ContextMenuGroup>
|
|
167
|
+
<ContextMenuLabel className="flex items-center gap-1.5">
|
|
168
|
+
<Entry
|
|
169
|
+
id={id}
|
|
170
|
+
kind={kind}
|
|
171
|
+
dataset={dataset}
|
|
172
|
+
lang={lang}
|
|
173
|
+
langMap={langMap}
|
|
174
|
+
size="sm"
|
|
175
|
+
labeled
|
|
176
|
+
href={false}
|
|
177
|
+
tooltip={false}
|
|
178
|
+
/>
|
|
179
|
+
</ContextMenuLabel>
|
|
180
|
+
</ContextMenuGroup>
|
|
181
|
+
<ContextMenuSeparator />
|
|
182
|
+
{input != null ? (
|
|
183
|
+
<ContextMenuItem
|
|
184
|
+
className="whitespace-nowrap"
|
|
185
|
+
onClick={() => onRequestSupply(node, input)}
|
|
186
|
+
>
|
|
187
|
+
<Plus />
|
|
188
|
+
{t('Keep as external source', { note: 'recipe.calc.supply.source' })}
|
|
189
|
+
</ContextMenuItem>
|
|
190
|
+
) : null}
|
|
191
|
+
{out === 0 && !node.recipe && node.availableRecipes.length > 0 ? (
|
|
192
|
+
<ContextMenuItem
|
|
193
|
+
className="whitespace-nowrap"
|
|
194
|
+
onClick={() => onRequestPicker(node)}
|
|
195
|
+
>
|
|
196
|
+
<ListFilter />
|
|
197
|
+
{t('Pick a recipe', { note: 'recipe.calc.pick.title' })}
|
|
142
198
|
</ContextMenuItem>
|
|
143
199
|
) : null}
|
|
200
|
+
<ContextMenuItem
|
|
201
|
+
className="whitespace-nowrap"
|
|
202
|
+
onClick={() => onAddCard(id, kind)}
|
|
203
|
+
>
|
|
204
|
+
<Target />
|
|
205
|
+
{t('Add card', { note: 'recipe.calc.add.goal' })}
|
|
206
|
+
</ContextMenuItem>
|
|
207
|
+
<ContextMenuItem
|
|
208
|
+
className="whitespace-nowrap"
|
|
209
|
+
onClick={() => onOpenItem(id, kind)}
|
|
210
|
+
>
|
|
211
|
+
<ExternalLink />
|
|
212
|
+
{t('Open item page', { note: 'recipe.calc.open.item' })}
|
|
213
|
+
</ContextMenuItem>
|
|
144
214
|
</ContextMenuContent>
|
|
145
215
|
);
|
|
146
216
|
}
|
|
@@ -209,3 +279,4 @@ export function NodeHoverContent({
|
|
|
209
279
|
</HoverCardContent>
|
|
210
280
|
);
|
|
211
281
|
}
|
|
282
|
+
|