@rpg-engine/long-bow 0.8.182 → 0.8.184
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/CharacterListingForm.d.ts +4 -2
- package/dist/components/Marketplace/CharacterListingModal.d.ts +17 -0
- package/dist/components/Marketplace/CharacterMarketplacePanel.d.ts +4 -0
- package/dist/components/Marketplace/CharacterMarketplaceRows.d.ts +6 -0
- package/dist/components/Marketplace/Marketplace.d.ts +3 -2
- package/dist/components/Marketplace/MyCharacterListingsPanel.d.ts +4 -0
- package/dist/components/shared/DCRateStrip.d.ts +2 -0
- package/dist/components/shared/RadioOption.d.ts +22 -0
- package/dist/long-bow.cjs.development.js +476 -371
- 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 +477 -372
- package/dist/long-bow.esm.js.map +1 -1
- package/dist/stories/Features/marketplace/CharacterListingModal.stories.d.ts +8 -0
- package/dist/stories/shared/RadioOption.stories.d.ts +8 -0
- package/package.json +1 -1
- package/src/components/DCWallet/DCWalletContent.tsx +5 -47
- package/src/components/Marketplace/CharacterListingForm.tsx +56 -351
- package/src/components/Marketplace/CharacterListingModal.tsx +404 -0
- package/src/components/Marketplace/CharacterMarketplacePanel.tsx +112 -67
- package/src/components/Marketplace/CharacterMarketplaceRows.tsx +21 -9
- package/src/components/Marketplace/Marketplace.tsx +11 -6
- package/src/components/Marketplace/MyCharacterListingsPanel.tsx +15 -14
- package/src/components/shared/DCRateStrip.tsx +67 -0
- package/src/components/shared/RadioOption.tsx +93 -0
- package/src/stories/Features/marketplace/CharacterListingModal.stories.tsx +131 -0
- package/src/stories/Features/marketplace/CharacterMarketplace.stories.tsx +39 -23
- package/src/stories/shared/RadioOption.stories.tsx +93 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Meta, Story } from '@storybook/react';
|
|
2
|
+
import { ICharacterListingModalProps } from '../../../components/Marketplace/CharacterListingModal';
|
|
3
|
+
declare const meta: Meta<ICharacterListingModalProps>;
|
|
4
|
+
export default meta;
|
|
5
|
+
export declare const WithMultipleCharacters: Story;
|
|
6
|
+
export declare const WithAlreadyListedFiltered: Story;
|
|
7
|
+
export declare const NoEligibleCharacters: Story;
|
|
8
|
+
export declare const SingleCharacter: Story;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Meta, Story } from '@storybook/react';
|
|
2
|
+
import { IRadioOptionProps } from '../../components/shared/RadioOption';
|
|
3
|
+
declare const meta: Meta;
|
|
4
|
+
export default meta;
|
|
5
|
+
export declare const Unselected: Story<IRadioOptionProps>;
|
|
6
|
+
export declare const Selected: Story<IRadioOptionProps>;
|
|
7
|
+
export declare const Disabled: Story<IRadioOptionProps>;
|
|
8
|
+
export declare const InteractiveGroup: Story;
|
package/package.json
CHANGED
|
@@ -2,6 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import { FaShoppingCart } from 'react-icons/fa';
|
|
3
3
|
import styled from 'styled-components';
|
|
4
4
|
import { InternalTabs } from '../InternalTabs/InternalTabs';
|
|
5
|
+
import { DCRateStrip } from '../shared/DCRateStrip';
|
|
5
6
|
import { DCHistoryPanel, IDCTransaction } from './DCHistoryPanel';
|
|
6
7
|
import { DCTransferPanel, IDCTransferCharacterResult } from './DCTransferPanel';
|
|
7
8
|
|
|
@@ -22,7 +23,8 @@ export interface IDCWalletContentProps {
|
|
|
22
23
|
searchResults?: IDCTransferCharacterResult[];
|
|
23
24
|
}
|
|
24
25
|
|
|
25
|
-
|
|
26
|
+
import { DC_TO_GOLD_SWAP_RATE } from '@rpg-engine/shared';
|
|
27
|
+
|
|
26
28
|
const DC_TO_USD = 100;
|
|
27
29
|
|
|
28
30
|
export const DCWalletContent: React.FC<IDCWalletContentProps> = ({
|
|
@@ -42,7 +44,7 @@ export const DCWalletContent: React.FC<IDCWalletContentProps> = ({
|
|
|
42
44
|
searchResults,
|
|
43
45
|
}) => {
|
|
44
46
|
const usdValue = (dcBalance / DC_TO_USD).toFixed(2);
|
|
45
|
-
const goldValue = (dcBalance *
|
|
47
|
+
const goldValue = (dcBalance * DC_TO_GOLD_SWAP_RATE).toLocaleString();
|
|
46
48
|
|
|
47
49
|
const tabs = [
|
|
48
50
|
{
|
|
@@ -94,13 +96,7 @@ export const DCWalletContent: React.FC<IDCWalletContentProps> = ({
|
|
|
94
96
|
</BuyButton>
|
|
95
97
|
)}
|
|
96
98
|
</BalanceTop>
|
|
97
|
-
<
|
|
98
|
-
<RateItem><RateNum>1 DC</RateNum><RateSep>=</RateSep><RateVal>5,500 Gold</RateVal></RateItem>
|
|
99
|
-
<RateDivider />
|
|
100
|
-
<RateItem><RateNum>100 DC</RateNum><RateSep>=</RateSep><RateVal>1 USD</RateVal></RateItem>
|
|
101
|
-
<RateDivider />
|
|
102
|
-
<RateItem><RateNum>1 USD</RateNum><RateSep>=</RateSep><RateVal>550K Gold</RateVal></RateItem>
|
|
103
|
-
</RateStrip>
|
|
99
|
+
<DCRateStrip />
|
|
104
100
|
</BalanceHeader>
|
|
105
101
|
|
|
106
102
|
<TabsWrapper>
|
|
@@ -207,44 +203,6 @@ const BuyButtonLabel = styled.span`
|
|
|
207
203
|
text-shadow: none !important;
|
|
208
204
|
`;
|
|
209
205
|
|
|
210
|
-
const RateStrip = styled.div`
|
|
211
|
-
display: flex;
|
|
212
|
-
align-items: center;
|
|
213
|
-
border-top: 1px solid rgba(245, 158, 11, 0.1);
|
|
214
|
-
padding-top: 8px;
|
|
215
|
-
`;
|
|
216
|
-
|
|
217
|
-
const RateItem = styled.div`
|
|
218
|
-
display: flex;
|
|
219
|
-
align-items: center;
|
|
220
|
-
gap: 5px;
|
|
221
|
-
flex: 1;
|
|
222
|
-
justify-content: center;
|
|
223
|
-
`;
|
|
224
|
-
|
|
225
|
-
const RateDivider = styled.div`
|
|
226
|
-
width: 1px;
|
|
227
|
-
height: 12px;
|
|
228
|
-
background: rgba(245, 158, 11, 0.2);
|
|
229
|
-
`;
|
|
230
|
-
|
|
231
|
-
const RateNum = styled.span`
|
|
232
|
-
font-family: 'Press Start 2P', cursive !important;
|
|
233
|
-
font-size: 6px !important;
|
|
234
|
-
color: rgba(255, 255, 255, 0.5) !important;
|
|
235
|
-
`;
|
|
236
|
-
|
|
237
|
-
const RateSep = styled.span`
|
|
238
|
-
font-family: 'Press Start 2P', cursive !important;
|
|
239
|
-
font-size: 6px !important;
|
|
240
|
-
color: rgba(255, 255, 255, 0.2) !important;
|
|
241
|
-
`;
|
|
242
|
-
|
|
243
|
-
const RateVal = styled.span`
|
|
244
|
-
font-family: 'Press Start 2P', cursive !important;
|
|
245
|
-
font-size: 6px !important;
|
|
246
|
-
color: rgba(254, 240, 138, 0.6) !important;
|
|
247
|
-
`;
|
|
248
206
|
|
|
249
207
|
const TabsWrapper = styled.div`
|
|
250
208
|
padding: 0 2.5%;
|
|
@@ -2,396 +2,101 @@ import { ICharacter } from '@rpg-engine/shared';
|
|
|
2
2
|
import { ShoppingBag } from 'pixelarticons/react/ShoppingBag';
|
|
3
3
|
import React, { useState } from 'react';
|
|
4
4
|
import styled from 'styled-components';
|
|
5
|
-
import { ConfirmModal } from '../ConfirmModal';
|
|
6
|
-
import { Input } from '../Input';
|
|
7
|
-
import { SpriteFromAtlas } from '../shared/SpriteFromAtlas';
|
|
8
5
|
import { CTAButton } from '../shared/CTAButton/CTAButton';
|
|
6
|
+
import { CharacterListingModal } from './CharacterListingModal';
|
|
9
7
|
|
|
10
8
|
export interface ICharacterListingFormProps {
|
|
11
9
|
accountCharacters: ICharacter[];
|
|
12
|
-
selectedCharacterToList: ICharacter | null;
|
|
13
|
-
onCharacterSelectToList: (character: ICharacter) => void;
|
|
14
10
|
onCharacterList: (characterId: string, price: number) => void;
|
|
11
|
+
/** Items atlas — for UI sprites like the DC coin */
|
|
15
12
|
atlasJSON: any;
|
|
16
13
|
atlasIMG: any;
|
|
14
|
+
/** Entities atlas — for character sprites */
|
|
15
|
+
characterAtlasJSON: any;
|
|
16
|
+
characterAtlasIMG: any;
|
|
17
17
|
enableHotkeys?: () => void;
|
|
18
18
|
disableHotkeys?: () => void;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
export const CharacterListingForm: React.FC<ICharacterListingFormProps> = ({
|
|
22
22
|
accountCharacters,
|
|
23
|
-
selectedCharacterToList,
|
|
24
|
-
onCharacterSelectToList,
|
|
25
23
|
onCharacterList,
|
|
26
24
|
atlasJSON,
|
|
27
25
|
atlasIMG,
|
|
26
|
+
characterAtlasJSON,
|
|
27
|
+
characterAtlasIMG,
|
|
28
28
|
enableHotkeys,
|
|
29
29
|
disableHotkeys,
|
|
30
30
|
}) => {
|
|
31
|
-
const [
|
|
32
|
-
const [isCreatingOffer, setIsCreatingOffer] = useState(false);
|
|
31
|
+
const [isModalOpen, setIsModalOpen] = useState(false);
|
|
33
32
|
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
);
|
|
37
|
-
|
|
38
|
-
const handleListClick = () => {
|
|
39
|
-
if (selectedCharacterToList && price && Number(price) > 0) {
|
|
40
|
-
setIsCreatingOffer(true);
|
|
41
|
-
}
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
const handleListConfirm = () => {
|
|
45
|
-
if (selectedCharacterToList && price && Number(price) > 0) {
|
|
46
|
-
onCharacterList(selectedCharacterToList._id!, Number(price));
|
|
47
|
-
setPrice('');
|
|
48
|
-
onCharacterSelectToList({} as ICharacter); // Clear selection
|
|
49
|
-
setIsCreatingOffer(false);
|
|
50
|
-
enableHotkeys?.();
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
const getCharacterLevel = (character: ICharacter): number => {
|
|
55
|
-
return character.skills?.level || 1;
|
|
56
|
-
};
|
|
33
|
+
const eligibleCount = accountCharacters.filter(
|
|
34
|
+
c => !c.isListedForSale && !c.tradedAt
|
|
35
|
+
).length;
|
|
57
36
|
|
|
58
37
|
return (
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
38
|
+
<Wrapper>
|
|
39
|
+
<CharacterListingModal
|
|
40
|
+
isOpen={isModalOpen}
|
|
41
|
+
onClose={() => setIsModalOpen(false)}
|
|
42
|
+
accountCharacters={accountCharacters}
|
|
43
|
+
atlasJSON={atlasJSON}
|
|
44
|
+
atlasIMG={atlasIMG}
|
|
45
|
+
characterAtlasJSON={characterAtlasJSON}
|
|
46
|
+
characterAtlasIMG={characterAtlasIMG}
|
|
47
|
+
onCharacterList={onCharacterList}
|
|
48
|
+
enableHotkeys={enableHotkeys}
|
|
49
|
+
disableHotkeys={disableHotkeys}
|
|
50
|
+
/>
|
|
51
|
+
|
|
52
|
+
<Description>
|
|
53
|
+
List one of your offline characters on the marketplace. Prices are set in DC.
|
|
54
|
+
</Description>
|
|
55
|
+
|
|
56
|
+
<OpenButton
|
|
57
|
+
icon={<ShoppingBag width={20} height={20} />}
|
|
58
|
+
label={`List a Character${eligibleCount > 0 ? ` (${eligibleCount} eligible)` : ''}`}
|
|
59
|
+
disabled={eligibleCount === 0}
|
|
60
|
+
onClick={() => setIsModalOpen(true)}
|
|
61
|
+
/>
|
|
62
|
+
|
|
63
|
+
{eligibleCount === 0 && (
|
|
64
|
+
<NoEligible>No eligible characters to list.</NoEligible>
|
|
69
65
|
)}
|
|
70
|
-
|
|
71
|
-
<FormContainer>
|
|
72
|
-
<SectionHeader>
|
|
73
|
-
<SectionLabel>List Character for Sale</SectionLabel>
|
|
74
|
-
<SectionDescription>
|
|
75
|
-
Select an offline character to list on the marketplace.
|
|
76
|
-
</SectionDescription>
|
|
77
|
-
</SectionHeader>
|
|
78
|
-
|
|
79
|
-
<CharacterSelectionRow>
|
|
80
|
-
<CharacterSlotWrapper>
|
|
81
|
-
{selectedCharacterToList ? (
|
|
82
|
-
<CharacterSpriteLarge>
|
|
83
|
-
<SpriteFromAtlas
|
|
84
|
-
atlasIMG={atlasIMG}
|
|
85
|
-
atlasJSON={atlasJSON}
|
|
86
|
-
spriteKey={`${selectedCharacterToList.textureKey}/down/standing/0.png`}
|
|
87
|
-
imgScale={3}
|
|
88
|
-
height={64}
|
|
89
|
-
width={64}
|
|
90
|
-
/>
|
|
91
|
-
</CharacterSpriteLarge>
|
|
92
|
-
) : (
|
|
93
|
-
<EmptyCharacterSlot>
|
|
94
|
-
<EmptySlotIcon>?</EmptySlotIcon>
|
|
95
|
-
</EmptyCharacterSlot>
|
|
96
|
-
)}
|
|
97
|
-
</CharacterSlotWrapper>
|
|
98
|
-
|
|
99
|
-
<CharacterDetails>
|
|
100
|
-
{selectedCharacterToList ? (
|
|
101
|
-
<>
|
|
102
|
-
<CharacterName>{selectedCharacterToList.name || 'Unknown'}</CharacterName>
|
|
103
|
-
<CharacterMeta>Level {getCharacterLevel(selectedCharacterToList)}</CharacterMeta>
|
|
104
|
-
</>
|
|
105
|
-
) : (
|
|
106
|
-
<EmptySelection>Select a character</EmptySelection>
|
|
107
|
-
)}
|
|
108
|
-
</CharacterDetails>
|
|
109
|
-
</CharacterSelectionRow>
|
|
110
|
-
|
|
111
|
-
<PriceInputWrapper>
|
|
112
|
-
<PriceLabel>Set Price (Gold)</PriceLabel>
|
|
113
|
-
<PriceInputRow>
|
|
114
|
-
<Input
|
|
115
|
-
onChange={e => setPrice(e.target.value)}
|
|
116
|
-
value={price}
|
|
117
|
-
placeholder="Amount..."
|
|
118
|
-
type="number"
|
|
119
|
-
disabled={!selectedCharacterToList}
|
|
120
|
-
onBlur={enableHotkeys}
|
|
121
|
-
onFocus={disableHotkeys}
|
|
122
|
-
className="price-input"
|
|
123
|
-
/>
|
|
124
|
-
<ListButton
|
|
125
|
-
icon={<ShoppingBag width={18} height={18} />}
|
|
126
|
-
label="List"
|
|
127
|
-
disabled={!selectedCharacterToList || !price || Number(price) <= 0}
|
|
128
|
-
onClick={handleListClick}
|
|
129
|
-
/>
|
|
130
|
-
</PriceInputRow>
|
|
131
|
-
</PriceInputWrapper>
|
|
132
|
-
|
|
133
|
-
{eligibleCharacters.length > 0 && (
|
|
134
|
-
<AvailableCharactersSection>
|
|
135
|
-
<AvailableCharactersLabel>Available Characters</AvailableCharactersLabel>
|
|
136
|
-
<AvailableCharactersList>
|
|
137
|
-
{eligibleCharacters.map((character) => (
|
|
138
|
-
<AvailableCharacterItem
|
|
139
|
-
key={character._id}
|
|
140
|
-
$selected={selectedCharacterToList?._id === character._id}
|
|
141
|
-
onClick={() => onCharacterSelectToList(character)}
|
|
142
|
-
type="button"
|
|
143
|
-
>
|
|
144
|
-
<MiniSprite>
|
|
145
|
-
<SpriteFromAtlas
|
|
146
|
-
atlasIMG={atlasIMG}
|
|
147
|
-
atlasJSON={atlasJSON}
|
|
148
|
-
spriteKey={`${character.textureKey}/down/standing/0.png`}
|
|
149
|
-
imgScale={2}
|
|
150
|
-
height={32}
|
|
151
|
-
width={32}
|
|
152
|
-
/>
|
|
153
|
-
</MiniSprite>
|
|
154
|
-
<MiniCharacterInfo>
|
|
155
|
-
<MiniCharacterName>{character.name}</MiniCharacterName>
|
|
156
|
-
<MiniCharacterMeta>Lvl {getCharacterLevel(character)}</MiniCharacterMeta>
|
|
157
|
-
</MiniCharacterInfo>
|
|
158
|
-
</AvailableCharacterItem>
|
|
159
|
-
))}
|
|
160
|
-
</AvailableCharactersList>
|
|
161
|
-
</AvailableCharactersSection>
|
|
162
|
-
)}
|
|
163
|
-
|
|
164
|
-
{eligibleCharacters.length === 0 && (
|
|
165
|
-
<EmptyState>
|
|
166
|
-
<EmptyText>No eligible characters to list.</EmptyText>
|
|
167
|
-
</EmptyState>
|
|
168
|
-
)}
|
|
169
|
-
</FormContainer>
|
|
170
|
-
</>
|
|
66
|
+
</Wrapper>
|
|
171
67
|
);
|
|
172
68
|
};
|
|
173
69
|
|
|
174
|
-
const
|
|
175
|
-
width: 95%;
|
|
176
|
-
margin: 0 auto;
|
|
177
|
-
background: rgba(0, 0, 0, 0.15);
|
|
178
|
-
border-radius: 4px;
|
|
179
|
-
border: 1px solid rgba(255, 255, 255, 0.05);
|
|
180
|
-
padding: 16px;
|
|
181
|
-
display: flex;
|
|
182
|
-
flex-direction: column;
|
|
183
|
-
gap: 16px;
|
|
184
|
-
`;
|
|
185
|
-
|
|
186
|
-
const SectionHeader = styled.div`
|
|
70
|
+
const Wrapper = styled.div`
|
|
187
71
|
display: flex;
|
|
188
72
|
flex-direction: column;
|
|
189
|
-
gap: 4px;
|
|
190
|
-
`;
|
|
191
|
-
|
|
192
|
-
const SectionLabel = styled.p`
|
|
193
|
-
margin: 0;
|
|
194
|
-
font-size: 0.65rem;
|
|
195
|
-
color: #aaa;
|
|
196
|
-
text-transform: uppercase;
|
|
197
|
-
letter-spacing: 1px;
|
|
198
|
-
`;
|
|
199
|
-
|
|
200
|
-
const SectionDescription = styled.p`
|
|
201
|
-
margin: 0;
|
|
202
|
-
font-size: 0.5rem;
|
|
203
|
-
color: #666;
|
|
204
|
-
line-height: 1.4;
|
|
205
|
-
`;
|
|
206
|
-
|
|
207
|
-
const CharacterSelectionRow = styled.div`
|
|
208
|
-
display: flex;
|
|
209
|
-
gap: 12px;
|
|
210
|
-
align-items: center;
|
|
211
|
-
padding: 12px;
|
|
212
|
-
background: rgba(0, 0, 0, 0.2);
|
|
213
|
-
border-radius: 4px;
|
|
214
|
-
border: 1px solid rgba(255, 255, 255, 0.05);
|
|
215
|
-
`;
|
|
216
|
-
|
|
217
|
-
const CharacterSlotWrapper = styled.div`
|
|
218
|
-
flex-shrink: 0;
|
|
219
|
-
`;
|
|
220
|
-
|
|
221
|
-
const CharacterSpriteLarge = styled.div`
|
|
222
|
-
display: flex;
|
|
223
73
|
align-items: center;
|
|
224
74
|
justify-content: center;
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
border: 1px solid rgba(255, 255, 255, 0.08);
|
|
230
|
-
border-radius: 8px;
|
|
231
|
-
`;
|
|
232
|
-
|
|
233
|
-
const EmptyCharacterSlot = styled.div`
|
|
234
|
-
width: 64px;
|
|
235
|
-
height: 64px;
|
|
236
|
-
background: rgba(0, 0, 0, 0.3);
|
|
237
|
-
border: 2px dashed rgba(255, 255, 255, 0.1);
|
|
238
|
-
border-radius: 8px;
|
|
239
|
-
display: flex;
|
|
240
|
-
align-items: center;
|
|
241
|
-
justify-content: center;
|
|
242
|
-
`;
|
|
243
|
-
|
|
244
|
-
const EmptySlotIcon = styled.span`
|
|
245
|
-
font-size: 1.5rem;
|
|
246
|
-
color: #666;
|
|
247
|
-
font-family: 'Press Start 2P', cursive;
|
|
248
|
-
`;
|
|
249
|
-
|
|
250
|
-
const CharacterDetails = styled.div`
|
|
251
|
-
display: flex;
|
|
252
|
-
flex-direction: column;
|
|
253
|
-
gap: 4px;
|
|
254
|
-
flex: 1;
|
|
255
|
-
`;
|
|
256
|
-
|
|
257
|
-
const CharacterName = styled.span`
|
|
258
|
-
font-family: 'Press Start 2P', cursive;
|
|
259
|
-
font-size: 0.6rem;
|
|
260
|
-
color: #f3f4f6;
|
|
261
|
-
`;
|
|
262
|
-
|
|
263
|
-
const CharacterMeta = styled.span`
|
|
264
|
-
font-size: 0.5rem;
|
|
265
|
-
color: #888;
|
|
266
|
-
text-transform: uppercase;
|
|
267
|
-
letter-spacing: 0.5px;
|
|
75
|
+
gap: 20px;
|
|
76
|
+
padding: 40px 24px;
|
|
77
|
+
width: 95%;
|
|
78
|
+
margin: 0 auto;
|
|
268
79
|
`;
|
|
269
80
|
|
|
270
|
-
const
|
|
81
|
+
const Description = styled.p`
|
|
82
|
+
margin: 0;
|
|
271
83
|
font-size: 0.5rem;
|
|
272
84
|
color: #666;
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
const PriceInputWrapper = styled.div`
|
|
277
|
-
display: flex;
|
|
278
|
-
flex-direction: column;
|
|
279
|
-
gap: 8px;
|
|
280
|
-
`;
|
|
281
|
-
|
|
282
|
-
const PriceLabel = styled.p`
|
|
283
|
-
margin: 0;
|
|
284
|
-
font-size: 0.55rem;
|
|
285
|
-
color: #888;
|
|
286
|
-
text-transform: uppercase;
|
|
287
|
-
letter-spacing: 0.5px;
|
|
288
|
-
`;
|
|
289
|
-
|
|
290
|
-
const PriceInputRow = styled.div`
|
|
291
|
-
display: flex;
|
|
292
|
-
gap: 8px;
|
|
293
|
-
align-items: center;
|
|
294
|
-
|
|
295
|
-
.price-input {
|
|
296
|
-
flex: 1;
|
|
297
|
-
height: 12px;
|
|
298
|
-
}
|
|
299
|
-
`;
|
|
300
|
-
|
|
301
|
-
const ListButton = styled(CTAButton)`
|
|
302
|
-
padding: 10px 16px;
|
|
303
|
-
height: 32px;
|
|
304
|
-
flex-shrink: 0;
|
|
305
|
-
|
|
306
|
-
span {
|
|
307
|
-
font-size: 0.6rem;
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
svg {
|
|
311
|
-
font-size: 1.1rem;
|
|
312
|
-
}
|
|
313
|
-
`;
|
|
314
|
-
|
|
315
|
-
const AvailableCharactersSection = styled.div`
|
|
316
|
-
display: flex;
|
|
317
|
-
flex-direction: column;
|
|
318
|
-
gap: 8px;
|
|
319
|
-
`;
|
|
320
|
-
|
|
321
|
-
const AvailableCharactersLabel = styled.p`
|
|
322
|
-
margin: 0;
|
|
323
|
-
font-size: 0.55rem;
|
|
324
|
-
color: #888;
|
|
325
|
-
text-transform: uppercase;
|
|
326
|
-
letter-spacing: 0.5px;
|
|
327
|
-
`;
|
|
328
|
-
|
|
329
|
-
const AvailableCharactersList = styled.div`
|
|
330
|
-
display: flex;
|
|
331
|
-
flex-direction: column;
|
|
332
|
-
gap: 6px;
|
|
333
|
-
max-height: 200px;
|
|
334
|
-
overflow-y: auto;
|
|
335
|
-
padding: 4px;
|
|
336
|
-
`;
|
|
337
|
-
|
|
338
|
-
const AvailableCharacterItem = styled.button<{ $selected: boolean }>`
|
|
339
|
-
display: flex;
|
|
340
|
-
align-items: center;
|
|
341
|
-
gap: 10px;
|
|
342
|
-
padding: 8px;
|
|
343
|
-
background: ${({ $selected }) => $selected ? 'rgba(245, 158, 11, 0.1)' : 'rgba(255, 255, 255, 0.02)'};
|
|
344
|
-
border: 1px solid ${({ $selected }) => $selected ? 'rgba(245, 158, 11, 0.4)' : 'rgba(255, 255, 255, 0.08)'};
|
|
345
|
-
border-radius: 6px;
|
|
346
|
-
cursor: pointer;
|
|
347
|
-
transition: border-color 0.15s, background 0.15s;
|
|
348
|
-
|
|
349
|
-
&:hover {
|
|
350
|
-
border-color: rgba(245, 158, 11, 0.3);
|
|
351
|
-
background: rgba(245, 158, 11, 0.05);
|
|
352
|
-
}
|
|
85
|
+
text-align: center;
|
|
86
|
+
line-height: 1.6;
|
|
87
|
+
max-width: 320px;
|
|
353
88
|
`;
|
|
354
89
|
|
|
355
|
-
const
|
|
356
|
-
|
|
357
|
-
align-items: center;
|
|
358
|
-
justify-content: center;
|
|
359
|
-
image-rendering: pixelated;
|
|
360
|
-
flex-shrink: 0;
|
|
361
|
-
`;
|
|
90
|
+
const OpenButton = styled(CTAButton)`
|
|
91
|
+
padding: 14px 24px;
|
|
362
92
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
flex-direction: column;
|
|
366
|
-
gap: 2px;
|
|
367
|
-
align-items: flex-start;
|
|
93
|
+
span { font-size: 0.65rem; }
|
|
94
|
+
svg { font-size: 1.2rem; }
|
|
368
95
|
`;
|
|
369
96
|
|
|
370
|
-
const
|
|
371
|
-
font-family: 'Press Start 2P', cursive;
|
|
97
|
+
const NoEligible = styled.span`
|
|
372
98
|
font-size: 0.45rem;
|
|
373
|
-
color: #
|
|
374
|
-
`;
|
|
375
|
-
|
|
376
|
-
const MiniCharacterMeta = styled.span`
|
|
377
|
-
font-size: 0.4rem;
|
|
378
|
-
color: #888;
|
|
99
|
+
color: #52525b;
|
|
379
100
|
text-transform: uppercase;
|
|
380
|
-
letter-spacing:
|
|
381
|
-
`;
|
|
382
|
-
|
|
383
|
-
const EmptyState = styled.div`
|
|
384
|
-
display: flex;
|
|
385
|
-
align-items: center;
|
|
386
|
-
justify-content: center;
|
|
387
|
-
padding: 20px;
|
|
388
|
-
background: rgba(255, 255, 255, 0.02);
|
|
389
|
-
border-radius: 6px;
|
|
390
|
-
`;
|
|
391
|
-
|
|
392
|
-
const EmptyText = styled.span`
|
|
393
|
-
font-size: 0.45rem;
|
|
394
|
-
color: #666;
|
|
395
|
-
text-transform: uppercase;
|
|
396
|
-
letter-spacing: 0.5px;
|
|
101
|
+
letter-spacing: 1px;
|
|
397
102
|
`;
|