minecraft-inventory 0.1.24 → 0.1.25
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/README.md
CHANGED
|
@@ -9,7 +9,7 @@ A flexible, scalable React library for rendering Minecraft inventory GUIs. Desig
|
|
|
9
9
|
- `<img>`-rendered item textures with automatic `items/` → `blocks/` fallback (via PrismarineJS asset mirror by default)
|
|
10
10
|
- Tooltips that follow the cursor, matching the original Minecraft style
|
|
11
11
|
- Full keyboard support: number keys (1-9) to swap hotbar, Q to drop, double-click to collect, scroll wheel to pick/place
|
|
12
|
-
- Mobile support: tap
|
|
12
|
+
- Mobile support: tap-to-focus inventory interactions plus long-press slot actions (pick half / custom amount / drop one / drop all)
|
|
13
13
|
- Optional JEI (item browser) panel on the left or right
|
|
14
14
|
- Bot connector layer — plugs into a mineflayer bot or any custom server connection
|
|
15
15
|
- Demo connector with action logging for local development
|
|
@@ -414,13 +414,13 @@ const myConnector: InventoryConnector = {
|
|
|
414
414
|
|
|
415
415
|
## Mobile Support
|
|
416
416
|
|
|
417
|
-
On touch devices, tapping a slot with no held item opens a context menu
|
|
417
|
+
On touch devices, tapping a slot uses the mobile focus/swap flow. Long-pressing a populated slot with no held item opens a context menu. The menu appears to the side in landscape or below in portrait.
|
|
418
418
|
|
|
419
419
|
Context menu options:
|
|
420
|
-
- **
|
|
421
|
-
- **
|
|
422
|
-
- **
|
|
423
|
-
- **Drop** — drops the stack from the slot
|
|
420
|
+
- **Pick Half** — picks up half and highlights the selected slot
|
|
421
|
+
- **Pick Amount…** — `window.prompt` to enter a custom quantity, remembering the last value entered
|
|
422
|
+
- **Drop One** — drops a single item from the slot (same as `Q`)
|
|
423
|
+
- **Drop All** — drops the full stack from the slot (same as `Ctrl+Q`)
|
|
424
424
|
- **Cancel**
|
|
425
425
|
|
|
426
426
|
When you have a held item, tapping a slot places/transfers it (same as left-click on desktop).
|
package/package.json
CHANGED
|
@@ -54,6 +54,8 @@ export function Slot({
|
|
|
54
54
|
setPKeyActive,
|
|
55
55
|
focusedSlot,
|
|
56
56
|
setFocusedSlot,
|
|
57
|
+
mobilePickAmount,
|
|
58
|
+
setMobilePickAmount,
|
|
57
59
|
dragEndedRef,
|
|
58
60
|
noPlaceholders,
|
|
59
61
|
} = useInventoryContext()
|
|
@@ -331,6 +333,7 @@ export function Slot({
|
|
|
331
333
|
|
|
332
334
|
if (heldItem) {
|
|
333
335
|
// When holding an item, place it (standard behavior, no focus needed)
|
|
336
|
+
if (focusedSlot !== null) setFocusedSlot(null)
|
|
334
337
|
sendAction({ type: 'click', slotIndex: index, button: 'left', mode: 'normal' })
|
|
335
338
|
return
|
|
336
339
|
}
|
|
@@ -351,28 +354,25 @@ export function Slot({
|
|
|
351
354
|
[isMobile, disabled, heldItem, sendAction, index, pKeyActive, setPKeyActive, focusedSlot, setFocusedSlot, onClickOverride, cancelLongPress, mobileMenuOpen],
|
|
352
355
|
)
|
|
353
356
|
|
|
354
|
-
const handleMobilePickAll = useCallback(() => {
|
|
355
|
-
setMobileMenuOpen(false)
|
|
356
|
-
setShowTooltip(false)
|
|
357
|
-
sendAction({ type: 'click', slotIndex: index, button: 'left', mode: 'normal' })
|
|
358
|
-
}, [sendAction, index])
|
|
359
|
-
|
|
360
357
|
const handleMobilePickHalf = useCallback(() => {
|
|
361
358
|
setMobileMenuOpen(false)
|
|
362
359
|
setShowTooltip(false)
|
|
360
|
+
setFocusedSlot(index)
|
|
363
361
|
sendAction({ type: 'click', slotIndex: index, button: 'right', mode: 'normal' })
|
|
364
|
-
}, [sendAction, index])
|
|
362
|
+
}, [sendAction, index, setFocusedSlot])
|
|
365
363
|
|
|
366
364
|
const handleMobilePickCustom = useCallback(() => {
|
|
367
365
|
if (!item) return
|
|
368
|
-
const input = window.prompt(`Pick amount (max ${item.count}):`, String(
|
|
366
|
+
const input = window.prompt(`Pick amount (max ${item.count}):`, String(mobilePickAmount))
|
|
369
367
|
const amount = parseInt(input ?? '', 10)
|
|
370
368
|
if (isNaN(amount) || amount <= 0) return
|
|
369
|
+
setMobilePickAmount(amount)
|
|
371
370
|
setMobileMenuOpen(false)
|
|
372
371
|
setShowTooltip(false)
|
|
372
|
+
setFocusedSlot(index)
|
|
373
373
|
const take = Math.min(amount, item.count)
|
|
374
374
|
if (take >= item.count) {
|
|
375
|
-
//
|
|
375
|
+
// Pick all: just left-click
|
|
376
376
|
sendAction({ type: 'click', slotIndex: index, button: 'left', mode: 'normal' })
|
|
377
377
|
} else {
|
|
378
378
|
// Pick up all, then put back (count - take) items one-by-one via right-click
|
|
@@ -381,13 +381,21 @@ export function Slot({
|
|
|
381
381
|
sendAction({ type: 'click', slotIndex: index, button: 'right', mode: 'normal' })
|
|
382
382
|
}
|
|
383
383
|
}
|
|
384
|
-
}, [item, sendAction, index])
|
|
384
|
+
}, [item, mobilePickAmount, sendAction, index, setFocusedSlot, setMobilePickAmount])
|
|
385
|
+
|
|
386
|
+
const handleMobileDropOne = useCallback(() => {
|
|
387
|
+
setMobileMenuOpen(false)
|
|
388
|
+
setShowTooltip(false)
|
|
389
|
+
setFocusedSlot(null)
|
|
390
|
+
sendAction({ type: 'drop', slotIndex: index, all: false })
|
|
391
|
+
}, [sendAction, index, setFocusedSlot])
|
|
385
392
|
|
|
386
|
-
const
|
|
393
|
+
const handleMobileDropAll = useCallback(() => {
|
|
387
394
|
setMobileMenuOpen(false)
|
|
388
395
|
setShowTooltip(false)
|
|
396
|
+
setFocusedSlot(null)
|
|
389
397
|
sendAction({ type: 'drop', slotIndex: index, all: true })
|
|
390
|
-
}, [sendAction, index])
|
|
398
|
+
}, [sendAction, index, setFocusedSlot])
|
|
391
399
|
|
|
392
400
|
const closeMobileMenu = useCallback(() => {
|
|
393
401
|
setMobileMenuOpen(false)
|
|
@@ -532,10 +540,10 @@ export function Slot({
|
|
|
532
540
|
item={item}
|
|
533
541
|
x={mobileTouchPos.x}
|
|
534
542
|
y={mobileTouchPos.y}
|
|
535
|
-
onPickAll={handleMobilePickAll}
|
|
536
543
|
onPickHalf={handleMobilePickHalf}
|
|
537
544
|
onPickCustom={handleMobilePickCustom}
|
|
538
|
-
|
|
545
|
+
onDropOne={handleMobileDropOne}
|
|
546
|
+
onDropAll={handleMobileDropAll}
|
|
539
547
|
onClose={closeMobileMenu}
|
|
540
548
|
/>
|
|
541
549
|
</>
|
|
@@ -548,14 +556,14 @@ interface MobileSlotMenuProps {
|
|
|
548
556
|
item: ItemStack
|
|
549
557
|
x: number
|
|
550
558
|
y: number
|
|
551
|
-
onPickAll(): void
|
|
552
559
|
onPickHalf(): void
|
|
553
560
|
onPickCustom(): void
|
|
554
|
-
|
|
561
|
+
onDropOne(): void
|
|
562
|
+
onDropAll(): void
|
|
555
563
|
onClose(): void
|
|
556
564
|
}
|
|
557
565
|
|
|
558
|
-
function MobileSlotMenu({ item, x, y,
|
|
566
|
+
function MobileSlotMenu({ item, x, y, onPickHalf, onPickCustom, onDropOne, onDropAll, onClose }: MobileSlotMenuProps) {
|
|
559
567
|
const { scale } = useScale()
|
|
560
568
|
const menuRef = useRef<HTMLDivElement>(null)
|
|
561
569
|
const [pos, setPos] = useState({ left: x, top: y })
|
|
@@ -600,10 +608,10 @@ function MobileSlotMenu({ item, x, y, onPickAll, onPickHalf, onPickCustom, onDro
|
|
|
600
608
|
<div className={styles.mobileMenuTitle}>
|
|
601
609
|
{item.displayName ?? item.name ?? `Item #${item.type}`} ×{item.count}
|
|
602
610
|
</div>
|
|
603
|
-
<button className={styles.mobileBtn} {...touchBtn(
|
|
604
|
-
<button className={styles.mobileBtn} {...touchBtn(
|
|
605
|
-
<button className={styles.mobileBtn} {...touchBtn(
|
|
606
|
-
<button className={[styles.mobileBtn, styles.mobileBtnDanger].join(' ')} {...touchBtn(
|
|
611
|
+
<button className={styles.mobileBtn} {...touchBtn(onPickHalf)}>Pick Half ({Math.ceil(item.count / 2)})</button>
|
|
612
|
+
<button className={styles.mobileBtn} {...touchBtn(onPickCustom)}>Pick Amount…</button>
|
|
613
|
+
<button className={[styles.mobileBtn, styles.mobileBtnDanger].join(' ')} {...touchBtn(onDropOne)}>Drop One</button>
|
|
614
|
+
<button className={[styles.mobileBtn, styles.mobileBtnDanger].join(' ')} {...touchBtn(onDropAll)}>Drop All</button>
|
|
607
615
|
<button className={styles.mobileBtn} {...touchBtn(onClose)}>Cancel</button>
|
|
608
616
|
</div>
|
|
609
617
|
)
|
|
@@ -44,6 +44,9 @@ export interface InventoryContextValue {
|
|
|
44
44
|
/** Pending first digit for P-key slot number entry */
|
|
45
45
|
pKeyDigit: string
|
|
46
46
|
setPKeyDigit: (d: string) => void
|
|
47
|
+
/** Last amount entered in the mobile pick-amount prompt */
|
|
48
|
+
mobilePickAmount: number
|
|
49
|
+
setMobilePickAmount: (amount: number) => void
|
|
47
50
|
/** Ref set to true when a drag just ended; cleared on next mouseDown.
|
|
48
51
|
* Used by Slot to suppress spurious click events that fire after endDrag. */
|
|
49
52
|
dragEndedRef: React.MutableRefObject<boolean>
|
|
@@ -90,6 +93,7 @@ export function InventoryProvider({ connector, children, noDragSpread = false, n
|
|
|
90
93
|
const [pKeyActive, setPKeyActive] = useState(false)
|
|
91
94
|
const [focusedSlot, setFocusedSlot] = useState<number | null>(null)
|
|
92
95
|
const [pKeyDigit, setPKeyDigit] = useState('')
|
|
96
|
+
const [mobilePickAmount, setMobilePickAmount] = useState(1)
|
|
93
97
|
|
|
94
98
|
const connectorRef = useRef(connector)
|
|
95
99
|
connectorRef.current = connector
|
|
@@ -320,6 +324,8 @@ export function InventoryProvider({ connector, children, noDragSpread = false, n
|
|
|
320
324
|
setFocusedSlot,
|
|
321
325
|
pKeyDigit,
|
|
322
326
|
setPKeyDigit,
|
|
327
|
+
mobilePickAmount,
|
|
328
|
+
setMobilePickAmount,
|
|
323
329
|
dragEndedRef,
|
|
324
330
|
resolveEnchantmentName,
|
|
325
331
|
}
|