Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Road to v1 #10

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.*
dist
coverage
exampleDist
node_modules
52 changes: 52 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
module.exports = {
plugins: ["react", "jest-dom", "testing-library", "react-hooks"],
extends: [
"eslint:recommended",
"plugin:react-hooks/recommended",
"plugin:react/recommended",
"prettier",
],
settings: {
react: {
pragma: "React",
version: "detect",
},
},
overrides: [
{
files: ["*.test.js", "**/__tests__/**/*.js"],
env: { jest: true },
extends: [
"plugin:jest-dom/recommended",
"plugin:testing-library/recommended",
],
},
{
files: ["**/*.ts"],
parser: "@typescript-eslint/parser",
plugins: ["@typescript-eslint"],
extends: [
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"prettier/@typescript-eslint",
],
rules: {
"@typescript-eslint/no-non-null-assertion": "off",
},
},
],
env: { browser: true, node: true },
parserOptions: {
ecmaVersion: 2020,
sourceType: "module",
ecmaFeatures: {
jsx: true,
},
},
rules: {
"no-console": ["error", { allow: ["warn"] }],
"no-debugger": "error",
"no-alert": "error",
"react/prop-types": "off",
},
};
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@
.DS_Store
npm-debug.log*
.cache
/coverage
/coverage
.eslintcache
38 changes: 24 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,27 +20,27 @@
This module is distributed via [npm][npm] which is bundled with [node][node] and
should be installed as one of your project's `dependencies`:

```
```sh
npm install --save react-use-context-menu
```

or

```
```sh
yarn add react-use-context-menu
```

## Features

- Supports Keyboard navigation
- Fully customizable
- Fully accessible
- No dependencies
- Only 1kb gzipped
- RTL support
- supports touch screen with hold to display!
- Detects the size of the menu and always places it inside the viewport when clicking near the borders.
- ESM and CommonJS dist
- Supports Keyboard navigation
- Fully customizable
- Fully accessible
- No dependencies
- Only 1kb gzipped
- RTL support
- supports touch screen with hold to display!
- Detects the size of the menu and always places it inside the viewport when clicking near the borders.
- ESM and CommonJS dist

## Usage

Expand Down Expand Up @@ -94,8 +94,10 @@ const [
```

### bindMenu

The first element of the result array is an Object used to bind the context menu element.
It has 4 properties:

```js
{
style, // Mandatory
Expand All @@ -104,9 +106,12 @@ It has 4 properties:
tabIndex: -1 // same as above, also this is needed for keyboard navigation
}
```

Keep in mind that you need to spread this over an actual element (like a div or a nav), if you spread it to a Component, then the Component should take care of passing the props to the underlying wrapper element.
If you as well need to access the ref of the element you can simply do:

```jsx

<div {...bindMenu} ref={(el) => {
bindMenu.ref(el);
// put your code here
Expand All @@ -116,21 +121,25 @@ If you as well need to access the ref of the element you can simply do:
### bindMenuItems

The second element is an Object with 3 props:

```js
{
ref, // Mandatory
role: "menuitem", // Optional, if you don't care about a11y 😠
tabIndex: -1 // same as above, also this is needed for kayboard navigation
tabIndex: -1 // same as above, also this is needed for keyboard navigation
}
```

used to bind the menu items. You can spread it or assign the props one by one. Same as above applies.

### useContextTrigger

The third element of the result array is another hook which you should use to bind the trigger component(s), which is the component which will trigger the context menu when right clicked.
It accepts an optional config object for fine tuning and advanced usage

```js
const [bindTrigger] = useContextTrigger({
// those are the default values
// those are the default values
disable: false, // disable the trigger
holdToDisplay: 1000, // time in ms after which the context menu will appear when holding the touch
posX: 0, // distance in pixel from which the context menu will appear related to the right click X coord
Expand All @@ -141,7 +150,7 @@ const [bindTrigger] = useContextTrigger({
});
```

## Examples:
## Examples

You can check the example folder or [this codesandbox][codesandbox-example] for more advanced examples.

Expand All @@ -152,6 +161,7 @@ Other packages are using components which requires lot of configuration and are
Also this is the smallest and most configurable 💃

## Gratitude

This package have been deeply inspired by https://github.com/vkbansal/react-contextmenu, thanks a lot to @vkbansal! 🙏

[npm]: https://www.npmjs.com/
Expand Down
12 changes: 7 additions & 5 deletions babel.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ module.exports = {
"@babel/preset-env",
{
targets: {
node: "current"
}
}
]
]
node: "current",
},
},
],
"@babel/preset-react",
"@babel/preset-typescript",
],
};
30 changes: 30 additions & 0 deletions e2e/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from "react";
import useContextMenu from "../src";

export default function ContextMenuWrapper({ menuConfig, triggerConfig }) {
const [
bindMenu,
bindMenuItem,
useContextTrigger,
{ coords },
] = useContextMenu(menuConfig);
const [bindTrigger] = useContextTrigger(triggerConfig);

return (
<div>
<div>outside</div>
<h1 data-testid="trigger" {...bindTrigger}>
useContextMenu
</h1>

<div data-testid="contextMenu" {...bindMenu}>
<p>
<span>Click coords: {JSON.stringify(coords)}</span>
</p>
<p data-testid="contextMenuItem" {...bindMenuItem}>
Context menu opened
</p>
</div>
</div>
);
}
Loading