@rpg-engine/long-bow 0.8.206 → 0.8.208
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/CharacterListingModal.d.ts +2 -0
- package/dist/components/Marketplace/MyCharacterListingsPanel.d.ts +2 -0
- package/dist/long-bow.cjs.development.js +150 -69
- 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 +150 -69
- package/dist/long-bow.esm.js.map +1 -1
- package/package.json +2 -2
- package/src/components/Marketplace/CharacterDetailModal.tsx +185 -96
- package/src/components/Marketplace/CharacterListingModal.tsx +37 -16
- package/src/components/Marketplace/Marketplace.tsx +1 -0
- package/src/components/Marketplace/MyCharacterListingsPanel.tsx +4 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rpg-engine/long-bow",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.208",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"typings": "dist/index.d.ts",
|
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
"dependencies": {
|
|
85
85
|
"@capacitor/core": "^6.1.0",
|
|
86
86
|
"@rollup/plugin-image": "^2.1.1",
|
|
87
|
-
"@rpg-engine/shared": "^0.10.
|
|
87
|
+
"@rpg-engine/shared": "^0.10.115",
|
|
88
88
|
"dayjs": "^1.11.2",
|
|
89
89
|
"font-awesome": "^4.7.0",
|
|
90
90
|
"fs-extra": "^10.1.0",
|
|
@@ -5,6 +5,7 @@ import { FaTimes } from 'react-icons/fa';
|
|
|
5
5
|
import styled, { keyframes } from 'styled-components';
|
|
6
6
|
import ModalPortal from '../Abstractions/ModalPortal';
|
|
7
7
|
import { ConfirmModal } from '../ConfirmModal';
|
|
8
|
+
import { gemColors } from '../Item/Inventory/ItemGem';
|
|
8
9
|
import { CTAButton } from '../shared/CTAButton/CTAButton';
|
|
9
10
|
import { SpriteFromAtlas } from '../shared/SpriteFromAtlas';
|
|
10
11
|
|
|
@@ -34,6 +35,12 @@ const RARITY_COLORS: Record<string, string> = {
|
|
|
34
35
|
const rarityColor = (rarity?: string) =>
|
|
35
36
|
RARITY_COLORS[(rarity ?? '').toLowerCase()] ?? RARITY_COLORS.common;
|
|
36
37
|
|
|
38
|
+
const rarityGlowColor = (rarity?: string): string | null => {
|
|
39
|
+
const key = (rarity ?? '').toLowerCase();
|
|
40
|
+
if (!key || key === 'common') return null;
|
|
41
|
+
return RARITY_COLORS[key] ?? null;
|
|
42
|
+
};
|
|
43
|
+
|
|
37
44
|
const formatEquipmentSlot = (slot?: string) => {
|
|
38
45
|
if (!slot) return 'Unknown';
|
|
39
46
|
|
|
@@ -86,9 +93,9 @@ export const CharacterDetailModal: React.FC<ICharacterDetailModalProps> = ({
|
|
|
86
93
|
if (!isOpen || !listing) return null;
|
|
87
94
|
|
|
88
95
|
const snap = listing.characterSnapshot;
|
|
89
|
-
const topSkills = Object.entries(snap.skills ?? {})
|
|
90
|
-
|
|
91
|
-
|
|
96
|
+
const topSkills = Object.entries(snap.skills ?? {}).sort(
|
|
97
|
+
([, a], [, b]) => b - a
|
|
98
|
+
);
|
|
92
99
|
|
|
93
100
|
return (
|
|
94
101
|
<ModalPortal>
|
|
@@ -121,83 +128,101 @@ export const CharacterDetailModal: React.FC<ICharacterDetailModalProps> = ({
|
|
|
121
128
|
</CloseButton>
|
|
122
129
|
</Header>
|
|
123
130
|
|
|
124
|
-
<
|
|
125
|
-
<
|
|
126
|
-
<
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
<
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
{snap.mode
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
131
|
+
<ScrollableBody>
|
|
132
|
+
<HeroSection>
|
|
133
|
+
<SpriteContainer>
|
|
134
|
+
<SpriteFromAtlas
|
|
135
|
+
atlasIMG={characterAtlasIMG}
|
|
136
|
+
atlasJSON={characterAtlasJSON}
|
|
137
|
+
spriteKey={`${snap.textureKey}/down/standing/0.png`}
|
|
138
|
+
imgScale={4}
|
|
139
|
+
height={96}
|
|
140
|
+
width={96}
|
|
141
|
+
centered
|
|
142
|
+
/>
|
|
143
|
+
</SpriteContainer>
|
|
144
|
+
<HeroInfo>
|
|
145
|
+
<CharacterName>{snap.name || 'Unknown'}</CharacterName>
|
|
146
|
+
<CharacterClass>
|
|
147
|
+
Lv.{snap.level} · {snap.class}
|
|
148
|
+
</CharacterClass>
|
|
149
|
+
<CharacterOrigin>
|
|
150
|
+
{snap.race} · {snap.faction}
|
|
151
|
+
</CharacterOrigin>
|
|
152
|
+
<ModeBadge $hardcore={snap.mode?.toLowerCase() === 'hardcore'}>
|
|
153
|
+
{snap.mode || 'Standard'}
|
|
154
|
+
</ModeBadge>
|
|
155
|
+
{snap.gold != null && snap.gold > 0 && (
|
|
156
|
+
<GoldRow>
|
|
157
|
+
<GoldLabel>GOLD</GoldLabel>
|
|
158
|
+
<GoldAmount>{snap.gold.toLocaleString()}</GoldAmount>
|
|
159
|
+
</GoldRow>
|
|
160
|
+
)}
|
|
161
|
+
</HeroInfo>
|
|
162
|
+
</HeroSection>
|
|
163
|
+
|
|
164
|
+
<Divider />
|
|
165
|
+
|
|
166
|
+
<MetaColumns>
|
|
167
|
+
{topSkills.length > 0 && (
|
|
168
|
+
<Section>
|
|
169
|
+
<SectionTitle>Skills</SectionTitle>
|
|
170
|
+
<SkillsList>
|
|
171
|
+
{topSkills.map(([name, value]) => (
|
|
172
|
+
<SkillRow key={name}>
|
|
173
|
+
<SkillName>{name}</SkillName>
|
|
174
|
+
<SkillValue>{value}</SkillValue>
|
|
175
|
+
</SkillRow>
|
|
176
|
+
))}
|
|
177
|
+
</SkillsList>
|
|
178
|
+
</Section>
|
|
179
|
+
)}
|
|
180
|
+
|
|
181
|
+
{snap.equipment?.length > 0 && (
|
|
182
|
+
<Section>
|
|
183
|
+
<SectionTitle>Equipment</SectionTitle>
|
|
184
|
+
<EquipmentList>
|
|
185
|
+
{snap.equipment.map((eq, i) => (
|
|
186
|
+
<EquipmentRow key={i}>
|
|
187
|
+
<EquipmentSprite $rarity={eq.rarity}>
|
|
188
|
+
<SpriteFromAtlas
|
|
189
|
+
atlasIMG={atlasIMG}
|
|
190
|
+
atlasJSON={atlasJSON}
|
|
191
|
+
spriteKey={eq.itemKey}
|
|
192
|
+
imgScale={2}
|
|
193
|
+
width={32}
|
|
194
|
+
height={32}
|
|
195
|
+
centered
|
|
196
|
+
/>
|
|
197
|
+
{eq.attachedGems && eq.attachedGems.length > 0 && (
|
|
198
|
+
<GemRow>
|
|
199
|
+
{eq.attachedGems.map((gem, gi) => (
|
|
200
|
+
<GemDot
|
|
201
|
+
key={gi}
|
|
202
|
+
$color={gemColors[gem.key] ?? '#fff'}
|
|
203
|
+
/>
|
|
204
|
+
))}
|
|
205
|
+
</GemRow>
|
|
206
|
+
)}
|
|
207
|
+
</EquipmentSprite>
|
|
208
|
+
<EquipMeta>
|
|
209
|
+
<EquipName>{eq.itemName}</EquipName>
|
|
210
|
+
<EquipDetails>
|
|
211
|
+
<EquipSlot>{formatEquipmentSlot(eq.slot)}</EquipSlot>
|
|
212
|
+
<RarityBadge $rarity={eq.rarity}>
|
|
213
|
+
{eq.rarity || 'Common'}
|
|
214
|
+
</RarityBadge>
|
|
215
|
+
</EquipDetails>
|
|
216
|
+
</EquipMeta>
|
|
217
|
+
</EquipmentRow>
|
|
218
|
+
))}
|
|
219
|
+
</EquipmentList>
|
|
220
|
+
</Section>
|
|
221
|
+
)}
|
|
222
|
+
</MetaColumns>
|
|
223
|
+
</ScrollableBody>
|
|
224
|
+
|
|
225
|
+
<FooterDivider />
|
|
201
226
|
|
|
202
227
|
<Footer>
|
|
203
228
|
<SellerInfo>Listed by {listing.listedByCharacterName}</SellerInfo>
|
|
@@ -257,29 +282,16 @@ const ModalContent = styled.div`
|
|
|
257
282
|
background: #1a1a2e;
|
|
258
283
|
border: 2px solid #f59e0b;
|
|
259
284
|
border-radius: 8px;
|
|
260
|
-
padding: 20px 24px;
|
|
285
|
+
padding: 20px 24px 16px;
|
|
261
286
|
width: 580px;
|
|
262
287
|
max-width: 96%;
|
|
263
288
|
max-height: 85dvh;
|
|
264
289
|
display: flex;
|
|
265
290
|
flex-direction: column;
|
|
266
291
|
gap: 14px;
|
|
267
|
-
overflow
|
|
268
|
-
overflow-x: hidden;
|
|
292
|
+
overflow: hidden;
|
|
269
293
|
pointer-events: auto;
|
|
270
294
|
animation: ${scaleIn} 0.15s ease-out;
|
|
271
|
-
|
|
272
|
-
&::-webkit-scrollbar {
|
|
273
|
-
width: 6px;
|
|
274
|
-
}
|
|
275
|
-
&::-webkit-scrollbar-track {
|
|
276
|
-
background: rgba(0, 0, 0, 0.2);
|
|
277
|
-
border-radius: 4px;
|
|
278
|
-
}
|
|
279
|
-
&::-webkit-scrollbar-thumb {
|
|
280
|
-
background: rgba(245, 158, 11, 0.3);
|
|
281
|
-
border-radius: 4px;
|
|
282
|
-
}
|
|
283
295
|
`;
|
|
284
296
|
|
|
285
297
|
const Header = styled.div`
|
|
@@ -377,6 +389,30 @@ const Divider = styled.hr`
|
|
|
377
389
|
flex-shrink: 0;
|
|
378
390
|
`;
|
|
379
391
|
|
|
392
|
+
const FooterDivider = styled(Divider)``;
|
|
393
|
+
|
|
394
|
+
const ScrollableBody = styled.div`
|
|
395
|
+
flex: 1;
|
|
396
|
+
overflow-y: auto;
|
|
397
|
+
overflow-x: hidden;
|
|
398
|
+
display: flex;
|
|
399
|
+
flex-direction: column;
|
|
400
|
+
gap: 14px;
|
|
401
|
+
min-height: 0;
|
|
402
|
+
|
|
403
|
+
&::-webkit-scrollbar {
|
|
404
|
+
width: 6px;
|
|
405
|
+
}
|
|
406
|
+
&::-webkit-scrollbar-track {
|
|
407
|
+
background: rgba(0, 0, 0, 0.2);
|
|
408
|
+
border-radius: 4px;
|
|
409
|
+
}
|
|
410
|
+
&::-webkit-scrollbar-thumb {
|
|
411
|
+
background: rgba(245, 158, 11, 0.3);
|
|
412
|
+
border-radius: 4px;
|
|
413
|
+
}
|
|
414
|
+
`;
|
|
415
|
+
|
|
380
416
|
const Section = styled.div`
|
|
381
417
|
display: flex;
|
|
382
418
|
flex-direction: column;
|
|
@@ -445,13 +481,66 @@ const EquipmentRow = styled.div`
|
|
|
445
481
|
min-width: 0;
|
|
446
482
|
`;
|
|
447
483
|
|
|
448
|
-
const EquipmentSprite = styled.div
|
|
484
|
+
const EquipmentSprite = styled.div<{ $rarity?: string }>`
|
|
485
|
+
position: relative;
|
|
449
486
|
display: flex;
|
|
450
487
|
align-items: center;
|
|
451
488
|
justify-content: center;
|
|
452
489
|
width: 32px;
|
|
453
490
|
height: 32px;
|
|
454
491
|
flex-shrink: 0;
|
|
492
|
+
border-radius: 3px;
|
|
493
|
+
${({ $rarity }) => {
|
|
494
|
+
const color = rarityGlowColor($rarity);
|
|
495
|
+
return color
|
|
496
|
+
? `box-shadow: 0 0 4px 3px ${color} inset, 0 0 6px 2px ${color};`
|
|
497
|
+
: '';
|
|
498
|
+
}}
|
|
499
|
+
`;
|
|
500
|
+
|
|
501
|
+
const GemRow = styled.div`
|
|
502
|
+
position: absolute;
|
|
503
|
+
bottom: -1px;
|
|
504
|
+
left: 0;
|
|
505
|
+
display: flex;
|
|
506
|
+
gap: 1px;
|
|
507
|
+
pointer-events: none;
|
|
508
|
+
`;
|
|
509
|
+
|
|
510
|
+
const GemDot = styled.div<{ $color: string }>`
|
|
511
|
+
width: 5px;
|
|
512
|
+
height: 5px;
|
|
513
|
+
border-radius: 1px;
|
|
514
|
+
transform: rotate(45deg);
|
|
515
|
+
background: radial-gradient(
|
|
516
|
+
circle at 30% 30%,
|
|
517
|
+
rgba(255, 255, 255, 0.8),
|
|
518
|
+
transparent 40%
|
|
519
|
+
),
|
|
520
|
+
linear-gradient(45deg, ${({ $color }) => $color}, rgba(255, 255, 255, 0.2));
|
|
521
|
+
border: 1px solid rgba(0, 0, 0, 0.6);
|
|
522
|
+
box-shadow: 0 0 3px ${({ $color }) => $color};
|
|
523
|
+
`;
|
|
524
|
+
|
|
525
|
+
const GoldRow = styled.div`
|
|
526
|
+
display: flex;
|
|
527
|
+
align-items: center;
|
|
528
|
+
gap: 4px;
|
|
529
|
+
margin-top: 2px;
|
|
530
|
+
`;
|
|
531
|
+
|
|
532
|
+
const GoldLabel = styled.span`
|
|
533
|
+
font-family: 'Press Start 2P', cursive !important;
|
|
534
|
+
font-size: 0.35rem !important;
|
|
535
|
+
color: #6b7280 !important;
|
|
536
|
+
text-transform: uppercase;
|
|
537
|
+
letter-spacing: 0.5px;
|
|
538
|
+
`;
|
|
539
|
+
|
|
540
|
+
const GoldAmount = styled.span`
|
|
541
|
+
font-family: 'Press Start 2P', cursive !important;
|
|
542
|
+
font-size: 0.38rem !important;
|
|
543
|
+
color: #fde68a !important;
|
|
455
544
|
`;
|
|
456
545
|
|
|
457
546
|
const EquipMeta = styled.div`
|
|
@@ -15,6 +15,8 @@ export interface ICharacterListingModalProps {
|
|
|
15
15
|
isOpen: boolean;
|
|
16
16
|
onClose: () => void;
|
|
17
17
|
accountCharacters: ICharacter[];
|
|
18
|
+
/** ID of the currently active/playing character — cannot be listed */
|
|
19
|
+
activeCharacterId?: string;
|
|
18
20
|
/** Items atlas — for UI sprites like the DC coin */
|
|
19
21
|
atlasJSON: any;
|
|
20
22
|
atlasIMG: any;
|
|
@@ -30,6 +32,7 @@ export const CharacterListingModal: React.FC<ICharacterListingModalProps> = ({
|
|
|
30
32
|
isOpen,
|
|
31
33
|
onClose,
|
|
32
34
|
accountCharacters,
|
|
35
|
+
activeCharacterId,
|
|
33
36
|
atlasJSON,
|
|
34
37
|
atlasIMG,
|
|
35
38
|
characterAtlasJSON,
|
|
@@ -55,7 +58,9 @@ export const CharacterListingModal: React.FC<ICharacterListingModalProps> = ({
|
|
|
55
58
|
c => !c.isListedForSale && !c.tradedAt
|
|
56
59
|
);
|
|
57
60
|
|
|
58
|
-
const
|
|
61
|
+
const isActiveCharacter = (c: ICharacter) => !!activeCharacterId && c._id === activeCharacterId;
|
|
62
|
+
|
|
63
|
+
const canList = !!selectedId && Number(price) > 0 && selectedId !== activeCharacterId;
|
|
59
64
|
|
|
60
65
|
const handleClose = () => {
|
|
61
66
|
setSelectedId(null);
|
|
@@ -110,22 +115,25 @@ export const CharacterListingModal: React.FC<ICharacterListingModalProps> = ({
|
|
|
110
115
|
) : (
|
|
111
116
|
eligibleCharacters.map(character => {
|
|
112
117
|
const isSelected = selectedId === character._id;
|
|
118
|
+
const isActive = isActiveCharacter(character);
|
|
113
119
|
return (
|
|
114
120
|
<CharacterRow
|
|
115
121
|
key={character._id}
|
|
116
|
-
$selected={isSelected}
|
|
117
|
-
|
|
122
|
+
$selected={isSelected && !isActive}
|
|
123
|
+
$disabled={isActive}
|
|
124
|
+
onPointerDown={() => !isActive && setSelectedId(character._id!)}
|
|
118
125
|
role="radio"
|
|
119
|
-
aria-checked={isSelected}
|
|
120
|
-
|
|
126
|
+
aria-checked={isSelected && !isActive}
|
|
127
|
+
aria-disabled={isActive}
|
|
128
|
+
tabIndex={isActive ? -1 : 0}
|
|
121
129
|
onKeyDown={e => {
|
|
122
|
-
if (e.key === 'Enter' || e.key === ' ') {
|
|
130
|
+
if (!isActive && (e.key === 'Enter' || e.key === ' ')) {
|
|
123
131
|
e.preventDefault();
|
|
124
132
|
setSelectedId(character._id!);
|
|
125
133
|
}
|
|
126
134
|
}}
|
|
127
135
|
>
|
|
128
|
-
<RadioCircle $selected={isSelected} />
|
|
136
|
+
<RadioCircle $selected={isSelected && !isActive} $disabled={isActive} />
|
|
129
137
|
<SpriteWrapper>
|
|
130
138
|
<SpriteFromAtlas
|
|
131
139
|
atlasIMG={characterAtlasIMG}
|
|
@@ -140,6 +148,7 @@ export const CharacterListingModal: React.FC<ICharacterListingModalProps> = ({
|
|
|
140
148
|
<CharacterName>{character.name || 'Unknown'}</CharacterName>
|
|
141
149
|
<CharacterMeta>Level {getLevel(character)}</CharacterMeta>
|
|
142
150
|
</CharacterInfo>
|
|
151
|
+
{isActive && <ActiveTag>In-game</ActiveTag>}
|
|
143
152
|
</CharacterRow>
|
|
144
153
|
);
|
|
145
154
|
})
|
|
@@ -266,20 +275,21 @@ const CharacterList = styled.div`
|
|
|
266
275
|
&::-webkit-scrollbar-thumb { background: rgba(245,158,11,0.3); border-radius: 4px; }
|
|
267
276
|
`;
|
|
268
277
|
|
|
269
|
-
const CharacterRow = styled.div<{ $selected: boolean }>`
|
|
278
|
+
const CharacterRow = styled.div<{ $selected: boolean; $disabled?: boolean }>`
|
|
270
279
|
display: flex;
|
|
271
280
|
align-items: center;
|
|
272
281
|
gap: 12px;
|
|
273
282
|
padding: 10px 12px;
|
|
274
|
-
border: 1px solid ${({ $selected }) => ($selected ? '#f59e0b' : 'rgba(255,255,255,0.08)')};
|
|
283
|
+
border: 1px solid ${({ $selected, $disabled }) => ($disabled ? 'rgba(255,255,255,0.04)' : $selected ? '#f59e0b' : 'rgba(255,255,255,0.08)')};
|
|
275
284
|
border-radius: 6px;
|
|
276
|
-
background: ${({ $selected }) => ($selected ? 'rgba(245,158,11,0.1)' : 'rgba(255,255,255,0.02)')};
|
|
277
|
-
cursor: pointer;
|
|
285
|
+
background: ${({ $selected, $disabled }) => ($disabled ? 'rgba(0,0,0,0.15)' : $selected ? 'rgba(245,158,11,0.1)' : 'rgba(255,255,255,0.02)')};
|
|
286
|
+
cursor: ${({ $disabled }) => ($disabled ? 'not-allowed' : 'pointer')};
|
|
287
|
+
opacity: ${({ $disabled }) => ($disabled ? 0.5 : 1)};
|
|
278
288
|
transition: border-color 0.15s, background 0.15s;
|
|
279
289
|
|
|
280
290
|
&:hover {
|
|
281
|
-
border-color: ${({ $selected }) => ($selected ? '#f59e0b' : 'rgba(245,158,11,0.4)')};
|
|
282
|
-
background: ${({ $selected }) => ($selected ? 'rgba(245,158,11,0.1)' : 'rgba(245,158,11,0.05)')};
|
|
291
|
+
border-color: ${({ $selected, $disabled }) => ($disabled ? 'rgba(255,255,255,0.04)' : $selected ? '#f59e0b' : 'rgba(245,158,11,0.4)')};
|
|
292
|
+
background: ${({ $selected, $disabled }) => ($disabled ? 'rgba(0,0,0,0.15)' : $selected ? 'rgba(245,158,11,0.1)' : 'rgba(245,158,11,0.05)')};
|
|
283
293
|
}
|
|
284
294
|
|
|
285
295
|
&:focus-visible {
|
|
@@ -288,11 +298,11 @@ const CharacterRow = styled.div<{ $selected: boolean }>`
|
|
|
288
298
|
}
|
|
289
299
|
`;
|
|
290
300
|
|
|
291
|
-
const RadioCircle = styled.div<{ $selected: boolean }>`
|
|
301
|
+
const RadioCircle = styled.div<{ $selected: boolean; $disabled?: boolean }>`
|
|
292
302
|
width: 14px;
|
|
293
303
|
height: 14px;
|
|
294
304
|
border-radius: 50%;
|
|
295
|
-
border: 2px solid ${({ $selected }) => ($selected ? '#f59e0b' : 'rgba(255,255,255,0.4)')};
|
|
305
|
+
border: 2px solid ${({ $selected, $disabled }) => ($disabled ? 'rgba(255,255,255,0.15)' : $selected ? '#f59e0b' : 'rgba(255,255,255,0.4)')};
|
|
296
306
|
flex-shrink: 0;
|
|
297
307
|
display: flex;
|
|
298
308
|
align-items: center;
|
|
@@ -303,12 +313,23 @@ const RadioCircle = styled.div<{ $selected: boolean }>`
|
|
|
303
313
|
width: 6px;
|
|
304
314
|
height: 6px;
|
|
305
315
|
border-radius: 50%;
|
|
306
|
-
background: #f59e0b;
|
|
316
|
+
background: ${({ $disabled }) => ($disabled ? 'rgba(255,255,255,0.15)' : '#f59e0b')};
|
|
307
317
|
opacity: ${({ $selected }) => ($selected ? 1 : 0)};
|
|
308
318
|
transition: opacity 0.15s;
|
|
309
319
|
}
|
|
310
320
|
`;
|
|
311
321
|
|
|
322
|
+
const ActiveTag = styled.span`
|
|
323
|
+
font-family: 'Press Start 2P', cursive !important;
|
|
324
|
+
font-size: 0.35rem !important;
|
|
325
|
+
color: #666 !important;
|
|
326
|
+
background: rgba(255,255,255,0.06);
|
|
327
|
+
padding: 3px 6px;
|
|
328
|
+
border-radius: 3px;
|
|
329
|
+
white-space: nowrap;
|
|
330
|
+
margin-left: auto;
|
|
331
|
+
`;
|
|
332
|
+
|
|
312
333
|
const SpriteWrapper = styled.div`
|
|
313
334
|
display: flex;
|
|
314
335
|
align-items: center;
|
|
@@ -336,6 +336,7 @@ export const Marketplace: React.FC<IMarketPlaceProps> = props => {
|
|
|
336
336
|
onCharacterDelist={onCharacterDelist ?? (() => {})}
|
|
337
337
|
accountCharacters={accountCharacters ?? []}
|
|
338
338
|
onCharacterList={onCharacterList ?? (() => {})}
|
|
339
|
+
activeCharacterId={props.characterId}
|
|
339
340
|
atlasJSON={props.atlasJSON}
|
|
340
341
|
atlasIMG={props.atlasIMG}
|
|
341
342
|
characterAtlasJSON={characterAtlasJSON ?? props.atlasJSON}
|
|
@@ -20,6 +20,8 @@ export interface IMyCharacterListingsPanelProps {
|
|
|
20
20
|
/** Characters that can be listed (used for the List a Character modal) */
|
|
21
21
|
accountCharacters: ICharacter[];
|
|
22
22
|
onCharacterList: (characterId: string, price: number) => void;
|
|
23
|
+
/** ID of the currently active character */
|
|
24
|
+
activeCharacterId?: string;
|
|
23
25
|
/** Items atlas — for UI sprites like the DC coin */
|
|
24
26
|
atlasJSON: any;
|
|
25
27
|
atlasIMG: any;
|
|
@@ -39,6 +41,7 @@ export const MyCharacterListingsPanel: React.FC<IMyCharacterListingsPanelProps>
|
|
|
39
41
|
onCharacterDelist,
|
|
40
42
|
accountCharacters,
|
|
41
43
|
onCharacterList,
|
|
44
|
+
activeCharacterId,
|
|
42
45
|
atlasJSON,
|
|
43
46
|
atlasIMG,
|
|
44
47
|
characterAtlasJSON,
|
|
@@ -80,6 +83,7 @@ export const MyCharacterListingsPanel: React.FC<IMyCharacterListingsPanelProps>
|
|
|
80
83
|
isOpen={isListingModalOpen}
|
|
81
84
|
onClose={() => setIsListingModalOpen(false)}
|
|
82
85
|
accountCharacters={accountCharacters}
|
|
86
|
+
activeCharacterId={activeCharacterId}
|
|
83
87
|
atlasJSON={atlasJSON}
|
|
84
88
|
atlasIMG={atlasIMG}
|
|
85
89
|
characterAtlasJSON={characterAtlasJSON}
|