{"id":25024927,"url":"https://github.com/tlow92/expo-key-event","last_synced_at":"2026-01-03T15:03:10.159Z","repository":{"id":270270014,"uuid":"909816062","full_name":"tlow92/expo-key-event","owner":"tlow92","description":"Provides an interface for reading key events such as from external bluetooth keyboards on Android, iOS and Web.","archived":false,"fork":false,"pushed_at":"2025-03-13T20:51:43.000Z","size":5848,"stargazers_count":18,"open_issues_count":4,"forks_count":4,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-27T02:11:58.449Z","etag":null,"topics":["expo","expo-module","key-event","key-events","react-native"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tlow92.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-12-29T21:20:39.000Z","updated_at":"2025-03-22T17:16:24.000Z","dependencies_parsed_at":null,"dependency_job_id":"a28c239e-d0d7-46b4-bca2-7208f878f23a","html_url":"https://github.com/tlow92/expo-key-event","commit_stats":null,"previous_names":["tlow92/expo-key-event"],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tlow92%2Fexpo-key-event","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tlow92%2Fexpo-key-event/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tlow92%2Fexpo-key-event/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tlow92%2Fexpo-key-event/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tlow92","download_url":"https://codeload.github.com/tlow92/expo-key-event/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248703196,"owners_count":21148117,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["expo","expo-module","key-event","key-events","react-native"],"created_at":"2025-02-05T16:33:40.724Z","updated_at":"2026-01-03T15:03:10.154Z","avatar_url":"https://github.com/tlow92.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003ch2 align=\"center\"\u003eExpo-key-event\u003c/h2\u003e\n\n  \u003cp align=\"center\"\u003e\n    Interface for reading key events from external devices such as Bluetooth keyboards/gamepads.\n    \u003cbr /\u003e\n    \u003ca href=\"https://github.com/tlow92/expo-key-event?tab=readme-ov-file#getting-started\"\u003eGetting started\u003c/a\u003e\n    \u0026middot;\n    \u003ca href=\"https://github.com/tlow92/expo-key-event/issues/new\"\u003eReport Bug\u003c/a\u003e\n  \u003c/p\u003e\n\u003c/div\u003e\n\n\u003cbr /\u003e\n\u003cbr /\u003e\n\n\u003cdiv align=\"center\"\u003e\n  \u003ctable\u003e\n    \u003ctr\u003e\n      \u003ctd align=\"center\"\u003e\n        \u003cstrong\u003eiOS\u003c/strong\u003e\u003cbr/\u003e\n        \u003cimg src=\".github/key-event-ios.gif\" alt=\"iOS preview\" width=\"250\" /\u003e\n      \u003c/td\u003e\n      \u003ctd align=\"center\"\u003e\n        \u003cstrong\u003eAndroid\u003c/strong\u003e\u003cbr/\u003e\n        \u003cimg src=\".github/key-event-android.gif\" alt=\"Android preview\" width=\"250\" /\u003e\n      \u003c/td\u003e\n      \u003ctd align=\"center\"\u003e\n        \u003cstrong\u003eWeb\u003c/strong\u003e\u003cbr/\u003e\n        \u003cimg src=\".github/key-event-web.gif\" alt=\"Web preview\" width=\"350\" /\u003e\n      \u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/table\u003e\n\n\u003c/div\u003e\n\n## Supported platforms\n\n- iOS\n- Android\n- Web\n- macOS (Mac Catalyst \u0026 react-native-macos)\n\n## Requirements\n\nExpo SDK \u003e= 52\n\n## Getting started\n\n`npm i expo-key-event`\n\n\u003cbr /\u003e\n\n## Usage\n\n#### Basic\nAutomatic listening: Key events are listened to as soon as `MyComponent` is mounted.\n\n```tsx\nimport { useKeyEvent } from \"expo-key-event\";\nimport { Text } from \"react-native\";\n\nexport function MyComponent() {\n  const { keyEvent } = useKeyEvent();\n\n  return \u003cText\u003e{keyEvent?.key}\u003c/Text\u003e;\n}\n```\n\n#### Control listening\nManual listening: Key events are listened to when `startListening` is called.\n\n```tsx\nimport { useKeyEvent } from \"expo-key-event\";\nimport { Text, View } from \"react-native\";\n\nexport function MyComponent() {\n  // deprecated way\n  // const { keyEvent, startListening, stopListening } = useKeyEvent(false);\n  // new way\n  const { keyEvent, keyReleaseEvent, startListening, stopListening } =\n    useKeyEvent({ listenOnMount: false });\n\n  return (\n    \u003cView\u003e\n      \u003cText\u003e{keyEvent?.key}\u003c/Text\u003e\n      \u003cButton title=\"Start listening\" onPress={() =\u003e startListening()} /\u003e\n      \u003cButton title=\"Stop listening\" onPress={() =\u003e stopListening()} /\u003e\n    \u003c/View\u003e\n  );\n}\n```\n\n#### Using event listener\nHandling state yourself: If you want to handle the state yourself or don't need the state at all, you can use the `useKeyEventListener` hook instead of the `useKeyEvent` hook.\n\n```tsx\nimport { KeyPressEvent, useKeyEventListener } from \"expo-key-event\";\nimport { Text, View } from \"react-native\";\n\nexport function MyComponent() {\n  const [keyEvent, setKeyEvent] = useState\u003cKeyPressEvent\u003e();\n  // deprecated way\n  // const { startListening, stopListening } = useKeyEventListener((event) =\u003e {\n  //   setKeyEvent(event);\n  // }, automaticControl);\n  // new way\n  const { startListening, stopListening } = useKeyEventListener(\n    (event) =\u003e {\n      setKeyEvent(event);\n    },\n    {\n      listenOnMount: automaticControl,\n    }\n  );\n\n  return (\n    \u003cView\u003e\n      \u003cText\u003e{keyEvent?.key}\u003c/Text\u003e\n      \u003cButton title=\"Start listening\" onPress={() =\u003e startListening()} /\u003e\n      \u003cButton title=\"Stop listening\" onPress={() =\u003e stopListening()} /\u003e\n    \u003c/View\u003e\n  );\n}\n```\n\n#### Modifier keys\nUsing modifier keys: Key events include modifier key states (shift, ctrl, alt, meta) and repeat information when `captureModifiers` is enabled.\n\n```tsx\nimport { useKeyEvent } from \"expo-key-event\";\nimport { Text, View } from \"react-native\";\n\nexport function MyComponent() {\n  const { keyEvent } = useKeyEvent({\n    listenOnMount: true,\n    captureModifiers: true, // Enable modifier key capture\n  });\n\n  return (\n    \u003cView\u003e\n      \u003cText\u003eKey: {keyEvent?.key}\u003c/Text\u003e\n      \u003cText\u003eShift: {keyEvent?.shiftKey ? \"Yes\" : \"No\"}\u003c/Text\u003e\n      \u003cText\u003eCtrl: {keyEvent?.ctrlKey ? \"Yes\" : \"No\"}\u003c/Text\u003e\n      \u003cText\u003eAlt: {keyEvent?.altKey ? \"Yes\" : \"No\"}\u003c/Text\u003e\n      \u003cText\u003eMeta: {keyEvent?.metaKey ? \"Yes\" : \"No\"}\u003c/Text\u003e\n      \u003cText\u003eRepeat: {keyEvent?.repeat ? \"Yes\" : \"No\"}\u003c/Text\u003e\n    \u003c/View\u003e\n  );\n}\n```\n\n#### Modifier key combinations\nChecking for specific key combinations:\n\n```tsx\nimport { useState } from \"react\";\nimport { KeyPressEvent, useKeyEventListener } from \"expo-key-event\";\nimport { Text } from \"react-native\";\n\nexport function MyComponent() {\n  const [message, setMessage] = useState(\"\");\n\n  useKeyEventListener(\n    (event: KeyPressEvent) =\u003e {\n      // Check for Cmd+S (macOS) or Ctrl+S (Windows/Linux)\n      if (event.key === \"KeyS\" \u0026\u0026 (event.metaKey || event.ctrlKey)) {\n        setMessage(\"Save shortcut pressed!\");\n      }\n      // Check for Shift+Enter\n      else if (event.key === \"Enter\" \u0026\u0026 event.shiftKey) {\n        setMessage(\"New line!\");\n      }\n      // Check for Alt+Arrow\n      else if (event.key === \"ArrowRight\" \u0026\u0026 event.altKey) {\n        setMessage(\"Navigate forward!\");\n      }\n    },\n    {\n      listenOnMount: true,\n      captureModifiers: true, // Required to receive modifier key states\n    }\n  );\n\n  return \u003cText\u003e{message}\u003c/Text\u003e;\n}\n```\n\n\u003cbr /\u003e\n\n## Run example app\n\n`cd example`\n\n`npm run ios` / `npm run android` / `npm run web`\n\n\u003cbr /\u003e\n\n## Troubleshooting\n\n### \\_expo.useEvent is not a function\n\nThis is most likely due to using Expo SDK lower than 52. `useEvent` was introduced in SDK 52.\n\n### Error: Cannot find native module 'ExpoKeyEvent'\n\nMake sure to use a development build and not `Expo Go`.\nSee https://docs.expo.dev/guides/local-app-development/ for more details.\n\nIn short: Use `npx expo run:ios` instead of `npx expo start` (make sure bundleIdentifier is set in `app.json`).\n\n### Key events are not registered in iOS simulator\n\nMake sure that hardware keyboard is connected to the simulator.\n\u003cimg src=\".github/connect-hardware-keyboard.png\" alt=\"hardware-keyboard-simulator\" width=\"400px\" /\u003e\n\n### Key events are not registered in Android emulator\n\nSince the Android emulator does not support USB or Bluetooth, you need to use a physical device so that key events can be registered.\n\nAnother option is to use `adb` to send key events to the emulator.\n\ne.g. `adb shell input keyevent 10`\n\n\u003cbr /\u003e\n\n## How it works\n\nThis module translates the [Apple UIKit](https://developer.apple.com/documentation/uikit/uikeyboardhidusage) and [Android KeyEvent](https://developer.android.com/reference/android/view/KeyEvent) constants to a common set of key event types matching the ones from [Web](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftlow92%2Fexpo-key-event","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftlow92%2Fexpo-key-event","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftlow92%2Fexpo-key-event/lists"}