diff --git a/documentation/.gitignore b/documentation/.gitignore deleted file mode 100644 index b2d6de30..00000000 --- a/documentation/.gitignore +++ /dev/null @@ -1,20 +0,0 @@ -# Dependencies -/node_modules - -# Production -/build - -# Generated files -.docusaurus -.cache-loader - -# Misc -.DS_Store -.env.local -.env.development.local -.env.test.local -.env.production.local - -npm-debug.log* -yarn-debug.log* -yarn-error.log* diff --git a/documentation/README.md b/documentation/README.md deleted file mode 100644 index aaba2fa1..00000000 --- a/documentation/README.md +++ /dev/null @@ -1,41 +0,0 @@ -# Website - -This website is built using [Docusaurus 2](https://docusaurus.io/), a modern static website generator. - -### Installation - -``` -$ yarn -``` - -### Local Development - -``` -$ yarn start -``` - -This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server. - -### Build - -``` -$ yarn build -``` - -This command generates static content into the `build` directory and can be served using any static contents hosting service. - -### Deployment - -Using SSH: - -``` -$ USE_SSH=true yarn deploy -``` - -Not using SSH: - -``` -$ GIT_USER= yarn deploy -``` - -If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch. diff --git a/documentation/babel.config.js b/documentation/babel.config.js deleted file mode 100644 index e00595da..00000000 --- a/documentation/babel.config.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - presets: [require.resolve('@docusaurus/core/lib/babel/preset')], -}; diff --git a/documentation/blog/2021-09-24-new-documentation.md b/documentation/blog/2021-09-24-new-documentation.md deleted file mode 100644 index c36e4aab..00000000 --- a/documentation/blog/2021-09-24-new-documentation.md +++ /dev/null @@ -1,51 +0,0 @@ ---- -slug: new-documentation -title: New Documentation and Support Channel -author: Johannes Klauss -author_title: Software Engineer @ Spaceteams -author_url: https://github.com/johannesklauss -author_image_url: https://avatars0.githubusercontent.com/u/6214415?s=400&v=4 -tags: [documentation, support, v4] ---- - -## New Docs - -The last couple of weeks I overhauled the documentation to better explain how the hook works and what you can do with it. -I hope this will reduce questions that are frequently popping up in the issues panel of the -[Github repo](https://github.com/JohannesKlauss/react-hotkeys-hook). -The new site is powered by [Docusaurus](https://docusaurus.io/), an awesome tool to quickly set up a complete documentation ecosystem. -Be sure to check that out if you yourself have to write a documentation. - -This includes a [Quick Start section](/docs/intro), extensive documentation about [every parameter the hook accepts](/docs/api/use-hotkeys) -with a lot of examples to cover different scenarios, -different approaches, pitfalls and shortcomings. - -The recipes section will get content later on. I might also add a comparison page to other hotkey packages for react, -probably the most interesting would be a comparison to [react-hotkeys](https://github.com/greena13/react-hotkeys). - -If you find any typos, confusing sentences, have questions or think that some points need to be elaborated on, please let -me know by [opening an issue](https://github.com/JohannesKlauss/react-hotkeys-hook/issues/new). - -There is no search functionality yet. I hope to add that soon. - -I will now start the work on version 4, which everyone is welcome to contribute to. There is an -[open issue](https://github.com/JohannesKlauss/react-hotkeys-hook/issues/574) titled "Roadmap to Version 4" where you can -join our discussion about what version 4 should look like and add feature wise. - -## New Support Channel - -Since there are popping up question on all different kind of channels (Github issues, email, private messages, etc.) -on how to use react-hotkeys-hook I added a [discussions](https://github.com/JohannesKlauss/react-hotkeys-hook/discussions) -panel on the Github Repo. If you have questions please use this section to ask them, and I am happy to help you out. -Make sure to use the Q&A category. -Of course you can also ask your questions on [Stackoverflow](https://stackoverflow.com/search?page=1&tab=Relevance&q=react-hotkeys-hook). - -### [Ask a question on Github Discussions](https://github.com/JohannesKlauss/react-hotkeys-hook/discussions/new) -### [Ask a question on Stackoverflow](https://stackoverflow.com/search?page=1&tab=Relevance&q=react-hotkeys-hook) - -Last but not least: thank you all for the ongoing interest in this package. - -## In need for a logo/icon - -I'd love to have an icon for this package, but I have zero talent for graphic design. If anybody would like to contribute -a small and simple logo for this package, I'd more than welcome it. \ No newline at end of file diff --git a/documentation/docs/api/_category_.json b/documentation/docs/api/_category_.json deleted file mode 100644 index a4b6671f..00000000 --- a/documentation/docs/api/_category_.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "label": "API", - "position": 3 -} diff --git a/documentation/docs/api/is-hotkey-pressed.mdx b/documentation/docs/api/is-hotkey-pressed.mdx deleted file mode 100644 index 9307e3ce..00000000 --- a/documentation/docs/api/is-hotkey-pressed.mdx +++ /dev/null @@ -1,47 +0,0 @@ ---- -sidebar_position: 3 -title: isHotkeyPressed ---- - -# isHotkeyPressed API - -Function signature: - -```ts -function isHotkeyPressed(key: string | string[], splitKey: string = ','): boolean -``` - -This function allows us to check if a specific key is pressed by the user. - -```jsx -const isHotkeyPressed = useIsHotkeyPressed(); - -const onClick = () => isHotkeyPressed('shift') ? setCount(count - 1) : setCount(count + 1); -``` - -*** - -## Arguments - -### key - -```ts -key: string | string[] -``` - -The key we want to listen to. This can be a string (like `'a'`, `'shift+a'`) or an array of strings (like `['a', 'shift+a']`). - -### splitKey - -```ts -key: string = ',' -``` - -We can combine to check for multiple keys in one string by separating them with a comma (`,`). We can change -this by passing a different key. - -## Return value - -### boolean - -The function returns `true` if the key or keystroke is currently pressed down, otherwise it will return `false`. diff --git a/documentation/docs/api/use-hotkeys.mdx b/documentation/docs/api/use-hotkeys.mdx deleted file mode 100644 index 0ee094f0..00000000 --- a/documentation/docs/api/use-hotkeys.mdx +++ /dev/null @@ -1,445 +0,0 @@ ---- -sidebar_position: 1 -title: useHotkeys ---- - -import { useState } from "react"; -import { useHotkeys } from "react-hotkeys-hook"; - -# useHotkeys API - -Function signature: - -```ts -function useHotkeys( - keys: string | string[], - callback: (event: KeyboardEvent, handler: HotkeysEvent) => void, - options: Options = {}, - deps: any[] = [] -): React.MutableRef -``` - -*** - -## Arguments - -### `keys` - -```ts -keys: string | string[] -``` - -Set the keystrokes we want the hook to listen to. We can use single or multiple keys, -modifier combinations, arrow keys, function keys, etc. - -#### Listening to all keys - -```jsx -useHotkeys('*', (_, handler) => alert(handler.key)) -``` - -#### Using modifiers - -```jsx -useHotkeys('ctrl+s, shift+w', () => alert('We\'re using modifiers now!')) -``` - -#### Using F keys - -```jsx -useHotkeys('f5', () => alert('F5 was pressed')) -``` - -#### Using multiple keys - -```jsx -useHotkeys('w, a, s, d', () => alert('Player moved!')) -``` - -:::tip Differentiating between multiple possible keys - -If we use a combination of possible keys that use the same hook, we can use `handler.keys` to check which key the user -pressed. - -```jsx -useHotkeys('ctrl+a, shift+b, r, f', (_, handler) => { - switch (handler.keys.join('')) { - case 'a': alert('You pressed ctrl+a!'); - break; - case 'b': alert('You pressed ctrl+b!'); - break; - case 'r': alert('You pressed r!'); - break; - case 'f': alert('You pressed f!'); - break; - } -}) -``` - -::: - -This can also be an array: - -```jsx -useHotkeys(['ctrl+a', 'shift+b', 'r', 'f'], (_, handler) => { - switch (handler.keys.join('')) { - case 'a': alert('You pressed ctrl+a!'); - break; - case 'b': alert('You pressed ctrl+b!'); - break; - case 'r': alert('You pressed r!'); - break; - case 'f': alert('You pressed f!'); - break; - } -}) -``` - -*** - -### `callback` - -```ts -callback: (event: KeyboardEvent, handler: HotkeysEvent) => void -``` - -Gets executed when the defined keystroke gets hit by the user. `event` holds the browsers keyboard event, `handler` passes -some additional information to handle the pressed key. - -#### `event` - -The browsers native keyboard event that gets created when the user hits a key. For a thorough documentation of this event -check out the [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent). - -#### `handler` - -The `handler` holds information about the pressed key. In general, we should only need this object to handle our keyboard -events. -The most important property of the `handler` object is the `keys` prop: - -* `keys: string[]` - This will hold the pressed keystroke. So if we use multiple possible keystroke combinations for the same callback -we can use this property to check which specific keystroke was pressed. - -> There are more properties attached to the handle that currently don't get populated with values. So we can safely ignore those. - -:::info The callback gets memoised - -The callback we pass into the hook gets memoised, so every variable we reference inside the callback must be added to the -dependencies array, otherwise we will get stale values. For more on memoisation in the context of React hooks read -[this nice article](https://medium.com/@sdolidze/react-hooks-memoization-99a9a91c8853). - -::: - -*** - -### `options` - -We can extensively configure how the hook behaves by passing it an `options` object. Below are all properties that the -object takes. - -```js -// Default values -const options = { - enabled: true, - enableOnFormTags: false, - enableOnContentEditable: false, - combinationKey: '+', - splitKey: ',', - scopes: '*', - keyup: undefined, - keydown: true, - preventDefault: false, - description: undefined, - document: undefined, - ignoreModifiers: false, -}; -``` - -```ts -// Type Definitions -type Trigger = boolean | ((keyboardEvent: KeyboardEvent, hotkeysEvent: HotkeysEvent) => boolean) -type FormTags = 'input' | 'textarea' | 'select' | 'INPUT' | 'TEXTAREA' | 'SELECT'; - -type Options = { - enabled?: Trigger - enableOnFormTags?: FormTags[] | boolean - enableOnContentEditable?: boolean - combinationKey?: string - splitKey?: string - scopes?: string | string[] - keyup?: boolean - keydown?: boolean - preventDefault?: Trigger - description?: string - document?: Document - ignoreModifiers?: boolean -}; -``` - -#### Properties - -##### `enabled` - -```ts -enabled: boolean | ((keyboardEvent: KeyboardEvent, hotkeysEvent: HotkeysEvent) => boolean) // default: true -``` - -Determines if the callback should get triggered. Return `false` to __prevent__ the execution -of the callback and `true` to __allow__ the callback to be triggered. You can also pass a function that returns a boolean. - -##### `enableOnFormTags` - -```ts -enableOnFormTags: string[] // default: undefined -``` - -Normally we do not want a hotkey being triggered while a user types something into an input field. In some cases however -this might desirable. We can enable the callback trigger for an input tag using the following values: - -`INPUT`, `TEXTAREA`, `SELECT` - -##### `ignoreEventWhen` - -```ts -ignoreEventWhen: (e: KeyboardEvent) => boolean // default: undefined -``` - -Provides a fine control over what events to ignore. Can be used in special cases, for example - -```js -useHotkeys('a', someCallback, { - ignoreEventWhen: (e) => { - return e.target.className.includes('special-element') - }, -}) -``` - -##### `enabled` - -```ts -enabled: boolean // default: true -``` - -Setting this to `false` prevents the hook from doing anything. - -##### `splitKey` - -```ts -splitKey: string // default: "+" -``` - -Specifies the key that is used to combine multiple hotkeys into keystrokes. The default value is `+`, so `shift+a` triggers -when the user presses the "shift" key __and__ the "a" key. - -##### `scopes` - -To group your hotkeys into different scopes, you can pass a string or an array of strings to the `scopes` property. This -way you can easily enable or disable a group of hotkeys at once. More on this in the -[Grouping Hotkeys together](/docs/documentation/hotkeys-provider) section. -By default all hotkeys are assigned to the wildcard `*` scope. - -##### `keyup` - -```ts -keyup: boolean // default: false -``` - -Set this to `true` if we want the hook to trigger our callback on the browsers `keyUp` event. - -##### `keydown` - -```ts -keydown: boolean // default: true -``` - -Set this to `true` if we want the hook to trigger our callback on the browsers `keyDown` event. This is the default behavior. - -:::tip Setting `keydown` __and__ `keyup` -If we set `keyup` to `true` and __don't__ set the `keydown` prop (leaving the default), React Hotkeys Hook will assume -that we want to only listen to the browsers `keyUp` event. - -If we in fact want the callback to get triggered by both events, we have to explicitly set both properties like so: - -```js -useHotkeys('a', () => someCallback, { - keydown: true, - keyup: true -}) -``` - -::: - -##### `preventDefault` - -```ts -preventDefault: boolean | ((keyboardEvent: KeyboardEvent, hotkeysEvent: HotkeysEvent) => boolean) // default: false -``` - -This flag determines if the default browser behavior should be prevented. `false` is the default value, so the browser -will proceed with its default behavior. Setting this to `true` will prevent __some__ of the default browser behavior. - -A good example for this behavior is the override of `meta+s`, which normally triggers a save page dialog -inside the browser. - -```js -useHotkeys('meta+s', someCallback, { - // This will prevent the browser from showing the save page dialog - preventDefault: true, -}); -``` - -##### `document` - -if our React app uses iframes, we can pass the `document` object of the iframe to the hook. This way the hook will bind -the hotkeys to the iframe instead of the main document. - -```js -import FrameComponent from 'react-frame-component' - -const InsideFrameComponent = () => { - const { document } = useFrame() - - useHotkeys("s", () => console.log("I am triggered inside an iframe"), { document }) - - return
....
-} - -function App() { - return ( - - - - ) -} -``` - -##### `ignoreModifiers` - -```ts -ignoreModifiers: boolean // default: false -``` - -When listening to keystrokes, we can ignore the modifier keys (e.g. `shift`, `alt`, `ctrl`, `meta`) by setting this option -to true. This is especially useful when we want to to listen to secondary key combinations like `shift+1` (producing -the exclamation point `!`). A common use case for this would be to listen to the `/` Character in order to focus a search -input field. - -```tsx -function App() { - useHotkeys('/', () => inputRef.current?.focus(), { ignoreModifiers: true, preventDefault: true }) - - const inputRef = useRef(null) - - return ( - - ) -} -``` - -:::info Why is this necessary? -There are tons of keyboard layouts all across different languages and operating systems. For example, we reach the -hashtag sign `#` via `Shift+3` on a US keyboard, but on a German keyboard it has its own dedicated key. On the other hand -in a German keyboard layout we reach the character `[` via `Option+5` on macOS, but on windows there is a dedicated key for that. - -This is already confusing, and it gets even worse when we consider that users can customize their keyboard layout. -So listening to something like `#` can or cannot involve a shift modifier. - -But there are also two different scenarios possible from our apps view: -We could say that we want to listen to the `#` character, no matter if the user presses `Shift+3` or its own dedicated key. -Here we can ignore any potential modifiers, so we set `ignoreModifiers: true`. -But we could also say that we only want to listen to `Shift+3`, no matter the produced character. In this case we do need to listen to the modifier. - -With this option, react-hotkeys-hook supports both ways. -::: - -*** - -### `deps` - -```ts -deps: any[] // default: [] -``` - -The dependency array lets us use the hook just like Reacts internal `useCallback` or `useMemo` hook. This is where our -dependencies of the callback live. If for example our callback actions depend on a referentially unstable value or a -value that will change over time, we should add this value to our deps array. Check out the -[documentation part](/docs/documentation/useHotkeys/setting-callback-dependencies) -for examples. - -## Return value - -### `React.MutableRef` - -The `useHotkeys` hook returns a React ref. This ref by default holds the value of `null`. We can use this ref to only -trigger the hotkeys if a specific element has been focused by the user. - -```jsx live -function App() { - const [count, setCount] = useState(0); - const ref = useHotkeys("s", () => setCount((prevCount) => prevCount + 1)); - - return ( -
-
Count: {count}
- - -
- ); -} -``` - -:::info Not every html tag is able to receive focus by default -Elements that don't provide any native interactivity like `
`, ``, `

`, etc. cannot receive a focus by default. -If we want to use `

` tags instead of the ` - -
- ) -} -``` - -You can also toggle scopes by using the `toggleScope` function. - -:::tip Get currently active scopes -If your app is highly dynamic and you want to know which scopes are currently active, you can get an array of string via -`enabledScopes` from the context. -::: - -## Set initially active scopes - -You can set the initially active scopes by passing an array of strings to the `initiallyActiveScopes` prop of the `HotkeysProvider`. - -```jsx -import { HotkeysProvider } from 'react-hotkeys-hook'; - -function App() { - return ( - -
-

My App

-
-
- ) -} -``` - -:::info Wildcard scope when using `initiallyActiveScopes` -If you set the `initiallyActiveScopes` prop, the wildcard scope will not be active by default. You would have to set `['scopeA', '*']`. -::: diff --git a/documentation/docs/documentation/installation.mdx b/documentation/docs/documentation/installation.mdx deleted file mode 100644 index 95a9a137..00000000 --- a/documentation/docs/documentation/installation.mdx +++ /dev/null @@ -1,63 +0,0 @@ ---- -sidebar_position: 1 ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; -import CodeBlock from '@theme/CodeBlock'; - -# Installation - -> Note: React 16.8+ is required to use Hooks. - -## Yarn & NPM - -To install the package we use our favorite package manager. - - - - yarn add react-hotkeys-hook - - - npm i react-hotkeys-hook --save - - - -## ES Module - -To use the ES Module we can reference it directly from [unpkg.com](https://unpkg.com): - -```js -import { useHotkeys } from 'https://unpkg.com/browse/react-hotkeys-hook@3.4.0/dist/react-hotkeys-hook.esm.js'; -``` - -## Direct CommonJS Module - -We also have access to a development as well as a minified production bundle for CommonJS: - - - - - {'