@rpg-engine/long-bow 0.7.68 → 0.7.70
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 +2 -4
- package/dist/components/Item/Inventory/ItemSlotTooltips.d.ts +2 -10
- package/dist/components/Item/Inventory/context/{DraggingContext.d.ts → ItemSlotDraggingContext.d.ts} +6 -6
- package/dist/components/Item/Inventory/context/ItemSlotTooltipContext.d.ts +28 -0
- package/dist/components/Item/Inventory/hooks/useItemSlotDragAndDrop.d.ts +2 -6
- package/dist/hooks/useCursorPosition.d.ts +1 -1
- package/dist/long-bow.cjs.development.js +433 -365
- 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 +435 -367
- package/dist/long-bow.esm.js.map +1 -1
- package/package.json +3 -2
- package/src/components/Equipment/EquipmentSet.tsx +61 -29
- package/src/components/Item/Inventory/DraggedItem.tsx +2 -2
- package/src/components/Item/Inventory/ItemContainer.tsx +68 -44
- package/src/components/Item/Inventory/ItemSlot.tsx +46 -65
- package/src/components/Item/Inventory/ItemSlotTooltips.tsx +48 -42
- package/src/components/Item/Inventory/context/{DraggingContext.tsx → ItemSlotDraggingContext.tsx} +10 -10
- package/src/components/Item/Inventory/context/ItemSlotTooltipContext.tsx +95 -0
- package/src/components/Item/Inventory/hooks/useItemSlotDragAndDrop.ts +50 -30
- package/src/hooks/useCursorPosition.ts +29 -20
- package/src/mocks/skills.mocks.ts +0 -4
|
@@ -3,18 +3,12 @@ import React from 'react';
|
|
|
3
3
|
import { RelativeListMenu } from '../../RelativeListMenu';
|
|
4
4
|
import { ItemTooltip } from '../Cards/ItemTooltip';
|
|
5
5
|
import { MobileItemTooltip } from '../Cards/MobileItemTooltip';
|
|
6
|
-
import {
|
|
7
|
-
import type { ContextMenuState, TooltipState } from './ItemSlot';
|
|
6
|
+
import { useItemSlotTooltip } from './context/ItemSlotTooltipContext';
|
|
8
7
|
|
|
9
8
|
interface IProps {
|
|
10
|
-
tooltipState: TooltipState;
|
|
11
|
-
setTooltipState: React.Dispatch<React.SetStateAction<TooltipState>>;
|
|
12
|
-
contextMenuState: ContextMenuState;
|
|
13
|
-
setContextMenuState: React.Dispatch<React.SetStateAction<ContextMenuState>>;
|
|
14
9
|
isFocused: boolean;
|
|
15
10
|
isContextMenuDisabled: boolean;
|
|
16
|
-
|
|
17
|
-
contextActions: IContextMenuItem[];
|
|
11
|
+
|
|
18
12
|
dragScale: number | undefined;
|
|
19
13
|
onSelected?: (optionId: string, item: IItem) => void;
|
|
20
14
|
atlasIMG: any;
|
|
@@ -23,23 +17,48 @@ interface IProps {
|
|
|
23
17
|
}
|
|
24
18
|
|
|
25
19
|
export const ItemSlotToolTips = ({
|
|
26
|
-
tooltipState,
|
|
27
|
-
setTooltipState,
|
|
28
|
-
contextMenuState,
|
|
29
|
-
setContextMenuState,
|
|
30
20
|
isFocused,
|
|
31
21
|
isContextMenuDisabled,
|
|
32
|
-
|
|
33
|
-
contextActions,
|
|
22
|
+
|
|
34
23
|
dragScale,
|
|
35
24
|
onSelected,
|
|
36
25
|
atlasIMG,
|
|
37
26
|
atlasJSON,
|
|
38
27
|
equipmentSet,
|
|
39
28
|
}: IProps): JSX.Element => {
|
|
29
|
+
const { itemDetails, updateItemDetails } = useItemSlotTooltip();
|
|
30
|
+
|
|
31
|
+
const item = itemDetails.item;
|
|
32
|
+
|
|
33
|
+
const handleCloseTooltip = () => {
|
|
34
|
+
updateItemDetails({
|
|
35
|
+
item,
|
|
36
|
+
tooltip: { mobileVisible: false },
|
|
37
|
+
});
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const handleContextMenuSelect = (optionId: string) => {
|
|
41
|
+
updateItemDetails({
|
|
42
|
+
item,
|
|
43
|
+
contextMenu: { visible: false },
|
|
44
|
+
});
|
|
45
|
+
if (item) {
|
|
46
|
+
onSelected?.(optionId, item);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const handleOutsideClick = () => {
|
|
51
|
+
updateItemDetails({
|
|
52
|
+
item,
|
|
53
|
+
contextMenu: { visible: false },
|
|
54
|
+
});
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
// monitor why mobileVisible is not working
|
|
58
|
+
|
|
40
59
|
return (
|
|
41
60
|
<>
|
|
42
|
-
{
|
|
61
|
+
{itemDetails.tooltip?.visible && item && !isFocused && (
|
|
43
62
|
<ItemTooltip
|
|
44
63
|
item={item}
|
|
45
64
|
atlasIMG={atlasIMG}
|
|
@@ -48,42 +67,29 @@ export const ItemSlotToolTips = ({
|
|
|
48
67
|
/>
|
|
49
68
|
)}
|
|
50
69
|
|
|
51
|
-
{
|
|
70
|
+
{itemDetails.tooltip?.mobileVisible && item && (
|
|
52
71
|
<MobileItemTooltip
|
|
53
72
|
item={item}
|
|
54
73
|
atlasIMG={atlasIMG}
|
|
55
74
|
atlasJSON={atlasJSON}
|
|
56
75
|
equipmentSet={equipmentSet}
|
|
57
|
-
closeTooltip={
|
|
58
|
-
setTooltipState(prev => ({ ...prev, mobileVisible: false }));
|
|
59
|
-
}}
|
|
76
|
+
closeTooltip={handleCloseTooltip}
|
|
60
77
|
scale={dragScale}
|
|
61
|
-
options={
|
|
62
|
-
onSelected={
|
|
63
|
-
setContextMenuState(prev => ({ ...prev, visible: false }));
|
|
64
|
-
if (item) {
|
|
65
|
-
onSelected?.(optionId, item);
|
|
66
|
-
}
|
|
67
|
-
}}
|
|
78
|
+
options={itemDetails.contextMenu?.actions || []}
|
|
79
|
+
onSelected={handleContextMenuSelect}
|
|
68
80
|
/>
|
|
69
81
|
)}
|
|
70
82
|
|
|
71
|
-
{!isContextMenuDisabled &&
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
onOutsideClick={() => {
|
|
82
|
-
setContextMenuState(prev => ({ ...prev, visible: false }));
|
|
83
|
-
}}
|
|
84
|
-
pos={contextMenuState.position}
|
|
85
|
-
/>
|
|
86
|
-
)}
|
|
83
|
+
{!isContextMenuDisabled &&
|
|
84
|
+
itemDetails.contextMenu?.visible &&
|
|
85
|
+
itemDetails.contextMenu.actions && (
|
|
86
|
+
<RelativeListMenu
|
|
87
|
+
options={itemDetails.contextMenu.actions}
|
|
88
|
+
onSelected={handleContextMenuSelect}
|
|
89
|
+
onOutsideClick={handleOutsideClick}
|
|
90
|
+
pos={itemDetails.contextMenu.position!}
|
|
91
|
+
/>
|
|
92
|
+
)}
|
|
87
93
|
</>
|
|
88
94
|
);
|
|
89
95
|
};
|
package/src/components/Item/Inventory/context/{DraggingContext.tsx → ItemSlotDraggingContext.tsx}
RENAMED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
import { IItem } from '@rpg-engine/shared';
|
|
2
2
|
import React, { createContext, useContext, useState } from 'react';
|
|
3
3
|
|
|
4
|
-
export interface
|
|
4
|
+
export interface IDragState {
|
|
5
5
|
isFocused: boolean;
|
|
6
6
|
wasDragged: boolean;
|
|
7
7
|
position: { x: number; y: number };
|
|
8
8
|
dropPosition: { x: number; y: number } | null;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
interface
|
|
11
|
+
interface IDraggingContextType {
|
|
12
12
|
item: IItem | null;
|
|
13
13
|
setDraggingItem: React.Dispatch<React.SetStateAction<IItem | null>>;
|
|
14
|
-
dragState:
|
|
15
|
-
setDragState: React.Dispatch<React.SetStateAction<
|
|
14
|
+
dragState: IDragState;
|
|
15
|
+
setDragState: React.Dispatch<React.SetStateAction<IDragState>>;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
const
|
|
18
|
+
const ItemSlotDraggingContext = createContext<IDraggingContextType>({
|
|
19
19
|
item: null,
|
|
20
20
|
setDraggingItem: () => {},
|
|
21
21
|
dragState: {
|
|
@@ -31,9 +31,9 @@ interface IProps {
|
|
|
31
31
|
children: React.ReactNode;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
export const
|
|
34
|
+
export const ItemSlotDraggingProvider = ({ children }: IProps) => {
|
|
35
35
|
const [item, setDraggingItem] = useState<IItem | null>(null);
|
|
36
|
-
const [dragState, setDragState] = useState<
|
|
36
|
+
const [dragState, setDragState] = useState<IDragState>({
|
|
37
37
|
isFocused: false,
|
|
38
38
|
wasDragged: false,
|
|
39
39
|
position: { x: 0, y: 0 },
|
|
@@ -41,12 +41,12 @@ export const DraggingProvider = ({ children }: IProps) => {
|
|
|
41
41
|
});
|
|
42
42
|
|
|
43
43
|
return (
|
|
44
|
-
<
|
|
44
|
+
<ItemSlotDraggingContext.Provider
|
|
45
45
|
value={{ item, setDraggingItem, dragState, setDragState }}
|
|
46
46
|
>
|
|
47
47
|
{children}
|
|
48
|
-
</
|
|
48
|
+
</ItemSlotDraggingContext.Provider>
|
|
49
49
|
);
|
|
50
50
|
};
|
|
51
51
|
|
|
52
|
-
export const
|
|
52
|
+
export const useItemSlotDragging = () => useContext(ItemSlotDraggingContext);
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { IItem } from '@rpg-engine/shared';
|
|
2
|
+
import React, {
|
|
3
|
+
createContext,
|
|
4
|
+
FC,
|
|
5
|
+
ReactNode,
|
|
6
|
+
useCallback,
|
|
7
|
+
useContext,
|
|
8
|
+
useEffect,
|
|
9
|
+
useState,
|
|
10
|
+
} from 'react';
|
|
11
|
+
import { IPosition } from '../../../../types/eventTypes';
|
|
12
|
+
import { IContextMenuItem } from '../itemContainerHelper';
|
|
13
|
+
|
|
14
|
+
// Define smaller, focused interfaces for better readability
|
|
15
|
+
interface TooltipState {
|
|
16
|
+
visible?: boolean;
|
|
17
|
+
mobileVisible?: boolean;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface ContextMenuState {
|
|
21
|
+
visible?: boolean;
|
|
22
|
+
position?: IPosition;
|
|
23
|
+
actions?: IContextMenuItem[];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
interface ItemDetails {
|
|
27
|
+
item?: IItem | null;
|
|
28
|
+
tooltip?: TooltipState;
|
|
29
|
+
contextMenu?: ContextMenuState;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
interface ItemSlotTooltipContextProps {
|
|
33
|
+
itemDetails: ItemDetails;
|
|
34
|
+
updateItemDetails: (updates: Partial<ItemDetails>) => void;
|
|
35
|
+
clearItemDetails: () => void;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Set default state with clearly defined initial values
|
|
39
|
+
const defaultItemDetails: ItemDetails = {
|
|
40
|
+
item: null,
|
|
41
|
+
tooltip: { visible: false, mobileVisible: false },
|
|
42
|
+
contextMenu: { visible: false, position: { x: 0, y: 0 }, actions: [] },
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// Create context with default values
|
|
46
|
+
const ItemSlotTooltipContext = createContext<ItemSlotTooltipContextProps>({
|
|
47
|
+
itemDetails: defaultItemDetails,
|
|
48
|
+
updateItemDetails: () => {},
|
|
49
|
+
clearItemDetails: () => {},
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
// Provider component
|
|
53
|
+
export const ItemSlotTooltipProvider: FC<{ children: ReactNode }> = ({
|
|
54
|
+
children,
|
|
55
|
+
}) => {
|
|
56
|
+
const [itemDetails, setItemDetails] = useState<ItemDetails>(
|
|
57
|
+
defaultItemDetails
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
console.log('itemDetails', itemDetails);
|
|
62
|
+
}, [itemDetails]);
|
|
63
|
+
|
|
64
|
+
// Memoize the update function to optimize performance
|
|
65
|
+
const updateItemDetails = useCallback((updates: Partial<ItemDetails>) => {
|
|
66
|
+
setItemDetails(prev => ({
|
|
67
|
+
...prev,
|
|
68
|
+
...updates,
|
|
69
|
+
tooltip: { ...prev.tooltip, ...updates.tooltip },
|
|
70
|
+
contextMenu: {
|
|
71
|
+
...prev.contextMenu,
|
|
72
|
+
...updates.contextMenu,
|
|
73
|
+
// Ensure actions are properly merged or overridden
|
|
74
|
+
actions: updates.contextMenu?.actions ?? prev.contextMenu?.actions,
|
|
75
|
+
},
|
|
76
|
+
}));
|
|
77
|
+
}, []);
|
|
78
|
+
|
|
79
|
+
const clearItemDetails = useCallback(() => {
|
|
80
|
+
setItemDetails(defaultItemDetails);
|
|
81
|
+
}, []);
|
|
82
|
+
|
|
83
|
+
return (
|
|
84
|
+
<ItemSlotTooltipContext.Provider
|
|
85
|
+
value={{ itemDetails, updateItemDetails, clearItemDetails }}
|
|
86
|
+
>
|
|
87
|
+
{children}
|
|
88
|
+
</ItemSlotTooltipContext.Provider>
|
|
89
|
+
);
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// Custom hook for consuming the context
|
|
93
|
+
export const useItemSlotTooltip = (): ItemSlotTooltipContextProps => {
|
|
94
|
+
return useContext(ItemSlotTooltipContext);
|
|
95
|
+
};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { IItem, ItemContainerType, ItemType } from '@rpg-engine/shared';
|
|
2
2
|
import { useCallback, useEffect, useRef } from 'react';
|
|
3
3
|
import { DraggableEventHandler } from 'react-draggable';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { useItemSlotDragging } from '../context/ItemSlotDraggingContext';
|
|
5
|
+
import { useItemSlotTooltip } from '../context/ItemSlotTooltipContext';
|
|
6
6
|
|
|
7
7
|
interface IUseItemSlotDragAndDrop {
|
|
8
8
|
isDepotSystem: boolean;
|
|
@@ -30,9 +30,6 @@ interface IUseItemSlotDragAndDrop {
|
|
|
30
30
|
onSuccess: (quantity?: number) => void
|
|
31
31
|
) => void;
|
|
32
32
|
isContextMenuDisabled: boolean;
|
|
33
|
-
setTooltipState: React.Dispatch<React.SetStateAction<TooltipState>>;
|
|
34
|
-
setContextMenuState: React.Dispatch<React.SetStateAction<ContextMenuState>>;
|
|
35
|
-
contextMenuState: ContextMenuState;
|
|
36
33
|
}
|
|
37
34
|
|
|
38
35
|
export const useItemSlotDragAndDrop = ({
|
|
@@ -50,8 +47,6 @@ export const useItemSlotDragAndDrop = ({
|
|
|
50
47
|
slotIndex,
|
|
51
48
|
openQuantitySelector,
|
|
52
49
|
isContextMenuDisabled,
|
|
53
|
-
setTooltipState,
|
|
54
|
-
setContextMenuState,
|
|
55
50
|
}: IUseItemSlotDragAndDrop) => {
|
|
56
51
|
const dragContainer = useRef<HTMLDivElement>(null);
|
|
57
52
|
const {
|
|
@@ -59,7 +54,9 @@ export const useItemSlotDragAndDrop = ({
|
|
|
59
54
|
setDraggingItem,
|
|
60
55
|
dragState,
|
|
61
56
|
setDragState,
|
|
62
|
-
} =
|
|
57
|
+
} = useItemSlotDragging();
|
|
58
|
+
|
|
59
|
+
const { updateItemDetails, itemDetails } = useItemSlotTooltip();
|
|
63
60
|
|
|
64
61
|
useEffect(() => {
|
|
65
62
|
setDragState(prev => ({
|
|
@@ -89,16 +86,24 @@ export const useItemSlotDragAndDrop = ({
|
|
|
89
86
|
}, []);
|
|
90
87
|
|
|
91
88
|
const resetDragState = useCallback(() => {
|
|
89
|
+
console.log('RESET_DRAG_STATE!');
|
|
92
90
|
setDragState(prev => ({
|
|
93
91
|
...prev,
|
|
94
92
|
wasDragged: false,
|
|
95
93
|
isFocused: false,
|
|
96
94
|
position: { x: 0, y: 0 },
|
|
97
95
|
}));
|
|
98
|
-
|
|
96
|
+
setDraggingItem(null);
|
|
97
|
+
|
|
98
|
+
// Reset tooltip visibility
|
|
99
|
+
updateItemDetails({
|
|
100
|
+
tooltip: { visible: false, mobileVisible: false },
|
|
101
|
+
});
|
|
102
|
+
}, [updateItemDetails, setDragState]);
|
|
99
103
|
|
|
100
104
|
const handleSuccessfulDrag = useCallback(
|
|
101
105
|
(quantity?: number) => {
|
|
106
|
+
console.log('HANDLE_SUCCESSFUL_DRAG!');
|
|
102
107
|
resetDragState();
|
|
103
108
|
if (quantity !== -1 && item) {
|
|
104
109
|
onDragEnd?.(quantity);
|
|
@@ -108,31 +113,35 @@ export const useItemSlotDragAndDrop = ({
|
|
|
108
113
|
);
|
|
109
114
|
|
|
110
115
|
const onDraggableStart: DraggableEventHandler = useCallback(() => {
|
|
116
|
+
console.log('ON_DRAGGABLE_START!');
|
|
111
117
|
if (!item || isSelectingShortcut) return;
|
|
112
118
|
if (onDragStart && containerType) {
|
|
113
119
|
onDragStart(item, slotIndex, containerType);
|
|
114
120
|
}
|
|
121
|
+
|
|
122
|
+
if (!draggingItem && item) {
|
|
123
|
+
console.log('!!! SETTING DRAGGING ITEM ', item._id);
|
|
124
|
+
setDraggingItem(item);
|
|
125
|
+
}
|
|
115
126
|
}, [item, isSelectingShortcut, onDragStart, containerType, slotIndex]);
|
|
116
127
|
|
|
117
128
|
const onDraggableProgress: DraggableEventHandler = useCallback(
|
|
118
129
|
(_e, data) => {
|
|
130
|
+
console.log('ON_DRAGGABLE_PROGRESS!');
|
|
119
131
|
const { x, y } = dragState.position;
|
|
120
132
|
if (Math.abs(data.x - x) > 5 || Math.abs(data.y - y) > 5) {
|
|
121
133
|
setDragState(prev => ({ ...prev, wasDragged: true, isFocused: true }));
|
|
122
134
|
}
|
|
123
|
-
if (!draggingItem) {
|
|
124
|
-
setDraggingItem(item);
|
|
125
|
-
}
|
|
126
135
|
},
|
|
127
136
|
[dragState.position, draggingItem, item, setDraggingItem, setDragState]
|
|
128
137
|
);
|
|
129
138
|
|
|
130
139
|
const onDraggableStop: DraggableEventHandler = useCallback(
|
|
131
140
|
(e, data) => {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
}, 50);
|
|
141
|
+
console.log('ON_DRAGGABLE_STOP!');
|
|
142
|
+
|
|
135
143
|
const target = e.target as HTMLElement;
|
|
144
|
+
|
|
136
145
|
if (!target) return;
|
|
137
146
|
|
|
138
147
|
target.classList.remove('react-draggable-dragging');
|
|
@@ -175,26 +184,39 @@ export const useItemSlotDragAndDrop = ({
|
|
|
175
184
|
}, 50);
|
|
176
185
|
} else if (item) {
|
|
177
186
|
const isTouch = e.type === 'touchend';
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
isTouch
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
187
|
+
|
|
188
|
+
console.log(`Debug:
|
|
189
|
+
isTouch: ${isTouch},
|
|
190
|
+
isSelectingShortcut: ${isSelectingShortcut},
|
|
191
|
+
draggingItem: ${draggingItem},
|
|
192
|
+
dragginState: ${JSON.stringify(dragState)}
|
|
193
|
+
`);
|
|
194
|
+
|
|
195
|
+
if (!isContextMenuDisabled && isTouch && !isSelectingShortcut) {
|
|
196
|
+
updateItemDetails({
|
|
197
|
+
item,
|
|
198
|
+
tooltip: { mobileVisible: true },
|
|
199
|
+
});
|
|
185
200
|
} else if (!isContextMenuDisabled && !isSelectingShortcut && !isTouch) {
|
|
186
201
|
const event = e as MouseEvent;
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
202
|
+
|
|
203
|
+
updateItemDetails({
|
|
204
|
+
item,
|
|
205
|
+
contextMenu: {
|
|
206
|
+
visible: !itemDetails?.contextMenu?.visible,
|
|
207
|
+
position: {
|
|
208
|
+
x: event.clientX - 10,
|
|
209
|
+
y: event.clientY - 5,
|
|
210
|
+
},
|
|
192
211
|
},
|
|
193
|
-
})
|
|
212
|
+
});
|
|
194
213
|
}
|
|
195
214
|
|
|
196
215
|
onPointerDown?.(item.type, containerType ?? null, item);
|
|
197
216
|
}
|
|
217
|
+
|
|
218
|
+
console.log('setting draggingItem to null');
|
|
219
|
+
setDraggingItem(null);
|
|
198
220
|
},
|
|
199
221
|
[
|
|
200
222
|
dragState.wasDragged,
|
|
@@ -206,8 +228,6 @@ export const useItemSlotDragAndDrop = ({
|
|
|
206
228
|
handleSuccessfulDrag,
|
|
207
229
|
resetDragState,
|
|
208
230
|
isContextMenuDisabled,
|
|
209
|
-
setTooltipState,
|
|
210
|
-
setContextMenuState,
|
|
211
231
|
onPointerDown,
|
|
212
232
|
containerType,
|
|
213
233
|
setItemShortcut,
|
|
@@ -6,37 +6,46 @@ interface ICursorPositionProps {
|
|
|
6
6
|
scale?: number;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
export const useCursorPosition = ({
|
|
9
|
+
export const useCursorPosition = ({
|
|
10
|
+
scale = 1,
|
|
11
|
+
}: ICursorPositionProps): IPosition => {
|
|
10
12
|
const [position, setPosition] = useState<IPosition>({ x: 0, y: 0 });
|
|
11
13
|
|
|
12
|
-
const scalePosition = useCallback(
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
const scalePosition = useCallback(
|
|
15
|
+
(x: number, y: number): IPosition => {
|
|
16
|
+
return {
|
|
17
|
+
x: (x - GRID_WIDTH / 2) / scale + GRID_WIDTH / 2,
|
|
18
|
+
y: (y - GRID_HEIGHT / 2) / scale + GRID_HEIGHT / 2,
|
|
19
|
+
};
|
|
20
|
+
},
|
|
21
|
+
[scale]
|
|
22
|
+
);
|
|
18
23
|
|
|
19
|
-
const setFromEvent = useCallback(
|
|
20
|
-
|
|
24
|
+
const setFromEvent = useCallback(
|
|
25
|
+
(e: MouseEvent | TouchEvent) => {
|
|
26
|
+
let x, y;
|
|
21
27
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
if ('touches' in e) {
|
|
29
|
+
x = e.touches[0].clientX;
|
|
30
|
+
y = e.touches[0].clientY;
|
|
31
|
+
} else {
|
|
32
|
+
x = e.clientX;
|
|
33
|
+
y = e.clientY;
|
|
34
|
+
}
|
|
29
35
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
36
|
+
const scaledPosition = scalePosition(x, y);
|
|
37
|
+
setPosition(scaledPosition);
|
|
38
|
+
},
|
|
39
|
+
[scale, scalePosition]
|
|
40
|
+
);
|
|
33
41
|
|
|
34
42
|
const cleanup = useCallback(() => {
|
|
35
43
|
setPosition({ x: 0, y: 0 });
|
|
36
44
|
}, []);
|
|
37
45
|
|
|
38
46
|
useEffect(() => {
|
|
39
|
-
const handleEvent = (e: Event) =>
|
|
47
|
+
const handleEvent = (e: Event) =>
|
|
48
|
+
setFromEvent(e as MouseEvent | TouchEvent);
|
|
40
49
|
|
|
41
50
|
window.addEventListener('mousemove', handleEvent);
|
|
42
51
|
window.addEventListener('touchmove', handleEvent);
|