@rpg-engine/long-bow 0.5.28 → 0.5.30
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/Item/Inventory/ItemSlot.d.ts +0 -1
- package/dist/components/Item/Inventory/ItemSlotRarity.d.ts +2 -0
- package/dist/hooks/useTapAndHold.d.ts +10 -0
- package/dist/long-bow.cjs.development.js +108 -105
- 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 +110 -106
- package/dist/long-bow.esm.js.map +1 -1
- package/dist/stories/ItemContainer.stories.d.ts +0 -1
- package/package.json +1 -1
- package/src/components/Item/Cards/ItemInfo.tsx +2 -1
- package/src/components/Item/Inventory/ItemSlot.tsx +110 -128
- package/src/components/Item/Inventory/ItemSlotRarity.ts +17 -0
- package/src/components/Item/Inventory/ItemSlotRenderer.tsx +8 -8
- package/src/components/Marketplace/MarketplaceRows.tsx +1 -1
- package/src/hooks/useTapAndHold.ts +30 -0
- package/src/stories/ItemContainer.stories.tsx +0 -6
|
@@ -8,5 +8,4 @@ interface ITemplateProps {
|
|
|
8
8
|
scale?: number;
|
|
9
9
|
}
|
|
10
10
|
export declare const Inventory: import("@storybook/csf").AnnotatedStoryFn<import("@storybook/react").ReactFramework, IItemContainerProps & ITemplateProps>;
|
|
11
|
-
export declare const InventoryScaledDown: import("@storybook/csf").AnnotatedStoryFn<import("@storybook/react").ReactFramework, IItemContainerProps & ITemplateProps>;
|
|
12
11
|
export declare const Depot: import("@storybook/csf").AnnotatedStoryFn<import("@storybook/react").ReactFramework, IItemContainerProps & ITemplateProps>;
|
package/package.json
CHANGED
|
@@ -5,7 +5,8 @@ import { uiColors } from '../../../constants/uiColors';
|
|
|
5
5
|
import { uiFonts } from '../../../constants/uiFonts';
|
|
6
6
|
import { SpriteFromAtlas } from '../../shared/SpriteFromAtlas';
|
|
7
7
|
import { ErrorBoundary } from '../Inventory/ErrorBoundary';
|
|
8
|
-
import { EquipmentSlotSpriteByType
|
|
8
|
+
import { EquipmentSlotSpriteByType } from '../Inventory/ItemSlot';
|
|
9
|
+
import { rarityColor } from '../Inventory/ItemSlotRarity';
|
|
9
10
|
|
|
10
11
|
interface IItemInfoProps {
|
|
11
12
|
item: IItem;
|
|
@@ -3,16 +3,16 @@ import {
|
|
|
3
3
|
IItem,
|
|
4
4
|
IItemContainer,
|
|
5
5
|
ItemContainerType,
|
|
6
|
-
ItemRarities,
|
|
7
6
|
ItemSlotType,
|
|
8
7
|
ItemType,
|
|
9
8
|
} from '@rpg-engine/shared';
|
|
10
9
|
|
|
11
10
|
import { observer } from 'mobx-react-lite';
|
|
12
11
|
import React, { useEffect, useRef, useState } from 'react';
|
|
13
|
-
import Draggable from 'react-draggable';
|
|
12
|
+
import Draggable, { DraggableEventHandler } from 'react-draggable';
|
|
14
13
|
import styled from 'styled-components';
|
|
15
14
|
import { IPosition } from '../../../types/eventTypes';
|
|
15
|
+
import { rarityColor } from './ItemSlotRarity';
|
|
16
16
|
import { ItemSlotRenderer } from './ItemSlotRenderer';
|
|
17
17
|
import { ItemSlotToolTips } from './ItemSlotTooltips';
|
|
18
18
|
import { useDragging } from './context/DraggingContext';
|
|
@@ -156,6 +156,107 @@ export const ItemSlot: React.FC<IProps> = observer(
|
|
|
156
156
|
}
|
|
157
157
|
};
|
|
158
158
|
|
|
159
|
+
const onDraggableStop: DraggableEventHandler = (e, data) => {
|
|
160
|
+
setDraggingItem(null);
|
|
161
|
+
|
|
162
|
+
const target = e.target as HTMLElement;
|
|
163
|
+
if (target?.id.includes('shortcutSetter') && setItemShortcut && item) {
|
|
164
|
+
const index = parseInt(target.id.split('_')[1]);
|
|
165
|
+
if (!isNaN(index)) {
|
|
166
|
+
setItemShortcut(item, index);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (wasDragged && item && !isSelectingShortcut) {
|
|
171
|
+
//@ts-ignore
|
|
172
|
+
const classes: string[] = Array.from(e.target?.classList);
|
|
173
|
+
|
|
174
|
+
const isOutsideDrop =
|
|
175
|
+
classes.some(elm => {
|
|
176
|
+
return elm.includes('rpgui-content');
|
|
177
|
+
}) || classes.length === 0;
|
|
178
|
+
|
|
179
|
+
if (isOutsideDrop) {
|
|
180
|
+
setDropPosition({
|
|
181
|
+
x: data.x,
|
|
182
|
+
y: data.y,
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
setWasDragged(false);
|
|
187
|
+
|
|
188
|
+
const target = dragContainer.current;
|
|
189
|
+
if (!target || !wasDragged) return;
|
|
190
|
+
|
|
191
|
+
const style = window.getComputedStyle(target);
|
|
192
|
+
const matrix = new DOMMatrixReadOnly(style.transform);
|
|
193
|
+
const x = matrix.m41;
|
|
194
|
+
const y = matrix.m42;
|
|
195
|
+
|
|
196
|
+
setDragPosition({ x, y });
|
|
197
|
+
|
|
198
|
+
setTimeout(() => {
|
|
199
|
+
if (checkIfItemCanBeMoved?.()) {
|
|
200
|
+
if (checkIfItemShouldDragEnd && !checkIfItemShouldDragEnd()) return;
|
|
201
|
+
|
|
202
|
+
if (item.stackQty && item.stackQty !== 1 && openQuantitySelector)
|
|
203
|
+
openQuantitySelector(item.stackQty, onSuccessfulDrag);
|
|
204
|
+
else onSuccessfulDrag(item.stackQty);
|
|
205
|
+
} else {
|
|
206
|
+
resetItem();
|
|
207
|
+
setIsFocused(false);
|
|
208
|
+
setDragPosition({ x: 0, y: 0 });
|
|
209
|
+
}
|
|
210
|
+
}, 50);
|
|
211
|
+
} else if (item) {
|
|
212
|
+
let isTouch = false;
|
|
213
|
+
if (
|
|
214
|
+
!isContextMenuDisabled &&
|
|
215
|
+
e.type === 'touchend' &&
|
|
216
|
+
!isSelectingShortcut
|
|
217
|
+
) {
|
|
218
|
+
isTouch = true;
|
|
219
|
+
setIsTooltipMobileVisible(true);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
if (!isContextMenuDisabled && !isSelectingShortcut && !isTouch) {
|
|
223
|
+
setIsContextMenuVisible(!isContextMenuVisible);
|
|
224
|
+
const event = e as MouseEvent;
|
|
225
|
+
|
|
226
|
+
if (event.clientX && event.clientY) {
|
|
227
|
+
setContextMenuPosition({
|
|
228
|
+
x: event.clientX - 10,
|
|
229
|
+
y: event.clientY - 5,
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
onPointerDown(item.type, containerType ?? null, item);
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
const onDraggableStart: DraggableEventHandler = () => {
|
|
239
|
+
if (!item || isSelectingShortcut) {
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if (onDragStart && containerType) {
|
|
244
|
+
setDraggingItem(item);
|
|
245
|
+
|
|
246
|
+
onDragStart(item, slotIndex, containerType);
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
const onDraggableProgress: DraggableEventHandler = (_e, data) => {
|
|
251
|
+
if (
|
|
252
|
+
Math.abs(data.x - dragPosition.x) > 5 ||
|
|
253
|
+
Math.abs(data.y - dragPosition.y) > 5
|
|
254
|
+
) {
|
|
255
|
+
setWasDragged(true);
|
|
256
|
+
setIsFocused(true);
|
|
257
|
+
}
|
|
258
|
+
};
|
|
259
|
+
|
|
159
260
|
return (
|
|
160
261
|
<Container
|
|
161
262
|
item={item}
|
|
@@ -194,113 +295,9 @@ export const ItemSlot: React.FC<IProps> = observer(
|
|
|
194
295
|
defaultClassName={item ? 'draggable' : 'empty-slot'}
|
|
195
296
|
scale={dragScale}
|
|
196
297
|
disabled={onDragStart === undefined || onDragEnd === undefined}
|
|
197
|
-
onStop={
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
const target = e.target as HTMLElement;
|
|
201
|
-
if (
|
|
202
|
-
target?.id.includes('shortcutSetter') &&
|
|
203
|
-
setItemShortcut &&
|
|
204
|
-
item
|
|
205
|
-
) {
|
|
206
|
-
const index = parseInt(target.id.split('_')[1]);
|
|
207
|
-
if (!isNaN(index)) {
|
|
208
|
-
setItemShortcut(item, index);
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
if (wasDragged && item && !isSelectingShortcut) {
|
|
213
|
-
//@ts-ignore
|
|
214
|
-
const classes: string[] = Array.from(e.target?.classList);
|
|
215
|
-
|
|
216
|
-
const isOutsideDrop =
|
|
217
|
-
classes.some(elm => {
|
|
218
|
-
return elm.includes('rpgui-content');
|
|
219
|
-
}) || classes.length === 0;
|
|
220
|
-
|
|
221
|
-
if (isOutsideDrop) {
|
|
222
|
-
setDropPosition({
|
|
223
|
-
x: data.x,
|
|
224
|
-
y: data.y,
|
|
225
|
-
});
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
setWasDragged(false);
|
|
229
|
-
|
|
230
|
-
const target = dragContainer.current;
|
|
231
|
-
if (!target || !wasDragged) return;
|
|
232
|
-
|
|
233
|
-
const style = window.getComputedStyle(target);
|
|
234
|
-
const matrix = new DOMMatrixReadOnly(style.transform);
|
|
235
|
-
const x = matrix.m41;
|
|
236
|
-
const y = matrix.m42;
|
|
237
|
-
|
|
238
|
-
setDragPosition({ x, y });
|
|
239
|
-
|
|
240
|
-
setTimeout(() => {
|
|
241
|
-
if (checkIfItemCanBeMoved?.()) {
|
|
242
|
-
if (checkIfItemShouldDragEnd && !checkIfItemShouldDragEnd())
|
|
243
|
-
return;
|
|
244
|
-
|
|
245
|
-
if (
|
|
246
|
-
item.stackQty &&
|
|
247
|
-
item.stackQty !== 1 &&
|
|
248
|
-
openQuantitySelector
|
|
249
|
-
)
|
|
250
|
-
openQuantitySelector(item.stackQty, onSuccessfulDrag);
|
|
251
|
-
else onSuccessfulDrag(item.stackQty);
|
|
252
|
-
} else {
|
|
253
|
-
resetItem();
|
|
254
|
-
setIsFocused(false);
|
|
255
|
-
setDragPosition({ x: 0, y: 0 });
|
|
256
|
-
}
|
|
257
|
-
}, 50);
|
|
258
|
-
} else if (item) {
|
|
259
|
-
let isTouch = false;
|
|
260
|
-
if (
|
|
261
|
-
!isContextMenuDisabled &&
|
|
262
|
-
e.type === 'touchend' &&
|
|
263
|
-
!isSelectingShortcut
|
|
264
|
-
) {
|
|
265
|
-
isTouch = true;
|
|
266
|
-
setIsTooltipMobileVisible(true);
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
if (!isContextMenuDisabled && !isSelectingShortcut && !isTouch) {
|
|
270
|
-
setIsContextMenuVisible(!isContextMenuVisible);
|
|
271
|
-
const event = e as MouseEvent;
|
|
272
|
-
|
|
273
|
-
if (event.clientX && event.clientY) {
|
|
274
|
-
setContextMenuPosition({
|
|
275
|
-
x: event.clientX - 10,
|
|
276
|
-
y: event.clientY - 5,
|
|
277
|
-
});
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
onPointerDown(item.type, containerType ?? null, item);
|
|
282
|
-
}
|
|
283
|
-
}}
|
|
284
|
-
onStart={() => {
|
|
285
|
-
if (!item || isSelectingShortcut) {
|
|
286
|
-
return;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
if (onDragStart && containerType) {
|
|
290
|
-
setDraggingItem(item);
|
|
291
|
-
|
|
292
|
-
onDragStart(item, slotIndex, containerType);
|
|
293
|
-
}
|
|
294
|
-
}}
|
|
295
|
-
onDrag={(_e, data) => {
|
|
296
|
-
if (
|
|
297
|
-
Math.abs(data.x - dragPosition.x) > 5 ||
|
|
298
|
-
Math.abs(data.y - dragPosition.y) > 5
|
|
299
|
-
) {
|
|
300
|
-
setWasDragged(true);
|
|
301
|
-
setIsFocused(true);
|
|
302
|
-
}
|
|
303
|
-
}}
|
|
298
|
+
onStop={onDraggableStop}
|
|
299
|
+
onStart={onDraggableStart}
|
|
300
|
+
onDrag={onDraggableProgress}
|
|
304
301
|
position={dragPosition}
|
|
305
302
|
cancel=".empty-slot"
|
|
306
303
|
>
|
|
@@ -362,21 +359,6 @@ export const ItemSlot: React.FC<IProps> = observer(
|
|
|
362
359
|
}
|
|
363
360
|
);
|
|
364
361
|
|
|
365
|
-
export const rarityColor = (item: IItem | null) => {
|
|
366
|
-
switch (item?.rarity) {
|
|
367
|
-
case ItemRarities.Uncommon:
|
|
368
|
-
return 'rgba(13, 193, 13, 0.6)';
|
|
369
|
-
case ItemRarities.Rare:
|
|
370
|
-
return 'rgba(8, 104, 187, 0.6)';
|
|
371
|
-
case ItemRarities.Epic:
|
|
372
|
-
return 'rgba(191, 0, 255, 0.6)';
|
|
373
|
-
case ItemRarities.Legendary:
|
|
374
|
-
return 'rgba(255, 191, 0,0.6)';
|
|
375
|
-
default:
|
|
376
|
-
return null;
|
|
377
|
-
}
|
|
378
|
-
};
|
|
379
|
-
|
|
380
362
|
interface ContainerTypes {
|
|
381
363
|
item: IItem | null;
|
|
382
364
|
containerType?: ItemContainerType | null;
|
|
@@ -387,10 +369,11 @@ const Container = styled.div<ContainerTypes>`
|
|
|
387
369
|
margin: 0.1rem;
|
|
388
370
|
|
|
389
371
|
.react-draggable-dragging {
|
|
390
|
-
|
|
372
|
+
opacity: 0;
|
|
391
373
|
}
|
|
392
|
-
|
|
393
|
-
|
|
374
|
+
|
|
375
|
+
position: relative;
|
|
376
|
+
|
|
394
377
|
.sprite-from-atlas-img--item {
|
|
395
378
|
position: relative;
|
|
396
379
|
top: 1.5rem;
|
|
@@ -401,7 +384,6 @@ const Container = styled.div<ContainerTypes>`
|
|
|
401
384
|
}) => `0 0 4px 3px ${rarityColor(item)}`};
|
|
402
385
|
//background-color: ${({ item }) => rarityColor(item)};
|
|
403
386
|
}
|
|
404
|
-
position: relative;
|
|
405
387
|
|
|
406
388
|
&::before {
|
|
407
389
|
content: '';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { IItem, ItemRarities } from '@rpg-engine/shared';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
export const rarityColor = (item: IItem | null) => {
|
|
5
|
+
switch (item?.rarity) {
|
|
6
|
+
case ItemRarities.Uncommon:
|
|
7
|
+
return 'rgba(13, 193, 13, 0.6)';
|
|
8
|
+
case ItemRarities.Rare:
|
|
9
|
+
return 'rgba(8, 104, 187, 0.6)';
|
|
10
|
+
case ItemRarities.Epic:
|
|
11
|
+
return 'rgba(191, 0, 255, 0.6)';
|
|
12
|
+
case ItemRarities.Legendary:
|
|
13
|
+
return 'rgba(255, 191, 0,0.6)';
|
|
14
|
+
default:
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
};
|
|
@@ -26,29 +26,29 @@ export const ItemSlotRenderer: React.FC<IProps> = ({
|
|
|
26
26
|
slotSpriteMask,
|
|
27
27
|
item,
|
|
28
28
|
}) => {
|
|
29
|
-
const renderItem = (
|
|
30
|
-
if (!
|
|
29
|
+
const renderItem = (item: IItem | null) => {
|
|
30
|
+
if (!item?.texturePath) {
|
|
31
31
|
return null;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
return (
|
|
35
|
-
<ErrorBoundary key={
|
|
35
|
+
<ErrorBoundary key={item._id}>
|
|
36
36
|
<SpriteFromAtlas
|
|
37
37
|
atlasIMG={atlasIMG}
|
|
38
38
|
atlasJSON={atlasJSON}
|
|
39
39
|
spriteKey={getItemTextureKeyPath(
|
|
40
40
|
{
|
|
41
|
-
key:
|
|
42
|
-
texturePath:
|
|
43
|
-
stackQty:
|
|
44
|
-
isStackable:
|
|
41
|
+
key: item.texturePath,
|
|
42
|
+
texturePath: item.texturePath,
|
|
43
|
+
stackQty: item.stackQty || 1,
|
|
44
|
+
isStackable: item.isStackable,
|
|
45
45
|
},
|
|
46
46
|
atlasJSON
|
|
47
47
|
)}
|
|
48
48
|
imgScale={3}
|
|
49
49
|
imgClassname="sprite-from-atlas-img--item"
|
|
50
50
|
/>
|
|
51
|
-
{onRenderStackInfo(
|
|
51
|
+
{onRenderStackInfo(item._id, item.stackQty ?? 0)}
|
|
52
52
|
</ErrorBoundary>
|
|
53
53
|
);
|
|
54
54
|
};
|
|
@@ -9,7 +9,7 @@ import { uiColors } from '../../constants/uiColors';
|
|
|
9
9
|
import { uiFonts } from '../../constants/uiFonts';
|
|
10
10
|
import { Button, ButtonTypes } from '../Button';
|
|
11
11
|
import { ItemInfoWrapper } from '../Item/Cards/ItemInfoWrapper';
|
|
12
|
-
import { rarityColor } from '../Item/Inventory/
|
|
12
|
+
import { rarityColor } from '../Item/Inventory/ItemSlotRarity';
|
|
13
13
|
import { Ellipsis } from '../shared/Ellipsis';
|
|
14
14
|
import { SpriteFromAtlas } from '../shared/SpriteFromAtlas';
|
|
15
15
|
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { useCallback, useState } from 'react';
|
|
2
|
+
|
|
3
|
+
interface ITapAndHoldProps {
|
|
4
|
+
onHoldFn: (...args: any[]) => void;
|
|
5
|
+
holdTime?: number;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const useTapAndHold = ({ onHoldFn: onHold, holdTime = 500 }: ITapAndHoldProps) => {
|
|
9
|
+
const [timer, setTimer] = useState<NodeJS.Timeout | null>(null);
|
|
10
|
+
|
|
11
|
+
const start = useCallback(() => {
|
|
12
|
+
const timeout = setTimeout(onHold, holdTime);
|
|
13
|
+
setTimer(timeout);
|
|
14
|
+
}, [onHold, holdTime]);
|
|
15
|
+
|
|
16
|
+
const clear = useCallback(() => {
|
|
17
|
+
if (timer) {
|
|
18
|
+
clearTimeout(timer);
|
|
19
|
+
setTimer(null);
|
|
20
|
+
}
|
|
21
|
+
}, [timer]);
|
|
22
|
+
|
|
23
|
+
const bind = {
|
|
24
|
+
onTouchStart: start,
|
|
25
|
+
onTouchEnd: clear,
|
|
26
|
+
onTouchCancel: clear,
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
return bind;
|
|
30
|
+
};
|
|
@@ -161,12 +161,6 @@ Inventory.args = {
|
|
|
161
161
|
type: ItemContainerType.Inventory,
|
|
162
162
|
};
|
|
163
163
|
|
|
164
|
-
export const InventoryScaledDown = Template.bind({});
|
|
165
|
-
InventoryScaledDown.args = {
|
|
166
|
-
type: ItemContainerType.Inventory,
|
|
167
|
-
scale: 0.8,
|
|
168
|
-
};
|
|
169
|
-
|
|
170
164
|
export const Depot = Template.bind({});
|
|
171
165
|
Depot.args = {
|
|
172
166
|
type: ItemContainerType.Depot,
|