@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.
@@ -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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rpg-engine/long-bow",
3
- "version": "0.5.28",
3
+ "version": "0.5.30",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.js",
6
6
  "typings": "dist/index.d.ts",
@@ -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, rarityColor } from '../Inventory/ItemSlot';
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={(e, data) => {
198
- setDraggingItem(null);
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
- display: none;
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 = (itemToRender: IItem | null) => {
30
- if (!itemToRender?.texturePath) {
29
+ const renderItem = (item: IItem | null) => {
30
+ if (!item?.texturePath) {
31
31
  return null;
32
32
  }
33
33
 
34
34
  return (
35
- <ErrorBoundary key={itemToRender._id}>
35
+ <ErrorBoundary key={item._id}>
36
36
  <SpriteFromAtlas
37
37
  atlasIMG={atlasIMG}
38
38
  atlasJSON={atlasJSON}
39
39
  spriteKey={getItemTextureKeyPath(
40
40
  {
41
- key: itemToRender.texturePath,
42
- texturePath: itemToRender.texturePath,
43
- stackQty: itemToRender.stackQty || 1,
44
- isStackable: itemToRender.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(itemToRender._id, itemToRender.stackQty ?? 0)}
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/ItemSlot';
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,