@rpg-engine/long-bow 0.7.51 → 0.7.53

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rpg-engine/long-bow",
3
- "version": "0.7.51",
3
+ "version": "0.7.53",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.js",
6
6
  "typings": "dist/index.d.ts",
@@ -142,6 +142,12 @@ export const ItemSlot = React.memo(
142
142
  const [contextActions, setContextActions] = useState<IContextMenuItem[]>(
143
143
  []
144
144
  );
145
+ const [touchStartTime, setTouchStartTime] = useState<number | null>(null);
146
+ const [
147
+ touchStartPosition,
148
+ setTouchStartPosition,
149
+ ] = useState<IPosition | null>(null);
150
+ const [isDragging, setIsDragging] = useState<boolean>(false); // New state to track dragging
145
151
 
146
152
  useEffect(() => {
147
153
  setDragState(prev => ({
@@ -180,8 +186,13 @@ export const ItemSlot = React.memo(
180
186
  }, [dragContainer]);
181
187
 
182
188
  const resetItem = () => {
183
- setTooltipState(prev => ({ ...prev, visible: false }));
189
+ setTooltipState(prev => ({
190
+ ...prev,
191
+ visible: false,
192
+ mobileVisible: false,
193
+ }));
184
194
  setDragState(prev => ({ ...prev, wasDragged: false }));
195
+ setIsDragging(false); // Reset dragging flag
185
196
  };
186
197
 
187
198
  const onSuccessfulDrag = (quantity?: number) => {
@@ -211,12 +222,40 @@ export const ItemSlot = React.memo(
211
222
  }
212
223
  }
213
224
 
214
- // remove the class react-draggable-dragging from the element
225
+ // Remove the class react-draggable-dragging from the element
215
226
  // to prevent the item from being dragged again
216
227
  target.classList.remove('react-draggable-dragging');
217
228
 
218
229
  const isTouch = e.type.startsWith('touch');
219
230
 
231
+ if (isTouch) {
232
+ const touchEvent = e as TouchEvent;
233
+ const touch = touchEvent.changedTouches[0];
234
+ const touchEndTime = new Date().getTime();
235
+ const touchDuration = touchStartTime
236
+ ? touchEndTime - touchStartTime
237
+ : 0;
238
+
239
+ // Check if it's a short tap (less than 200ms) and hasn't moved much
240
+ const isShortTap = touchDuration < 200;
241
+ const hasMovedSignificantly =
242
+ touchStartPosition &&
243
+ (Math.abs(touch.clientX - touchStartPosition.x) > 10 ||
244
+ Math.abs(touch.clientY - touchStartPosition.y) > 10);
245
+
246
+ if (isShortTap && !hasMovedSignificantly) {
247
+ // Handle as a tap/click
248
+ if (item) {
249
+ setTooltipState(prev => ({
250
+ ...prev,
251
+ mobileVisible: true,
252
+ }));
253
+ onPointerDown(item.type, containerType ?? null, item);
254
+ }
255
+ return;
256
+ }
257
+ }
258
+
220
259
  // Threshold for considering a tap/click as a drag
221
260
  const dragThreshold = 5; // pixels
222
261
  const isDrag =
@@ -274,16 +313,22 @@ export const ItemSlot = React.memo(
274
313
  }
275
314
  }, 50);
276
315
  } else if (item) {
277
- if (isTouch && !isDrag) {
316
+ if (isTouch && isDragging) {
317
+ // If it's a touch and we were dragging, do not show context menu
318
+ return;
319
+ } else if (isTouch && !isDrag) {
320
+ // Handle as a tap/click
278
321
  setTooltipState(prev => ({
279
322
  ...prev,
280
323
  mobileVisible: true,
281
324
  }));
325
+ onPointerDown(item.type, containerType ?? null, item);
282
326
  } else if (
283
327
  !isTouch &&
284
328
  !isContextMenuDisabled &&
285
329
  !isSelectingShortcut
286
330
  ) {
331
+ // Handle as context menu for mouse devices
287
332
  setContextMenuState(prev => ({
288
333
  ...prev,
289
334
  visible: !contextMenuState.visible,
@@ -302,7 +347,7 @@ export const ItemSlot = React.memo(
302
347
  }
303
348
  }
304
349
 
305
- if (!isDrag || !isTouch) {
350
+ if (!isDrag && !isTouch) {
306
351
  console.log('Calling onPointerDown');
307
352
  onPointerDown(item.type, containerType ?? null, item);
308
353
  }
@@ -320,6 +365,8 @@ export const ItemSlot = React.memo(
320
365
  if (onDragStart && containerType) {
321
366
  onDragStart(item, slotIndex, containerType);
322
367
  }
368
+
369
+ setIsDragging(true); // Set dragging flag on start
323
370
  };
324
371
 
325
372
  const onDraggableProgress: DraggableEventHandler = (_e, data) => {
@@ -339,6 +386,58 @@ export const ItemSlot = React.memo(
339
386
  }
340
387
  };
341
388
 
389
+ const onTouchStartHandler = (e: React.TouchEvent) => {
390
+ setTouchStartTime(new Date().getTime());
391
+ setTouchStartPosition({
392
+ x: e.touches[0].clientX,
393
+ y: e.touches[0].clientY,
394
+ });
395
+ };
396
+
397
+ const onTouchEndHandler = (e: React.TouchEvent) => {
398
+ // Only prevent default if not dragging
399
+ if (!isDragging) {
400
+ e.preventDefault();
401
+ }
402
+
403
+ const touch = e.changedTouches[0];
404
+ const touchEndTime = new Date().getTime();
405
+ const touchDuration = touchStartTime
406
+ ? touchEndTime - touchStartTime
407
+ : 0;
408
+
409
+ // Check if it's a short tap (less than 200ms) and hasn't moved much
410
+ const isShortTap = touchDuration < 200;
411
+ const hasMovedSignificantly =
412
+ touchStartPosition &&
413
+ (Math.abs(touch.clientX - touchStartPosition.x) > 10 ||
414
+ Math.abs(touch.clientY - touchStartPosition.y) > 10);
415
+
416
+ if (isShortTap && !hasMovedSignificantly) {
417
+ // Handle as a tap/click
418
+ if (item) {
419
+ setTooltipState(prev => ({
420
+ ...prev,
421
+ mobileVisible: true,
422
+ }));
423
+ onPointerDown(item.type, containerType ?? null, item);
424
+ }
425
+ } else {
426
+ // Handle as a drag end
427
+ const simulatedEvent = new MouseEvent('mouseup', {
428
+ clientX: touch.clientX,
429
+ clientY: touch.clientY,
430
+ bubbles: true,
431
+ });
432
+
433
+ document
434
+ .elementFromPoint(touch.clientX, touch.clientY)
435
+ ?.dispatchEvent(simulatedEvent);
436
+ }
437
+
438
+ setIsDragging(false); // Reset dragging flag on touch end
439
+ };
440
+
342
441
  const bounds = getContainerBounds();
343
442
  return (
344
443
  <Container
@@ -351,18 +450,6 @@ export const ItemSlot = React.memo(
351
450
  onPlaceDrop(data, slotIndex, containerType);
352
451
  }
353
452
  }}
354
- onTouchEnd={e => {
355
- const { clientX, clientY } = e.changedTouches[0];
356
- const simulatedEvent = new MouseEvent('mouseup', {
357
- clientX,
358
- clientY,
359
- bubbles: true,
360
- });
361
-
362
- document
363
- .elementFromPoint(clientX, clientY)
364
- ?.dispatchEvent(simulatedEvent);
365
- }}
366
453
  onPointerDown={
367
454
  onDragStart !== undefined && onDragEnd !== undefined
368
455
  ? undefined
@@ -377,6 +464,8 @@ export const ItemSlot = React.memo(
377
464
  item?.type === ItemType.Tool ||
378
465
  item?.subType === ItemSubType.Seed)
379
466
  }
467
+ onTouchStart={onTouchStartHandler}
468
+ onTouchEnd={onTouchEndHandler}
380
469
  >
381
470
  <Draggable
382
471
  axis={isSelectingShortcut ? 'none' : 'both'}
@@ -506,5 +595,6 @@ const ItemContainer = styled.div<{ isFocused?: boolean }>`
506
595
  height: 64px;
507
596
 
508
597
  position: relative;
509
- ${props => props.isFocused && 'z-index: 100; pointer-events: none;'};
598
+ ${({ isFocused }) =>
599
+ isFocused ? 'z-index: 100; pointer-events: none;' : ''};
510
600
  `;