@rpg-engine/long-bow 0.8.145 → 0.8.146
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Marketplace/BlueprintTable.d.ts +9 -0
- package/dist/long-bow.cjs.development.js +116 -72
- package/dist/long-bow.cjs.development.js.map +1 -1
- package/dist/long-bow.cjs.production.min.js +1 -1
- package/dist/long-bow.cjs.production.min.js.map +1 -1
- package/dist/long-bow.esm.js +116 -72
- package/dist/long-bow.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/components/Marketplace/BlueprintSearchModal.tsx +14 -137
- package/src/components/Marketplace/BlueprintTable.tsx +158 -0
- package/src/components/Marketplace/BuyOrderDetailsModal.tsx +9 -10
- package/src/components/Marketplace/BuyOrderPanel.tsx +25 -7
- package/src/stories/Features/marketplace/BuyOrderPanel.stories.tsx +197 -81
- package/src/stories/Features/trading/Marketplace.stories.tsx +27 -4
package/package.json
CHANGED
|
@@ -5,13 +5,13 @@ import {
|
|
|
5
5
|
} from '@rpg-engine/shared';
|
|
6
6
|
import React, { useState } from 'react';
|
|
7
7
|
import { FaTimes } from 'react-icons/fa';
|
|
8
|
-
import styled from 'styled-components';
|
|
8
|
+
import styled, { keyframes } from 'styled-components';
|
|
9
9
|
import { Dropdown } from '../Dropdown';
|
|
10
10
|
import { IOptionsProps } from '../Dropdown';
|
|
11
11
|
import { Input } from '../Input';
|
|
12
12
|
import { Pager } from '../Pager';
|
|
13
13
|
import ModalPortal from '../Abstractions/ModalPortal';
|
|
14
|
-
import {
|
|
14
|
+
import { BlueprintTable } from './BlueprintTable';
|
|
15
15
|
|
|
16
16
|
export interface IBlueprintSearchModalProps {
|
|
17
17
|
isOpen: boolean;
|
|
@@ -28,6 +28,11 @@ export interface IBlueprintSearchModalProps {
|
|
|
28
28
|
|
|
29
29
|
const BLUEPRINTS_PER_PAGE = 10;
|
|
30
30
|
|
|
31
|
+
const scaleIn = keyframes`
|
|
32
|
+
from { transform: scale(0.85); opacity: 0; }
|
|
33
|
+
to { transform: scale(1); opacity: 1; }
|
|
34
|
+
`;
|
|
35
|
+
|
|
31
36
|
const typeOptions: IOptionsProps[] = [
|
|
32
37
|
{ id: 1, value: '', option: 'All Types' },
|
|
33
38
|
...Object.keys(ItemSubType)
|
|
@@ -145,42 +150,12 @@ export const BlueprintSearchModal: React.FC<IBlueprintSearchModalProps> = ({
|
|
|
145
150
|
) : blueprints.length === 0 ? (
|
|
146
151
|
<EmptyState>No blueprints found</EmptyState>
|
|
147
152
|
) : (
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
{blueprints.map((blueprint) => (
|
|
155
|
-
<ResultRow
|
|
156
|
-
key={blueprint.key}
|
|
157
|
-
onPointerDown={() => onSelect(blueprint)}
|
|
158
|
-
>
|
|
159
|
-
<SpriteWrapper>
|
|
160
|
-
<SpriteFromAtlas
|
|
161
|
-
atlasJSON={atlasJSON}
|
|
162
|
-
atlasIMG={atlasIMG}
|
|
163
|
-
spriteKey={blueprint.texturePath || blueprint.key}
|
|
164
|
-
width={32}
|
|
165
|
-
height={32}
|
|
166
|
-
imgScale={2}
|
|
167
|
-
centered
|
|
168
|
-
/>
|
|
169
|
-
</SpriteWrapper>
|
|
170
|
-
<ColName>
|
|
171
|
-
<BlueprintName>{blueprint.name}</BlueprintName>
|
|
172
|
-
<BlueprintKey>{blueprint.key}</BlueprintKey>
|
|
173
|
-
</ColName>
|
|
174
|
-
<ColType>
|
|
175
|
-
<TypeText>{blueprint.type}</TypeText>
|
|
176
|
-
{blueprint.subType && blueprint.subType !== blueprint.type && (
|
|
177
|
-
<SubTypeText>{blueprint.subType}</SubTypeText>
|
|
178
|
-
)}
|
|
179
|
-
</ColType>
|
|
180
|
-
<ColTier>T{blueprint.tier}</ColTier>
|
|
181
|
-
</ResultRow>
|
|
182
|
-
))}
|
|
183
|
-
</>
|
|
153
|
+
<BlueprintTable
|
|
154
|
+
blueprints={blueprints}
|
|
155
|
+
atlasJSON={atlasJSON}
|
|
156
|
+
atlasIMG={atlasIMG}
|
|
157
|
+
onSelect={onSelect}
|
|
158
|
+
/>
|
|
184
159
|
)}
|
|
185
160
|
</ResultsWrapper>
|
|
186
161
|
|
|
@@ -226,12 +201,7 @@ const ModalContent = styled.div`
|
|
|
226
201
|
flex-direction: column;
|
|
227
202
|
gap: 12px;
|
|
228
203
|
pointer-events: auto;
|
|
229
|
-
animation: scaleIn 0.15s ease-out;
|
|
230
|
-
|
|
231
|
-
@keyframes scaleIn {
|
|
232
|
-
from { transform: scale(0.85); opacity: 0; }
|
|
233
|
-
to { transform: scale(1); opacity: 1; }
|
|
234
|
-
}
|
|
204
|
+
animation: ${scaleIn} 0.15s ease-out;
|
|
235
205
|
`;
|
|
236
206
|
|
|
237
207
|
const Header = styled.div`
|
|
@@ -284,7 +254,6 @@ const InputWrapper = styled.div`
|
|
|
284
254
|
|
|
285
255
|
const StyledInput = styled(Input)`
|
|
286
256
|
flex: 1;
|
|
287
|
-
height: 10px;
|
|
288
257
|
`;
|
|
289
258
|
|
|
290
259
|
const FiltersRow = styled.div`
|
|
@@ -306,98 +275,6 @@ const ResultsWrapper = styled.div`
|
|
|
306
275
|
border-radius: 4px;
|
|
307
276
|
`;
|
|
308
277
|
|
|
309
|
-
const tableRowBase = `
|
|
310
|
-
display: grid;
|
|
311
|
-
grid-template-columns: 32px 1fr 120px 60px;
|
|
312
|
-
align-items: center;
|
|
313
|
-
gap: 8px;
|
|
314
|
-
padding: 6px 12px;
|
|
315
|
-
`;
|
|
316
|
-
|
|
317
|
-
const ResultsHeader = styled.div`
|
|
318
|
-
${tableRowBase}
|
|
319
|
-
background: rgba(0, 0, 0, 0.4);
|
|
320
|
-
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
|
321
|
-
position: sticky;
|
|
322
|
-
top: 0;
|
|
323
|
-
z-index: 1;
|
|
324
|
-
|
|
325
|
-
> * {
|
|
326
|
-
font-size: 0.45rem;
|
|
327
|
-
color: #888;
|
|
328
|
-
text-transform: uppercase;
|
|
329
|
-
letter-spacing: 1px;
|
|
330
|
-
}
|
|
331
|
-
`;
|
|
332
|
-
|
|
333
|
-
const ResultRow = styled.div`
|
|
334
|
-
${tableRowBase}
|
|
335
|
-
border-bottom: 1px solid rgba(255, 255, 255, 0.04);
|
|
336
|
-
cursor: pointer;
|
|
337
|
-
transition: background 0.1s;
|
|
338
|
-
|
|
339
|
-
&:hover {
|
|
340
|
-
background: rgba(245, 158, 11, 0.08);
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
&:last-child {
|
|
344
|
-
border-bottom: none;
|
|
345
|
-
}
|
|
346
|
-
`;
|
|
347
|
-
|
|
348
|
-
const SpriteWrapper = styled.div`
|
|
349
|
-
display: flex;
|
|
350
|
-
align-items: center;
|
|
351
|
-
justify-content: center;
|
|
352
|
-
width: 32px;
|
|
353
|
-
height: 32px;
|
|
354
|
-
`;
|
|
355
|
-
|
|
356
|
-
const ColName = styled.div`
|
|
357
|
-
display: flex;
|
|
358
|
-
flex-direction: column;
|
|
359
|
-
gap: 2px;
|
|
360
|
-
overflow: hidden;
|
|
361
|
-
`;
|
|
362
|
-
|
|
363
|
-
const BlueprintName = styled.span`
|
|
364
|
-
font-size: 0.5rem;
|
|
365
|
-
color: #ddd;
|
|
366
|
-
overflow: hidden;
|
|
367
|
-
text-overflow: ellipsis;
|
|
368
|
-
white-space: nowrap;
|
|
369
|
-
`;
|
|
370
|
-
|
|
371
|
-
const BlueprintKey = styled.span`
|
|
372
|
-
font-size: 0.4rem;
|
|
373
|
-
color: #666;
|
|
374
|
-
overflow: hidden;
|
|
375
|
-
text-overflow: ellipsis;
|
|
376
|
-
white-space: nowrap;
|
|
377
|
-
`;
|
|
378
|
-
|
|
379
|
-
const ColType = styled.div`
|
|
380
|
-
display: flex;
|
|
381
|
-
flex-direction: column;
|
|
382
|
-
gap: 2px;
|
|
383
|
-
`;
|
|
384
|
-
|
|
385
|
-
const TypeText = styled.span`
|
|
386
|
-
font-size: 0.45rem;
|
|
387
|
-
color: #aaa;
|
|
388
|
-
`;
|
|
389
|
-
|
|
390
|
-
const SubTypeText = styled.span`
|
|
391
|
-
font-size: 0.4rem;
|
|
392
|
-
color: #666;
|
|
393
|
-
`;
|
|
394
|
-
|
|
395
|
-
const ColTier = styled.div`
|
|
396
|
-
font-size: 0.5rem;
|
|
397
|
-
color: #f59e0b;
|
|
398
|
-
text-align: center;
|
|
399
|
-
`;
|
|
400
|
-
|
|
401
278
|
const EmptyState = styled.div`
|
|
402
279
|
display: flex;
|
|
403
280
|
align-items: center;
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { IMarketplaceBlueprintSummary } from '@rpg-engine/shared';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import styled from 'styled-components';
|
|
4
|
+
import { SpriteFromAtlas } from '../shared/SpriteFromAtlas';
|
|
5
|
+
|
|
6
|
+
export interface IBlueprintTableProps {
|
|
7
|
+
blueprints: IMarketplaceBlueprintSummary[];
|
|
8
|
+
atlasJSON: any;
|
|
9
|
+
atlasIMG: any;
|
|
10
|
+
onSelect?: (blueprint: IMarketplaceBlueprintSummary) => void;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const BlueprintTable: React.FC<IBlueprintTableProps> = ({
|
|
14
|
+
blueprints,
|
|
15
|
+
atlasJSON,
|
|
16
|
+
atlasIMG,
|
|
17
|
+
onSelect,
|
|
18
|
+
}) => {
|
|
19
|
+
return (
|
|
20
|
+
<>
|
|
21
|
+
<ResultsHeader>
|
|
22
|
+
<span />
|
|
23
|
+
<ColName>Name</ColName>
|
|
24
|
+
<ColType>Type</ColType>
|
|
25
|
+
<ColTier>Tier</ColTier>
|
|
26
|
+
</ResultsHeader>
|
|
27
|
+
{blueprints.map((blueprint) => (
|
|
28
|
+
<ResultRow
|
|
29
|
+
key={blueprint.key}
|
|
30
|
+
$selectable={!!onSelect}
|
|
31
|
+
onPointerDown={onSelect ? () => onSelect(blueprint) : undefined}
|
|
32
|
+
>
|
|
33
|
+
<SpriteWrapper>
|
|
34
|
+
<SpriteFromAtlas
|
|
35
|
+
atlasJSON={atlasJSON}
|
|
36
|
+
atlasIMG={atlasIMG}
|
|
37
|
+
spriteKey={blueprint.texturePath || blueprint.key}
|
|
38
|
+
width={32}
|
|
39
|
+
height={32}
|
|
40
|
+
imgScale={2}
|
|
41
|
+
centered
|
|
42
|
+
/>
|
|
43
|
+
</SpriteWrapper>
|
|
44
|
+
<ColName>
|
|
45
|
+
<BlueprintName>{blueprint.name}</BlueprintName>
|
|
46
|
+
{(blueprint.type || blueprint.subType) && (
|
|
47
|
+
<BlueprintMeta>
|
|
48
|
+
{[blueprint.type, blueprint.subType]
|
|
49
|
+
.filter(Boolean)
|
|
50
|
+
.filter((v, i, arr) => arr.indexOf(v) === i)
|
|
51
|
+
.join(' · ')}
|
|
52
|
+
</BlueprintMeta>
|
|
53
|
+
)}
|
|
54
|
+
</ColName>
|
|
55
|
+
<ColType>
|
|
56
|
+
<TypeText>{blueprint.type}</TypeText>
|
|
57
|
+
{blueprint.subType && blueprint.subType !== blueprint.type && (
|
|
58
|
+
<SubTypeText>{blueprint.subType}</SubTypeText>
|
|
59
|
+
)}
|
|
60
|
+
</ColType>
|
|
61
|
+
<ColTier>T{blueprint.tier}</ColTier>
|
|
62
|
+
</ResultRow>
|
|
63
|
+
))}
|
|
64
|
+
</>
|
|
65
|
+
);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const tableRowBase = `
|
|
69
|
+
display: grid;
|
|
70
|
+
grid-template-columns: 40px 1fr 120px 50px;
|
|
71
|
+
align-items: center;
|
|
72
|
+
gap: 8px;
|
|
73
|
+
padding: 6px 12px;
|
|
74
|
+
`;
|
|
75
|
+
|
|
76
|
+
const ResultsHeader = styled.div`
|
|
77
|
+
${tableRowBase}
|
|
78
|
+
background: rgba(0, 0, 0, 0.4);
|
|
79
|
+
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
|
80
|
+
position: sticky;
|
|
81
|
+
top: 0;
|
|
82
|
+
z-index: 1;
|
|
83
|
+
|
|
84
|
+
> * {
|
|
85
|
+
font-size: 0.45rem;
|
|
86
|
+
color: #888;
|
|
87
|
+
text-transform: uppercase;
|
|
88
|
+
letter-spacing: 1px;
|
|
89
|
+
}
|
|
90
|
+
`;
|
|
91
|
+
|
|
92
|
+
const ResultRow = styled.div<{ $selectable: boolean }>`
|
|
93
|
+
${tableRowBase}
|
|
94
|
+
border-bottom: 1px solid rgba(255, 255, 255, 0.04);
|
|
95
|
+
cursor: ${p => p.$selectable ? 'pointer' : 'default'};
|
|
96
|
+
transition: background 0.1s;
|
|
97
|
+
|
|
98
|
+
&:hover {
|
|
99
|
+
background: ${p => p.$selectable ? 'rgba(245, 158, 11, 0.08)' : 'none'};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
&:last-child {
|
|
103
|
+
border-bottom: none;
|
|
104
|
+
}
|
|
105
|
+
`;
|
|
106
|
+
|
|
107
|
+
const SpriteWrapper = styled.div`
|
|
108
|
+
display: flex;
|
|
109
|
+
align-items: center;
|
|
110
|
+
justify-content: center;
|
|
111
|
+
width: 40px;
|
|
112
|
+
height: 32px;
|
|
113
|
+
`;
|
|
114
|
+
|
|
115
|
+
const ColName = styled.div`
|
|
116
|
+
display: flex;
|
|
117
|
+
flex-direction: column;
|
|
118
|
+
gap: 2px;
|
|
119
|
+
overflow: hidden;
|
|
120
|
+
`;
|
|
121
|
+
|
|
122
|
+
const BlueprintName = styled.span`
|
|
123
|
+
font-size: 0.5rem;
|
|
124
|
+
color: #ddd;
|
|
125
|
+
overflow: hidden;
|
|
126
|
+
text-overflow: ellipsis;
|
|
127
|
+
white-space: nowrap;
|
|
128
|
+
`;
|
|
129
|
+
|
|
130
|
+
const BlueprintMeta = styled.span`
|
|
131
|
+
font-size: 0.4rem;
|
|
132
|
+
color: #666;
|
|
133
|
+
overflow: hidden;
|
|
134
|
+
text-overflow: ellipsis;
|
|
135
|
+
white-space: nowrap;
|
|
136
|
+
`;
|
|
137
|
+
|
|
138
|
+
const ColType = styled.div`
|
|
139
|
+
display: flex;
|
|
140
|
+
flex-direction: column;
|
|
141
|
+
gap: 2px;
|
|
142
|
+
`;
|
|
143
|
+
|
|
144
|
+
const TypeText = styled.span`
|
|
145
|
+
font-size: 0.45rem;
|
|
146
|
+
color: #aaa;
|
|
147
|
+
`;
|
|
148
|
+
|
|
149
|
+
const SubTypeText = styled.span`
|
|
150
|
+
font-size: 0.4rem;
|
|
151
|
+
color: #666;
|
|
152
|
+
`;
|
|
153
|
+
|
|
154
|
+
const ColTier = styled.div`
|
|
155
|
+
font-size: 0.5rem;
|
|
156
|
+
color: #f59e0b;
|
|
157
|
+
text-align: center;
|
|
158
|
+
`;
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
import { ShoppingCart } from 'pixelarticons/react/ShoppingCart';
|
|
5
5
|
import React from 'react';
|
|
6
6
|
import { FaTimes } from 'react-icons/fa';
|
|
7
|
-
import styled from 'styled-components';
|
|
7
|
+
import styled, { keyframes } from 'styled-components';
|
|
8
8
|
import { Dropdown } from '../Dropdown';
|
|
9
9
|
import { IOptionsProps } from '../Dropdown';
|
|
10
10
|
import { Input } from '../Input';
|
|
@@ -27,6 +27,11 @@ export interface IBuyOrderDetailsModalProps {
|
|
|
27
27
|
atlasIMG: any;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
const scaleIn = keyframes`
|
|
31
|
+
from { transform: scale(0.85); opacity: 0; }
|
|
32
|
+
to { transform: scale(1); opacity: 1; }
|
|
33
|
+
`;
|
|
34
|
+
|
|
30
35
|
const rarityOptions: IOptionsProps[] = [
|
|
31
36
|
{ id: 1, value: 'Common', option: 'Common' },
|
|
32
37
|
{ id: 2, value: 'Uncommon', option: 'Uncommon' },
|
|
@@ -89,7 +94,7 @@ export const BuyOrderDetailsModal: React.FC<IBuyOrderDetailsModalProps> = ({
|
|
|
89
94
|
</SpriteWrapper>
|
|
90
95
|
<ItemInfo>
|
|
91
96
|
<ItemName>{blueprint.name}</ItemName>
|
|
92
|
-
<
|
|
97
|
+
<ItemMeta>{[blueprint.type, blueprint.subType].filter(Boolean).filter((v, i, arr) => arr.indexOf(v) === i).join(' · ')} · T{blueprint.tier}</ItemMeta>
|
|
93
98
|
</ItemInfo>
|
|
94
99
|
</ItemDisplay>
|
|
95
100
|
|
|
@@ -170,12 +175,7 @@ const ModalContent = styled.div`
|
|
|
170
175
|
flex-direction: column;
|
|
171
176
|
gap: 16px;
|
|
172
177
|
pointer-events: auto;
|
|
173
|
-
animation: scaleIn 0.15s ease-out;
|
|
174
|
-
|
|
175
|
-
@keyframes scaleIn {
|
|
176
|
-
from { transform: scale(0.85); opacity: 0; }
|
|
177
|
-
to { transform: scale(1); opacity: 1; }
|
|
178
|
-
}
|
|
178
|
+
animation: ${scaleIn} 0.15s ease-out;
|
|
179
179
|
`;
|
|
180
180
|
|
|
181
181
|
const Header = styled.div`
|
|
@@ -238,7 +238,7 @@ const ItemName = styled.span`
|
|
|
238
238
|
white-space: nowrap;
|
|
239
239
|
`;
|
|
240
240
|
|
|
241
|
-
const
|
|
241
|
+
const ItemMeta = styled.span`
|
|
242
242
|
font-size: 0.4rem;
|
|
243
243
|
color: #666;
|
|
244
244
|
overflow: hidden;
|
|
@@ -270,7 +270,6 @@ const Label = styled.label`
|
|
|
270
270
|
`;
|
|
271
271
|
|
|
272
272
|
const StyledInput = styled(Input)`
|
|
273
|
-
height: 10px;
|
|
274
273
|
width: 100%;
|
|
275
274
|
`;
|
|
276
275
|
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
IMarketplaceBuyOrderItem,
|
|
4
4
|
} from '@rpg-engine/shared';
|
|
5
5
|
import { Search } from 'pixelarticons/react/Search';
|
|
6
|
-
import React from 'react';
|
|
6
|
+
import React, { useEffect, useState } from 'react';
|
|
7
7
|
import styled from 'styled-components';
|
|
8
8
|
import { Pager } from '../Pager';
|
|
9
9
|
import { CTAButton } from '../shared/CTAButton/CTAButton';
|
|
@@ -56,23 +56,41 @@ export const BuyOrderPanel: React.FC<IBuyOrderPanelProps> = (props) => {
|
|
|
56
56
|
onCancelBuyOrder,
|
|
57
57
|
} = props;
|
|
58
58
|
|
|
59
|
+
// Local blueprint display: cleared immediately on Place Request so the
|
|
60
|
+
// panel returns to "Select Item" without waiting for the consumer to update
|
|
61
|
+
// the prop. Cancel keeps it shown so the user can reopen the modal.
|
|
62
|
+
const [displayedBlueprint, setDisplayedBlueprint] = useState(selectedBlueprint);
|
|
63
|
+
const [isDetailsOpen, setIsDetailsOpen] = useState(!!selectedBlueprint);
|
|
64
|
+
|
|
65
|
+
// Sync when consumer provides a new blueprint (e.g. after search selection)
|
|
66
|
+
useEffect(() => {
|
|
67
|
+
if (selectedBlueprint) {
|
|
68
|
+
setDisplayedBlueprint(selectedBlueprint);
|
|
69
|
+
setIsDetailsOpen(true);
|
|
70
|
+
}
|
|
71
|
+
}, [selectedBlueprint]);
|
|
72
|
+
|
|
73
|
+
// Place request: clear display + close modal, then notify consumer
|
|
59
74
|
const handleConfirm = () => {
|
|
60
75
|
onPlaceBuyOrder();
|
|
76
|
+
setDisplayedBlueprint(undefined);
|
|
77
|
+
setIsDetailsOpen(false);
|
|
61
78
|
onCloseDetails?.();
|
|
62
79
|
};
|
|
63
80
|
|
|
81
|
+
// Cancel: just close the modal, keep blueprint displayed for reopening
|
|
64
82
|
const handleCloseDetails = () => {
|
|
65
|
-
|
|
83
|
+
setIsDetailsOpen(false);
|
|
66
84
|
};
|
|
67
85
|
|
|
68
86
|
return (
|
|
69
87
|
<PanelWrapper>
|
|
70
88
|
{/* ── Details modal ── */}
|
|
71
|
-
{
|
|
89
|
+
{displayedBlueprint && isDetailsOpen && (
|
|
72
90
|
<BuyOrderDetailsModal
|
|
73
91
|
isOpen
|
|
74
92
|
onClose={handleCloseDetails}
|
|
75
|
-
blueprint={
|
|
93
|
+
blueprint={displayedBlueprint}
|
|
76
94
|
quantity={currentQuantity}
|
|
77
95
|
maxPrice={currentMaxPrice}
|
|
78
96
|
rarity={selectedRarity}
|
|
@@ -87,13 +105,13 @@ export const BuyOrderPanel: React.FC<IBuyOrderPanelProps> = (props) => {
|
|
|
87
105
|
|
|
88
106
|
{/* ── Form row — outside scroll so dropdown isn't clipped ── */}
|
|
89
107
|
<FormRow>
|
|
90
|
-
{
|
|
108
|
+
{displayedBlueprint ? (
|
|
91
109
|
<SelectedBlueprintDisplay onPointerDown={onOpenBlueprintSearch}>
|
|
92
110
|
<RarityContainer $rarity={selectedRarity}>
|
|
93
111
|
<SpriteFromAtlas
|
|
94
112
|
atlasIMG={atlasIMG}
|
|
95
113
|
atlasJSON={atlasJSON}
|
|
96
|
-
spriteKey={
|
|
114
|
+
spriteKey={displayedBlueprint.texturePath || displayedBlueprint.key}
|
|
97
115
|
width={32}
|
|
98
116
|
height={32}
|
|
99
117
|
imgScale={2}
|
|
@@ -101,7 +119,7 @@ export const BuyOrderPanel: React.FC<IBuyOrderPanelProps> = (props) => {
|
|
|
101
119
|
/>
|
|
102
120
|
</RarityContainer>
|
|
103
121
|
<ChangeTextWrapper>
|
|
104
|
-
<BlueprintName>{
|
|
122
|
+
<BlueprintName>{displayedBlueprint.name}</BlueprintName>
|
|
105
123
|
<ChangeText>change</ChangeText>
|
|
106
124
|
</ChangeTextWrapper>
|
|
107
125
|
</SelectedBlueprintDisplay>
|