Skip to content

Commit

Permalink
feat: shortcuts plugin for react
Browse files Browse the repository at this point in the history
  • Loading branch information
y1j2x34 committed Apr 1, 2024
1 parent bbd6d58 commit ff8d01f
Show file tree
Hide file tree
Showing 10 changed files with 215 additions and 0 deletions.
37 changes: 37 additions & 0 deletions packages/react/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"name": "@vgerbot/shortcuts-react",
"version": "1.0.0",
"description": "Shortcuts for React",
"author": "y1j2x34 <[email protected]>",
"homepage": "https://github.com/y1j2x34/shortcuts/tree/main/packages/react#readme",
"license": "MIT",
"main": "lib/index.cjs.js",
"directories": {
"lib": "lib",
"test": "__tests__"
},
"files": [
"lib"
],
"publishConfig": {
"registry": "https://registry.npmmirror.com/"
},
"repository": {
"type": "git",
"url": "git+https://github.com/y1j2x34/shortcuts.git"
},
"scripts": {},
"bugs": {
"url": "https://github.com/y1j2x34/shortcuts/issues"
},
"dependencies": {
"@vgerbot/shortcuts": "^1.0.0",
"react": "^16.8.0"
},
"devDependencies": {
"@types/react": "^16.8.0"
},
"peerDependencies": {
"react": ">= 16.8.0"
}
}
6 changes: 6 additions & 0 deletions packages/react/src/context/KeyboardContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { Keyboard } from '@vgerbot/shortcuts';
import React from 'react';

export const KeyboardContext = React.createContext<Keyboard>(
null as unknown as Keyboard
);
45 changes: 45 additions & 0 deletions packages/react/src/context/KeyboardContextProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { Keyboard } from '@vgerbot/shortcuts';
import { KeyboardConstructorOptions } from '@vgerbot/shortcuts/lib/foundation/KeyboardConstructorOptions';
import React, { useEffect, useRef } from 'react';
import { KeyboardContext } from './KeyboardContext';
const KEYBOARD_PROPS = Symbol('keyboard-props');

type KeyboardProviderProps =
React.PropsWithChildren<KeyboardConstructorOptions>;

interface ReactKeyboard extends Keyboard {
[KEYBOARD_PROPS]: KeyboardProviderProps;
}

export function KeyboardProvider(props: KeyboardProviderProps) {
const keyboardRef = useRef<ReactKeyboard>();
if (!keyboardRef.current) {
keyboardRef.current = new Keyboard(props) as ReactKeyboard;
keyboardRef.current[KEYBOARD_PROPS] = props;
}
useEffect(() => {
const anchor = keyboardRef.current?.getAnchor();
if (!props.anchor || anchor === props.anchor) {
return;
}
keyboardRef.current?.setAnchor(props.anchor);
}, [props.anchor]);
useEffect(() => {
if (
keyboardRef.current &&
keyboardRef.current[KEYBOARD_PROPS] === props
) {
return;
}
keyboardRef.current?.destroy();
const keyboard = (keyboardRef.current = new Keyboard(
props
) as ReactKeyboard);
keyboard[KEYBOARD_PROPS] = props;
}, [props.eventOptions, props.macroRegistry]);
return (
<KeyboardContext.Provider value={keyboardRef.current}>
{props.children}
</KeyboardContext.Provider>
);
}
3 changes: 3 additions & 0 deletions packages/react/src/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './useCommand';
export * from './useKeyboard';
export * from './useShortcutKeyMatch';
10 changes: 10 additions & 0 deletions packages/react/src/hooks/useCommand.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { ShortcutEventHandler } from '@vgerbot/shortcuts';
import { useKeyboard } from './useKeyboard';
import { useEffect } from 'react';

export function useCommand(command: string, callback: ShortcutEventHandler) {
const keyboard = useKeyboard();
useEffect(() => {
return keyboard.on(command, callback);
}, [keyboard, callback]);
}
6 changes: 6 additions & 0 deletions packages/react/src/hooks/useKeyboard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { useContext } from 'react';
import { KeyboardContext } from '../context/KeyboardContext';

export function useKeyboard() {
return useContext(KeyboardContext);
}
13 changes: 13 additions & 0 deletions packages/react/src/hooks/useShortcutKeyMatch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { useEffect } from 'react';
import { useKeyboard } from './useKeyboard';
import { Shortcut, ShortcutEventHandler } from '@vgerbot/shortcuts';

export function useShortcutKeyMatch(
shortcut: string | Shortcut,
callback: ShortcutEventHandler
) {
const keyboard = useKeyboard();
useEffect(() => {
return keyboard.onShortcutKeyMatch(shortcut, callback);
}, [keyboard]);
}
2 changes: 2 additions & 0 deletions packages/react/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './hooks/index';
export * from './context/KeyboardContextProvider';
7 changes: 7 additions & 0 deletions packages/react/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"compilerOptions": {
"jsx": "react"
},
"extends": "../../tsconfig.json",
"include": ["src"]
}
86 changes: 86 additions & 0 deletions packages/react/yarn.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1


"@types/prop-types@*":
version "15.7.12"
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.12.tgz#12bb1e2be27293c1406acb6af1c3f3a1481d98c6"
integrity sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==

"@types/react@^16.8.0":
version "16.14.60"
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.14.60.tgz#f7ab62a329b82826f12d02bc8031d4ef4b5e0d81"
integrity sha512-wIFmnczGsTcgwCBeIYOuy2mdXEiKZ5znU/jNOnMZPQyCcIxauMGWlX0TNG4lZ7NxRKj7YUIZRneJQSSdB2jKgg==
dependencies:
"@types/prop-types" "*"
"@types/scheduler" "^0.16"
csstype "^3.0.2"

"@types/scheduler@^0.16":
version "0.16.8"
resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.8.tgz#ce5ace04cfeabe7ef87c0091e50752e36707deff"
integrity sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==

"@vgerbot/shortcuts@^1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@vgerbot/shortcuts/-/shortcuts-1.0.0.tgz#1d0341b3024f5d795d6cce9887040d072bc27f43"
integrity sha512-KqfEfkvi/mX+oeySNP55/mBQxM/rgA8dssx9UdiTN+TXqdaLkMr3af4bbzVVzioe5X6km5jJ1paJGXKdXgrVfA==
dependencies:
browser-detect "^0.2.28"

browser-detect@^0.2.28:
version "0.2.28"
resolved "https://registry.yarnpkg.com/browser-detect/-/browser-detect-0.2.28.tgz#5688fc22f638390614ebea4646483403fb20ebfb"
integrity sha512-KeWGHqYQmHDkCFG2dIiX/2wFUgqevbw/rd6wNi9N6rZbaSJFtG5kel0HtprRwCGp8sqpQP79LzDJXf/WCx4WAw==
dependencies:
core-js "^2.5.7"

core-js@^2.5.7:
version "2.6.12"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec"
integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==

csstype@^3.0.2:
version "3.1.3"
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81"
integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==

"js-tokens@^3.0.0 || ^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==

loose-envify@^1.1.0, loose-envify@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
dependencies:
js-tokens "^3.0.0 || ^4.0.0"

object-assign@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==

prop-types@^15.6.2:
version "15.8.1"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
dependencies:
loose-envify "^1.4.0"
object-assign "^4.1.1"
react-is "^16.13.1"

react-is@^16.13.1:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==

react@^16.8.0:
version "16.14.0"
resolved "https://registry.yarnpkg.com/react/-/react-16.14.0.tgz#94d776ddd0aaa37da3eda8fc5b6b18a4c9a3114d"
integrity sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==
dependencies:
loose-envify "^1.1.0"
object-assign "^4.1.1"
prop-types "^15.6.2"

0 comments on commit ff8d01f

Please sign in to comment.