@rpg-engine/long-bow 0.8.220 → 0.8.222
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/Store/CartView.d.ts +0 -2
- package/dist/components/Store/Store.d.ts +0 -1
- package/dist/long-bow.cjs.development.js +39 -52
- 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 +40 -53
- package/dist/long-bow.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/components/DraggableContainer.tsx +6 -0
- package/src/components/Store/CartView.tsx +130 -137
- package/src/components/Store/Store.tsx +0 -3
package/package.json
CHANGED
|
@@ -181,6 +181,12 @@ const Container = styled.div<IContainerProps>`
|
|
|
181
181
|
&.rpgui-container {
|
|
182
182
|
padding-top: 1.5rem;
|
|
183
183
|
}
|
|
184
|
+
|
|
185
|
+
@media (max-width: 600px) {
|
|
186
|
+
width: 100vw !important;
|
|
187
|
+
min-width: unset !important;
|
|
188
|
+
height: 100dvh !important;
|
|
189
|
+
}
|
|
184
190
|
`;
|
|
185
191
|
|
|
186
192
|
const CloseButton = styled.div`
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { IProductBlueprint, MetadataType } from '@rpg-engine/shared';
|
|
2
2
|
import React, { useState } from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import { FaInfoCircle, FaShoppingBag, FaTimes, FaTrash } from 'react-icons/fa';
|
|
4
4
|
import styled from 'styled-components';
|
|
5
5
|
import characterAtlasJSON from '../../mocks/atlas/entities/entities.json';
|
|
6
6
|
import characterAtlasIMG from '../../mocks/atlas/entities/entities.png';
|
|
@@ -27,8 +27,6 @@ export interface ICartViewProps {
|
|
|
27
27
|
paymentMethodLabel?: string;
|
|
28
28
|
trustSignals?: ITrustSignal[];
|
|
29
29
|
onCloseStore?: () => void;
|
|
30
|
-
/** Called when user taps the "Buy DC" nudge — open wallet/DC purchase flow */
|
|
31
|
-
onBuyDC?: () => void;
|
|
32
30
|
/** Fires when user taps the pay button — before the purchase resolves */
|
|
33
31
|
onCheckoutStart?: (items: Array<{ key: string; name: string; quantity: number }>, total: number) => void;
|
|
34
32
|
/** Fires after a successful purchase */
|
|
@@ -69,7 +67,6 @@ export const CartView: React.FC<ICartViewProps> = ({
|
|
|
69
67
|
paymentMethodLabel,
|
|
70
68
|
trustSignals,
|
|
71
69
|
onCloseStore,
|
|
72
|
-
onBuyDC,
|
|
73
70
|
onCheckoutStart,
|
|
74
71
|
onPurchaseSuccess,
|
|
75
72
|
onPurchaseError,
|
|
@@ -118,10 +115,6 @@ export const CartView: React.FC<ICartViewProps> = ({
|
|
|
118
115
|
}
|
|
119
116
|
};
|
|
120
117
|
|
|
121
|
-
// Show DC discount nudge when items have DC pricing and user might benefit
|
|
122
|
-
const hasDCItems = cartItems.some(ci => (ci.item as any).dcPrice);
|
|
123
|
-
const showDCNudge = hasDCItems && onBuyDC;
|
|
124
|
-
|
|
125
118
|
if (purchasedItems) {
|
|
126
119
|
return (
|
|
127
120
|
<PurchaseSuccess
|
|
@@ -150,100 +143,95 @@ export const CartView: React.FC<ICartViewProps> = ({
|
|
|
150
143
|
</CloseButton>
|
|
151
144
|
</Header>
|
|
152
145
|
|
|
153
|
-
<
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
/>
|
|
175
|
-
</ItemIconContainer>
|
|
176
|
-
<ItemDetails>
|
|
177
|
-
<ItemName>{cartItem.item.name}</ItemName>
|
|
178
|
-
{cartItem.metadata?.inputValue && (
|
|
179
|
-
<CartMeta>{cartItem.metadata.inputValue}</CartMeta>
|
|
180
|
-
)}
|
|
181
|
-
<ItemInfo>
|
|
182
|
-
<span>{currencySymbol}{formatPrice((cartItem.item as any).regionalPrice ?? cartItem.item.price)}</span>
|
|
183
|
-
<span>×</span>
|
|
184
|
-
<span>{cartItem.quantity}</span>
|
|
185
|
-
<span>=</span>
|
|
186
|
-
<span>
|
|
187
|
-
{currencySymbol}{formatPrice(((cartItem.item as any).regionalPrice ?? cartItem.item.price) * cartItem.quantity)}
|
|
188
|
-
</span>
|
|
189
|
-
</ItemInfo>
|
|
190
|
-
|
|
191
|
-
{cartItem.metadata && cartItem.item.metadataType && (
|
|
192
|
-
<MetadataDisplay
|
|
193
|
-
type={cartItem.item.metadataType}
|
|
194
|
-
metadata={cartItem.metadata}
|
|
146
|
+
<MainContent>
|
|
147
|
+
<CartItems>
|
|
148
|
+
{cartItems.length === 0 ? (
|
|
149
|
+
<EmptyCart>Your cart is empty</EmptyCart>
|
|
150
|
+
) : (
|
|
151
|
+
cartItems.map(cartItem => {
|
|
152
|
+
const getSpriteKey = (textureKey: string) => {
|
|
153
|
+
return textureKey + '/down/standing/0.png';
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
return (
|
|
157
|
+
<CartItemRow key={cartItem.item.key}>
|
|
158
|
+
<ItemIconContainer>
|
|
159
|
+
<SpriteFromAtlas
|
|
160
|
+
atlasJSON={cartItem.item.metadataType === MetadataType.CharacterSkin ? characterAtlasJSON : atlasJSON}
|
|
161
|
+
atlasIMG={cartItem.item.metadataType === MetadataType.CharacterSkin ? characterAtlasIMG : atlasIMG}
|
|
162
|
+
spriteKey={cartItem.item.metadataType === MetadataType.CharacterSkin && cartItem.metadata?.selectedSkinTextureKey ? getSpriteKey(cartItem.metadata.selectedSkinTextureKey) : cartItem.item.texturePath}
|
|
163
|
+
width={24}
|
|
164
|
+
height={24}
|
|
165
|
+
imgScale={1.5}
|
|
166
|
+
centered
|
|
195
167
|
/>
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
168
|
+
</ItemIconContainer>
|
|
169
|
+
<ItemDetails>
|
|
170
|
+
<ItemName>{cartItem.item.name}</ItemName>
|
|
171
|
+
{cartItem.metadata?.inputValue && (
|
|
172
|
+
<CartMeta>{cartItem.metadata.inputValue}</CartMeta>
|
|
173
|
+
)}
|
|
174
|
+
<ItemInfo>
|
|
175
|
+
<span>{currencySymbol}{formatPrice((cartItem.item as any).regionalPrice ?? cartItem.item.price)}</span>
|
|
176
|
+
<span>×</span>
|
|
177
|
+
<span>{cartItem.quantity}</span>
|
|
178
|
+
<span>=</span>
|
|
179
|
+
<span>
|
|
180
|
+
{currencySymbol}{formatPrice(((cartItem.item as any).regionalPrice ?? cartItem.item.price) * cartItem.quantity)}
|
|
181
|
+
</span>
|
|
182
|
+
</ItemInfo>
|
|
183
|
+
|
|
184
|
+
{cartItem.metadata && cartItem.item.metadataType && (
|
|
185
|
+
<MetadataDisplay
|
|
186
|
+
type={cartItem.item.metadataType}
|
|
187
|
+
metadata={cartItem.metadata}
|
|
188
|
+
/>
|
|
189
|
+
)}
|
|
190
|
+
</ItemDetails>
|
|
191
|
+
|
|
192
|
+
<CTAButton
|
|
193
|
+
icon={<FaTrash />}
|
|
194
|
+
onClick={e => {
|
|
195
|
+
e.stopPropagation();
|
|
196
|
+
onRemoveFromCart(cartItem.item.key);
|
|
197
|
+
}}
|
|
198
|
+
/>
|
|
199
|
+
</CartItemRow>
|
|
200
|
+
);
|
|
201
|
+
})
|
|
202
|
+
)}
|
|
203
|
+
</CartItems>
|
|
211
204
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
<
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
205
|
+
{cartItems.length > 0 && (
|
|
206
|
+
<OrderSummaryPanel>
|
|
207
|
+
<OrderSummaryLabel>Order Summary</OrderSummaryLabel>
|
|
208
|
+
<TotalRow>
|
|
209
|
+
<span>Subtotal:</span>
|
|
210
|
+
<span>{currencySymbol}{formatPrice(total)}</span>
|
|
211
|
+
</TotalRow>
|
|
212
|
+
{dcTotal > 0 && (
|
|
213
|
+
<TotalRow>
|
|
214
|
+
<span>DC:</span>
|
|
215
|
+
<span><MMORPGNumber value={dcTotal} /> DC</span>
|
|
216
|
+
</TotalRow>
|
|
217
|
+
)}
|
|
218
|
+
<TotalRow $isTotal>
|
|
219
|
+
<span>Total:</span>
|
|
220
|
+
<span>{currencySymbol}{formatPrice(total)}</span>
|
|
221
|
+
</TotalRow>
|
|
222
|
+
{paymentMethodLabel && (
|
|
223
|
+
<PaymentMethodRow>
|
|
224
|
+
<span>Paying with:</span>
|
|
225
|
+
<span>{paymentMethodLabel}</span>
|
|
226
|
+
</PaymentMethodRow>
|
|
227
|
+
)}
|
|
228
|
+
</OrderSummaryPanel>
|
|
219
229
|
)}
|
|
230
|
+
</MainContent>
|
|
220
231
|
|
|
232
|
+
<Footer>
|
|
221
233
|
<TrustBar signals={trustSignals} />
|
|
222
|
-
|
|
223
|
-
<TotalInfo>
|
|
224
|
-
<OrderSummaryLabel>Order Summary</OrderSummaryLabel>
|
|
225
|
-
<TotalRow>
|
|
226
|
-
<span>Subtotal:</span>
|
|
227
|
-
<span>{currencySymbol}{formatPrice(total)}</span>
|
|
228
|
-
</TotalRow>
|
|
229
|
-
{dcTotal > 0 && (
|
|
230
|
-
<TotalRow>
|
|
231
|
-
<span>DC:</span>
|
|
232
|
-
<span><MMORPGNumber value={dcTotal} /> DC</span>
|
|
233
|
-
</TotalRow>
|
|
234
|
-
)}
|
|
235
|
-
<TotalRow $isTotal>
|
|
236
|
-
<span>Total:</span>
|
|
237
|
-
<span>{currencySymbol}{formatPrice(total)}</span>
|
|
238
|
-
</TotalRow>
|
|
239
|
-
{paymentMethodLabel && (
|
|
240
|
-
<PaymentMethodRow>
|
|
241
|
-
<span>Paying with:</span>
|
|
242
|
-
<span>{paymentMethodLabel}</span>
|
|
243
|
-
</PaymentMethodRow>
|
|
244
|
-
)}
|
|
245
|
-
{error && <ErrorMessage>{error}</ErrorMessage>}
|
|
246
|
-
</TotalInfo>
|
|
234
|
+
{error && <ErrorMessage>{error}</ErrorMessage>}
|
|
247
235
|
<CTAButton
|
|
248
236
|
icon={<FaShoppingBag />}
|
|
249
237
|
label={isLoading ? 'Processing...' : `Pay ${currencySymbol}${formatPrice(total)}`}
|
|
@@ -264,6 +252,10 @@ const Container = styled.div`
|
|
|
264
252
|
padding: 1rem;
|
|
265
253
|
overflow: hidden;
|
|
266
254
|
box-sizing: border-box;
|
|
255
|
+
|
|
256
|
+
@media (max-width: 480px) {
|
|
257
|
+
padding: 0.75rem 0.5rem;
|
|
258
|
+
}
|
|
267
259
|
`;
|
|
268
260
|
|
|
269
261
|
const Header = styled.div`
|
|
@@ -292,14 +284,26 @@ const CloseButton = styled.div`
|
|
|
292
284
|
justify-content: center;
|
|
293
285
|
`;
|
|
294
286
|
|
|
287
|
+
const MainContent = styled.div`
|
|
288
|
+
display: grid;
|
|
289
|
+
grid-template-columns: 1fr 260px;
|
|
290
|
+
gap: 1rem;
|
|
291
|
+
flex: 1;
|
|
292
|
+
min-height: 0;
|
|
293
|
+
margin: 1rem 0;
|
|
294
|
+
|
|
295
|
+
@media (max-width: 700px) {
|
|
296
|
+
grid-template-columns: 1fr;
|
|
297
|
+
gap: 0.75rem;
|
|
298
|
+
}
|
|
299
|
+
`;
|
|
300
|
+
|
|
295
301
|
const CartItems = styled.div`
|
|
296
302
|
display: flex;
|
|
297
303
|
flex-direction: column;
|
|
298
304
|
gap: 0.5rem;
|
|
299
|
-
flex: 1;
|
|
300
305
|
min-height: 0;
|
|
301
306
|
overflow-y: auto;
|
|
302
|
-
margin: 1rem 0;
|
|
303
307
|
padding-right: 0.5rem;
|
|
304
308
|
|
|
305
309
|
&::-webkit-scrollbar {
|
|
@@ -312,13 +316,28 @@ const CartItems = styled.div`
|
|
|
312
316
|
&::-webkit-scrollbar-thumb {
|
|
313
317
|
background: #f59e0b;
|
|
314
318
|
border-radius: 4px;
|
|
315
|
-
|
|
319
|
+
|
|
316
320
|
&:hover {
|
|
317
321
|
background: #fbbf24;
|
|
318
322
|
}
|
|
319
323
|
}
|
|
320
324
|
`;
|
|
321
325
|
|
|
326
|
+
const OrderSummaryPanel = styled.div`
|
|
327
|
+
display: flex;
|
|
328
|
+
flex-direction: column;
|
|
329
|
+
gap: 0.5rem;
|
|
330
|
+
padding: 1rem;
|
|
331
|
+
background: rgba(0, 0, 0, 0.25);
|
|
332
|
+
border: 1px solid rgba(255, 255, 255, 0.08);
|
|
333
|
+
border-radius: 6px;
|
|
334
|
+
align-self: start;
|
|
335
|
+
|
|
336
|
+
@media (max-width: 480px) {
|
|
337
|
+
padding: 0.75rem;
|
|
338
|
+
}
|
|
339
|
+
`;
|
|
340
|
+
|
|
322
341
|
const EmptyCart = styled.div`
|
|
323
342
|
display: flex;
|
|
324
343
|
align-items: center;
|
|
@@ -337,6 +356,11 @@ const CartItemRow = styled.div`
|
|
|
337
356
|
padding: 0.5rem 0.75rem;
|
|
338
357
|
background: rgba(0, 0, 0, 0.2);
|
|
339
358
|
border-radius: 4px;
|
|
359
|
+
|
|
360
|
+
@media (max-width: 480px) {
|
|
361
|
+
gap: 0.5rem;
|
|
362
|
+
padding: 0.4rem 0.5rem;
|
|
363
|
+
}
|
|
340
364
|
`;
|
|
341
365
|
|
|
342
366
|
const ItemIconContainer = styled.div`
|
|
@@ -365,6 +389,7 @@ const ItemName = styled.div`
|
|
|
365
389
|
const ItemInfo = styled.div`
|
|
366
390
|
display: flex;
|
|
367
391
|
align-items: center;
|
|
392
|
+
flex-wrap: wrap;
|
|
368
393
|
gap: 0.4rem;
|
|
369
394
|
font-family: 'Press Start 2P', cursive;
|
|
370
395
|
font-size: 0.55rem;
|
|
@@ -385,12 +410,6 @@ const Footer = styled.div`
|
|
|
385
410
|
}
|
|
386
411
|
`;
|
|
387
412
|
|
|
388
|
-
const TotalInfo = styled.div`
|
|
389
|
-
display: flex;
|
|
390
|
-
flex-direction: column;
|
|
391
|
-
gap: 0.5rem;
|
|
392
|
-
`;
|
|
393
|
-
|
|
394
413
|
const OrderSummaryLabel = styled.div`
|
|
395
414
|
font-family: 'Press Start 2P', cursive;
|
|
396
415
|
font-size: 0.55rem;
|
|
@@ -417,6 +436,11 @@ const TotalRow = styled.div<{ $isTotal?: boolean }>`
|
|
|
417
436
|
span:last-child {
|
|
418
437
|
color: #fef08a;
|
|
419
438
|
}
|
|
439
|
+
|
|
440
|
+
@media (max-width: 480px) {
|
|
441
|
+
font-size: ${p => p.$isTotal ? '0.7rem' : '0.55rem'};
|
|
442
|
+
gap: 0.5rem;
|
|
443
|
+
}
|
|
420
444
|
`;
|
|
421
445
|
|
|
422
446
|
const PaymentMethodRow = styled.div`
|
|
@@ -434,37 +458,6 @@ const PaymentMethodRow = styled.div`
|
|
|
434
458
|
}
|
|
435
459
|
`;
|
|
436
460
|
|
|
437
|
-
const DCNudge = styled.div`
|
|
438
|
-
display: flex;
|
|
439
|
-
align-items: center;
|
|
440
|
-
gap: 0.5rem;
|
|
441
|
-
padding: 0.5rem 0.75rem;
|
|
442
|
-
background: rgba(245, 158, 11, 0.1);
|
|
443
|
-
border: 1px solid rgba(245, 158, 11, 0.3);
|
|
444
|
-
border-radius: 4px;
|
|
445
|
-
cursor: pointer;
|
|
446
|
-
font-family: 'Press Start 2P', cursive;
|
|
447
|
-
font-size: 0.45rem;
|
|
448
|
-
color: #fbbf24;
|
|
449
|
-
transition: background 0.15s;
|
|
450
|
-
line-height: 1.4;
|
|
451
|
-
flex-wrap: wrap;
|
|
452
|
-
|
|
453
|
-
&:hover {
|
|
454
|
-
background: rgba(245, 158, 11, 0.18);
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
svg { flex-shrink: 0; font-size: 0.7rem; }
|
|
458
|
-
span { flex: 1; min-width: 140px; }
|
|
459
|
-
`;
|
|
460
|
-
|
|
461
|
-
const DCNudgeLink = styled.span`
|
|
462
|
-
color: #f59e0b;
|
|
463
|
-
white-space: nowrap;
|
|
464
|
-
text-decoration: underline;
|
|
465
|
-
flex: 0 0 auto !important;
|
|
466
|
-
`;
|
|
467
|
-
|
|
468
461
|
const ErrorMessage = styled.div`
|
|
469
462
|
color: #ef4444;
|
|
470
463
|
font-size: 0.875rem;
|
|
@@ -61,7 +61,6 @@ export interface IStoreProps {
|
|
|
61
61
|
onCheckoutStart?: (items: Array<{ key: string; name: string; quantity: number }>, total: number) => void;
|
|
62
62
|
onPurchaseSuccess?: (items: Array<{ key: string; name: string; quantity: number }>, total: number) => void;
|
|
63
63
|
onPurchaseError?: (error: string) => void;
|
|
64
|
-
onBuyDC?: () => void;
|
|
65
64
|
currencySymbol?: string;
|
|
66
65
|
onRedeem?: (code: string) => Promise<{ success: boolean; dcAmount?: number; error?: string }>;
|
|
67
66
|
onRedeemInputFocus?: () => void;
|
|
@@ -114,7 +113,6 @@ export const Store: React.FC<IStoreProps> = ({
|
|
|
114
113
|
onCheckoutStart,
|
|
115
114
|
onPurchaseSuccess,
|
|
116
115
|
onPurchaseError,
|
|
117
|
-
onBuyDC,
|
|
118
116
|
currencySymbol = '$',
|
|
119
117
|
onRedeem,
|
|
120
118
|
onRedeemInputFocus,
|
|
@@ -321,7 +319,6 @@ export const Store: React.FC<IStoreProps> = ({
|
|
|
321
319
|
onCheckoutStart={onCheckoutStart}
|
|
322
320
|
onPurchaseSuccess={onPurchaseSuccess}
|
|
323
321
|
onPurchaseError={onPurchaseError}
|
|
324
|
-
onBuyDC={onBuyDC}
|
|
325
322
|
currencySymbol={currencySymbol}
|
|
326
323
|
/>
|
|
327
324
|
) : selectedPack ? (
|