@rpg-engine/long-bow 0.8.188 → 0.8.190

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.
@@ -7,4 +7,5 @@ export declare const CharacterBrowseEmpty: Story;
7
7
  export declare const CharacterBrowseFiltered: Story;
8
8
  export declare const MyCharacterListings: Story;
9
9
  export declare const MyCharacterListingsEmpty: Story;
10
+ export declare const MyCharacterListingsNoEligible: Story;
10
11
  export declare const CharacterListingPending: Story;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rpg-engine/long-bow",
3
- "version": "0.8.188",
3
+ "version": "0.8.190",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.js",
6
6
  "typings": "dist/index.d.ts",
@@ -32,7 +32,6 @@ import { MarketplacePaymentMethod } from './MarketplaceBuyModal';
32
32
  import { MarketplaceAcceptedCurrency, MarketplaceSettingsPanel } from './MarketplaceSettingsPanel';
33
33
  import { CharacterMarketplacePanel } from './CharacterMarketplacePanel';
34
34
  import { MyCharacterListingsPanel } from './MyCharacterListingsPanel';
35
- import { CharacterListingForm } from './CharacterListingForm';
36
35
 
37
36
  export interface IMarketPlaceProps {
38
37
  items: IMarketplaceItem[];
@@ -206,7 +205,7 @@ export const Marketplace: React.FC<IMarketPlaceProps> = props => {
206
205
  const [activeTab, setActiveTab] = useState<ActiveTab>('marketplace');
207
206
  const [acceptedCurrency, setAcceptedCurrency] = useState<MarketplaceAcceptedCurrency>(acceptedCurrencyProp ?? MarketplaceAcceptedCurrency.GoldOrDc);
208
207
  const [isBlueprintSearchOpen, setIsBlueprintSearchOpen] = useState(false);
209
- const [characterSubTab, setCharacterSubTab] = useState<'browse' | 'my-listings' | 'list'>('browse');
208
+ const [characterSubTab, setCharacterSubTab] = useState<'browse' | 'my-listings'>('browse');
210
209
 
211
210
  const handleCurrencyChange = (value: MarketplaceAcceptedCurrency) => {
212
211
  setAcceptedCurrency(value);
@@ -305,13 +304,6 @@ export const Marketplace: React.FC<IMarketPlaceProps> = props => {
305
304
  >
306
305
  My Listings
307
306
  </CharacterSubTab>
308
- <CharacterSubTab
309
- $active={characterSubTab === 'list'}
310
- onClick={() => setCharacterSubTab('list')}
311
- type="button"
312
- >
313
- List Character
314
- </CharacterSubTab>
315
307
  </CharacterSubTabs>
316
308
 
317
309
  {characterSubTab === 'browse' && (
@@ -342,17 +334,6 @@ export const Marketplace: React.FC<IMarketPlaceProps> = props => {
342
334
  itemsPerPage={10}
343
335
  onPageChange={onMyCharacterListingsPageChange ?? (() => {})}
344
336
  onCharacterDelist={onCharacterDelist ?? (() => {})}
345
- atlasJSON={props.atlasJSON}
346
- atlasIMG={props.atlasIMG}
347
- characterAtlasJSON={characterAtlasJSON ?? props.atlasJSON}
348
- characterAtlasIMG={characterAtlasIMG ?? props.atlasIMG}
349
- enableHotkeys={props.enableHotkeys}
350
- disableHotkeys={props.disableHotkeys}
351
- />
352
- )}
353
-
354
- {characterSubTab === 'list' && (
355
- <CharacterListingForm
356
337
  accountCharacters={accountCharacters ?? []}
357
338
  onCharacterList={onCharacterList ?? (() => {})}
358
339
  atlasJSON={props.atlasJSON}
@@ -363,6 +344,7 @@ export const Marketplace: React.FC<IMarketPlaceProps> = props => {
363
344
  disableHotkeys={props.disableHotkeys}
364
345
  />
365
346
  )}
347
+
366
348
  </>
367
349
  )}
368
350
 
@@ -1,11 +1,14 @@
1
- import { formatDCAmount, ICharacterListing } from '@rpg-engine/shared';
1
+ import { formatDCAmount, ICharacter, ICharacterListing } from '@rpg-engine/shared';
2
2
  import { Delete } from 'pixelarticons/react/Delete';
3
+ import { ShoppingBag } from 'pixelarticons/react/ShoppingBag';
3
4
  import { User } from 'pixelarticons/react/User';
4
5
  import React, { useEffect, useRef, useState } from 'react';
5
6
  import styled from 'styled-components';
6
7
  import { ConfirmModal } from '../ConfirmModal';
8
+ import { Pagination } from '../shared/Pagination/Pagination';
7
9
  import { SpriteFromAtlas } from '../shared/SpriteFromAtlas';
8
10
  import { CTAButton } from '../shared/CTAButton/CTAButton';
11
+ import { CharacterListingModal } from './CharacterListingModal';
9
12
 
10
13
  export interface IMyCharacterListingsPanelProps {
11
14
  myCharacterListings: ICharacterListing[];
@@ -14,6 +17,9 @@ export interface IMyCharacterListingsPanelProps {
14
17
  itemsPerPage: number;
15
18
  onPageChange: (page: number) => void;
16
19
  onCharacterDelist: (listingId: string) => void;
20
+ /** Characters that can be listed (used for the List a Character modal) */
21
+ accountCharacters: ICharacter[];
22
+ onCharacterList: (characterId: string, price: number) => void;
17
23
  /** Items atlas — for UI sprites like the DC coin */
18
24
  atlasJSON: any;
19
25
  atlasIMG: any;
@@ -31,60 +37,81 @@ export const MyCharacterListingsPanel: React.FC<IMyCharacterListingsPanelProps>
31
37
  itemsPerPage,
32
38
  onPageChange,
33
39
  onCharacterDelist,
40
+ accountCharacters,
41
+ onCharacterList,
34
42
  atlasJSON,
35
43
  atlasIMG,
36
44
  characterAtlasJSON,
37
45
  characterAtlasIMG,
38
46
  enableHotkeys,
47
+ disableHotkeys,
39
48
  }) => {
40
- const [delistingListingId, setDelistingListingId] = useState<string | null>(null);
49
+ const [delistingId, setDelistingId] = useState<string | null>(null);
50
+ const [isListingModalOpen, setIsListingModalOpen] = useState(false);
41
51
  const itemsContainer = useRef<HTMLDivElement>(null);
42
52
 
43
53
  useEffect(() => {
44
54
  itemsContainer.current?.scrollTo(0, 0);
45
55
  }, [currentPage]);
46
56
 
47
- const handleDelistClick = (listingId: string) => {
48
- setDelistingListingId(listingId);
49
- };
50
-
51
57
  const handleDelistConfirm = () => {
52
- if (delistingListingId) {
53
- onCharacterDelist(delistingListingId);
54
- setDelistingListingId(null);
58
+ if (delistingId) {
59
+ onCharacterDelist(delistingId);
60
+ setDelistingId(null);
55
61
  enableHotkeys?.();
56
62
  }
57
63
  };
58
64
 
59
-
60
- const getFormattedDate = (date: Date) => {
61
- return new Date(date).toLocaleDateString();
62
- };
65
+ const eligibleCount = accountCharacters.filter(
66
+ c => !c.isListedForSale && !c.tradedAt
67
+ ).length;
63
68
 
64
69
  return (
65
70
  <>
66
- {delistingListingId && (
71
+ {delistingId && (
67
72
  <ConfirmModal
68
- onClose={() => {
69
- setDelistingListingId(null);
70
- enableHotkeys?.();
71
- }}
73
+ onClose={() => { setDelistingId(null); enableHotkeys?.(); }}
72
74
  onConfirm={handleDelistConfirm}
73
75
  message="Are you sure you want to delist this character?"
74
76
  />
75
77
  )}
76
78
 
77
- <ListingsContainer id="MarketContainer" ref={itemsContainer}>
79
+ <CharacterListingModal
80
+ isOpen={isListingModalOpen}
81
+ onClose={() => setIsListingModalOpen(false)}
82
+ accountCharacters={accountCharacters}
83
+ atlasJSON={atlasJSON}
84
+ atlasIMG={atlasIMG}
85
+ characterAtlasJSON={characterAtlasJSON}
86
+ characterAtlasIMG={characterAtlasIMG}
87
+ onCharacterList={(id, price) => {
88
+ onCharacterList(id, price);
89
+ setIsListingModalOpen(false);
90
+ }}
91
+ enableHotkeys={enableHotkeys}
92
+ disableHotkeys={disableHotkeys}
93
+ />
94
+
95
+ <Toolbar>
96
+ <ListCharacterBtn
97
+ icon={<ShoppingBag width={16} height={16} />}
98
+ label={`List a Character${eligibleCount > 0 ? ` (${eligibleCount} eligible)` : ''}`}
99
+ onClick={() => setIsListingModalOpen(true)}
100
+ disabled={eligibleCount === 0}
101
+ />
102
+ </Toolbar>
103
+
104
+ <ListingsContainer ref={itemsContainer}>
78
105
  {myCharacterListings.length === 0 ? (
79
106
  <EmptyState>
80
107
  <User width={32} height={32} />
81
- <EmptyText>You have no listed characters.</EmptyText>
82
- <EmptySubtext>Use the "List Character" tab to list a character for sale.</EmptySubtext>
108
+ <EmptyText>No listed characters.</EmptyText>
109
+ <EmptySubtext>Use the "List Character" tab to put a character up for sale.</EmptySubtext>
83
110
  </EmptyState>
84
111
  ) : (
85
112
  <ListingsGrid>
86
113
  {myCharacterListings.map((listing) => (
87
- <CharacterListingCard key={listing._id}>
114
+ <CharacterListingCard key={listing._id} $isBeingBought={listing.isBeingBought}>
88
115
  <CharacterSprite>
89
116
  <SpriteFromAtlas
90
117
  atlasIMG={characterAtlasIMG}
@@ -98,7 +125,9 @@ export const MyCharacterListingsPanel: React.FC<IMyCharacterListingsPanelProps>
98
125
  </CharacterSprite>
99
126
  <CharacterInfo>
100
127
  <CharacterName>{listing.characterSnapshot.name || 'Unknown'}</CharacterName>
101
- <CharacterMeta>Level {listing.characterSnapshot.level}</CharacterMeta>
128
+ <CharacterMeta>
129
+ Lv.{listing.characterSnapshot.level} · {listing.characterSnapshot.class}
130
+ </CharacterMeta>
102
131
  <ListingPrice>
103
132
  <DCCoinWrapper>
104
133
  <SpriteFromAtlas
@@ -111,18 +140,19 @@ export const MyCharacterListingsPanel: React.FC<IMyCharacterListingsPanelProps>
111
140
  </DCCoinWrapper>
112
141
  {formatDCAmount(listing.price)} DC
113
142
  </ListingPrice>
114
- <ListingMeta>Listed {getFormattedDate(listing.createdAt)}</ListingMeta>
115
- {listing.isBeingBought && (
116
- <ListingStatus $status="pending">Sale Pending</ListingStatus>
117
- )}
143
+ <ListingDate>
144
+ Listed {new Date(listing.createdAt).toLocaleDateString()}
145
+ </ListingDate>
118
146
  </CharacterInfo>
119
- <ActionButton
120
- icon={<Delete width={16} height={16} />}
147
+ <DelistBtn
148
+ icon={<Delete width={14} height={14} />}
121
149
  label="Delist"
122
- onClick={() => handleDelistClick(listing._id)}
123
- iconColor="#ef4444"
150
+ onClick={() => setDelistingId(listing._id)}
124
151
  disabled={listing.isBeingBought}
125
152
  />
153
+ {listing.isBeingBought && (
154
+ <PendingBadge>Pending</PendingBadge>
155
+ )}
126
156
  </CharacterListingCard>
127
157
  ))}
128
158
  </ListingsGrid>
@@ -131,18 +161,11 @@ export const MyCharacterListingsPanel: React.FC<IMyCharacterListingsPanelProps>
131
161
 
132
162
  {totalCount > itemsPerPage && (
133
163
  <PagerFooter>
134
- <Pagination>
135
- {Array.from({ length: Math.ceil(totalCount / itemsPerPage) }, (_, i) => i + 1).map(page => (
136
- <PageButton
137
- key={page}
138
- $active={currentPage === page}
139
- type="button"
140
- onClick={() => onPageChange(page)}
141
- >
142
- {page}
143
- </PageButton>
144
- ))}
145
- </Pagination>
164
+ <Pagination
165
+ currentPage={currentPage}
166
+ totalPages={Math.ceil(totalCount / itemsPerPage)}
167
+ onPageChange={onPageChange}
168
+ />
146
169
  </PagerFooter>
147
170
  )}
148
171
  </>
@@ -171,15 +194,26 @@ const ListingsGrid = styled.div`
171
194
  padding: 12px;
172
195
  `;
173
196
 
174
- const CharacterListingCard = styled.div`
197
+ const CharacterListingCard = styled.div<{ $isBeingBought?: boolean }>`
175
198
  display: flex;
176
199
  flex-direction: column;
177
200
  align-items: center;
178
201
  gap: 8px;
179
202
  background: rgba(255, 255, 255, 0.03);
180
- border: 1px solid rgba(255, 255, 255, 0.08);
203
+ border: 1px solid ${({ $isBeingBought }) =>
204
+ $isBeingBought ? 'rgba(239,68,68,0.3)' : 'rgba(255,255,255,0.08)'};
181
205
  border-radius: 8px;
182
206
  padding: 12px;
207
+ position: relative;
208
+ opacity: ${({ $isBeingBought }) => ($isBeingBought ? 0.7 : 1)};
209
+ transition: border-color 0.15s, background 0.15s;
210
+
211
+ &:hover {
212
+ border-color: ${({ $isBeingBought }) =>
213
+ $isBeingBought ? 'rgba(239,68,68,0.5)' : 'rgba(245,158,11,0.3)'};
214
+ background: ${({ $isBeingBought }) =>
215
+ $isBeingBought ? 'rgba(239,68,68,0.04)' : 'rgba(245,158,11,0.04)'};
216
+ }
183
217
  `;
184
218
 
185
219
  const CharacterSprite = styled.div`
@@ -187,6 +221,9 @@ const CharacterSprite = styled.div`
187
221
  align-items: center;
188
222
  justify-content: center;
189
223
  image-rendering: pixelated;
224
+ width: 64px;
225
+ height: 64px;
226
+ flex-shrink: 0;
190
227
  `;
191
228
 
192
229
  const CharacterInfo = styled.div`
@@ -195,19 +232,21 @@ const CharacterInfo = styled.div`
195
232
  align-items: center;
196
233
  gap: 4px;
197
234
  text-align: center;
235
+ width: 100%;
198
236
  `;
199
237
 
200
238
  const CharacterName = styled.span`
201
- font-family: 'Press Start 2P', cursive;
202
- font-size: 0.55rem;
203
- color: #f3f4f6;
239
+ font-family: 'Press Start 2P', cursive !important;
240
+ font-size: 0.55rem !important;
241
+ color: #f3f4f6 !important;
204
242
  text-transform: uppercase;
205
243
  letter-spacing: 0.5px;
206
244
  `;
207
245
 
208
246
  const CharacterMeta = styled.span`
209
- font-size: 0.45rem;
210
- color: #888;
247
+ font-family: 'Press Start 2P', cursive !important;
248
+ font-size: 0.45rem !important;
249
+ color: #888 !important;
211
250
  text-transform: uppercase;
212
251
  letter-spacing: 0.5px;
213
252
  `;
@@ -215,10 +254,12 @@ const CharacterMeta = styled.span`
215
254
  const ListingPrice = styled.div`
216
255
  display: flex;
217
256
  align-items: center;
218
- gap: 6px;
219
- font-family: 'Press Start 2P', cursive;
220
- font-size: 0.5rem;
221
- color: #fef08a;
257
+ justify-content: center;
258
+ gap: 4px;
259
+ font-family: 'Press Start 2P', cursive !important;
260
+ font-size: 0.5rem !important;
261
+ color: #fef08a !important;
262
+ line-height: 1;
222
263
  `;
223
264
 
224
265
  const DCCoinWrapper = styled.span`
@@ -226,48 +267,55 @@ const DCCoinWrapper = styled.span`
226
267
  align-items: center;
227
268
  justify-content: center;
228
269
  flex-shrink: 0;
270
+ line-height: 0;
229
271
  `;
230
272
 
231
- const ListingMeta = styled.span`
232
- font-size: 0.38rem;
233
- color: #52525b;
273
+ const ListingDate = styled.span`
274
+ font-family: 'Press Start 2P', cursive !important;
275
+ font-size: 0.35rem !important;
276
+ color: #52525b !important;
234
277
  text-transform: uppercase;
235
278
  letter-spacing: 0.5px;
236
279
  `;
237
280
 
238
- const ListingStatus = styled.span<{ $status: 'pending' | 'sold' }>`
239
- font-size: 0.38rem;
240
- padding: 2px 6px;
281
+ const DelistBtn = styled(CTAButton)`
282
+ width: 100%;
283
+ padding: 6px 10px;
284
+ height: 28px;
285
+ margin-top: 2px;
286
+
287
+ span { font-size: 0.48rem; }
288
+ svg { font-size: 0.9rem; }
289
+ `;
290
+
291
+ const PendingBadge = styled.span`
292
+ position: absolute;
293
+ top: 6px;
294
+ right: 6px;
295
+ background: rgba(239, 68, 68, 0.2);
296
+ border: 1px solid rgba(239, 68, 68, 0.4);
241
297
  border-radius: 4px;
298
+ padding: 2px 6px;
299
+ font-family: 'Press Start 2P', cursive !important;
300
+ font-size: 0.35rem !important;
301
+ color: #ef4444 !important;
242
302
  text-transform: uppercase;
243
303
  letter-spacing: 0.5px;
244
- ${({ $status }) =>
245
- $status === 'pending'
246
- ? `
247
- background: rgba(239, 68, 68, 0.2);
248
- border: 1px solid rgba(239, 68, 68, 0.4);
249
- color: #ef4444;
250
- `
251
- : `
252
- background: rgba(34, 197, 94, 0.2);
253
- border: 1px solid rgba(34, 197, 94, 0.4);
254
- color: #22c55e;
255
- `}
256
304
  `;
257
305
 
258
- const ActionButton = styled(CTAButton)<{ disabled?: boolean }>`
259
- padding: 6px 12px;
260
- height: 28px;
261
- opacity: ${({ disabled }) => (disabled ? 0.5 : 1)};
262
- pointer-events: ${({ disabled }) => (disabled ? 'none' : 'auto')};
306
+ const Toolbar = styled.div`
307
+ width: 95%;
308
+ margin: 10px auto 0 auto;
309
+ display: flex;
310
+ justify-content: flex-end;
311
+ `;
263
312
 
264
- span {
265
- font-size: 0.5rem;
266
- }
313
+ const ListCharacterBtn = styled(CTAButton)`
314
+ padding: 8px 16px;
315
+ height: 32px;
267
316
 
268
- svg {
269
- font-size: 1rem;
270
- }
317
+ span { font-size: 0.5rem; }
318
+ svg { font-size: 1rem; }
271
319
  `;
272
320
 
273
321
  const PagerFooter = styled.div`
@@ -280,28 +328,6 @@ const PagerFooter = styled.div`
280
328
  margin: 0 auto;
281
329
  `;
282
330
 
283
- const Pagination = styled.div`
284
- display: flex;
285
- gap: 6px;
286
- `;
287
-
288
- const PageButton = styled.button<{ $active: boolean }>`
289
- padding: 6px 10px;
290
- font-family: 'Press Start 2P', cursive;
291
- font-size: 0.5rem;
292
- border-radius: 4px;
293
- border: 1px solid ${({ $active }) => ($active ? '#f59e0b' : 'rgba(255,255,255,0.12)')};
294
- background: ${({ $active }) => ($active ? 'rgba(245,158,11,0.15)' : 'rgba(0,0,0,0.3)')};
295
- color: ${({ $active }) => ($active ? '#f59e0b' : '#777')};
296
- cursor: pointer;
297
- transition: border-color 0.15s, background 0.15s, color 0.15s;
298
-
299
- &:hover {
300
- border-color: ${({ $active }) => ($active ? '#f59e0b' : 'rgba(255,255,255,0.3)')};
301
- color: ${({ $active }) => ($active ? '#f59e0b' : '#bbb')};
302
- }
303
- `;
304
-
305
331
  const EmptyState = styled.div`
306
332
  display: flex;
307
333
  flex-direction: column;
@@ -313,17 +339,19 @@ const EmptyState = styled.div`
313
339
  `;
314
340
 
315
341
  const EmptyText = styled.span`
316
- font-size: 0.55rem;
317
- color: #71717a;
342
+ font-family: 'Press Start 2P', cursive !important;
343
+ font-size: 0.48rem !important;
344
+ color: #71717a !important;
318
345
  text-transform: uppercase;
319
346
  letter-spacing: 1px;
320
347
  `;
321
348
 
322
349
  const EmptySubtext = styled.span`
323
- font-size: 0.45rem;
324
- color: #52525b;
325
- text-transform: none;
326
- letter-spacing: 0.5px;
350
+ font-family: 'Press Start 2P', cursive !important;
351
+ font-size: 0.38rem !important;
352
+ color: #52525b !important;
327
353
  text-align: center;
328
- max-width: 280px;
354
+ max-width: 260px;
355
+ line-height: 1.6;
329
356
  `;
357
+
@@ -1,4 +1,4 @@
1
- import { ICharacterListing } from '@rpg-engine/shared';
1
+ import { ICharacter, ICharacterListing } from '@rpg-engine/shared';
2
2
  import { Meta, Story } from '@storybook/react';
3
3
  import React from 'react';
4
4
  import { RPGUIRoot } from '../../..';
@@ -189,6 +189,25 @@ const mockMyCharacterListings: ICharacterListing[] = [
189
189
  },
190
190
  ];
191
191
 
192
+ const mockAccountCharacters: ICharacter[] = [
193
+ {
194
+ _id: 'char-a1',
195
+ name: 'MyRogue',
196
+ textureKey: 'redhair-girl-1',
197
+ isListedForSale: false,
198
+ tradedAt: undefined,
199
+ skills: { level: 22 } as any,
200
+ } as ICharacter,
201
+ {
202
+ _id: 'char-a2',
203
+ name: 'MyPaladin',
204
+ textureKey: 'dragon-knight',
205
+ isListedForSale: false,
206
+ tradedAt: undefined,
207
+ skills: { level: 38 } as any,
208
+ } as ICharacter,
209
+ ];
210
+
192
211
  export const CharacterBrowse: Story = () => (
193
212
  <RPGUIRoot>
194
213
  <CharacterMarketplacePanel
@@ -288,6 +307,8 @@ export const MyCharacterListings: Story = () => (
288
307
  itemsPerPage={8}
289
308
  onPageChange={() => {}}
290
309
  onCharacterDelist={() => {}}
310
+ accountCharacters={mockAccountCharacters}
311
+ onCharacterList={() => {}}
291
312
  atlasJSON={itemsAtlasJSON}
292
313
  atlasIMG={itemsAtlasIMG}
293
314
  characterAtlasJSON={entitiesAtlasJSON}
@@ -307,6 +328,8 @@ export const MyCharacterListingsEmpty: Story = () => (
307
328
  itemsPerPage={8}
308
329
  onPageChange={() => {}}
309
330
  onCharacterDelist={() => {}}
331
+ accountCharacters={mockAccountCharacters}
332
+ onCharacterList={() => {}}
310
333
  atlasJSON={itemsAtlasJSON}
311
334
  atlasIMG={itemsAtlasIMG}
312
335
  characterAtlasJSON={entitiesAtlasJSON}
@@ -317,6 +340,27 @@ export const MyCharacterListingsEmpty: Story = () => (
317
340
 
318
341
  MyCharacterListingsEmpty.storyName = 'My Listings - Empty State';
319
342
 
343
+ export const MyCharacterListingsNoEligible: Story = () => (
344
+ <RPGUIRoot>
345
+ <MyCharacterListingsPanel
346
+ myCharacterListings={mockMyCharacterListings}
347
+ totalCount={2}
348
+ currentPage={1}
349
+ itemsPerPage={8}
350
+ onPageChange={() => {}}
351
+ onCharacterDelist={() => {}}
352
+ accountCharacters={[]}
353
+ onCharacterList={() => {}}
354
+ atlasJSON={itemsAtlasJSON}
355
+ atlasIMG={itemsAtlasIMG}
356
+ characterAtlasJSON={entitiesAtlasJSON}
357
+ characterAtlasIMG={entitiesAtlasIMG}
358
+ />
359
+ </RPGUIRoot>
360
+ );
361
+
362
+ MyCharacterListingsNoEligible.storyName = 'My Listings - No eligible chars to list';
363
+
320
364
  export const CharacterListingPending: Story = () => (
321
365
  <RPGUIRoot>
322
366
  <CharacterMarketplacePanel