@rpg-engine/long-bow 0.5.21 → 0.5.23
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/Abstractions/SlotsContainer.d.ts +1 -0
- package/dist/components/Item/Inventory/DraggedItem.d.ts +7 -0
- package/dist/components/Item/Inventory/ItemQuantitySelectorModal.d.ts +12 -0
- package/dist/components/Item/Inventory/ItemSlotQty/ItemSlotQty.d.ts +9 -0
- package/dist/components/Item/Inventory/ItemSlotRenderer.d.ts +11 -0
- package/dist/components/Item/Inventory/ItemSlotTooltips.d.ts +24 -0
- package/dist/components/Item/Inventory/context/DraggingContext.d.ts +11 -0
- package/dist/hooks/useMousePosition.d.ts +6 -0
- package/dist/long-bow.cjs.development.js +449 -275
- 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 +450 -276
- package/dist/long-bow.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/components/Abstractions/SlotsContainer.tsx +3 -1
- package/src/components/Equipment/EquipmentSet.tsx +24 -19
- package/src/components/Item/Inventory/DraggedItem.tsx +107 -0
- package/src/components/Item/Inventory/ItemContainer.tsx +11 -41
- package/src/components/Item/Inventory/ItemQuantitySelectorModal.tsx +59 -0
- package/src/components/Item/Inventory/ItemSlot.tsx +50 -211
- package/src/components/Item/Inventory/ItemSlotQty/ItemSlotQty.tsx +70 -0
- package/src/components/Item/Inventory/ItemSlotRenderer.tsx +92 -0
- package/src/components/Item/Inventory/ItemSlotTooltips.tsx +93 -0
- package/src/components/Item/Inventory/context/DraggingContext.tsx +26 -0
- package/src/hooks/useMousePosition.ts +49 -0
package/package.json
CHANGED
|
@@ -13,6 +13,7 @@ interface IProps {
|
|
|
13
13
|
onOutsideClick?: () => void;
|
|
14
14
|
initialPosition?: IPosition;
|
|
15
15
|
scale?: number;
|
|
16
|
+
width?: string;
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
export const SlotsContainer: React.FC<IProps> = ({
|
|
@@ -25,6 +26,7 @@ export const SlotsContainer: React.FC<IProps> = ({
|
|
|
25
26
|
onOutsideClick,
|
|
26
27
|
initialPosition,
|
|
27
28
|
scale,
|
|
29
|
+
width,
|
|
28
30
|
}) => {
|
|
29
31
|
return (
|
|
30
32
|
<DraggableContainer
|
|
@@ -35,7 +37,7 @@ export const SlotsContainer: React.FC<IProps> = ({
|
|
|
35
37
|
onClose();
|
|
36
38
|
}
|
|
37
39
|
}}
|
|
38
|
-
width=
|
|
40
|
+
width={width ?? '415px'}
|
|
39
41
|
cancelDrag=".item-container-body, #shortcuts_list"
|
|
40
42
|
onPositionChange={({ x, y }) => {
|
|
41
43
|
if (onPositionChange) {
|
|
@@ -10,7 +10,9 @@ import React from 'react';
|
|
|
10
10
|
import styled from 'styled-components';
|
|
11
11
|
import { IPosition } from '../../types/eventTypes';
|
|
12
12
|
import { DraggableContainer } from '../DraggableContainer';
|
|
13
|
+
import DraggedItem from '../Item/Inventory/DraggedItem';
|
|
13
14
|
import { ItemSlot } from '../Item/Inventory/ItemSlot';
|
|
15
|
+
import { DraggingProvider } from '../Item/Inventory/context/DraggingContext';
|
|
14
16
|
import { RPGUIContainerTypes } from '../RPGUIContainer';
|
|
15
17
|
|
|
16
18
|
export interface IEquipmentSetProps {
|
|
@@ -159,25 +161,28 @@ export const EquipmentSet: React.FC<IEquipmentSetProps> = ({
|
|
|
159
161
|
};
|
|
160
162
|
|
|
161
163
|
return (
|
|
162
|
-
<
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
<
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
164
|
+
<DraggingProvider>
|
|
165
|
+
<DraggedItem atlasIMG={atlasIMG} atlasJSON={atlasJSON} />
|
|
166
|
+
<DraggableContainer
|
|
167
|
+
title={'Equipments'}
|
|
168
|
+
type={RPGUIContainerTypes.Framed}
|
|
169
|
+
onCloseButton={() => {
|
|
170
|
+
if (onClose) onClose();
|
|
171
|
+
}}
|
|
172
|
+
width="330px"
|
|
173
|
+
cancelDrag=".equipment-container-body"
|
|
174
|
+
scale={scale}
|
|
175
|
+
initialPosition={initialPosition}
|
|
176
|
+
onPositionChangeEnd={onPositionChangeEnd}
|
|
177
|
+
onPositionChangeStart={onPositionChangeStart}
|
|
178
|
+
>
|
|
179
|
+
<EquipmentSetContainer className="equipment-container-body">
|
|
180
|
+
<EquipmentColumn>{onRenderEquipmentSlotRange(0, 3)}</EquipmentColumn>
|
|
181
|
+
<EquipmentColumn>{onRenderEquipmentSlotRange(3, 7)}</EquipmentColumn>
|
|
182
|
+
<EquipmentColumn>{onRenderEquipmentSlotRange(7, 10)}</EquipmentColumn>
|
|
183
|
+
</EquipmentSetContainer>
|
|
184
|
+
</DraggableContainer>
|
|
185
|
+
</DraggingProvider>
|
|
181
186
|
);
|
|
182
187
|
};
|
|
183
188
|
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { getItemTextureKeyPath } from '@rpg-engine/shared';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import styled from 'styled-components';
|
|
4
|
+
import { useCursorPosition } from '../../../hooks/useMousePosition';
|
|
5
|
+
import { SpriteFromAtlas } from '../../shared/SpriteFromAtlas';
|
|
6
|
+
import { onRenderStackInfo } from './ItemSlotQty/ItemSlotQty';
|
|
7
|
+
import { useDragging } from './context/DraggingContext';
|
|
8
|
+
|
|
9
|
+
const CONTAINER_SIZE = 32;
|
|
10
|
+
const OFFSET = CONTAINER_SIZE / 2;
|
|
11
|
+
|
|
12
|
+
interface IProps {
|
|
13
|
+
atlasJSON: any;
|
|
14
|
+
atlasIMG: any;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const DraggedItem = ({
|
|
18
|
+
atlasJSON,
|
|
19
|
+
atlasIMG,
|
|
20
|
+
}: IProps): JSX.Element | null => {
|
|
21
|
+
const { item } = useDragging();
|
|
22
|
+
const { x, y } = useCursorPosition();
|
|
23
|
+
|
|
24
|
+
if (!item) {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const centeredX = x - OFFSET;
|
|
29
|
+
const centeredY = y - OFFSET;
|
|
30
|
+
|
|
31
|
+
const stackInfo = onRenderStackInfo(item?._id ?? '', item?.stackQty ?? 0);
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<Container>
|
|
35
|
+
<SpriteContainer x={centeredX} y={centeredY}>
|
|
36
|
+
<SpriteFromAtlas
|
|
37
|
+
key={item._id}
|
|
38
|
+
atlasIMG={atlasIMG}
|
|
39
|
+
atlasJSON={atlasJSON}
|
|
40
|
+
spriteKey={getItemTextureKeyPath(
|
|
41
|
+
{
|
|
42
|
+
key: item.texturePath,
|
|
43
|
+
texturePath: item.texturePath,
|
|
44
|
+
stackQty: item.stackQty || 1,
|
|
45
|
+
isStackable: item.isStackable,
|
|
46
|
+
},
|
|
47
|
+
atlasJSON
|
|
48
|
+
)}
|
|
49
|
+
imgScale={3}
|
|
50
|
+
imgClassname="sprite-from-atlas-img--item"
|
|
51
|
+
/>
|
|
52
|
+
{stackInfo}
|
|
53
|
+
</SpriteContainer>
|
|
54
|
+
</Container>
|
|
55
|
+
);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
interface IContainer {
|
|
59
|
+
x: number;
|
|
60
|
+
y: number;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const pulse = `
|
|
64
|
+
@keyframes pulse {
|
|
65
|
+
0%, 100% {
|
|
66
|
+
transform: scale(1) rotate(-3deg);
|
|
67
|
+
}
|
|
68
|
+
50% {
|
|
69
|
+
transform: scale(0.95) rotate(-3deg);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
`;
|
|
73
|
+
|
|
74
|
+
const Container = styled.div`
|
|
75
|
+
position: relative;
|
|
76
|
+
`;
|
|
77
|
+
|
|
78
|
+
const SpriteContainer = styled.div.attrs<IContainer>(props => ({
|
|
79
|
+
style: {
|
|
80
|
+
left: `${props.x}px`,
|
|
81
|
+
top: `${props.y}px`,
|
|
82
|
+
},
|
|
83
|
+
}))<IContainer>`
|
|
84
|
+
${pulse}
|
|
85
|
+
|
|
86
|
+
position: absolute;
|
|
87
|
+
z-index: 100;
|
|
88
|
+
pointer-events: none;
|
|
89
|
+
|
|
90
|
+
width: ${CONTAINER_SIZE}px;
|
|
91
|
+
height: ${CONTAINER_SIZE}px;
|
|
92
|
+
|
|
93
|
+
transform: rotate(-3deg);
|
|
94
|
+
|
|
95
|
+
filter: grayscale(100%);
|
|
96
|
+
opacity: 0.35;
|
|
97
|
+
|
|
98
|
+
animation: pulse 2s infinite;
|
|
99
|
+
|
|
100
|
+
.item-slot-qty {
|
|
101
|
+
position: absolute;
|
|
102
|
+
bottom: 0;
|
|
103
|
+
margin-left: 0.8rem;
|
|
104
|
+
}
|
|
105
|
+
`;
|
|
106
|
+
|
|
107
|
+
export default DraggedItem;
|
|
@@ -9,12 +9,13 @@ import {
|
|
|
9
9
|
import React, { useState } from 'react';
|
|
10
10
|
import styled from 'styled-components';
|
|
11
11
|
import { SlotsContainer } from '../../Abstractions/SlotsContainer';
|
|
12
|
-
import { ItemQuantitySelector } from './ItemQuantitySelector';
|
|
13
12
|
|
|
14
13
|
import { IPosition } from '../../../types/eventTypes';
|
|
15
|
-
import ModalPortal from '../../Abstractions/ModalPortal';
|
|
16
14
|
import { ShortcutsSetter } from '../../Shortcuts/ShortcutsSetter';
|
|
15
|
+
import { DraggedItem } from './DraggedItem';
|
|
16
|
+
import { ItemQuantitySelectorModal } from './ItemQuantitySelectorModal';
|
|
17
17
|
import { ItemSlot } from './ItemSlot';
|
|
18
|
+
import { DraggingProvider } from './context/DraggingContext';
|
|
18
19
|
|
|
19
20
|
export interface IItemContainerProps {
|
|
20
21
|
itemContainer: IItemContainer;
|
|
@@ -157,7 +158,8 @@ export const ItemContainer: React.FC<IItemContainerProps> = ({
|
|
|
157
158
|
};
|
|
158
159
|
|
|
159
160
|
return (
|
|
160
|
-
|
|
161
|
+
<DraggingProvider>
|
|
162
|
+
<DraggedItem atlasIMG={atlasIMG} atlasJSON={atlasJSON} />
|
|
161
163
|
<SlotsContainer
|
|
162
164
|
title={itemContainer.name || 'Container'}
|
|
163
165
|
onClose={onClose}
|
|
@@ -183,31 +185,12 @@ export const ItemContainer: React.FC<IItemContainerProps> = ({
|
|
|
183
185
|
</ItemsContainer>
|
|
184
186
|
</SlotsContainer>
|
|
185
187
|
{quantitySelect.isOpen && (
|
|
186
|
-
<
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
onConfirm={quantity => {
|
|
191
|
-
quantitySelect.callback(quantity);
|
|
192
|
-
setQuantitySelect({
|
|
193
|
-
isOpen: false,
|
|
194
|
-
maxQuantity: 1,
|
|
195
|
-
callback: () => {},
|
|
196
|
-
});
|
|
197
|
-
}}
|
|
198
|
-
onClose={() => {
|
|
199
|
-
quantitySelect.callback(-1);
|
|
200
|
-
setQuantitySelect({
|
|
201
|
-
isOpen: false,
|
|
202
|
-
maxQuantity: 1,
|
|
203
|
-
callback: () => {},
|
|
204
|
-
});
|
|
205
|
-
}}
|
|
206
|
-
/>
|
|
207
|
-
</QuantitySelectorContainer>
|
|
208
|
-
</ModalPortal>
|
|
188
|
+
<ItemQuantitySelectorModal
|
|
189
|
+
quantitySelect={quantitySelect}
|
|
190
|
+
setQuantitySelect={setQuantitySelect}
|
|
191
|
+
/>
|
|
209
192
|
)}
|
|
210
|
-
|
|
193
|
+
</DraggingProvider>
|
|
211
194
|
);
|
|
212
195
|
};
|
|
213
196
|
|
|
@@ -218,18 +201,5 @@ const ItemsContainer = styled.div`
|
|
|
218
201
|
max-height: 270px;
|
|
219
202
|
overflow-y: auto;
|
|
220
203
|
overflow-x: hidden;
|
|
221
|
-
width:
|
|
222
|
-
`;
|
|
223
|
-
|
|
224
|
-
const QuantitySelectorContainer = styled.div`
|
|
225
|
-
position: absolute;
|
|
226
|
-
top: 0;
|
|
227
|
-
left: 0;
|
|
228
|
-
width: 100vw;
|
|
229
|
-
height: 100vh;
|
|
230
|
-
z-index: 100;
|
|
231
|
-
display: flex;
|
|
232
|
-
justify-content: center;
|
|
233
|
-
align-items: center;
|
|
234
|
-
background-color: rgba(0, 0, 0, 0.5);
|
|
204
|
+
width: 415px;
|
|
235
205
|
`;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import styled from 'styled-components';
|
|
3
|
+
import ModalPortal from '../../Abstractions/ModalPortal';
|
|
4
|
+
import { ItemQuantitySelector } from './ItemQuantitySelector';
|
|
5
|
+
|
|
6
|
+
export interface IQuantitySelect {
|
|
7
|
+
isOpen: boolean;
|
|
8
|
+
maxQuantity: number;
|
|
9
|
+
callback: (_quantity: number) => void;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface IProps {
|
|
13
|
+
quantitySelect: IQuantitySelect;
|
|
14
|
+
setQuantitySelect: React.Dispatch<React.SetStateAction<IQuantitySelect>>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const ItemQuantitySelectorModal = ({
|
|
18
|
+
quantitySelect,
|
|
19
|
+
setQuantitySelect,
|
|
20
|
+
}: IProps) => {
|
|
21
|
+
return (
|
|
22
|
+
<ModalPortal>
|
|
23
|
+
<QuantitySelectorContainer>
|
|
24
|
+
<ItemQuantitySelector
|
|
25
|
+
quantity={quantitySelect.maxQuantity}
|
|
26
|
+
onConfirm={quantity => {
|
|
27
|
+
quantitySelect.callback(quantity);
|
|
28
|
+
setQuantitySelect({
|
|
29
|
+
isOpen: false,
|
|
30
|
+
maxQuantity: 1,
|
|
31
|
+
callback: () => {},
|
|
32
|
+
});
|
|
33
|
+
}}
|
|
34
|
+
onClose={() => {
|
|
35
|
+
quantitySelect.callback(-1);
|
|
36
|
+
setQuantitySelect({
|
|
37
|
+
isOpen: false,
|
|
38
|
+
maxQuantity: 1,
|
|
39
|
+
callback: () => {},
|
|
40
|
+
});
|
|
41
|
+
}}
|
|
42
|
+
/>
|
|
43
|
+
</QuantitySelectorContainer>
|
|
44
|
+
</ModalPortal>
|
|
45
|
+
);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const QuantitySelectorContainer = styled.div`
|
|
49
|
+
position: absolute;
|
|
50
|
+
top: 0;
|
|
51
|
+
left: 0;
|
|
52
|
+
width: 100vw;
|
|
53
|
+
height: 100vh;
|
|
54
|
+
z-index: 100;
|
|
55
|
+
display: flex;
|
|
56
|
+
justify-content: center;
|
|
57
|
+
align-items: center;
|
|
58
|
+
background-color: rgba(0, 0, 0, 0.5);
|
|
59
|
+
`;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import {
|
|
2
|
-
getItemTextureKeyPath,
|
|
3
2
|
IEquipmentSet,
|
|
4
3
|
IItem,
|
|
5
4
|
IItemContainer,
|
|
@@ -13,16 +12,11 @@ import { observer } from 'mobx-react-lite';
|
|
|
13
12
|
import React, { useEffect, useRef, useState } from 'react';
|
|
14
13
|
import Draggable from 'react-draggable';
|
|
15
14
|
import styled from 'styled-components';
|
|
16
|
-
import { v4 as uuidv4 } from 'uuid';
|
|
17
|
-
import { uiFonts } from '../../../constants/uiFonts';
|
|
18
15
|
import { IPosition } from '../../../types/eventTypes';
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import { MobileItemTooltip } from '../Cards/MobileItemTooltip';
|
|
24
|
-
import { ErrorBoundary } from './ErrorBoundary';
|
|
25
|
-
import { generateContextMenu, IContextMenuItem } from './itemContainerHelper';
|
|
16
|
+
import { ItemSlotRenderer } from './ItemSlotRenderer';
|
|
17
|
+
import { ItemSlotToolTips } from './ItemSlotTooltips';
|
|
18
|
+
import { useDragging } from './context/DraggingContext';
|
|
19
|
+
import { IContextMenuItem, generateContextMenu } from './itemContainerHelper';
|
|
26
20
|
|
|
27
21
|
export const EquipmentSlotSpriteByType: any = {
|
|
28
22
|
Neck: 'accessories/corruption-necklace.png',
|
|
@@ -123,6 +117,8 @@ export const ItemSlot: React.FC<IProps> = observer(
|
|
|
123
117
|
const [dropPosition, setDropPosition] = useState<IPosition | null>(null);
|
|
124
118
|
const dragContainer = useRef<HTMLDivElement>(null);
|
|
125
119
|
|
|
120
|
+
const { setDraggingItem } = useDragging();
|
|
121
|
+
|
|
126
122
|
const [contextActions, setContextActions] = useState<IContextMenuItem[]>(
|
|
127
123
|
[]
|
|
128
124
|
);
|
|
@@ -144,134 +140,12 @@ export const ItemSlot: React.FC<IProps> = observer(
|
|
|
144
140
|
}
|
|
145
141
|
}, [dropPosition]);
|
|
146
142
|
|
|
147
|
-
const getStackInfo = (itemId: string, stackQty: number) => {
|
|
148
|
-
const isFractionalStackQty = stackQty % 1 !== 0;
|
|
149
|
-
const isLargerThan999 = stackQty > 999;
|
|
150
|
-
|
|
151
|
-
let qtyClassName = 'regular';
|
|
152
|
-
if (isLargerThan999) qtyClassName = 'small';
|
|
153
|
-
if (isFractionalStackQty) qtyClassName = 'xsmall';
|
|
154
|
-
|
|
155
|
-
if (stackQty > 1) {
|
|
156
|
-
return (
|
|
157
|
-
<ItemQtyContainer key={`qty-${itemId}`}>
|
|
158
|
-
<Ellipsis maxLines={1} maxWidth="48px">
|
|
159
|
-
<ItemQty className={qtyClassName}>
|
|
160
|
-
{Math.round(stackQty * 100) / 100}{' '}
|
|
161
|
-
</ItemQty>
|
|
162
|
-
</Ellipsis>
|
|
163
|
-
</ItemQtyContainer>
|
|
164
|
-
);
|
|
165
|
-
}
|
|
166
|
-
return undefined;
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
const renderItem = (itemToRender: IItem | null) => {
|
|
170
|
-
const element = [];
|
|
171
|
-
|
|
172
|
-
if (itemToRender?.texturePath) {
|
|
173
|
-
element.push(
|
|
174
|
-
<ErrorBoundary key={itemToRender._id}>
|
|
175
|
-
<SpriteFromAtlas
|
|
176
|
-
key={itemToRender._id}
|
|
177
|
-
atlasIMG={atlasIMG}
|
|
178
|
-
atlasJSON={atlasJSON}
|
|
179
|
-
spriteKey={getItemTextureKeyPath(
|
|
180
|
-
{
|
|
181
|
-
key: itemToRender.texturePath,
|
|
182
|
-
texturePath: itemToRender.texturePath,
|
|
183
|
-
stackQty: itemToRender.stackQty || 1,
|
|
184
|
-
isStackable: itemToRender.isStackable,
|
|
185
|
-
},
|
|
186
|
-
atlasJSON
|
|
187
|
-
)}
|
|
188
|
-
imgScale={3}
|
|
189
|
-
imgClassname="sprite-from-atlas-img--item"
|
|
190
|
-
/>
|
|
191
|
-
</ErrorBoundary>
|
|
192
|
-
);
|
|
193
|
-
}
|
|
194
|
-
const stackInfo = getStackInfo(
|
|
195
|
-
itemToRender?._id ?? '',
|
|
196
|
-
itemToRender?.stackQty ?? 0
|
|
197
|
-
);
|
|
198
|
-
if (stackInfo) {
|
|
199
|
-
element.push(stackInfo);
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
return element;
|
|
203
|
-
};
|
|
204
|
-
|
|
205
|
-
const renderEquipment = (itemToRender: IItem | null) => {
|
|
206
|
-
if (
|
|
207
|
-
itemToRender?.texturePath &&
|
|
208
|
-
itemToRender.allowedEquipSlotType?.includes(slotSpriteMask!)
|
|
209
|
-
) {
|
|
210
|
-
const element = [];
|
|
211
|
-
|
|
212
|
-
element.push(
|
|
213
|
-
<ErrorBoundary key={itemToRender._id}>
|
|
214
|
-
<SpriteFromAtlas
|
|
215
|
-
key={itemToRender._id}
|
|
216
|
-
atlasIMG={atlasIMG}
|
|
217
|
-
atlasJSON={atlasJSON}
|
|
218
|
-
spriteKey={getItemTextureKeyPath(
|
|
219
|
-
{
|
|
220
|
-
key: itemToRender.texturePath,
|
|
221
|
-
texturePath: itemToRender.texturePath,
|
|
222
|
-
stackQty: itemToRender.stackQty || 1,
|
|
223
|
-
isStackable: itemToRender.isStackable,
|
|
224
|
-
},
|
|
225
|
-
atlasJSON
|
|
226
|
-
)}
|
|
227
|
-
imgScale={3}
|
|
228
|
-
imgClassname="sprite-from-atlas-img--item"
|
|
229
|
-
/>
|
|
230
|
-
</ErrorBoundary>
|
|
231
|
-
);
|
|
232
|
-
const stackInfo = getStackInfo(
|
|
233
|
-
itemToRender?._id ?? '',
|
|
234
|
-
itemToRender?.stackQty ?? 0
|
|
235
|
-
);
|
|
236
|
-
if (stackInfo) {
|
|
237
|
-
element.push(stackInfo);
|
|
238
|
-
}
|
|
239
|
-
return element;
|
|
240
|
-
} else {
|
|
241
|
-
return (
|
|
242
|
-
<ErrorBoundary key={uuidv4()}>
|
|
243
|
-
<SpriteFromAtlas
|
|
244
|
-
key={uuidv4()}
|
|
245
|
-
atlasIMG={atlasIMG}
|
|
246
|
-
atlasJSON={atlasJSON}
|
|
247
|
-
spriteKey={EquipmentSlotSpriteByType[slotSpriteMask!]}
|
|
248
|
-
imgScale={3}
|
|
249
|
-
grayScale={true}
|
|
250
|
-
opacity={0.4}
|
|
251
|
-
imgClassname="sprite-from-atlas-img--item"
|
|
252
|
-
/>
|
|
253
|
-
</ErrorBoundary>
|
|
254
|
-
);
|
|
255
|
-
}
|
|
256
|
-
};
|
|
257
|
-
|
|
258
|
-
const onRenderSlot = (itemToRender: IItem | null) => {
|
|
259
|
-
switch (containerType) {
|
|
260
|
-
case ItemContainerType.Equipment:
|
|
261
|
-
return renderEquipment(itemToRender);
|
|
262
|
-
case ItemContainerType.Inventory:
|
|
263
|
-
return renderItem(itemToRender);
|
|
264
|
-
default:
|
|
265
|
-
return renderItem(itemToRender);
|
|
266
|
-
}
|
|
267
|
-
};
|
|
268
|
-
|
|
269
143
|
const resetItem = () => {
|
|
270
144
|
setTooltipVisible(false);
|
|
271
145
|
setWasDragged(false);
|
|
272
146
|
};
|
|
273
147
|
|
|
274
|
-
const
|
|
148
|
+
const onSuccessfulDrag = (quantity?: number) => {
|
|
275
149
|
resetItem();
|
|
276
150
|
|
|
277
151
|
if (quantity === -1) {
|
|
@@ -321,6 +195,8 @@ export const ItemSlot: React.FC<IProps> = observer(
|
|
|
321
195
|
scale={dragScale}
|
|
322
196
|
disabled={onDragStart === undefined || onDragEnd === undefined}
|
|
323
197
|
onStop={(e, data) => {
|
|
198
|
+
setDraggingItem(null);
|
|
199
|
+
|
|
324
200
|
const target = e.target as HTMLElement;
|
|
325
201
|
if (
|
|
326
202
|
target?.id.includes('shortcutSetter') &&
|
|
@@ -371,14 +247,14 @@ export const ItemSlot: React.FC<IProps> = observer(
|
|
|
371
247
|
item.stackQty !== 1 &&
|
|
372
248
|
openQuantitySelector
|
|
373
249
|
)
|
|
374
|
-
openQuantitySelector(item.stackQty,
|
|
375
|
-
else
|
|
250
|
+
openQuantitySelector(item.stackQty, onSuccessfulDrag);
|
|
251
|
+
else onSuccessfulDrag(item.stackQty);
|
|
376
252
|
} else {
|
|
377
253
|
resetItem();
|
|
378
254
|
setIsFocused(false);
|
|
379
255
|
setDragPosition({ x: 0, y: 0 });
|
|
380
256
|
}
|
|
381
|
-
},
|
|
257
|
+
}, 50);
|
|
382
258
|
} else if (item) {
|
|
383
259
|
let isTouch = false;
|
|
384
260
|
if (
|
|
@@ -410,6 +286,8 @@ export const ItemSlot: React.FC<IProps> = observer(
|
|
|
410
286
|
return;
|
|
411
287
|
}
|
|
412
288
|
|
|
289
|
+
setDraggingItem(item);
|
|
290
|
+
|
|
413
291
|
if (onDragStart && containerType) {
|
|
414
292
|
onDragStart(item, slotIndex, containerType);
|
|
415
293
|
}
|
|
@@ -448,54 +326,37 @@ export const ItemSlot: React.FC<IProps> = observer(
|
|
|
448
326
|
setTooltipVisible(false);
|
|
449
327
|
}}
|
|
450
328
|
>
|
|
451
|
-
|
|
329
|
+
<ItemSlotRenderer
|
|
330
|
+
item={item}
|
|
331
|
+
slotSpriteMask={slotSpriteMask}
|
|
332
|
+
atlasIMG={atlasIMG}
|
|
333
|
+
atlasJSON={atlasJSON}
|
|
334
|
+
containerType={containerType}
|
|
335
|
+
/>
|
|
452
336
|
</ItemContainer>
|
|
453
337
|
</Draggable>
|
|
454
338
|
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
setIsContextMenuVisible(false);
|
|
477
|
-
if (item) {
|
|
478
|
-
onSelected?.(optionId, item);
|
|
479
|
-
}
|
|
480
|
-
}}
|
|
481
|
-
/>
|
|
482
|
-
)}
|
|
483
|
-
|
|
484
|
-
{!isContextMenuDisabled && isContextMenuVisible && contextActions && (
|
|
485
|
-
<RelativeListMenu
|
|
486
|
-
options={contextActions}
|
|
487
|
-
onSelected={(optionId: string) => {
|
|
488
|
-
setIsContextMenuVisible(false);
|
|
489
|
-
if (item) {
|
|
490
|
-
onSelected?.(optionId, item);
|
|
491
|
-
}
|
|
492
|
-
}}
|
|
493
|
-
onOutsideClick={() => {
|
|
494
|
-
setIsContextMenuVisible(false);
|
|
495
|
-
}}
|
|
496
|
-
pos={contextMenuPosition}
|
|
497
|
-
/>
|
|
498
|
-
)}
|
|
339
|
+
<ItemSlotToolTips
|
|
340
|
+
isTooltipVisible={isTooltipVisible}
|
|
341
|
+
isTooltipMobileVisible={isTooltipMobileVisible}
|
|
342
|
+
setIsTooltipMobileVisible={setIsTooltipMobileVisible}
|
|
343
|
+
isFocused={isFocused}
|
|
344
|
+
isContextMenuVisible={isContextMenuVisible}
|
|
345
|
+
isContextMenuDisabled={isContextMenuDisabled}
|
|
346
|
+
item={item}
|
|
347
|
+
contextActions={contextActions}
|
|
348
|
+
contextMenuPosition={contextMenuPosition}
|
|
349
|
+
dragScale={dragScale}
|
|
350
|
+
setIsContextMenuVisible={setIsContextMenuVisible}
|
|
351
|
+
onSelected={(optionId: string, item: IItem) => {
|
|
352
|
+
setIsContextMenuVisible(false);
|
|
353
|
+
if (onSelected) onSelected(optionId, item);
|
|
354
|
+
}}
|
|
355
|
+
atlasIMG={atlasIMG}
|
|
356
|
+
atlasJSON={atlasJSON}
|
|
357
|
+
equipmentSet={equipmentSet}
|
|
358
|
+
setIsTooltipVisible={setTooltipVisible}
|
|
359
|
+
/>
|
|
499
360
|
</Container>
|
|
500
361
|
);
|
|
501
362
|
}
|
|
@@ -518,6 +379,7 @@ export const rarityColor = (item: IItem | null) => {
|
|
|
518
379
|
|
|
519
380
|
interface ContainerTypes {
|
|
520
381
|
item: IItem | null;
|
|
382
|
+
containerType?: ItemContainerType | null;
|
|
521
383
|
isSelectingShortcut?: boolean;
|
|
522
384
|
}
|
|
523
385
|
|
|
@@ -525,9 +387,10 @@ const Container = styled.div<ContainerTypes>`
|
|
|
525
387
|
margin: 0.1rem;
|
|
526
388
|
|
|
527
389
|
.react-draggable-dragging {
|
|
528
|
-
|
|
390
|
+
display: none;
|
|
529
391
|
}
|
|
530
|
-
|
|
392
|
+
|
|
393
|
+
|
|
531
394
|
.sprite-from-atlas-img--item {
|
|
532
395
|
position: relative;
|
|
533
396
|
top: 1.5rem;
|
|
@@ -568,33 +431,9 @@ const Container = styled.div<ContainerTypes>`
|
|
|
568
431
|
`;
|
|
569
432
|
|
|
570
433
|
const ItemContainer = styled.div<{ isFocused?: boolean }>`
|
|
571
|
-
width:
|
|
572
|
-
height:
|
|
434
|
+
width: 64px;
|
|
435
|
+
height: 64px;
|
|
436
|
+
// This fixes an issue where if you drag an item inside of a scrollable container (overflow), its cut out
|
|
573
437
|
position: relative;
|
|
574
|
-
|
|
575
|
-
${props => props.isFocused && 'z-index: 100; pointer-events: none;'}
|
|
576
|
-
`;
|
|
577
|
-
|
|
578
|
-
const ItemQtyContainer = styled.div`
|
|
579
|
-
position: relative;
|
|
580
|
-
width: 85%;
|
|
581
|
-
height: 16px;
|
|
582
|
-
top: 25px;
|
|
583
|
-
left: 2px;
|
|
584
|
-
pointer-events: none;
|
|
585
|
-
|
|
586
|
-
display: flex;
|
|
587
|
-
justify-content: flex-end;
|
|
588
|
-
`;
|
|
589
|
-
|
|
590
|
-
const ItemQty = styled.span`
|
|
591
|
-
&.regular {
|
|
592
|
-
font-size: ${uiFonts.size.small};
|
|
593
|
-
}
|
|
594
|
-
&.small {
|
|
595
|
-
font-size: ${uiFonts.size.xsmall};
|
|
596
|
-
}
|
|
597
|
-
&.xsmall {
|
|
598
|
-
font-size: ${uiFonts.size.xxsmall};
|
|
599
|
-
}
|
|
438
|
+
${props => props.isFocused && 'z-index: 100; pointer-events: none;'};
|
|
600
439
|
`;
|