fkhadra / react-contexify Goto Github PK
View Code? Open in Web Editor NEW๐ Add a context menu to your react app with ease
Home Page: https://fkhadra.github.io/react-contexify/
License: MIT License
๐ Add a context menu to your react app with ease
Home Page: https://fkhadra.github.io/react-contexify/
License: MIT License
Before I could delete object in which I have my context-menu(menu hides before onClick)
Could I trigger onClick after context-menu will be hidden, like before? Or how I can implement delete element now(context-menu triggers on this element)?
Beware to all considering using this repo. Installation of this via NPM absolutely destroy my dependencies, forcing me to have to rebuild from a package. Luckily I create backups everytime i install new packages.
Second attempt bore same results. Do not use this package if you read this. Nice try dev, i'm sure you got lots of people with this little scam.
I do not give my consent for this to be locked/removed as I want others to see this as a warning.
Created to elements with menu for each one. Open first menu, then opened second one - 2 menus appear. After click in non-context zone - both menu disappear.
Also, now have, sometimes, next problem: after click on menu item it still appears.
Hi There,
I'm not sure this is the correct place to ask for help, sorry in advance if it isn't.
I am new to React, so sorry for the crudity...
I am trying to integrate the contextify with react d3-tree component (which basically draws a tree).
I would like to couple the menu item to the tree node, while I am standing over it.
the problem is that I don't have explicit accsess to tree elements. what I do have is the onClick and onMouseOver callbacks which fires back the node in question.
Is there a way to somehow update the menu uppon mouseover event, or am I doomed?
Thanks,
Jonathan
How to add conditional disabled?
I am trying like this disabled={conditional}. But this doesn't works. At least, disabled={true} makes item looks like disabled, onClick will work, but menu will not disappear.
It would be really nice to tell the ContextMenuProvider
that the position where the context-menu opens is not the mouse but the actual element which is provided to the ContextMenuProvider
.
And then a position would be cool like top
, bottom
etc.
<Home>
<ContextMenuProvider id="home-context-menu">
{files.map((file) => (
<ContextMenuProvider id="list-iteme-context-menu">
<div>File</div>
</ContextMenuProvider>
))}
</ContextMenuProvider>
</Home>
const HomeContextMenu = props => (
<ContextMenu id='home-context-menu'>
<Item onClick={props.onClick}>Edit</Item>
</ContextMenu>
);
const ListItemContextMenu = props => (
<ContextMenu id='list-iteme-context-menu'>
<Item onClick={props.onClick}>Delete</Item>
</ContextMenu>
);
Then i did this, and clicked on File i have an error Cannot read property 'offsetWidth' of null
How to make different menus for Home and nested list items?
Hi @fkhadra
example https://codesandbox.io/s/3z3lq9zn1
thanks for nice lib
please when i click right click add row above, add row bellow and delete row
when i select multi rows using check box i want to show delete all text need to show please suggest me
thanks
Hi fkhadra,
I got next problem: I have the parent element with style transform. When I add context menu on child element, then its behaviour incorrectly.
Please, find example below.
import React from 'react';
import { ContextMenu, Item, ContextMenuProvider } from 'react-contexify';
import './App.css';
import 'react-contexify/dist/ReactContexify.min.css'
export default class App extends React.Component<any, any> {
childrenShow: boolean;
constructor(props) {
super(props);
this.childrenShow = true;
this.handleMenuSelect = this.handleMenuSelect.bind(this);
this.handleMenuUnSelect = this.handleMenuUnSelect.bind(this);
this.handleMenuDelete = this.handleMenuDelete.bind(this);
}
render() {
if ( this.childrenShow ) {
return (
<div className="App" style={{marginTop: '200px', transform: 'translate(0)'}}>
<ContextMenuClass handleMenuSelect={this.handleMenuSelect} handleMenuUnSelect={this.handleMenuUnSelect} handleMenuDelete={this.handleMenuDelete} />
</div>
);
}
return (
<div className="App">
Hiden
</div>
);
}
handleMenuUnSelect() {
this.childrenShow = false;
console.log('unSelect triggered');
}
handleMenuSelect() {
this.childrenShow = false;
console.log('select triggered');
}
handleMenuDelete() {
this.childrenShow = false;
console.log('delete triggered');
this.forceUpdate();
}
}
export class ContextMenuClass extends React.Component<any, any> {
render() {
return (
<div>
<ContextMenuProvider id={'context_menu'}>
ContextMenu
</ContextMenuProvider>
<ContextMenu theme="dark" id={'context_menu'}>
<Item onClick={this.props.handleMenuUnSelect} disabled>Unselect</Item>
<Item onClick={this.props.handleMenuSelect} disabled={true}>select</Item>
<Item onClick={this.props.handleMenuDelete}>Delete</Item>
</ContextMenu>
</div>
)
}
}
Please add code or in documentation explain how can Use the Left Click to open menu.
Code given only opens menu on right clicks only.
hello, May I have the demo's source code?
click right button - context menu appears;
press left button and move - context menu still appear;
unpress left button - context menu disappear
When I try to create a menu and right click on said MenuProvider I get thrown with the following error in the console. It seems that this.menu is null and it is trying to access a value of a null object.
I am not sure if I did something wrong, or they should have been a default value for it?
I've seen this issue reported on #60 but after trying the two methods to remedy it I've come up short.
Basically the goal is to have a single element as the context trigger.
I've tried
<ContextMenuProvider id={singleBookmark} event="onClick" className={s.singleContextContainer}>
<i className="fa fa-cog" aria-hidden="true" />
</ContextMenuProvider>
Any idea if I'm doing something fundamentally wrong here? Thanks for any help!
Hi,
We are trying to use react-contexify inside a table element. The table is formed using the package react-table.
We have a couple of scenarios which we wanted the context menu to fulfill:
In the below-mentioned sandbox environment, we are able to get the dynamic disabling of the menu items. But once that is established, the menu item is not clickable.
Note: If we try setting disabled={false}, the click action is triggered.
Sandbox Link: https://codesandbox.io/s/01yn11wkq0
When using react-contexif in a React TypeScript project the project fails to compile and produces the following error:
Failed to compile
C:/Temp/test2/node_modules/react-contexify/index.d.ts
(205,82): Statements are not allowed in ambient contexts.
This error occurred during the build time and cannot be dismissed.
create-react-app --scripts-version react-scripts-ts test1
yarn add react-contexify
import * as React from 'react';
import './App.css';
import {
ContextMenu,
Item,
ContextMenuProvider,
ItemCallback
} from 'react-contexify';
import 'react-contexify/dist/ReactContexify.min.css';
const onClick = ({ event, ref, data, dataFromProvider }: ItemCallback) =>
window.console.log('Hello');
// create your menu first
const MyAwesomeMenu = () => (
<ContextMenu id="menu_id">
<Item onClick={onClick}>Lorem</Item>
</ContextMenu>
);
class App extends React.Component {
render() {
return (
<div className="App">
<ContextMenuProvider id="menu_id">
<div>Some Content ... </div>
</ContextMenuProvider>
<MyAwesomeMenu />
</div>
);
}
}
export default App;
yarn start
Hi, I got strange warning, may be i use wrong implementation or something else. Please check.
my code:
import PropTypes from 'prop-types';
import moment from 'moment';
import { withStyles } from 'material-ui/styles';
import stylesFunc from './ChatTextMsg.styles';
import { ContextMenu, Item, Separator, Submenu, ContextMenuProvider } from 'react-contexify';
const styles = theme => (stylesFunc(theme, scrollWidth()));
class ChatTextMsg extends Component {
constructor(props) {
super(props);
this.state = {};
}
renderMessage({ files, created, from }) {
const { classes } = this.props;
const time = moment(created).format("HH:mm:ss A");
return (
<ContextMenuProvider id="text_bubble">
<li className={ classes.messageItem }>
<p>{
//render text data
}</p>
<p className={classes.messageTime}>{ time }</p>
</li>
</ContextMenuProvider>
)
}
render() {
const { classes, data, activeDialogId } = this.props;
return (
<ul className={data.from === activeDialogId ? `${classes.messageList} his-list` : `${classes.messageList}`}>
{ this.renderMessage(data) }
</ul>
)
}
}
ChatTextMsg.propTypes = {
classes: PropTypes.object.isRequired
};
export default withStyles(styles)(ChatTextMsg);
Hi. I'm hoping you can help with this error. Somehow, it seems like the menu isn't be set in certain situations. I'm adding a context menu in a react-virtualized grid that needs drag and drop. The app has multiple routes provided by react-router. All this to say that I'm having trouble getting the error to occur in isolation.
The problem seems to be when I navigate to the page with this particular menu (other menus seem to be okay). The first right-click causes an error:
Uncaught TypeError: Cannot read property 'offsetWidth' of null
at ContextMenu.setMenuPosition (ContextMenu.js:154)
at commitCallbacks (react-dom.development.js:6163)
at commitLifeCycles (react-dom.development.js:8784)
at commitAllLifeCycles (react-dom.development.js:9946)
at HTMLUnknownElement.callCallback (react-dom.development.js:542)
at Object.invokeGuardedCallbackDev (react-dom.development.js:581)
at invokeGuardedCallback (react-dom.development.js:438)
at commitRoot (react-dom.development.js:10050)
at performWorkOnRoot (react-dom.development.js:11017)
at performWork (react-dom.development.js:10967)
Clicking through the error, the browser complains about this section of code:
//....
key: 'setMenuPosition',
value: function setMenuPosition() {
var browserSize = {
width: window.innerWidth,
height: window.innerHeight
};
var menuSize = {
width: this.menu.offsetWidth, // <--- errors here
height: this.menu.offsetHeight
};
var _state = this.state,
x = _state.x,
y = _state.y;
//....
Stepping through the code, the menu does show up for an instant before it goes away.
What's also interesting is that if I load the page directly (that is, don't navigate to it through menus), right-click works fine.
Here's the component I'm wrapping.
class Front extends Component {
componentDidMount() {
const dragPreview = createDragPreviewImage();
dragPreview.onload = () => this.props.connectDragPreview(dragPreview);
}
render() {
const { appropriation, style, connectDragSource } = this.props;
const text = appropriation.get('Name');
return (
<ContextMenuProvider id="phase_menu"
ref={ref => {
const node = findDOMNode(ref);
connectDragSource(node);
}}
>
<div style={style}>
{text}
<FaFileTextO/>
</div>
</ContextMenuProvider>
);
}
}
Here's the context menu component
class PhaseContextMenu extends Component {
render() {
return (
<ContextMenu id="phase_menu">
<Item onClick={() => console.log("Open")}> Open </Item>
<Item onClick={() => console.log("Close")}> Close </Item>
<Item onClick={() => console.log("Neither")}> Neither </Item>
</ContextMenu>
);
}
}
And here's the use of the menu.
class VirtualGrid extends PureComponent {
//...
render() {
return (
<Fragment>
<ScrollSync>
{/* All the grid stuff including phases, which are context-menu wrapped.*/}
</ScrollSync>
<PhaseContextMenu/>
</Fragment>
);
}
}
It would be really useful to have undefined or null-values in the ContextMenu
because of certain conditions you don't want to display a ContextMenuItem
.
Add support for nested menus
In the spirit of a context menu, I'd like to enable/disable an <Item/>
in the menu based on the node that was clicked. I know there's the disable attribute for this, and the function calls on the <Item/>
pass in the clicked object as well, but I don't see how to get the clicked object before rendering the menu in order to set the disabled flag.
Hello, I have learning on Google Map APIs and want to add a a contextmenu in drawing polygons using React. Since the polygon does not exist utill user finish drawing it, I don't know how to handle this problem, I would appricate if you could help me.
I need to bind a rightclick event in Google Map DrawingManager's onPolygonComplete event, in this funtion:
const handlePolygonComplete=function(polygon){
// add a contextmenu in polygon
};
Because of the way the context menus themselves are rendered outside the React root, there does not seem to be a way to use context menus when the screen has a drawer or overlay on it. The context menus simply render underneath the drawer and overlay and become unclickable, even when the context menu is placed inside the drawer.
I have also tried simply setting the z-index of the context menu, to no avail.
The following code reproduces the issue. Right clicking a drawer item will bring up an unclickable context menu. The drawer is set to be docked, which enables the overlay. When the drawer is not docked and the overlay doesn't render, the menus are indeed clickable, but still render underneath the drawer.
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider'
import darkBaseTheme from 'material-ui/styles/baseThemes/darkBaseTheme'
import getMuiTheme from 'material-ui/styles/getMuiTheme'
import RaisedButton from 'material-ui/RaisedButton'
import Drawer from 'material-ui/Drawer'
import { MenuItem } from 'material-ui/Menu'
import { ContextMenu, ContextMenuProvider, Item as ContextMenuItem, menuProvider } from 'react-contexify'
import registerServiceWorker from './registerServiceWorker'
import 'react-contexify/dist/ReactContexify.min.css'
const ItemContextMenu = () =>
<ContextMenu theme='dark' animation='fade' id='demo-menu'>
<ContextMenuItem>Item 1</ContextMenuItem>
<ContextMenuItem>Item 2</ContextMenuItem>
<ContextMenuItem>Item 3</ContextMenuItem>
</ContextMenu>
class RawItem extends Component {
render () {
return (
<ContextMenuProvider id='demo-menu'>
<MenuItem>{ this.props.children }</MenuItem>
</ContextMenuProvider>
)
}
}
const addContextMenu = menuProvider('demo-menu')
const Item = addContextMenu(RawItem)
class App extends Component {
constructor (props) {
super(props)
this.state = {
open: false
}
}
_toggleDrawer = () => this.setState({ open: !this.state.open })
render() {
return (
<div>
<RaisedButton label='Toggle Drawer' onClick={this._toggleDrawer} />
<Drawer
open={this.state.open}
docked={false}
onRequestChange={open => this.setState({ open })}
>
<Item>Item 1</Item>
<Item>Item 2</Item>
<Item>Item 3</Item>
<ItemContextMenu />
</Drawer>
</div>
)
}
}
ReactDOM.render(
<MuiThemeProvider muiTheme={getMuiTheme(darkBaseTheme)}>
<App />
</MuiThemeProvider>, document.getElementById('root'))
registerServiceWorker()
Hi.
I'm trying to use this in a table where the entire <tr>
would be the right-click target. The problem is that a <div>
is not allowed as a child to a <tbody>
.
Is there an easy way to change the wrapper for the menuProvider
, or better still, not use one?
Hi
On clicking of item, the context-menu disappears, but is there any way that we can control the hiding of context-menu ? Because I want to accommodate a form inside the context-menu. Thanks in advance
next structure doesn't work in case of condition is false
{condition && <Separator/> && <Item label="label" disabled/>}
This relates to what have been discussed with @brezetsky during the issue 27
Hi
I reviewed branch next
and decided that I will add features mentioned in PRs #41 and #42 there as it makes more sense. You addressed already disabling on function and passing data to the onClick.
Therefore I have few items left to add:
visible
prop in Item
which is either boolean
or function
where, function has access to passed data (use case: some items exists only for specific data)toggleContextMenu
as a function, when you need create context without new DOM node (use case: I want div which is draggable and is also context menu provider)Please proceed with next
branch.
Thanks
Right button press and hold - menu appears.
Right button unpress - menu disappears(for Mozilla).
Works for Chrome.
I have ssr setup and I receive document is not defined error
The error fires from withProxy
hoc's componentWillMount hook.
Hello,
I'm trying to make context menu work but I have some issue when I right click on my text that should display the context menu :
js <display::menu> Event is not registered. Did you forgot to bind the event ?
const myMenu = () => (<ContextMenu id="menu">
<Item >Ipsum</Item>
</ContextMenu>);
return {icons: [
<div
style={iconStyle}
/>,
],
title :
<div>
<ContextMenuProvider id="menu">
<span>{rowInfo.node.title}</span>
</ContextMenuProvider>
{myMenu}
</div>
,
onClick: event => this.nodeClicked(event, rowInfo),
style : innerStyle
};
I'm using it with react-sortable-tree to add a contextual menu on my items...
Thanks !
Hi
I have noticed that now if you use css modules in your project and import styles from contexify context menu would not work until setting contexify styles globally. Are there any chances to support css-modules?
Thanks
Hi @fkhadra,
Unconditionally calling this.removeFromBody()
and this.appendToBody(this.props)
on componentWillReceiveProps()
results inconsistent behavior on List items.
react-contexify/src/util/withProxy.js
Line 16 in 20be6ca
This can be easily solved with:
function componentDidUpdate(prevProps) {
if (prevProps !== this.props) {
this.removeFromBody();
this.appendToBody(this.props)
}
}
Let me know if you agree on this, I can send a PR.
Might be a nice feature.
I have an component that based on position (mousemove) should use different data in context menu.
One way that I could work around it is to use my own contextmenu event handler and to open context menu like openContextMenu('menu_id', someData)
that I could use later on in Item
onClick
.
Another would be to have some kind of 'onBeforeContextMenuOpen` where I could calculate data to be passed to context menu.
Btw. right now I'm using ref to pass data to Item.onClick
and I don't really need custom data from 'Item' but it would be great to have custom data passed to ContextMenuProvider passed on Item.onClick
handler.
Due to my context menu's placement, I need to set a stopPropagation call on its parent, which causes Contexify to stop short of opening.
Is there a programatic way to open the context menu, perhaps a hook I can get to? I'll even take a hacky-approach at this point.
Thanks!
Hi, Any idea why I would just start getting the flattenChildren(...): Encountered two children with the same key, 'journal-menu'.
error after upgrading from 2.0.7 => 2.1.2?
As far as I can tell, there's no iteration or lists of components going on where I'm using it except for where I'm using the ContextMenuProfider
.
const JournalListItem = ({item}) => {
const journalId = item.get('Id');
return (
<li data-id={journalId}>
<ContextMenuProvider id="journal-menu">
<Link to={`/journal/${journalId}`}>{item.get('Name')}</Link>
</ContextMenuProvider>
</li>
);
};
Here's the whole message:
Warning: flattenChildren(...): Encountered two children with the same key, `journal-menu`. Child keys must be unique; when two children share a key, only the first child will be used.
in div (created by ProxyContainer)
in ProxyContainer
It looks like there was a ProxyContainer recently added. Could this be it adding duplicate keys, or am I just using it wrong now?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.