@rpg-engine/long-bow 0.5.23 → 0.5.24
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/hooks/useCursorPosition.d.ts +6 -0
- package/dist/hooks/useShortcuts.d.ts +12 -0
- package/dist/long-bow.cjs.development.js +22 -34
- 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 +22 -34
- package/dist/long-bow.esm.js.map +1 -1
- package/dist/mocks/itemContainer.mocks.d.ts +1 -1
- package/dist/stories/ItemContainer.stories.d.ts +6 -1
- package/package.json +1 -1
- package/src/components/Item/Inventory/DraggedItem.tsx +1 -1
- package/src/components/Item/Inventory/ItemSlotRenderer.tsx +2 -0
- package/src/hooks/useCursorPosition.ts +30 -0
- package/src/hooks/useShortcuts.ts +50 -0
- package/src/mocks/itemContainer.mocks.ts +38 -31
- package/src/stories/ItemContainer.stories.tsx +22 -74
- package/dist/hooks/useMousePosition.d.ts +0 -6
- package/src/hooks/useMousePosition.ts +0 -49
|
@@ -1,5 +1,10 @@
|
|
|
1
|
+
import { ItemContainerType } from '@rpg-engine/shared';
|
|
1
2
|
import { Meta } from '@storybook/react';
|
|
2
3
|
import { IItemContainerProps } from '../../src/components/Item/Inventory/ItemContainer';
|
|
3
4
|
declare const meta: Meta;
|
|
4
5
|
export default meta;
|
|
5
|
-
|
|
6
|
+
interface ITemplateProps {
|
|
7
|
+
type: ItemContainerType;
|
|
8
|
+
}
|
|
9
|
+
export declare const Inventory: import("@storybook/csf").AnnotatedStoryFn<import("@storybook/react").ReactFramework, IItemContainerProps & ITemplateProps>;
|
|
10
|
+
export declare const Depot: import("@storybook/csf").AnnotatedStoryFn<import("@storybook/react").ReactFramework, IItemContainerProps & ITemplateProps>;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getItemTextureKeyPath } from '@rpg-engine/shared';
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import styled from 'styled-components';
|
|
4
|
-
import { useCursorPosition } from '../../../hooks/
|
|
4
|
+
import { useCursorPosition } from '../../../hooks/useCursorPosition';
|
|
5
5
|
import { SpriteFromAtlas } from '../../shared/SpriteFromAtlas';
|
|
6
6
|
import { onRenderStackInfo } from './ItemSlotQty/ItemSlotQty';
|
|
7
7
|
import { useDragging } from './context/DraggingContext';
|
|
@@ -83,6 +83,8 @@ export const ItemSlotRenderer: React.FC<IProps> = ({
|
|
|
83
83
|
return renderEquipment(itemToRender);
|
|
84
84
|
case ItemContainerType.Inventory:
|
|
85
85
|
return renderItem(itemToRender);
|
|
86
|
+
case ItemContainerType.Depot:
|
|
87
|
+
return renderItem(itemToRender);
|
|
86
88
|
default:
|
|
87
89
|
return null;
|
|
88
90
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
|
|
3
|
+
type CursorPosition = {
|
|
4
|
+
x: number;
|
|
5
|
+
y: number;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export const useCursorPosition = (): CursorPosition => {
|
|
9
|
+
const [position, setPosition] = useState<CursorPosition>({ x: 0, y: 0 });
|
|
10
|
+
|
|
11
|
+
const setFromEvent = (e: MouseEvent | TouchEvent) => {
|
|
12
|
+
if ('touches' in e) {
|
|
13
|
+
setPosition({ x: e.touches[0].clientX, y: e.touches[0].clientY });
|
|
14
|
+
} else {
|
|
15
|
+
setPosition({ x: e.clientX, y: e.clientY });
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
window.addEventListener('mousemove', setFromEvent);
|
|
21
|
+
window.addEventListener('touchmove', setFromEvent);
|
|
22
|
+
|
|
23
|
+
return () => {
|
|
24
|
+
window.removeEventListener('mousemove', setFromEvent);
|
|
25
|
+
window.removeEventListener('touchmove', setFromEvent);
|
|
26
|
+
};
|
|
27
|
+
}, []);
|
|
28
|
+
|
|
29
|
+
return position;
|
|
30
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { IItem, IShortcut, ShortcutType } from '@rpg-engine/shared';
|
|
2
|
+
import { useCallback, useEffect, useState } from 'react';
|
|
3
|
+
import { SHORTCUTS_STORAGE_KEY, defaultShortcut } from '../components/Spellbook/constants';
|
|
4
|
+
|
|
5
|
+
interface IUseShortcuts {
|
|
6
|
+
itemContainer: { slots: Record<number, IItem | null | undefined>; };
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const useShortcuts = ({ itemContainer }: IUseShortcuts) => {
|
|
10
|
+
const [shortcuts, setShortcuts] = useState<IShortcut[]>([]);
|
|
11
|
+
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
const storedShortcuts = localStorage.getItem(SHORTCUTS_STORAGE_KEY);
|
|
14
|
+
if (storedShortcuts) {
|
|
15
|
+
setShortcuts(JSON.parse(storedShortcuts));
|
|
16
|
+
}
|
|
17
|
+
}, []);
|
|
18
|
+
|
|
19
|
+
const setItemShortcut = useCallback((key: string, index: number): void => {
|
|
20
|
+
const storedShortcuts = localStorage.getItem(SHORTCUTS_STORAGE_KEY);
|
|
21
|
+
let updatedShortcuts = storedShortcuts ? JSON.parse(storedShortcuts) as IShortcut[] : [];
|
|
22
|
+
|
|
23
|
+
let item: IItem | null = null;
|
|
24
|
+
Object.keys(itemContainer.slots).forEach(slot => {
|
|
25
|
+
const slotItem = itemContainer.slots[parseInt(slot)];
|
|
26
|
+
if (slotItem && slotItem.key === key) {
|
|
27
|
+
item = slotItem;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
if (!item) return;
|
|
32
|
+
|
|
33
|
+
updatedShortcuts[index] = { type: ShortcutType.Item, payload: item };
|
|
34
|
+
localStorage.setItem(SHORTCUTS_STORAGE_KEY, JSON.stringify(updatedShortcuts));
|
|
35
|
+
setShortcuts(updatedShortcuts);
|
|
36
|
+
}, [itemContainer]);
|
|
37
|
+
|
|
38
|
+
const removeShortcut = useCallback((index: number): void => {
|
|
39
|
+
const storedShortcuts = localStorage.getItem(SHORTCUTS_STORAGE_KEY);
|
|
40
|
+
let updatedShortcuts = storedShortcuts ? JSON.parse(storedShortcuts) as IShortcut[] : [];
|
|
41
|
+
|
|
42
|
+
if (updatedShortcuts[index]) {
|
|
43
|
+
updatedShortcuts[index] = defaultShortcut;
|
|
44
|
+
localStorage.setItem(SHORTCUTS_STORAGE_KEY, JSON.stringify(updatedShortcuts));
|
|
45
|
+
setShortcuts(updatedShortcuts);
|
|
46
|
+
}
|
|
47
|
+
}, []);
|
|
48
|
+
|
|
49
|
+
return { shortcuts, setItemShortcut, removeShortcut };
|
|
50
|
+
};
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
ItemSlotType,
|
|
6
6
|
ItemSubType,
|
|
7
7
|
ItemType,
|
|
8
|
-
UserAccountTypes
|
|
8
|
+
UserAccountTypes
|
|
9
9
|
} from '@rpg-engine/shared';
|
|
10
10
|
|
|
11
11
|
export const items: IItem[] = [
|
|
@@ -578,33 +578,40 @@ export const items: IItem[] = [
|
|
|
578
578
|
},
|
|
579
579
|
];
|
|
580
580
|
|
|
581
|
-
export const itemContainerMock
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
581
|
+
export const itemContainerMock = (
|
|
582
|
+
props?: Record<string, unknown>
|
|
583
|
+
): IItemContainer => {
|
|
584
|
+
{
|
|
585
|
+
return {
|
|
586
|
+
_id: '629ba0b6fe3f43002f58f23b',
|
|
587
|
+
name: 'Item Container',
|
|
588
|
+
owner: '629ba0b6fe3f43002f58f23b',
|
|
589
|
+
slotQty: 60,
|
|
590
|
+
slots: {
|
|
591
|
+
0: items[0],
|
|
592
|
+
1: items[1],
|
|
593
|
+
2: items[2],
|
|
594
|
+
3: items[3],
|
|
595
|
+
4: items[4],
|
|
596
|
+
5: items[5],
|
|
597
|
+
6: items[6],
|
|
598
|
+
7: items[7],
|
|
599
|
+
8: items[8],
|
|
600
|
+
9: items[9],
|
|
601
|
+
10: items[10],
|
|
602
|
+
11: items[11],
|
|
603
|
+
12: items[12],
|
|
604
|
+
13: items[13],
|
|
605
|
+
14: items[14],
|
|
606
|
+
15: items[15],
|
|
607
|
+
//remaining slots are considered null by default
|
|
608
|
+
},
|
|
609
|
+
allowedItemTypes: [],
|
|
610
|
+
parentItem: '629ba0b6fe3f43002f58f239',
|
|
611
|
+
isEmpty: false,
|
|
612
|
+
createdAt: '2022-06-04T18:13:10.581Z',
|
|
613
|
+
updatedAt: '2022-06-04T18:13:10.581Z',
|
|
614
|
+
...props,
|
|
615
|
+
};
|
|
616
|
+
}
|
|
617
|
+
}
|
|
@@ -1,12 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
IItem,
|
|
3
|
-
IShortcut,
|
|
4
|
-
ItemContainerType,
|
|
5
|
-
ItemType,
|
|
6
|
-
ShortcutType,
|
|
7
|
-
} from '@rpg-engine/shared';
|
|
1
|
+
import { IItem, ItemContainerType, ItemType } from '@rpg-engine/shared';
|
|
8
2
|
import { Meta, Story } from '@storybook/react';
|
|
9
|
-
import React, {
|
|
3
|
+
import React, { useState } from 'react';
|
|
10
4
|
import {
|
|
11
5
|
IItemContainerProps,
|
|
12
6
|
ItemContainer,
|
|
@@ -14,10 +8,7 @@ import {
|
|
|
14
8
|
import { RPGUIRoot } from '../../src/components/RPGUIRoot';
|
|
15
9
|
import { equipmentSetMock } from '../../src/mocks/equipmentSet.mocks';
|
|
16
10
|
import { itemContainerMock } from '../../src/mocks/itemContainer.mocks';
|
|
17
|
-
import {
|
|
18
|
-
defaultShortcut,
|
|
19
|
-
SHORTCUTS_STORAGE_KEY,
|
|
20
|
-
} from '../components/Spellbook/constants';
|
|
11
|
+
import { useShortcuts } from '../hooks/useShortcuts';
|
|
21
12
|
import atlasJSON from '../mocks/atlas/items/items.json';
|
|
22
13
|
import atlasIMG from '../mocks/atlas/items/items.png';
|
|
23
14
|
|
|
@@ -55,69 +46,18 @@ let allowedToDrop = false;
|
|
|
55
46
|
let dragSlot = -1;
|
|
56
47
|
let dropSlot = -1;
|
|
57
48
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
useEffect(() => {
|
|
63
|
-
const shortcuts = localStorage.getItem(SHORTCUTS_STORAGE_KEY);
|
|
64
|
-
if (shortcuts) {
|
|
65
|
-
setShortcuts(JSON.parse(shortcuts));
|
|
66
|
-
}
|
|
67
|
-
}, []);
|
|
68
|
-
|
|
69
|
-
const setItemShortcut = (key: string, index: number) => {
|
|
70
|
-
const shortcuts = JSON.parse(
|
|
71
|
-
localStorage.getItem(SHORTCUTS_STORAGE_KEY) as string
|
|
72
|
-
) as IShortcut[];
|
|
73
|
-
|
|
74
|
-
let item: IItem | null = null;
|
|
75
|
-
|
|
76
|
-
Object.keys(itemContainer.slots).forEach(slot => {
|
|
77
|
-
const slotItem = itemContainer.slots?.[parseInt(slot)];
|
|
78
|
-
if (slotItem && slotItem.key === key) {
|
|
79
|
-
item = slotItem;
|
|
80
|
-
}
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
if (!item) {
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
if (!shortcuts) {
|
|
88
|
-
const newShortcuts: IShortcut[] = Array(6).fill(defaultShortcut);
|
|
89
|
-
|
|
90
|
-
newShortcuts[index] = {
|
|
91
|
-
type: ShortcutType.Item,
|
|
92
|
-
payload: item,
|
|
93
|
-
};
|
|
49
|
+
interface ITemplateProps {
|
|
50
|
+
type: ItemContainerType;
|
|
51
|
+
}
|
|
94
52
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
shortcuts[index] = {
|
|
98
|
-
type: ShortcutType.Item,
|
|
99
|
-
payload: item,
|
|
100
|
-
};
|
|
53
|
+
const Template: Story<IItemContainerProps & ITemplateProps> = ({ type }) => {
|
|
54
|
+
const mock = itemContainerMock({ name: type });
|
|
101
55
|
|
|
102
|
-
|
|
103
|
-
}
|
|
56
|
+
const [itemContainer, setItemContainer] = useState(mock);
|
|
104
57
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
const removeShortcut = (index: number) => {
|
|
109
|
-
const shortcuts = JSON.parse(
|
|
110
|
-
localStorage.getItem(SHORTCUTS_STORAGE_KEY) as string
|
|
111
|
-
);
|
|
112
|
-
|
|
113
|
-
if (!shortcuts) return;
|
|
114
|
-
|
|
115
|
-
shortcuts[index] = defaultShortcut;
|
|
116
|
-
|
|
117
|
-
localStorage.setItem(SHORTCUTS_STORAGE_KEY, JSON.stringify(shortcuts));
|
|
118
|
-
|
|
119
|
-
setShortcuts(shortcuts);
|
|
120
|
-
};
|
|
58
|
+
const { shortcuts, setItemShortcut, removeShortcut } = useShortcuts({
|
|
59
|
+
itemContainer: mock,
|
|
60
|
+
});
|
|
121
61
|
|
|
122
62
|
return (
|
|
123
63
|
<RPGUIRoot>
|
|
@@ -185,7 +125,7 @@ const Template: Story<IItemContainerProps> = () => {
|
|
|
185
125
|
}
|
|
186
126
|
}}
|
|
187
127
|
onOutsideDrop={(item, pos) => console.log('drop', item, pos)}
|
|
188
|
-
type={
|
|
128
|
+
type={type}
|
|
189
129
|
atlasIMG={atlasIMG}
|
|
190
130
|
atlasJSON={atlasJSON}
|
|
191
131
|
shortcuts={shortcuts}
|
|
@@ -198,4 +138,12 @@ const Template: Story<IItemContainerProps> = () => {
|
|
|
198
138
|
);
|
|
199
139
|
};
|
|
200
140
|
|
|
201
|
-
export const
|
|
141
|
+
export const Inventory = Template.bind({});
|
|
142
|
+
Inventory.args = {
|
|
143
|
+
type: ItemContainerType.Inventory,
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
export const Depot = Template.bind({});
|
|
147
|
+
Depot.args = {
|
|
148
|
+
type: ItemContainerType.Depot,
|
|
149
|
+
};
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { useEffect, useState } from 'react';
|
|
2
|
-
|
|
3
|
-
interface ICursorPosition {
|
|
4
|
-
x: number;
|
|
5
|
-
y: number;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export const useCursorPosition = (): ICursorPosition => {
|
|
9
|
-
const [cursorPosition, setCursorPosition] = useState<ICursorPosition>({ x: 0, y: 0 });
|
|
10
|
-
|
|
11
|
-
useEffect(() => {
|
|
12
|
-
let animationFrameId: number;
|
|
13
|
-
|
|
14
|
-
const updateCursorPosition = (x: number, y: number) => {
|
|
15
|
-
// Cancel the previous frame request
|
|
16
|
-
cancelAnimationFrame(animationFrameId);
|
|
17
|
-
|
|
18
|
-
// Request a new frame
|
|
19
|
-
animationFrameId = requestAnimationFrame(() => {
|
|
20
|
-
setCursorPosition({ x, y });
|
|
21
|
-
});
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
const handleMouseMove = (event: MouseEvent) => {
|
|
25
|
-
updateCursorPosition(event.clientX, event.clientY);
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
const handleTouchMove = (event: TouchEvent) => {
|
|
29
|
-
// Prevent default touch behavior (like scrolling)
|
|
30
|
-
event.preventDefault();
|
|
31
|
-
if (event.touches.length > 0) {
|
|
32
|
-
const touch = event.touches[0];
|
|
33
|
-
updateCursorPosition(touch.clientX, touch.clientY);
|
|
34
|
-
}
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
window.addEventListener('mousemove', handleMouseMove);
|
|
38
|
-
window.addEventListener('touchmove', handleTouchMove, { passive: false });
|
|
39
|
-
|
|
40
|
-
// Cleanup function
|
|
41
|
-
return () => {
|
|
42
|
-
window.removeEventListener('mousemove', handleMouseMove);
|
|
43
|
-
window.removeEventListener('touchmove', handleTouchMove);
|
|
44
|
-
cancelAnimationFrame(animationFrameId);
|
|
45
|
-
};
|
|
46
|
-
}, []);
|
|
47
|
-
|
|
48
|
-
return cursorPosition;
|
|
49
|
-
};
|