minecraft-inventory 0.1.27 → 0.1.28

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": "minecraft-inventory",
3
- "version": "0.1.27",
3
+ "version": "0.1.28",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "release": {
@@ -326,7 +326,7 @@ export function InventoryOverlay({
326
326
  lineHeight: 1,
327
327
  }}
328
328
  >
329
- INV 0.1.27
329
+ INV 0.1.28
330
330
  </a>
331
331
  )}
332
332
 
@@ -1,8 +1,11 @@
1
1
  import React, { useState, useCallback, useRef, useEffect } from 'react'
2
+ import { useFocusInputShortcut } from '../../hooks/useFocusInputShortcut'
2
3
  import { useScale } from '../../context/ScaleContext'
3
4
  import { useTextures } from '../../context/TextureContext'
4
5
  import { useInventoryContext } from '../../context/InventoryContext'
5
6
 
7
+ const ANVIL_FOCUS_KEYS = ['KeyE'] as const
8
+
6
9
  interface AnvilInputProps {
7
10
  x: number
8
11
  y: number
@@ -21,6 +24,8 @@ export function AnvilInput({ x, y, width, height }: AnvilInputProps) {
21
24
 
22
25
  const hasInputItem = windowState?.slots.some((s) => s.index === 0 && s.item !== null) ?? false
23
26
 
27
+ useFocusInputShortcut(inputRef, ANVIL_FOCUS_KEYS, hasInputItem)
28
+
24
29
  const textFieldUrl = textures.getGuiTextureUrl(
25
30
  hasInputItem
26
31
  ? '1.21.11/textures/gui/sprites/container/anvil/text_field.png'
@@ -2,6 +2,7 @@ import React, { useState, useMemo, useCallback, useEffect, useLayoutEffect, useR
2
2
  import type { ItemStack, RecipeGuide, RecipeNavFrame, BlockTextureRender } from '../../types'
3
3
  import { useScale } from '../../context/ScaleContext'
4
4
  import { useInventoryContext } from '../../context/InventoryContext'
5
+ import { useSlashFocusInput } from '../../hooks/useFocusInputShortcut'
5
6
  import { Slot } from '../Slot'
6
7
  import { StarIcon } from './StarIcon'
7
8
  import styles from './JEI.module.css'
@@ -88,6 +89,8 @@ export function JEI({
88
89
  // Self-measured dimensions so the panel can be width:100% and fill its container
89
90
  const rootRef = useRef<HTMLDivElement>(null)
90
91
  const gridRef = useRef<HTMLDivElement>(null)
92
+ const searchInputRef = useRef<HTMLInputElement>(null)
93
+ useSlashFocusInput(searchInputRef, true)
91
94
  const [measuredCols, setMeasuredCols] = useState(ITEMS_PER_ROW)
92
95
  const [measuredRows, setMeasuredRows] = useState(5)
93
96
 
@@ -250,6 +253,7 @@ export function JEI({
250
253
  }}
251
254
  >
252
255
  <input
256
+ ref={searchInputRef}
253
257
  type="text"
254
258
  value={search}
255
259
  onChange={handleSearchChange}
@@ -0,0 +1,46 @@
1
+ import { useEffect, useMemo, type RefObject } from 'react'
2
+
3
+ function isTypingTarget(el: EventTarget | null): boolean {
4
+ if (!el || !(el instanceof HTMLElement)) return false
5
+ const tag = el.tagName
6
+ if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT') return true
7
+ if (el.isContentEditable) return true
8
+ return false
9
+ }
10
+
11
+ const SLASH_KEYS = ['Slash', 'NumpadDivide'] as const
12
+
13
+ /**
14
+ * Focus the input when one of the given keys is pressed; prevents the key from being typed.
15
+ * Skips when focus is in another input/textarea/select/contenteditable (same idea as useCloseOnWClick).
16
+ */
17
+ export function useFocusInputShortcut(
18
+ inputRef: RefObject<HTMLInputElement | null>,
19
+ keyCodes: readonly string[],
20
+ enabled = true,
21
+ ) {
22
+ const codesSet = useMemo(() => new Set(keyCodes), [keyCodes])
23
+
24
+ useEffect(() => {
25
+ if (!enabled) return
26
+
27
+ const onKeyDown = (e: KeyboardEvent) => {
28
+ if (!codesSet.has(e.code)) return
29
+ if (e.repeat) return
30
+ if (e.ctrlKey || e.metaKey || e.altKey) return
31
+ if (isTypingTarget(e.target)) return
32
+ const el = inputRef.current
33
+ if (!el || el.disabled) return
34
+ e.preventDefault()
35
+ el.focus()
36
+ }
37
+
38
+ window.addEventListener('keydown', onKeyDown)
39
+ return () => window.removeEventListener('keydown', onKeyDown)
40
+ }, [enabled, inputRef, codesSet])
41
+ }
42
+
43
+ /** `/` or numpad `/` — focus JEI search (when JEI is mounted). */
44
+ export function useSlashFocusInput(inputRef: RefObject<HTMLInputElement | null>, enabled = true) {
45
+ useFocusInputShortcut(inputRef, SLASH_KEYS, enabled)
46
+ }