@rpg-engine/long-bow 0.8.207 → 0.8.209
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/BuyOrderDetailsModal.d.ts +1 -0
- package/dist/components/Marketplace/BuyOrderPanel.d.ts +1 -0
- package/dist/components/Marketplace/Marketplace.d.ts +1 -0
- package/dist/components/Store/Store.d.ts +4 -1
- package/dist/long-bow.cjs.development.js +120 -44
- 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 +121 -45
- package/dist/long-bow.esm.js.map +1 -1
- package/package.json +2 -2
- package/src/components/Marketplace/BuyOrderDetailsModal.tsx +5 -2
- package/src/components/Marketplace/BuyOrderPanel.tsx +3 -0
- package/src/components/Marketplace/CharacterDetailModal.tsx +185 -96
- package/src/components/Marketplace/Marketplace.tsx +4 -0
- package/src/components/Store/Store.tsx +15 -2
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.209",
|
|
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",
|
|
@@ -27,6 +27,7 @@ export interface IBuyOrderDetailsModalProps {
|
|
|
27
27
|
atlasIMG: any;
|
|
28
28
|
enableHotkeys?: () => void;
|
|
29
29
|
disableHotkeys?: () => void;
|
|
30
|
+
scale?: number;
|
|
30
31
|
}
|
|
31
32
|
|
|
32
33
|
const scaleIn = keyframes`
|
|
@@ -57,6 +58,7 @@ export const BuyOrderDetailsModal: React.FC<IBuyOrderDetailsModalProps> = ({
|
|
|
57
58
|
atlasIMG,
|
|
58
59
|
enableHotkeys,
|
|
59
60
|
disableHotkeys,
|
|
61
|
+
scale,
|
|
60
62
|
}) => {
|
|
61
63
|
if (!isOpen || !blueprint) return null;
|
|
62
64
|
|
|
@@ -73,7 +75,7 @@ export const BuyOrderDetailsModal: React.FC<IBuyOrderDetailsModalProps> = ({
|
|
|
73
75
|
return (
|
|
74
76
|
<ModalPortal>
|
|
75
77
|
<Overlay onPointerDown={handleClose} />
|
|
76
|
-
<ModalContainer>
|
|
78
|
+
<ModalContainer $scale={scale}>
|
|
77
79
|
<ModalContent
|
|
78
80
|
onClick={stopPropagation as React.MouseEventHandler}
|
|
79
81
|
onPointerDown={stopPropagation as React.PointerEventHandler}
|
|
@@ -162,7 +164,7 @@ const Overlay = styled.div`
|
|
|
162
164
|
z-index: 1000;
|
|
163
165
|
`;
|
|
164
166
|
|
|
165
|
-
const ModalContainer = styled.div
|
|
167
|
+
const ModalContainer = styled.div<{ $scale?: number }>`
|
|
166
168
|
position: fixed;
|
|
167
169
|
inset: 0;
|
|
168
170
|
display: flex;
|
|
@@ -170,6 +172,7 @@ const ModalContainer = styled.div`
|
|
|
170
172
|
justify-content: center;
|
|
171
173
|
z-index: 1001;
|
|
172
174
|
pointer-events: none;
|
|
175
|
+
${({ $scale }) => $scale !== undefined && $scale !== 1 ? `transform: scale(${$scale});` : ''}
|
|
173
176
|
`;
|
|
174
177
|
|
|
175
178
|
const ModalContent = styled.div`
|
|
@@ -35,6 +35,7 @@ export interface IBuyOrderPanelProps {
|
|
|
35
35
|
onCancelBuyOrder: (buyOrderId: string) => void;
|
|
36
36
|
enableHotkeys?: () => void;
|
|
37
37
|
disableHotkeys?: () => void;
|
|
38
|
+
scale?: number;
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
const BUY_ORDERS_PER_PAGE = 5;
|
|
@@ -60,6 +61,7 @@ export const BuyOrderPanel: React.FC<IBuyOrderPanelProps> = (props) => {
|
|
|
60
61
|
onCancelBuyOrder,
|
|
61
62
|
enableHotkeys,
|
|
62
63
|
disableHotkeys,
|
|
64
|
+
scale,
|
|
63
65
|
} = props;
|
|
64
66
|
|
|
65
67
|
// Local blueprint display: cleared immediately on Place Request so the
|
|
@@ -111,6 +113,7 @@ export const BuyOrderPanel: React.FC<IBuyOrderPanelProps> = (props) => {
|
|
|
111
113
|
atlasIMG={atlasIMG}
|
|
112
114
|
enableHotkeys={enableHotkeys}
|
|
113
115
|
disableHotkeys={disableHotkeys}
|
|
116
|
+
scale={scale}
|
|
114
117
|
/>
|
|
115
118
|
)}
|
|
116
119
|
|
|
@@ -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`
|
|
@@ -136,6 +136,7 @@ export interface IMarketPlaceProps {
|
|
|
136
136
|
characterListingsLoading?: boolean;
|
|
137
137
|
characterNameFilter?: string;
|
|
138
138
|
onCharacterNameFilterChange?: (name: string) => void;
|
|
139
|
+
fullScreen?: boolean;
|
|
139
140
|
}
|
|
140
141
|
|
|
141
142
|
type ActiveTab = 'marketplace' | 'characters' | 'sell' | 'buy-orders' | 'history' | 'wallet' | 'settings';
|
|
@@ -200,6 +201,7 @@ export const Marketplace: React.FC<IMarketPlaceProps> = props => {
|
|
|
200
201
|
onCharacterNameFilterChange,
|
|
201
202
|
characterAtlasIMG,
|
|
202
203
|
characterAtlasJSON,
|
|
204
|
+
fullScreen = false,
|
|
203
205
|
} = props;
|
|
204
206
|
|
|
205
207
|
const [activeTab, setActiveTab] = useState<ActiveTab>('marketplace');
|
|
@@ -233,6 +235,7 @@ export const Marketplace: React.FC<IMarketPlaceProps> = props => {
|
|
|
233
235
|
onCloseButton={() => {
|
|
234
236
|
if (onClose) onClose();
|
|
235
237
|
}}
|
|
238
|
+
isFullScreen={fullScreen}
|
|
236
239
|
width="920px"
|
|
237
240
|
cancelDrag="#MarketContainer, .rpgui-dropdown-imp, input, .empty-slot, button"
|
|
238
241
|
scale={scale}
|
|
@@ -375,6 +378,7 @@ export const Marketplace: React.FC<IMarketPlaceProps> = props => {
|
|
|
375
378
|
onCancelBuyOrder={onCancelBuyOrder ?? (() => {})}
|
|
376
379
|
enableHotkeys={props.enableHotkeys}
|
|
377
380
|
disableHotkeys={props.disableHotkeys}
|
|
381
|
+
scale={scale}
|
|
378
382
|
/>
|
|
379
383
|
<BlueprintSearchModal
|
|
380
384
|
isOpen={isBlueprintSearchOpen}
|
|
@@ -4,7 +4,7 @@ import { Gift } from 'pixelarticons/react/Gift';
|
|
|
4
4
|
import { Package } from 'pixelarticons/react/Package';
|
|
5
5
|
import { Wallet } from 'pixelarticons/react/Wallet';
|
|
6
6
|
import React, { ReactNode, useMemo, useState } from 'react';
|
|
7
|
-
import { FaHistory, FaShoppingCart, FaTicketAlt, FaWallet } from 'react-icons/fa';
|
|
7
|
+
import { FaHistory, FaShoppingCart, FaTicketAlt, FaUsers, FaWallet } from 'react-icons/fa';
|
|
8
8
|
import styled from 'styled-components';
|
|
9
9
|
import { uiColors } from '../../constants/uiColors';
|
|
10
10
|
import { DraggableContainer } from '../DraggableContainer';
|
|
@@ -22,7 +22,7 @@ import { StoreRedeemSection } from './sections/StoreRedeemSection';
|
|
|
22
22
|
import { StoreItemDetails } from './StoreItemDetails';
|
|
23
23
|
|
|
24
24
|
// Define TabId union type for tab identifiers
|
|
25
|
-
type TabId = 'premium' | 'packs' | 'items' | 'wallet' | 'history' | 'redeem';
|
|
25
|
+
type TabId = 'premium' | 'packs' | 'items' | 'characters' | 'wallet' | 'history' | 'redeem';
|
|
26
26
|
|
|
27
27
|
// Define IStoreProps locally as a workaround
|
|
28
28
|
export interface IStoreProps {
|
|
@@ -44,8 +44,11 @@ export interface IStoreProps {
|
|
|
44
44
|
defaultActiveTab?: TabId;
|
|
45
45
|
textInputItemKeys?: string[];
|
|
46
46
|
customPacksContent?: React.ReactNode;
|
|
47
|
+
customCharactersContent?: React.ReactNode;
|
|
47
48
|
customWalletContent?: React.ReactNode;
|
|
48
49
|
customHistoryContent?: React.ReactNode;
|
|
50
|
+
/** When true the store renders full-screen (useful on mobile). */
|
|
51
|
+
fullScreen?: boolean;
|
|
49
52
|
packsBadge?: string;
|
|
50
53
|
featuredItems?: IFeaturedItem[];
|
|
51
54
|
onQuickBuy?: (item: IProductBlueprint, quantity?: number) => void;
|
|
@@ -103,8 +106,10 @@ export const Store: React.FC<IStoreProps> = ({
|
|
|
103
106
|
defaultActiveTab,
|
|
104
107
|
textInputItemKeys = [],
|
|
105
108
|
customPacksContent,
|
|
109
|
+
customCharactersContent,
|
|
106
110
|
customWalletContent,
|
|
107
111
|
customHistoryContent,
|
|
112
|
+
fullScreen = false,
|
|
108
113
|
packsTabLabel = 'Packs',
|
|
109
114
|
packsBadge,
|
|
110
115
|
featuredItems,
|
|
@@ -241,6 +246,7 @@ export const Store: React.FC<IStoreProps> = ({
|
|
|
241
246
|
// Build tabs dynamically based on props
|
|
242
247
|
const tabIds: TabId[] = [
|
|
243
248
|
...(tabOrder ?? defaultTabOrder),
|
|
249
|
+
...(customCharactersContent ? ['characters' as TabId] : []),
|
|
244
250
|
...(onRedeem ? ['redeem' as TabId] : []),
|
|
245
251
|
...((onShowWallet || customWalletContent) ? ['wallet' as TabId] : []),
|
|
246
252
|
...((onShowHistory || customHistoryContent) ? ['history' as TabId] : [])
|
|
@@ -347,6 +353,12 @@ export const Store: React.FC<IStoreProps> = ({
|
|
|
347
353
|
/>
|
|
348
354
|
),
|
|
349
355
|
},
|
|
356
|
+
characters: {
|
|
357
|
+
id: 'characters',
|
|
358
|
+
title: 'Characters',
|
|
359
|
+
icon: <FaUsers size={16} />,
|
|
360
|
+
content: customCharactersContent ?? null,
|
|
361
|
+
},
|
|
350
362
|
redeem: {
|
|
351
363
|
id: 'redeem',
|
|
352
364
|
title: 'Redeem',
|
|
@@ -390,6 +402,7 @@ export const Store: React.FC<IStoreProps> = ({
|
|
|
390
402
|
height="auto"
|
|
391
403
|
type={RPGUIContainerTypes.Framed}
|
|
392
404
|
cancelDrag="[class*='Store__Container'], [class*='CartView'], [class*='StoreItemDetails'], .close-button"
|
|
405
|
+
isFullScreen={fullScreen}
|
|
393
406
|
>
|
|
394
407
|
{isCollectingMetadata && currentMetadataItem && currentMetadataItem.metadataType ? (
|
|
395
408
|
<MetadataCollector
|