@rpg-engine/long-bow 0.8.161 → 0.8.162
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/BuyOrderRows.d.ts +11 -0
- package/dist/components/Marketplace/GroupedRowContainer.d.ts +7 -0
- package/dist/components/shared/ItemRowWrapper.d.ts +3 -0
- package/dist/long-bow.cjs.development.js +256 -165
- 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 +256 -166
- package/dist/long-bow.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/components/Marketplace/BuyOrderRows.tsx +53 -16
- package/src/components/Marketplace/BuyPanel.tsx +140 -114
- package/src/components/Marketplace/GroupedRowContainer.tsx +86 -0
- package/src/components/Marketplace/MarketplaceRows.tsx +24 -125
- package/src/components/Store/Store.tsx +22 -18
- package/src/components/Store/StoreItemRow.tsx +28 -33
- package/src/components/Store/sections/StoreItemsSection.tsx +7 -13
- package/src/components/Store/sections/StorePacksSection.tsx +19 -21
- package/src/components/shared/ItemRowWrapper.tsx +22 -0
- package/src/stories/Features/trading/Marketplace.stories.tsx +18 -5
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import { IItemPack, IPurchase, IProductBlueprint, ItemRarities, ItemSubType, ItemType, UserAccountTypes, PaymentCurrency, PurchaseType } from '@rpg-engine/shared';
|
|
2
|
+
import { Box } from 'pixelarticons/react/Box';
|
|
3
|
+
import { Crown } from 'pixelarticons/react/Crown';
|
|
4
|
+
import { Gift } from 'pixelarticons/react/Gift';
|
|
5
|
+
import { Wallet } from 'pixelarticons/react/Wallet';
|
|
2
6
|
import React, { ReactNode, useMemo, useState } from 'react';
|
|
3
7
|
import { FaHistory, FaShoppingCart, FaWallet } from 'react-icons/fa';
|
|
4
8
|
import styled from 'styled-components';
|
|
5
9
|
import { uiColors } from '../../constants/uiColors';
|
|
6
10
|
import { DraggableContainer } from '../DraggableContainer';
|
|
7
|
-
import { InternalTabs } from '../InternalTabs/InternalTabs';
|
|
8
11
|
import { RPGUIContainerTypes } from '../RPGUI/RPGUIContainer';
|
|
12
|
+
import { Tabs } from '../shared/Tabs';
|
|
9
13
|
import { CTAButton } from '../shared/CTAButton/CTAButton';
|
|
10
14
|
import { CartView } from './CartView';
|
|
11
15
|
import { useStoreCart } from './hooks/useStoreCart';
|
|
@@ -159,10 +163,11 @@ export const Store: React.FC<IStoreProps> = ({
|
|
|
159
163
|
const tabIds: TabId[] = tabOrder ?? ['premium', 'packs', 'items'];
|
|
160
164
|
const availableTabIds: TabId[] = tabIds.filter(id => !(hidePremiumTab && id === 'premium'));
|
|
161
165
|
|
|
162
|
-
const tabsMap: Record<string, { id: TabId; title: string; content: ReactNode }> = {
|
|
166
|
+
const tabsMap: Record<string, { id: TabId; title: string; icon: ReactNode; content: ReactNode }> = {
|
|
163
167
|
premium: {
|
|
164
168
|
id: 'premium',
|
|
165
169
|
title: 'Premium',
|
|
170
|
+
icon: <Crown width={18} height={18} />,
|
|
166
171
|
content: (
|
|
167
172
|
<StorePacksSection
|
|
168
173
|
packs={packs.filter(pack => pack.priceUSD >= 9.99)}
|
|
@@ -176,6 +181,7 @@ export const Store: React.FC<IStoreProps> = ({
|
|
|
176
181
|
packs: {
|
|
177
182
|
id: 'packs',
|
|
178
183
|
title: packsTabLabel,
|
|
184
|
+
icon: <Gift width={18} height={18} />,
|
|
179
185
|
content: customPacksContent ?? (
|
|
180
186
|
<StorePacksSection
|
|
181
187
|
packs={hidePremiumTab ? packs : packs.filter(pack => pack.priceUSD < 9.99)}
|
|
@@ -189,6 +195,7 @@ export const Store: React.FC<IStoreProps> = ({
|
|
|
189
195
|
items: {
|
|
190
196
|
id: 'items',
|
|
191
197
|
title: 'Items',
|
|
198
|
+
icon: <Box width={18} height={18} />,
|
|
192
199
|
content: (
|
|
193
200
|
<StoreItemsSection
|
|
194
201
|
items={filteredItems.items}
|
|
@@ -203,12 +210,11 @@ export const Store: React.FC<IStoreProps> = ({
|
|
|
203
210
|
wallet: {
|
|
204
211
|
id: 'wallet',
|
|
205
212
|
title: 'Wallet',
|
|
213
|
+
icon: <Wallet width={18} height={18} />,
|
|
206
214
|
content: customWalletContent ?? null,
|
|
207
215
|
},
|
|
208
216
|
};
|
|
209
217
|
|
|
210
|
-
const tabs = availableTabIds.map(id => tabsMap[id]);
|
|
211
|
-
|
|
212
218
|
return (
|
|
213
219
|
<DraggableContainer
|
|
214
220
|
title="Store"
|
|
@@ -276,16 +282,14 @@ export const Store: React.FC<IStoreProps> = ({
|
|
|
276
282
|
</CartButton>
|
|
277
283
|
</TopBar>
|
|
278
284
|
<MainContent>
|
|
279
|
-
<
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
inactiveColor="#6b7280"
|
|
284
|
-
borderColor="#f59e0b"
|
|
285
|
-
hoverColor="#fef3c7"
|
|
286
|
-
activeTab={activeTab}
|
|
287
|
-
onTabChange={(tabId: string) => setActiveTab(tabId as TabId)}
|
|
285
|
+
<Tabs
|
|
286
|
+
options={availableTabIds.map(id => ({ id, label: tabsMap[id].title, icon: tabsMap[id].icon }))}
|
|
287
|
+
activeTabId={activeTab}
|
|
288
|
+
onTabChange={(tabId) => setActiveTab(tabId as TabId)}
|
|
288
289
|
/>
|
|
290
|
+
<TabContent>
|
|
291
|
+
{tabsMap[activeTab]?.content}
|
|
292
|
+
</TabContent>
|
|
289
293
|
</MainContent>
|
|
290
294
|
{cartItems.length > 0 && (
|
|
291
295
|
<Footer>
|
|
@@ -349,12 +353,12 @@ const MainContent = styled.div`
|
|
|
349
353
|
flex-direction: column;
|
|
350
354
|
min-height: 0;
|
|
351
355
|
overflow: hidden;
|
|
356
|
+
`;
|
|
352
357
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
}
|
|
358
|
+
const TabContent = styled.div`
|
|
359
|
+
flex: 1;
|
|
360
|
+
overflow-y: auto;
|
|
361
|
+
padding-right: 0.5rem;
|
|
358
362
|
`;
|
|
359
363
|
|
|
360
364
|
const Footer = styled.div`
|
|
@@ -4,6 +4,7 @@ import { FaCartPlus } from 'react-icons/fa';
|
|
|
4
4
|
import styled from 'styled-components';
|
|
5
5
|
import { SelectArrow } from '../Arrow/SelectArrow';
|
|
6
6
|
import { CTAButton } from '../shared/CTAButton/CTAButton';
|
|
7
|
+
import { ItemRowWrapper } from '../shared/ItemRowWrapper';
|
|
7
8
|
import { SpriteFromAtlas } from '../shared/SpriteFromAtlas';
|
|
8
9
|
import { useQuantityControl } from '../../hooks/useQuantityControl';
|
|
9
10
|
|
|
@@ -56,27 +57,29 @@ export const StoreItemRow: React.FC<IStoreItemRowProps> = ({
|
|
|
56
57
|
};
|
|
57
58
|
|
|
58
59
|
return (
|
|
59
|
-
<
|
|
60
|
-
<
|
|
61
|
-
<
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
<
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
60
|
+
<ItemRowWrapper $isHighlighted={item.store?.isHighlighted || false}>
|
|
61
|
+
<LeftSection>
|
|
62
|
+
<ItemIconContainer>
|
|
63
|
+
<SpriteFromAtlas
|
|
64
|
+
atlasJSON={atlasJSON}
|
|
65
|
+
atlasIMG={atlasIMG}
|
|
66
|
+
spriteKey={item.texturePath}
|
|
67
|
+
width={32}
|
|
68
|
+
height={32}
|
|
69
|
+
imgScale={2}
|
|
70
|
+
centered
|
|
71
|
+
/>
|
|
72
|
+
</ItemIconContainer>
|
|
73
|
+
|
|
74
|
+
<ItemDetails>
|
|
75
|
+
<ItemName>{item.name}</ItemName>
|
|
76
|
+
<ItemPrice>
|
|
77
|
+
${item.price}
|
|
78
|
+
{(item as any).dcPrice ? ` · ${((item as any).dcPrice as number).toLocaleString()} DC` : ''}
|
|
79
|
+
</ItemPrice>
|
|
80
|
+
<ItemDescription>{item.description}</ItemDescription>
|
|
81
|
+
</ItemDetails>
|
|
82
|
+
</LeftSection>
|
|
80
83
|
|
|
81
84
|
<Controls>
|
|
82
85
|
{/* Show text input if configured, else show arrows only for stackable items */}
|
|
@@ -121,24 +124,16 @@ export const StoreItemRow: React.FC<IStoreItemRowProps> = ({
|
|
|
121
124
|
disabled={!hasRequiredAccount}
|
|
122
125
|
/>
|
|
123
126
|
</Controls>
|
|
124
|
-
</
|
|
127
|
+
</ItemRowWrapper>
|
|
125
128
|
);
|
|
126
129
|
};
|
|
127
130
|
|
|
128
|
-
const
|
|
131
|
+
const LeftSection = styled.div`
|
|
129
132
|
display: flex;
|
|
130
133
|
align-items: center;
|
|
131
134
|
gap: 0.75rem;
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
background: ${props =>
|
|
135
|
-
props.$isHighlighted ? 'rgba(255, 215, 0, 0.1)' : 'transparent'};
|
|
136
|
-
border-left: ${props =>
|
|
137
|
-
props.$isHighlighted ? '3px solid #ffd700' : '3px solid transparent'};
|
|
138
|
-
|
|
139
|
-
&:last-child {
|
|
140
|
-
border-bottom: none;
|
|
141
|
-
}
|
|
135
|
+
flex: 1;
|
|
136
|
+
min-width: 0;
|
|
142
137
|
`;
|
|
143
138
|
|
|
144
139
|
const ItemIconContainer = styled.div`
|
|
@@ -9,7 +9,7 @@ import styled from 'styled-components';
|
|
|
9
9
|
import { ScrollableContent } from '../../shared/ScrollableContent/ScrollableContent';
|
|
10
10
|
import { StoreCharacterSkinRow } from '../StoreCharacterSkinRow';
|
|
11
11
|
import { StoreItemRow } from '../StoreItemRow';
|
|
12
|
-
import {
|
|
12
|
+
import { SegmentedToggle } from '../../shared/SegmentedToggle';
|
|
13
13
|
import { SearchBar } from '../../shared/SearchBar/SearchBar';
|
|
14
14
|
import { useStoreFiltering } from '../../../hooks/useStoreFiltering';
|
|
15
15
|
|
|
@@ -37,6 +37,7 @@ export const StoreItemsSection: React.FC<IStoreItemsSectionProps> = ({
|
|
|
37
37
|
const {
|
|
38
38
|
searchQuery,
|
|
39
39
|
setSearchQuery,
|
|
40
|
+
selectedCategory,
|
|
40
41
|
setSelectedCategory,
|
|
41
42
|
categoryOptions,
|
|
42
43
|
filteredItems,
|
|
@@ -93,13 +94,11 @@ export const StoreItemsSection: React.FC<IStoreItemsSectionProps> = ({
|
|
|
93
94
|
placeholder="Search items..."
|
|
94
95
|
/>
|
|
95
96
|
</SearchBarContainer>
|
|
96
|
-
<
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
/>
|
|
102
|
-
</DropdownContainer>
|
|
97
|
+
<SegmentedToggle
|
|
98
|
+
options={categoryOptions.map(opt => ({ id: opt.value, label: opt.option }))}
|
|
99
|
+
activeId={selectedCategory}
|
|
100
|
+
onChange={id => setSelectedCategory(id as ItemType | 'all')}
|
|
101
|
+
/>
|
|
103
102
|
</SearchHeader>
|
|
104
103
|
|
|
105
104
|
<ScrollableContent
|
|
@@ -130,8 +129,3 @@ const SearchHeader = styled.div`
|
|
|
130
129
|
const SearchBarContainer = styled.div`
|
|
131
130
|
flex: 0.75;
|
|
132
131
|
`;
|
|
133
|
-
|
|
134
|
-
const DropdownContainer = styled.div`
|
|
135
|
-
flex: 0.25;
|
|
136
|
-
min-width: 140px;
|
|
137
|
-
`;
|
|
@@ -3,6 +3,7 @@ import React, { useCallback } from 'react';
|
|
|
3
3
|
import { FaCartPlus } from 'react-icons/fa';
|
|
4
4
|
import styled from 'styled-components';
|
|
5
5
|
import { CTAButton } from '../../shared/CTAButton/CTAButton';
|
|
6
|
+
import { ItemRowWrapper } from '../../shared/ItemRowWrapper';
|
|
6
7
|
import { SpriteFromAtlas } from '../../shared/SpriteFromAtlas';
|
|
7
8
|
import { ScrollableContent } from '../../shared/ScrollableContent/ScrollableContent';
|
|
8
9
|
import { usePackFiltering } from '../../../hooks/usePackFiltering';
|
|
@@ -43,15 +44,17 @@ export const StorePacksSection: React.FC<IStorePacksSectionProps> = ({
|
|
|
43
44
|
const renderPack = useCallback(
|
|
44
45
|
(pack: IItemPack) => (
|
|
45
46
|
<PackRow key={pack.key} onClick={() => onSelectPack?.(pack)}>
|
|
46
|
-
<
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
<
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
47
|
+
<LeftSection>
|
|
48
|
+
<PackIconContainer>
|
|
49
|
+
{renderPackIcon(pack)}
|
|
50
|
+
</PackIconContainer>
|
|
51
|
+
|
|
52
|
+
<PackDetails>
|
|
53
|
+
<PackName>{pack.title}</PackName>
|
|
54
|
+
<PackPrice>${pack.priceUSD}</PackPrice>
|
|
55
|
+
{pack.description && <PackDescription>{pack.description}</PackDescription>}
|
|
56
|
+
</PackDetails>
|
|
57
|
+
</LeftSection>
|
|
55
58
|
|
|
56
59
|
<Controls>
|
|
57
60
|
<CTAButton
|
|
@@ -84,21 +87,16 @@ export const StorePacksSection: React.FC<IStorePacksSectionProps> = ({
|
|
|
84
87
|
);
|
|
85
88
|
};
|
|
86
89
|
|
|
87
|
-
const PackRow = styled
|
|
90
|
+
const PackRow = styled(ItemRowWrapper)`
|
|
91
|
+
cursor: pointer;
|
|
92
|
+
`;
|
|
93
|
+
|
|
94
|
+
const LeftSection = styled.div`
|
|
88
95
|
display: flex;
|
|
89
96
|
align-items: center;
|
|
90
97
|
gap: 0.75rem;
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
cursor: pointer;
|
|
94
|
-
|
|
95
|
-
&:last-child {
|
|
96
|
-
border-bottom: none;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
&:hover {
|
|
100
|
-
background: rgba(255, 255, 255, 0.04);
|
|
101
|
-
}
|
|
98
|
+
flex: 1;
|
|
99
|
+
min-width: 0;
|
|
102
100
|
`;
|
|
103
101
|
|
|
104
102
|
const PackIconContainer = styled.div`
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import styled from 'styled-components';
|
|
2
|
+
|
|
3
|
+
export const ItemRowWrapper = styled.div<{ $isHighlighted?: boolean }>`
|
|
4
|
+
display: flex;
|
|
5
|
+
align-items: center;
|
|
6
|
+
justify-content: space-between;
|
|
7
|
+
padding: 0.6rem 1rem;
|
|
8
|
+
margin-bottom: 4px;
|
|
9
|
+
background: ${p => p.$isHighlighted ? 'rgba(255, 215, 0, 0.08)' : 'rgba(0, 0, 0, 0.25)'};
|
|
10
|
+
border: 1px solid rgba(255, 255, 255, 0.05);
|
|
11
|
+
border-radius: 6px;
|
|
12
|
+
border-left: 4px solid ${p => p.$isHighlighted ? '#ffd700' : 'transparent'};
|
|
13
|
+
transition: all 0.2s ease-in-out;
|
|
14
|
+
|
|
15
|
+
&:hover {
|
|
16
|
+
background: rgba(245, 158, 11, 0.08);
|
|
17
|
+
border-color: rgba(245, 158, 11, 0.2);
|
|
18
|
+
border-left-color: #f59e0b;
|
|
19
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
|
|
20
|
+
transform: translateY(-1px);
|
|
21
|
+
}
|
|
22
|
+
`;
|
|
@@ -43,13 +43,26 @@ const mockYourBuyOrders: IMarketplaceBuyOrderItem[] = [
|
|
|
43
43
|
];
|
|
44
44
|
|
|
45
45
|
const mockOpenBuyOrders: IMarketplaceBuyOrderItem[] = [
|
|
46
|
+
// Abyssal Tide Staff — single request
|
|
46
47
|
{ _id: 'obo-1', owner: 'player-2', itemBlueprintKey: 'items/abyssal-tide-staff', itemRarity: 'Epic', maxPrice: 1500, escrowedGold: 1500, fee: 75, status: MarketplaceBuyOrderStatus.Active, createdAt: daysAgo(1), updatedAt: daysAgo(1) },
|
|
48
|
+
// Wooden Shield — single request
|
|
47
49
|
{ _id: 'obo-2', owner: 'player-3', itemBlueprintKey: 'items/wooden-shield', maxPrice: 200, escrowedGold: 200, fee: 10, status: MarketplaceBuyOrderStatus.Active, createdAt: daysAgo(5), updatedAt: daysAgo(5) },
|
|
48
|
-
|
|
49
|
-
{ _id: 'obo-
|
|
50
|
+
// Fire Wand — 2 requests (grouped)
|
|
51
|
+
{ _id: 'obo-3a', owner: 'player-4', itemBlueprintKey: 'items/fire-wand', itemRarity: 'Rare', maxPrice: 800, escrowedGold: 800, fee: 40, status: MarketplaceBuyOrderStatus.Active, createdAt: daysAgo(2), updatedAt: daysAgo(2) },
|
|
52
|
+
{ _id: 'obo-3b', owner: 'player-10', itemBlueprintKey: 'items/fire-wand', maxPrice: 550, escrowedGold: 550, fee: 27, status: MarketplaceBuyOrderStatus.Active, createdAt: daysAgo(4), updatedAt: daysAgo(4) },
|
|
53
|
+
// Broad Sword — 3 requests (grouped)
|
|
54
|
+
{ _id: 'obo-4a', owner: 'player-5', itemBlueprintKey: 'items/broad-sword', maxPrice: 350, escrowedGold: 350, fee: 17, status: MarketplaceBuyOrderStatus.Active, createdAt: daysAgo(3), updatedAt: daysAgo(3) },
|
|
55
|
+
{ _id: 'obo-4b', owner: 'player-11', itemBlueprintKey: 'items/broad-sword', itemRarity: 'Rare', maxPrice: 480, escrowedGold: 480, fee: 24, status: MarketplaceBuyOrderStatus.Active, createdAt: daysAgo(1), updatedAt: daysAgo(1) },
|
|
56
|
+
{ _id: 'obo-4c', owner: 'player-12', itemBlueprintKey: 'items/broad-sword', maxPrice: 270, escrowedGold: 270, fee: 13, status: MarketplaceBuyOrderStatus.Active, createdAt: daysAgo(6), updatedAt: daysAgo(6) },
|
|
57
|
+
// Barbarian Helmet — single request
|
|
50
58
|
{ _id: 'obo-5', owner: 'player-6', itemBlueprintKey: 'items/barbarian-helmet', itemRarity: 'Uncommon', maxPrice: 600, escrowedGold: 600, fee: 30, status: MarketplaceBuyOrderStatus.Active, createdAt: daysAgo(1), updatedAt: daysAgo(1) },
|
|
51
|
-
|
|
52
|
-
{ _id: 'obo-
|
|
59
|
+
// Leather Armor — 2 requests (grouped)
|
|
60
|
+
{ _id: 'obo-6a', owner: 'player-7', itemBlueprintKey: 'items/leather-armor', maxPrice: 420, escrowedGold: 420, fee: 21, status: MarketplaceBuyOrderStatus.Active, createdAt: daysAgo(4), updatedAt: daysAgo(4) },
|
|
61
|
+
{ _id: 'obo-6b', owner: 'player-13', itemBlueprintKey: 'items/leather-armor', itemRarity: 'Uncommon', maxPrice: 380, escrowedGold: 380, fee: 19, status: MarketplaceBuyOrderStatus.Active, createdAt: daysAgo(2), updatedAt: daysAgo(2) },
|
|
62
|
+
// Angelic Sword — 2 requests (grouped)
|
|
63
|
+
{ _id: 'obo-7a', owner: 'player-8', itemBlueprintKey: 'items/angelic-sword', itemRarity: 'Legendary', maxPrice: 5000, escrowedGold: 5000, fee: 250, status: MarketplaceBuyOrderStatus.Active, createdAt: daysAgo(6), updatedAt: daysAgo(6) },
|
|
64
|
+
{ _id: 'obo-7b', owner: 'player-14', itemBlueprintKey: 'items/angelic-sword', itemRarity: 'Epic', maxPrice: 3500, escrowedGold: 3500, fee: 175, status: MarketplaceBuyOrderStatus.Active, createdAt: daysAgo(3), updatedAt: daysAgo(3) },
|
|
65
|
+
// Greater Life Potion — single request
|
|
53
66
|
{ _id: 'obo-8', owner: 'player-9', itemBlueprintKey: 'items/greater-life-potion', maxPrice: 90, stackQty: 10, escrowedGold: 900, fee: 45, status: MarketplaceBuyOrderStatus.Active, createdAt: daysAgo(2), updatedAt: daysAgo(2) },
|
|
54
67
|
];
|
|
55
68
|
|
|
@@ -169,7 +182,7 @@ const Template: Story = () => {
|
|
|
169
182
|
onYourBuyOrdersPageChange={p => console.log('your orders page:', p)}
|
|
170
183
|
onCancelBuyOrder={id => setYourBuyOrders(prev => prev.filter(o => o._id !== id))}
|
|
171
184
|
openBuyOrders={mockOpenBuyOrders}
|
|
172
|
-
openBuyOrdersTotal={mockOpenBuyOrders.length}
|
|
185
|
+
openBuyOrdersTotal={mockOpenBuyOrders.length}
|
|
173
186
|
openBuyOrdersPage={1}
|
|
174
187
|
onOpenBuyOrdersPageChange={(p: number) => console.log('open orders page:', p)}
|
|
175
188
|
// Blueprint Search props
|