@rpg-engine/long-bow 0.2.86 → 0.2.87

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.
Files changed (35) hide show
  1. package/dist/components/Abstractions/SlotsContainer.d.ts +1 -0
  2. package/dist/components/DraggableContainer.d.ts +1 -0
  3. package/dist/components/Equipment/EquipmentSet.d.ts +4 -0
  4. package/dist/components/Input.d.ts +1 -0
  5. package/dist/components/Item/Inventory/ItemContainer.d.ts +8 -0
  6. package/dist/components/Item/Inventory/ItemQuantitySelector.d.ts +7 -0
  7. package/dist/components/Item/Inventory/ItemSlot.d.ts +5 -0
  8. package/dist/components/RangeSlider.d.ts +1 -0
  9. package/dist/long-bow.cjs.development.js +362 -77
  10. package/dist/long-bow.cjs.development.js.map +1 -1
  11. package/dist/long-bow.cjs.production.min.js +1 -1
  12. package/dist/long-bow.cjs.production.min.js.map +1 -1
  13. package/dist/long-bow.esm.js +363 -78
  14. package/dist/long-bow.esm.js.map +1 -1
  15. package/dist/stories/ItemQuantitySelector.stories.d.ts +5 -0
  16. package/package.json +1 -1
  17. package/src/components/Abstractions/SlotsContainer.tsx +3 -0
  18. package/src/components/DraggableContainer.tsx +3 -0
  19. package/src/components/Equipment/EquipmentSet.tsx +30 -0
  20. package/src/components/Input.tsx +6 -2
  21. package/src/components/Item/Inventory/ItemContainer.tsx +92 -6
  22. package/src/components/Item/Inventory/ItemQuantitySelector.tsx +137 -0
  23. package/src/components/Item/Inventory/ItemSlot.tsx +144 -25
  24. package/src/components/ListMenu.tsx +1 -2
  25. package/src/components/RangeSlider.tsx +37 -14
  26. package/src/mocks/itemContainer.mocks.ts +1 -1
  27. package/src/stories/EquipmentSet.stories.tsx +4 -0
  28. package/src/stories/ItemContainer.stories.tsx +82 -15
  29. package/src/stories/ItemQuantitySelector.stories.tsx +26 -0
  30. package/src/stories/RangeSlider.stories.tsx +10 -9
  31. package/src/.DS_Store +0 -0
  32. package/src/components/NPCDialog/.DS_Store +0 -0
  33. package/src/components/NPCDialog/img/.DS_Store +0 -0
  34. package/src/mocks/.DS_Store +0 -0
  35. package/src/mocks/atlas/.DS_Store +0 -0
@@ -0,0 +1,5 @@
1
+ import { Meta } from '@storybook/react';
2
+ import { IItemQuantitySelectorProps } from '../components/Item/Inventory/ItemQuantitySelector';
3
+ declare const meta: Meta;
4
+ export default meta;
5
+ export declare const Default: import("@storybook/csf").AnnotatedStoryFn<import("@storybook/react").ReactFramework, IItemQuantitySelectorProps>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rpg-engine/long-bow",
3
- "version": "0.2.86",
3
+ "version": "0.2.87",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.js",
6
6
  "typings": "dist/index.d.ts",
@@ -9,6 +9,7 @@ interface IProps {
9
9
  onClose?: () => void;
10
10
  onPositionChange?: (position: IPosition) => void;
11
11
  onOutsideClick?: () => void;
12
+ initialPosition?: IPosition;
12
13
  }
13
14
 
14
15
  export const SlotsContainer: React.FC<IProps> = ({
@@ -17,6 +18,7 @@ export const SlotsContainer: React.FC<IProps> = ({
17
18
  onClose,
18
19
  onPositionChange,
19
20
  onOutsideClick,
21
+ initialPosition,
20
22
  }) => {
21
23
  return (
22
24
  <DraggableContainer
@@ -35,6 +37,7 @@ export const SlotsContainer: React.FC<IProps> = ({
35
37
  }
36
38
  }}
37
39
  onOutsideClick={onOutsideClick}
40
+ initialPosition={initialPosition}
38
41
  >
39
42
  {children}
40
43
  </DraggableContainer>
@@ -19,6 +19,7 @@ export interface IDraggableContainerProps {
19
19
  cancelDrag?: string;
20
20
  onPositionChange?: (position: IPosition) => void;
21
21
  onOutsideClick?: () => void;
22
+ initialPosition?: IPosition;
22
23
  }
23
24
 
24
25
  export const DraggableContainer: React.FC<IDraggableContainerProps> = ({
@@ -34,6 +35,7 @@ export const DraggableContainer: React.FC<IDraggableContainerProps> = ({
34
35
  cancelDrag,
35
36
  onPositionChange,
36
37
  onOutsideClick,
38
+ initialPosition = { x: 0, y: 0 },
37
39
  }) => {
38
40
  const draggableRef = useRef(null);
39
41
 
@@ -66,6 +68,7 @@ export const DraggableContainer: React.FC<IDraggableContainerProps> = ({
66
68
  });
67
69
  }
68
70
  }}
71
+ defaultPosition={initialPosition}
69
72
  >
70
73
  <Container
71
74
  ref={draggableRef}
@@ -20,6 +20,18 @@ export interface IEquipmentSetProps {
20
20
  item: IItem,
21
21
  itemContainerType: ItemContainerType | null
22
22
  ) => void;
23
+ onItemDragStart?: (
24
+ item: IItem,
25
+ slotIndex: number,
26
+ itemContainerType: ItemContainerType | null
27
+ ) => void;
28
+ onItemDragEnd?: (quantity?: number) => void;
29
+ onItemPlaceDrop?: (
30
+ item: IItem | null,
31
+ slotIndex: number,
32
+ itemContainerType: ItemContainerType | null
33
+ ) => void;
34
+ checkIfItemCanBeMoved: () => boolean;
23
35
  onMouseOver?: (e: any, slotIndex: number, item: IItem | null) => void;
24
36
  onSelected?: (optionId: string) => void;
25
37
  initialPosition?: { x: number; y: number };
@@ -36,6 +48,10 @@ export const EquipmentSet: React.FC<IEquipmentSetProps> = ({
36
48
  onItemClick,
37
49
  atlasIMG,
38
50
  atlasJSON,
51
+ onItemDragEnd,
52
+ onItemDragStart,
53
+ onItemPlaceDrop,
54
+ checkIfItemCanBeMoved,
39
55
  }) => {
40
56
  const {
41
57
  neck,
@@ -102,6 +118,18 @@ export const EquipmentSet: React.FC<IEquipmentSetProps> = ({
102
118
  onSelected={(optionId: string) => {
103
119
  if (onSelected) onSelected(optionId);
104
120
  }}
121
+ onDragStart={(item, slotIndex, itemContainerType) => {
122
+ if (onItemDragStart)
123
+ onItemDragStart(item, slotIndex, itemContainerType);
124
+ }}
125
+ onDragEnd={quantity => {
126
+ if (onItemDragEnd) onItemDragEnd(quantity);
127
+ }}
128
+ checkIfItemCanBeMoved={checkIfItemCanBeMoved}
129
+ onPlaceDrop={(item, slotIndex, itemContainerType) => {
130
+ if (onItemPlaceDrop)
131
+ onItemPlaceDrop(item, slotIndex, itemContainerType);
132
+ }}
105
133
  atlasIMG={atlasIMG}
106
134
  atlasJSON={atlasJSON}
107
135
  />
@@ -134,6 +162,7 @@ const EquipmentSetContainer = styled.div`
134
162
  justify-content: center;
135
163
  flex-wrap: wrap;
136
164
  flex-direction: row;
165
+ touch-action: none;
137
166
  `;
138
167
 
139
168
  const EquipmentColumn = styled.div`
@@ -141,4 +170,5 @@ const EquipmentColumn = styled.div`
141
170
  justify-content: center;
142
171
  flex-wrap: wrap;
143
172
  flex-direction: column;
173
+ touch-action: none;
144
174
  `;
@@ -4,8 +4,12 @@ export interface IInputProps
4
4
  extends React.DetailedHTMLProps<
5
5
  React.InputHTMLAttributes<HTMLInputElement>,
6
6
  HTMLInputElement
7
- > {}
7
+ > {
8
+ innerRef?: React.Ref<HTMLInputElement>;
9
+ }
8
10
 
9
11
  export const Input: React.FC<IInputProps> = ({ ...props }) => {
10
- return <input {...props} />;
12
+ const { innerRef, ...rest } = props;
13
+
14
+ return <input {...rest} ref={props.innerRef} />;
11
15
  };
@@ -1,7 +1,8 @@
1
1
  import { IItem, IItemContainer, ItemContainerType } from '@rpg-engine/shared';
2
- import React from 'react';
2
+ import React, { useState } from 'react';
3
3
  import styled from 'styled-components';
4
4
  import { SlotsContainer } from '../../Abstractions/SlotsContainer';
5
+ import { ItemQuantitySelector } from './ItemQuantitySelector';
5
6
 
6
7
  import { ItemSlot } from './ItemSlot';
7
8
 
@@ -13,12 +14,25 @@ export interface IItemContainerProps {
13
14
  ItemType: IItem['type'],
14
15
  itemContainerType: ItemContainerType | null
15
16
  ) => void;
17
+ onItemDragStart?: (
18
+ item: IItem,
19
+ slotIndex: number,
20
+ itemContainerType: ItemContainerType | null
21
+ ) => void;
22
+ onItemDragEnd?: (quantity?: number) => void;
23
+ onItemPlaceDrop?: (
24
+ item: IItem | null,
25
+ slotIndex: number,
26
+ itemContainerType: ItemContainerType | null
27
+ ) => void;
28
+ checkIfItemCanBeMoved: () => boolean;
16
29
  onMouseOver?: (e: any, slotIndex: number, item: IItem | null) => void;
17
30
  onSelected?: (optionId: string, item: IItem) => void;
18
31
  type: ItemContainerType;
19
32
  atlasJSON: any;
20
33
  atlasIMG: any;
21
34
  disableContextMenu?: boolean;
35
+ initialPosition?: { x: number; y: number };
22
36
  }
23
37
 
24
38
  export const ItemContainer: React.FC<IItemContainerProps> = ({
@@ -31,7 +45,18 @@ export const ItemContainer: React.FC<IItemContainerProps> = ({
31
45
  atlasJSON,
32
46
  atlasIMG,
33
47
  disableContextMenu = false,
48
+ onItemDragEnd,
49
+ onItemDragStart,
50
+ onItemPlaceDrop,
51
+ checkIfItemCanBeMoved,
52
+ initialPosition,
34
53
  }) => {
54
+ const [quantitySelect, setQuantitySelect] = useState({
55
+ isOpen: false,
56
+ maxQuantity: 1,
57
+ callback: (_quantity: number) => {},
58
+ });
59
+
35
60
  const onRenderSlots = () => {
36
61
  const slots = [];
37
62
 
@@ -52,6 +77,25 @@ export const ItemContainer: React.FC<IItemContainerProps> = ({
52
77
  onSelected={(optionId: string, item: IItem) => {
53
78
  if (onSelected) onSelected(optionId, item);
54
79
  }}
80
+ onDragStart={(item, slotIndex, itemContainerType) => {
81
+ if (onItemDragStart)
82
+ onItemDragStart(item, slotIndex, itemContainerType);
83
+ }}
84
+ onDragEnd={quantity => {
85
+ if (onItemDragEnd) onItemDragEnd(quantity);
86
+ }}
87
+ checkIfItemCanBeMoved={checkIfItemCanBeMoved}
88
+ openQuantitySelector={(maxQuantity, callback) => {
89
+ setQuantitySelect({
90
+ isOpen: true,
91
+ maxQuantity,
92
+ callback,
93
+ });
94
+ }}
95
+ onPlaceDrop={(item, slotIndex, itemContainerType) => {
96
+ if (onItemPlaceDrop)
97
+ onItemPlaceDrop(item, slotIndex, itemContainerType);
98
+ }}
55
99
  atlasIMG={atlasIMG}
56
100
  atlasJSON={atlasJSON}
57
101
  />
@@ -61,11 +105,40 @@ export const ItemContainer: React.FC<IItemContainerProps> = ({
61
105
  };
62
106
 
63
107
  return (
64
- <SlotsContainer title={itemContainer.name || 'Container'} onClose={onClose}>
65
- <ItemsContainer className="item-container-body">
66
- {onRenderSlots()}
67
- </ItemsContainer>
68
- </SlotsContainer>
108
+ <>
109
+ <SlotsContainer
110
+ title={itemContainer.name || 'Container'}
111
+ onClose={onClose}
112
+ initialPosition={initialPosition}
113
+ >
114
+ <ItemsContainer className="item-container-body">
115
+ {onRenderSlots()}
116
+ </ItemsContainer>
117
+ </SlotsContainer>
118
+ {quantitySelect.isOpen && (
119
+ <QuantitySelectorContainer>
120
+ <ItemQuantitySelector
121
+ quantity={quantitySelect.maxQuantity}
122
+ onConfirm={quantity => {
123
+ quantitySelect.callback(quantity);
124
+ setQuantitySelect({
125
+ isOpen: false,
126
+ maxQuantity: 1,
127
+ callback: () => {},
128
+ });
129
+ }}
130
+ onClose={() => {
131
+ quantitySelect.callback(-1);
132
+ setQuantitySelect({
133
+ isOpen: false,
134
+ maxQuantity: 1,
135
+ callback: () => {},
136
+ });
137
+ }}
138
+ />
139
+ </QuantitySelectorContainer>
140
+ )}
141
+ </>
69
142
  );
70
143
  };
71
144
 
@@ -75,3 +148,16 @@ const ItemsContainer = styled.div`
75
148
  justify-content: center;
76
149
  flex-wrap: wrap;
77
150
  `;
151
+
152
+ const QuantitySelectorContainer = styled.div`
153
+ position: absolute;
154
+ top: 0;
155
+ left: 0;
156
+ width: 100vw;
157
+ height: 100vh;
158
+ z-index: 100;
159
+ display: flex;
160
+ justify-content: center;
161
+ align-items: center;
162
+ background-color: rgba(0, 0, 0, 0.5);
163
+ `;
@@ -0,0 +1,137 @@
1
+ import React, { useEffect, useRef, useState } from 'react';
2
+ import styled from 'styled-components';
3
+ import { Button, ButtonTypes } from '../../Button';
4
+ import { Input } from '../../Input';
5
+ import { RangeSlider, RangeSliderType } from '../../RangeSlider';
6
+ import { RPGUIContainer, RPGUIContainerTypes } from '../../RPGUIContainer';
7
+
8
+ export interface IItemQuantitySelectorProps {
9
+ quantity: number;
10
+ onConfirm: (quantity: number) => void;
11
+ onClose: () => void;
12
+ }
13
+
14
+ export const ItemQuantitySelector: React.FC<IItemQuantitySelectorProps> = ({
15
+ quantity,
16
+ onConfirm,
17
+ onClose,
18
+ }) => {
19
+ const [value, setValue] = useState(quantity);
20
+
21
+ const inputRef = useRef<HTMLInputElement>(null);
22
+
23
+ useEffect(() => {
24
+ if (inputRef.current) {
25
+ inputRef.current.focus();
26
+ inputRef.current.select();
27
+
28
+ const closeSelector = (e: KeyboardEvent) => {
29
+ if (e.key === 'Escape') {
30
+ onClose();
31
+ }
32
+ };
33
+
34
+ document.addEventListener('keydown', closeSelector);
35
+
36
+ return () => {
37
+ document.removeEventListener('keydown', closeSelector);
38
+ };
39
+ }
40
+
41
+ return () => {};
42
+ }, []);
43
+
44
+ return (
45
+ <StyledContainer type={RPGUIContainerTypes.Framed} width="25rem">
46
+ <CloseButton
47
+ className="container-close"
48
+ onClick={onClose}
49
+ onTouchStart={onClose}
50
+ >
51
+ X
52
+ </CloseButton>
53
+ <h2>Select quantity to move</h2>
54
+ <StyledForm
55
+ style={{ width: '100%' }}
56
+ onSubmit={e => {
57
+ e.preventDefault();
58
+
59
+ const numberValue = Number(value);
60
+
61
+ if (Number.isNaN(numberValue)) {
62
+ return;
63
+ }
64
+
65
+ onConfirm(Math.max(1, Math.min(quantity, numberValue)));
66
+ }}
67
+ noValidate
68
+ >
69
+ <StyledInput
70
+ innerRef={inputRef}
71
+ placeholder="Enter quantity"
72
+ type="number"
73
+ min={1}
74
+ max={quantity}
75
+ value={value}
76
+ onChange={e => {
77
+ setValue((e.target.value as unknown) as number);
78
+ }}
79
+ onBlur={e => {
80
+ const newValue = Math.max(
81
+ 1,
82
+ Math.min(quantity, Number(e.target.value))
83
+ );
84
+
85
+ setValue(newValue);
86
+ }}
87
+ />
88
+ <RangeSlider
89
+ type={RangeSliderType.Slider}
90
+ valueMin={1}
91
+ valueMax={quantity}
92
+ width="100%"
93
+ onChange={setValue}
94
+ value={value}
95
+ />
96
+ <Button buttonType={ButtonTypes.RPGUIButton} type="submit">
97
+ Confirm
98
+ </Button>
99
+ </StyledForm>
100
+ </StyledContainer>
101
+ );
102
+ };
103
+
104
+ const StyledContainer = styled(RPGUIContainer)`
105
+ display: flex;
106
+ flex-direction: column;
107
+ align-items: center;
108
+ `;
109
+
110
+ const StyledForm = styled.form`
111
+ display: flex;
112
+ flex-direction: column;
113
+ align-items: center;
114
+ width: 100%;
115
+ `;
116
+ const StyledInput = styled(Input)`
117
+ text-align: center;
118
+
119
+ &::-webkit-outer-spin-button,
120
+ &::-webkit-inner-spin-button {
121
+ -webkit-appearance: none;
122
+ margin: 0;
123
+ }
124
+
125
+ &[type='number'] {
126
+ -moz-appearance: textfield;
127
+ }
128
+ `;
129
+
130
+ const CloseButton = styled.div`
131
+ position: absolute;
132
+ top: 3px;
133
+ right: 0px;
134
+ color: white;
135
+ z-index: 22;
136
+ font-size: 0.8rem;
137
+ `;
@@ -4,11 +4,12 @@ import {
4
4
  IItemContainer,
5
5
  ItemContainerType,
6
6
  ItemSlotType,
7
- ItemType
7
+ ItemType,
8
8
  } from '@rpg-engine/shared';
9
9
 
10
10
  import { observer } from 'mobx-react-lite';
11
- import React, { useEffect, useState } from 'react';
11
+ import React, { useEffect, useRef, useState } from 'react';
12
+ import Draggable from 'react-draggable';
12
13
  import styled from 'styled-components';
13
14
  import { v4 as uuidv4 } from 'uuid';
14
15
  import { uiFonts } from '../../../constants/uiFonts';
@@ -52,6 +53,19 @@ interface IProps {
52
53
  itemContainerType: ItemContainerType | null,
53
54
  item: IItem
54
55
  ) => void;
56
+ onDragStart: (
57
+ item: IItem,
58
+ slotIndex: number,
59
+ itemContainerType: ItemContainerType | null
60
+ ) => void;
61
+ onDragEnd: (quantity?: number) => void;
62
+ checkIfItemCanBeMoved: () => boolean;
63
+ openQuantitySelector?: (maxQuantity: number, callback: () => void) => void;
64
+ onPlaceDrop: (
65
+ item: IItem | null,
66
+ slotIndex: number,
67
+ itemContainerType: ItemContainerType | null
68
+ ) => void;
55
69
  atlasJSON: any;
56
70
  atlasIMG: any;
57
71
  isContextMenuDisabled?: boolean;
@@ -70,16 +84,28 @@ export const ItemSlot: React.FC<IProps> = observer(
70
84
  atlasJSON,
71
85
  atlasIMG,
72
86
  isContextMenuDisabled = false,
87
+ onDragEnd,
88
+ onDragStart,
89
+ onPlaceDrop,
90
+ checkIfItemCanBeMoved,
91
+ openQuantitySelector,
73
92
  }) => {
74
93
  const [isTooltipVisible, setTooltipVisible] = useState(false);
75
94
 
76
95
  const [isContextMenuVisible, setIsContextMenuVisible] = useState(false);
77
96
 
97
+ const [isFocused, setIsFocused] = useState(false);
98
+ const [wasDragged, setWasDragged] = useState(false);
99
+ const [dragPosition, setDragPosition] = useState({ x: 0, y: 0 });
100
+ const dragContainer = useRef<HTMLDivElement>(null);
101
+
78
102
  const [contextActions, setContextActions] = useState<IContextMenuItem[]>(
79
103
  []
80
104
  );
81
105
 
82
106
  useEffect(() => {
107
+ setDragPosition({ x: 0, y: 0 });
108
+
83
109
  if (item) {
84
110
  setContextActions(generateContextMenu(item, containerType));
85
111
  }
@@ -112,7 +138,7 @@ export const ItemSlot: React.FC<IProps> = observer(
112
138
 
113
139
  const renderItem = (itemToRender: IItem | null) => {
114
140
  const element = [];
115
-
141
+
116
142
  if (itemToRender?.texturePath) {
117
143
  element.push(
118
144
  <ErrorBoundary key={itemToRender._id}>
@@ -150,7 +176,7 @@ export const ItemSlot: React.FC<IProps> = observer(
150
176
  itemToRender.allowedEquipSlotType?.includes(slotSpriteMask!)
151
177
  ) {
152
178
  const element = [];
153
-
179
+
154
180
  element.push(
155
181
  <ErrorBoundary key={itemToRender._id}>
156
182
  <SpriteFromAtlas
@@ -205,29 +231,117 @@ export const ItemSlot: React.FC<IProps> = observer(
205
231
  }
206
232
  };
207
233
 
234
+ const resetItem = () => {
235
+ setTooltipVisible(false);
236
+ setIsFocused(false);
237
+ setWasDragged(false);
238
+ };
239
+
240
+ const onSuccesfulDrag = (quantity?: number) => {
241
+ resetItem();
242
+
243
+ if (quantity === -1) setDragPosition({ x: 0, y: 0 });
244
+ else if (item) {
245
+ onDragEnd(quantity);
246
+ resetItem();
247
+ }
248
+ };
249
+
208
250
  return (
209
251
  <Container
210
252
  className="rpgui-icon empty-slot"
211
- onMouseOver={event =>
212
- onMouseOver(event, slotIndex, item, event.clientX, event.clientY)
213
- }
214
- onMouseOut={() => {
215
- if (onMouseOut) onMouseOut();
253
+ onMouseUp={() => {
254
+ const data = item ? item : null;
255
+ if (onPlaceDrop) onPlaceDrop(data, slotIndex, containerType);
216
256
  }}
217
- onMouseEnter={() => setTooltipVisible(true)}
218
- onMouseLeave={() => setTooltipVisible(false)}
219
- onClick={() => {
220
- setTooltipVisible(false);
221
-
222
- if (item) {
223
- if (!isContextMenuDisabled) {
224
- setIsContextMenuVisible(!isContextMenuVisible);
225
- }
226
-
227
- onClick(item.type, containerType, item);
228
- }
257
+ onTouchEnd={e => {
258
+ const { clientX, clientY } = e.changedTouches[0];
259
+ const simulatedEvent = new MouseEvent('mouseup', {
260
+ clientX,
261
+ clientY,
262
+ bubbles: true,
263
+ });
264
+
265
+ document
266
+ .elementFromPoint(clientX, clientY)
267
+ ?.dispatchEvent(simulatedEvent);
229
268
  }}
230
269
  >
270
+ {item && (
271
+ <Draggable
272
+ onStop={() => {
273
+ if (wasDragged) {
274
+ setWasDragged(false);
275
+
276
+ const target = dragContainer.current;
277
+ if (!target || !wasDragged) return;
278
+
279
+ const style = window.getComputedStyle(target);
280
+ const matrix = new DOMMatrixReadOnly(style.transform);
281
+ const x = matrix.m41;
282
+ const y = matrix.m42;
283
+
284
+ setDragPosition({ x, y });
285
+
286
+ setTimeout(() => {
287
+ if (checkIfItemCanBeMoved()) {
288
+ if (
289
+ item.stackQty &&
290
+ item.stackQty !== 1 &&
291
+ openQuantitySelector
292
+ )
293
+ openQuantitySelector(item.stackQty, onSuccesfulDrag);
294
+ else onSuccesfulDrag(item.stackQty);
295
+ } else {
296
+ resetItem();
297
+ setDragPosition({ x: 0, y: 0 });
298
+ }
299
+ }, 100);
300
+ } else if (item) {
301
+ if (!isContextMenuDisabled)
302
+ setIsContextMenuVisible(!isContextMenuVisible);
303
+
304
+ onClick(item.type, containerType, item);
305
+ }
306
+ }}
307
+ onStart={() => {
308
+ if (onDragStart) onDragStart(item, slotIndex, containerType);
309
+ }}
310
+ onDrag={() => {
311
+ setWasDragged(true);
312
+ setIsFocused(true);
313
+ }}
314
+ position={dragPosition}
315
+ >
316
+ <ItemContainer
317
+ ref={dragContainer}
318
+ isFocused={isFocused}
319
+ onMouseOver={event => {
320
+ onMouseOver(
321
+ event,
322
+ slotIndex,
323
+ item,
324
+ event.clientX,
325
+ event.clientY
326
+ );
327
+ }}
328
+ onMouseOut={() => {
329
+ if (onMouseOut) onMouseOut();
330
+ }}
331
+ onMouseEnter={() => {
332
+ setTooltipVisible(true);
333
+ }}
334
+ onMouseLeave={() => {
335
+ setTooltipVisible(false);
336
+ }}
337
+ >
338
+ {onRenderSlot(item)}
339
+ </ItemContainer>
340
+ </Draggable>
341
+ )}
342
+
343
+ {isTooltipVisible && item && <ItemTooltip label={item.name} />}
344
+
231
345
  {!isContextMenuDisabled && isContextMenuVisible && contextActions && (
232
346
  <RelativeListMenu
233
347
  options={contextActions}
@@ -242,10 +356,6 @@ export const ItemSlot: React.FC<IProps> = observer(
242
356
  }}
243
357
  />
244
358
  )}
245
-
246
- {isTooltipVisible && item && <ItemTooltip label={item.name} />}
247
-
248
- {onRenderSlot(item)}
249
359
  </Container>
250
360
  );
251
361
  }
@@ -261,12 +371,21 @@ const Container = styled.div`
261
371
  position: relative;
262
372
  `;
263
373
 
374
+ const ItemContainer = styled.div<{ isFocused?: boolean }>`
375
+ width: 100%;
376
+ height: 100%;
377
+ position: relative;
378
+
379
+ ${props => props.isFocused && 'z-index: 100; pointer-events: none;'}
380
+ `;
381
+
264
382
  const ItemQtyContainer = styled.div`
265
383
  position: relative;
266
384
  width: 85%;
267
385
  height: 16px;
268
386
  top: 25px;
269
387
  left: 2px;
388
+ pointer-events: none;
270
389
 
271
390
  display: flex;
272
391
  justify-content: flex-end;
@@ -26,8 +26,7 @@ export const ListMenu: React.FC<IListMenuProps> = ({
26
26
  {options.map((params, index) => (
27
27
  <ListElement
28
28
  key={params?.id || index}
29
- onClick={(e: any) => {
30
- e.stopPropagation();
29
+ onClick={() => {
31
30
  onSelected(params?.id);
32
31
  }}
33
32
  >