@rpg-engine/long-bow 0.8.129 → 0.8.131

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rpg-engine/long-bow",
3
- "version": "0.8.129",
3
+ "version": "0.8.131",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.js",
6
6
  "typings": "dist/index.d.ts",
@@ -1,6 +1,6 @@
1
1
  import { IItemPack, IPurchase, IProductBlueprint, ItemRarities, ItemSubType, ItemType, UserAccountTypes, PaymentCurrency, PurchaseType } from '@rpg-engine/shared';
2
2
  import React, { ReactNode, useMemo, useState } from 'react';
3
- import { FaHistory, FaShoppingCart } from 'react-icons/fa';
3
+ import { FaHistory, FaShoppingCart, FaWallet } from 'react-icons/fa';
4
4
  import styled from 'styled-components';
5
5
  import { uiColors } from '../../constants/uiColors';
6
6
  import { DraggableContainer } from '../DraggableContainer';
@@ -15,7 +15,7 @@ import { StorePacksSection } from './sections/StorePacksSection';
15
15
  import { StoreItemDetails } from './StoreItemDetails';
16
16
 
17
17
  // Define TabId union type for tab identifiers
18
- type TabId = 'premium' | 'packs' | 'items';
18
+ type TabId = 'premium' | 'packs' | 'items' | 'wallet';
19
19
 
20
20
  // Define IStoreProps locally as a workaround
21
21
  export interface IStoreProps {
@@ -24,7 +24,9 @@ export interface IStoreProps {
24
24
  atlasJSON: any;
25
25
  atlasIMG: string;
26
26
  onPurchase: (purchase: Partial<IPurchase>) => Promise<boolean>;
27
- onShowHistory?: () => void; // Add the new optional prop
27
+ onShowHistory?: () => void;
28
+ onShowWallet?: () => void;
29
+ walletLabel?: string;
28
30
  userAccountType: UserAccountTypes;
29
31
  loading?: boolean;
30
32
  error?: string;
@@ -34,6 +36,7 @@ export interface IStoreProps {
34
36
  defaultActiveTab?: TabId;
35
37
  textInputItemKeys?: string[];
36
38
  customPacksContent?: React.ReactNode;
39
+ customWalletContent?: React.ReactNode;
37
40
  }
38
41
 
39
42
  export const Store: React.FC<IStoreProps> = ({
@@ -42,7 +45,9 @@ export const Store: React.FC<IStoreProps> = ({
42
45
  atlasJSON,
43
46
  atlasIMG,
44
47
  onPurchase,
45
- onShowHistory, // Destructure the new prop
48
+ onShowHistory,
49
+ onShowWallet,
50
+ walletLabel,
46
51
  userAccountType,
47
52
  loading = false,
48
53
  error,
@@ -52,6 +57,7 @@ export const Store: React.FC<IStoreProps> = ({
52
57
  defaultActiveTab,
53
58
  textInputItemKeys = [],
54
59
  customPacksContent,
60
+ customWalletContent,
55
61
  }) => {
56
62
  const [selectedPack, setSelectedPack] = useState<IItemPack | null>(null);
57
63
  const [activeTab, setActiveTab] = useState<TabId>(() => {
@@ -151,7 +157,7 @@ export const Store: React.FC<IStoreProps> = ({
151
157
  const tabIds: TabId[] = tabOrder ?? ['premium', 'packs', 'items'];
152
158
  const availableTabIds: TabId[] = tabIds.filter(id => !(hidePremiumTab && id === 'premium'));
153
159
 
154
- const tabsMap: Record<TabId, { id: TabId; title: string; content: ReactNode }> = {
160
+ const tabsMap: Record<string, { id: TabId; title: string; content: ReactNode }> = {
155
161
  premium: {
156
162
  id: 'premium',
157
163
  title: 'Premium',
@@ -188,6 +194,11 @@ export const Store: React.FC<IStoreProps> = ({
188
194
  />
189
195
  ),
190
196
  },
197
+ wallet: {
198
+ id: 'wallet',
199
+ title: 'Wallet',
200
+ content: customWalletContent ?? null,
201
+ },
191
202
  };
192
203
 
193
204
  const tabs = availableTabIds.map(id => tabsMap[id]);
@@ -235,7 +246,7 @@ export const Store: React.FC<IStoreProps> = ({
235
246
  ) : (
236
247
  <Container>
237
248
  <TopBar>
238
- <HistoryButton>
249
+ <LeftButtons>
239
250
  {onShowHistory && (
240
251
  <CTAButton
241
252
  icon={<FaHistory />}
@@ -243,7 +254,14 @@ export const Store: React.FC<IStoreProps> = ({
243
254
  onClick={onShowHistory}
244
255
  />
245
256
  )}
246
- </HistoryButton>
257
+ {onShowWallet && (
258
+ <CTAButton
259
+ icon={<FaWallet />}
260
+ label={walletLabel ?? 'DC Wallet'}
261
+ onClick={onShowWallet}
262
+ />
263
+ )}
264
+ </LeftButtons>
247
265
  <CartButton>
248
266
  <CTAButton
249
267
  icon={<FaShoppingCart />}
@@ -309,7 +327,9 @@ const TopBar = styled.div`
309
327
  margin-top: 0.5rem;
310
328
  `;
311
329
 
312
- const HistoryButton = styled.div`
330
+ const LeftButtons = styled.div`
331
+ display: flex;
332
+ gap: 0.5rem;
313
333
  min-width: fit-content;
314
334
  margin-right: auto;
315
335
  `;
@@ -4,7 +4,6 @@ import { FaCartPlus } from 'react-icons/fa';
4
4
  import styled from 'styled-components';
5
5
  import { CTAButton } from '../../shared/CTAButton/CTAButton';
6
6
  import { ScrollableContent } from '../../shared/ScrollableContent/ScrollableContent';
7
- import { ShoppingCardHorizontal } from '../../shared/ShoppingCart/CartCardHorizontal';
8
7
  import { usePackFiltering } from '../../../hooks/usePackFiltering';
9
8
 
10
9
  interface IStorePacksSectionProps {
@@ -18,39 +17,39 @@ export const StorePacksSection: React.FC<IStorePacksSectionProps> = ({
18
17
  onAddToCart,
19
18
  onSelectPack,
20
19
  }) => {
21
- const { searchQuery, setSearchQuery, filteredPacks } = usePackFiltering(
22
- packs
23
- );
20
+ const { searchQuery, setSearchQuery, filteredPacks } = usePackFiltering(packs);
24
21
 
25
- const renderPackFooter = useCallback(
26
- (pack: IItemPack) => (
27
- <FooterContainer>
28
- <Price>${pack.priceUSD}</Price>
29
- <CTAButton
30
- icon={<FaCartPlus />}
31
- label="Add"
32
- onClick={e => {
33
- e.stopPropagation();
34
- onAddToCart(pack);
35
- }}
36
- />
37
- </FooterContainer>
38
- ),
39
- [onAddToCart]
40
- );
22
+ const getImageSrc = (imageUrl: IItemPack['image']): string => {
23
+ if (typeof imageUrl === 'string') return imageUrl;
24
+ return imageUrl.default || imageUrl.src;
25
+ };
41
26
 
42
27
  const renderPack = useCallback(
43
28
  (pack: IItemPack) => (
44
- <ShoppingCardHorizontal
45
- key={pack.key}
46
- title={pack.title}
47
- description={pack.description}
48
- imageUrl={pack.image}
49
- footer={renderPackFooter(pack)}
50
- onClick={() => onSelectPack?.(pack)}
51
- />
29
+ <PackRow key={pack.key} onClick={() => onSelectPack?.(pack)}>
30
+ <PackIconContainer>
31
+ <img src={getImageSrc(pack.image)} alt={pack.title} />
32
+ </PackIconContainer>
33
+
34
+ <PackDetails>
35
+ <PackName>{pack.title}</PackName>
36
+ <PackPrice>${pack.priceUSD}</PackPrice>
37
+ {pack.description && <PackDescription>{pack.description}</PackDescription>}
38
+ </PackDetails>
39
+
40
+ <Controls>
41
+ <CTAButton
42
+ icon={<FaCartPlus />}
43
+ label="Add"
44
+ onClick={e => {
45
+ e.stopPropagation();
46
+ onAddToCart(pack);
47
+ }}
48
+ />
49
+ </Controls>
50
+ </PackRow>
52
51
  ),
53
- [onSelectPack, renderPackFooter]
52
+ [onSelectPack, onAddToCart]
54
53
  );
55
54
 
56
55
  return (
@@ -63,22 +62,73 @@ export const StorePacksSection: React.FC<IStorePacksSectionProps> = ({
63
62
  onChange: setSearchQuery,
64
63
  placeholder: 'Search packs...',
65
64
  }}
66
- layout="grid"
67
- gridColumns={2}
65
+ layout="list"
68
66
  maxHeight="420px"
69
67
  />
70
68
  );
71
69
  };
72
70
 
73
- const FooterContainer = styled.div`
71
+ const PackRow = styled.div`
74
72
  display: flex;
75
73
  align-items: center;
76
- justify-content: space-between;
77
- gap: 8px;
74
+ gap: 0.75rem;
75
+ padding: 0.5rem 1rem;
76
+ border-bottom: 1px solid rgba(255, 255, 255, 0.1);
77
+ cursor: pointer;
78
+
79
+ &:last-child {
80
+ border-bottom: none;
81
+ }
82
+
83
+ &:hover {
84
+ background: rgba(255, 255, 255, 0.04);
85
+ }
86
+ `;
87
+
88
+ const PackIconContainer = styled.div`
89
+ width: 40px;
90
+ height: 40px;
91
+ flex-shrink: 0;
92
+ display: flex;
93
+ align-items: center;
94
+ justify-content: center;
95
+
96
+ img {
97
+ width: 100%;
98
+ height: 100%;
99
+ object-fit: cover;
100
+ }
78
101
  `;
79
102
 
80
- const Price = styled.span`
103
+ const PackDetails = styled.div`
104
+ flex: 1;
105
+ display: flex;
106
+ flex-direction: column;
107
+ gap: 0.25rem;
108
+ min-width: 0;
109
+ `;
110
+
111
+ const PackName = styled.div`
81
112
  font-family: 'Press Start 2P', cursive;
82
- font-size: 0.6rem;
113
+ font-size: 0.75rem;
114
+ color: #ffffff;
115
+ `;
116
+
117
+ const PackPrice = styled.div`
118
+ font-family: 'Press Start 2P', cursive;
119
+ font-size: 0.625rem;
83
120
  color: #fef08a;
84
121
  `;
122
+
123
+ const PackDescription = styled.div`
124
+ font-family: 'Press Start 2P', cursive;
125
+ font-size: 0.625rem;
126
+ color: rgba(255, 255, 255, 0.7);
127
+ line-height: 1.4;
128
+ `;
129
+
130
+ const Controls = styled.div`
131
+ display: flex;
132
+ align-items: center;
133
+ flex-shrink: 0;
134
+ `;