@rpg-engine/long-bow 0.8.70 → 0.8.71
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/Store.d.ts +1 -0
- package/dist/components/Store/StoreItemRow.d.ts +1 -0
- package/dist/components/Store/sections/StoreItemsSection.d.ts +1 -0
- package/dist/long-bow.cjs.development.js +59 -14
- 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 +59 -14
- package/dist/long-bow.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/components/Store/CartView.tsx +11 -0
- package/src/components/Store/Store.tsx +3 -0
- package/src/components/Store/StoreItemRow.tsx +33 -3
- package/src/components/Store/sections/StoreItemsSection.tsx +18 -3
- package/src/stories/Features/store/Store.stories.tsx +1 -0
package/package.json
CHANGED
|
@@ -111,6 +111,9 @@ export const CartView: React.FC<ICartViewProps> = ({
|
|
|
111
111
|
</ItemIconContainer>
|
|
112
112
|
<ItemDetails>
|
|
113
113
|
<ItemName>{cartItem.item.name}</ItemName>
|
|
114
|
+
{cartItem.metadata?.inputValue && (
|
|
115
|
+
<CartMeta>{cartItem.metadata.inputValue}</CartMeta>
|
|
116
|
+
)}
|
|
114
117
|
<ItemInfo>
|
|
115
118
|
<span>${formatPrice(cartItem.item.price)}</span>
|
|
116
119
|
<span>×</span>
|
|
@@ -339,3 +342,11 @@ const MetadataValue = styled.div`
|
|
|
339
342
|
text-overflow: ellipsis;
|
|
340
343
|
white-space: nowrap;
|
|
341
344
|
`;
|
|
345
|
+
|
|
346
|
+
const CartMeta = styled.div`
|
|
347
|
+
font-family: 'Press Start 2P', cursive;
|
|
348
|
+
font-size: 0.75rem;
|
|
349
|
+
color: #ffffff;
|
|
350
|
+
opacity: 0.8;
|
|
351
|
+
margin-top: 0.25rem;
|
|
352
|
+
`;
|
|
@@ -32,6 +32,7 @@ export interface IStoreProps {
|
|
|
32
32
|
hidePremiumTab?: boolean;
|
|
33
33
|
tabOrder?: TabId[];
|
|
34
34
|
defaultActiveTab?: TabId;
|
|
35
|
+
textInputItemKeys?: string[];
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
export const Store: React.FC<IStoreProps> = ({
|
|
@@ -48,6 +49,7 @@ export const Store: React.FC<IStoreProps> = ({
|
|
|
48
49
|
hidePremiumTab = false,
|
|
49
50
|
tabOrder,
|
|
50
51
|
defaultActiveTab,
|
|
52
|
+
textInputItemKeys = [],
|
|
51
53
|
}) => {
|
|
52
54
|
const [selectedPack, setSelectedPack] = useState<IItemPack | null>(null);
|
|
53
55
|
const [activeTab, setActiveTab] = useState<TabId>(() => {
|
|
@@ -188,6 +190,7 @@ export const Store: React.FC<IStoreProps> = ({
|
|
|
188
190
|
atlasJSON={atlasJSON}
|
|
189
191
|
atlasIMG={atlasIMG}
|
|
190
192
|
userAccountType={userAccountType}
|
|
193
|
+
textInputItemKeys={textInputItemKeys}
|
|
191
194
|
/>
|
|
192
195
|
),
|
|
193
196
|
},
|
|
@@ -12,6 +12,7 @@ interface IStoreItemRowProps {
|
|
|
12
12
|
atlasIMG: string;
|
|
13
13
|
onAddToCart: (item: IStoreItem, quantity: number, metadata?: Record<string, any>) => void;
|
|
14
14
|
userAccountType: UserAccountTypes;
|
|
15
|
+
showTextInput?: boolean;
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
export const StoreItemRow: React.FC<IStoreItemRowProps> = ({
|
|
@@ -20,8 +21,10 @@ export const StoreItemRow: React.FC<IStoreItemRowProps> = ({
|
|
|
20
21
|
atlasIMG,
|
|
21
22
|
onAddToCart,
|
|
22
23
|
userAccountType,
|
|
24
|
+
showTextInput = false,
|
|
23
25
|
}) => {
|
|
24
26
|
const [quantity, setQuantity] = useState(1);
|
|
27
|
+
const [textInputValue, setTextInputValue] = useState('');
|
|
25
28
|
|
|
26
29
|
const handleQuantityChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
27
30
|
const value = parseInt(e.target.value) || 1;
|
|
@@ -45,10 +48,15 @@ export const StoreItemRow: React.FC<IStoreItemRowProps> = ({
|
|
|
45
48
|
!item.requiredAccountType?.length ||
|
|
46
49
|
item.requiredAccountType.includes(userAccountType);
|
|
47
50
|
|
|
48
|
-
const
|
|
51
|
+
const handleAddToCartInternal = () => {
|
|
49
52
|
if (!hasRequiredAccount) return;
|
|
53
|
+
if (showTextInput) {
|
|
54
|
+
onAddToCart(item, 1, { inputValue: textInputValue });
|
|
55
|
+
setTextInputValue('');
|
|
56
|
+
} else {
|
|
50
57
|
onAddToCart(item, quantity);
|
|
51
|
-
|
|
58
|
+
setQuantity(1);
|
|
59
|
+
}
|
|
52
60
|
};
|
|
53
61
|
|
|
54
62
|
return (
|
|
@@ -71,6 +79,16 @@ export const StoreItemRow: React.FC<IStoreItemRowProps> = ({
|
|
|
71
79
|
</ItemDetails>
|
|
72
80
|
|
|
73
81
|
<Controls>
|
|
82
|
+
{/* Show text input if configured, else show arrows only for stackable items */}
|
|
83
|
+
{showTextInput ? (
|
|
84
|
+
<TextInput
|
|
85
|
+
type="text"
|
|
86
|
+
value={textInputValue}
|
|
87
|
+
placeholder="Enter value"
|
|
88
|
+
onChange={e => setTextInputValue(e.target.value)}
|
|
89
|
+
className="rpgui-input"
|
|
90
|
+
/>
|
|
91
|
+
) : item.isStackable ? (
|
|
74
92
|
<ArrowsContainer>
|
|
75
93
|
<SelectArrow
|
|
76
94
|
direction="left"
|
|
@@ -94,11 +112,12 @@ export const StoreItemRow: React.FC<IStoreItemRowProps> = ({
|
|
|
94
112
|
size={24}
|
|
95
113
|
/>
|
|
96
114
|
</ArrowsContainer>
|
|
115
|
+
) : null}
|
|
97
116
|
|
|
98
117
|
<CTAButton
|
|
99
118
|
icon={<FaCartPlus />}
|
|
100
119
|
label="Add"
|
|
101
|
-
onClick={
|
|
120
|
+
onClick={handleAddToCartInternal}
|
|
102
121
|
disabled={!hasRequiredAccount}
|
|
103
122
|
/>
|
|
104
123
|
</Controls>
|
|
@@ -179,3 +198,14 @@ const QuantityInput = styled.input`
|
|
|
179
198
|
margin: 0;
|
|
180
199
|
}
|
|
181
200
|
`;
|
|
201
|
+
|
|
202
|
+
const TextInput = styled.input`
|
|
203
|
+
width: 120px;
|
|
204
|
+
text-align: center;
|
|
205
|
+
margin: 0 auto;
|
|
206
|
+
font-size: 0.875rem;
|
|
207
|
+
background: rgba(0, 0, 0, 0.2);
|
|
208
|
+
color: #ffffff;
|
|
209
|
+
border: none;
|
|
210
|
+
padding: 0.25rem;
|
|
211
|
+
`;
|
|
@@ -11,6 +11,7 @@ interface IStoreItemsSectionProps {
|
|
|
11
11
|
atlasJSON: Record<string, any>;
|
|
12
12
|
atlasIMG: string;
|
|
13
13
|
userAccountType?: UserAccountTypes;
|
|
14
|
+
textInputItemKeys?: string[];
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
export const StoreItemsSection: React.FC<IStoreItemsSectionProps> = ({
|
|
@@ -19,6 +20,7 @@ export const StoreItemsSection: React.FC<IStoreItemsSectionProps> = ({
|
|
|
19
20
|
atlasJSON,
|
|
20
21
|
atlasIMG,
|
|
21
22
|
userAccountType,
|
|
23
|
+
textInputItemKeys = [],
|
|
22
24
|
}) => {
|
|
23
25
|
const [searchQuery, setSearchQuery] = useState('');
|
|
24
26
|
|
|
@@ -27,7 +29,7 @@ export const StoreItemsSection: React.FC<IStoreItemsSectionProps> = ({
|
|
|
27
29
|
);
|
|
28
30
|
|
|
29
31
|
const renderStoreItem = (item: IStoreItem) => {
|
|
30
|
-
//
|
|
32
|
+
// Prefer a specialized character skin row when needed
|
|
31
33
|
if (item.metadataType === MetadataType.CharacterSkin) {
|
|
32
34
|
return (
|
|
33
35
|
<StoreCharacterSkinRow
|
|
@@ -40,8 +42,21 @@ export const StoreItemsSection: React.FC<IStoreItemsSectionProps> = ({
|
|
|
40
42
|
/>
|
|
41
43
|
);
|
|
42
44
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
+
// Render text input row when configured for this item key
|
|
46
|
+
if (textInputItemKeys.includes(item.key) || textInputItemKeys.includes(item._id)) {
|
|
47
|
+
return (
|
|
48
|
+
<StoreItemRow
|
|
49
|
+
key={item._id}
|
|
50
|
+
item={item}
|
|
51
|
+
atlasJSON={atlasJSON}
|
|
52
|
+
atlasIMG={atlasIMG}
|
|
53
|
+
onAddToCart={onAddToCart}
|
|
54
|
+
userAccountType={userAccountType || UserAccountTypes.Free}
|
|
55
|
+
showTextInput
|
|
56
|
+
/>
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
// Fallback to standard arrow-based row
|
|
45
60
|
return (
|
|
46
61
|
<StoreItemRow
|
|
47
62
|
key={item._id}
|