Skip to content

Commit

Permalink
Merge pull request #58 from jeff-phillips-18/context-menu-promise
Browse files Browse the repository at this point in the history
feature: withContextMenu support for Promise
  • Loading branch information
jeff-phillips-18 authored May 26, 2023
2 parents 212ed7e + 93ac874 commit a3d5e19
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 3 deletions.
47 changes: 47 additions & 0 deletions packages/demo-app-ts/src/demos/ContextMenus.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,50 @@ export const ContextMenuOnNode = withTopologySetup(() => {
return null;
});

const createDelayedMenu = (): Promise<React.ReactElement[]> => {
return new Promise((resolve) => {
setTimeout(() => {
resolve(defaultMenu);
}, 2000);
});
}
export const ContextMenuPromise = withTopologySetup(() => {
useComponentFactory(defaultComponentFactory);
useComponentFactory(
React.useCallback<ComponentFactory>(kind => {
if (kind === ModelKind.graph) {
return withPanZoom()(GraphComponent);
}
if (kind === ModelKind.node) {
return withDragNode()(withContextMenu(createDelayedMenu)(DemoDefaultNode));
}
return undefined;
}, [])
);
useModel(
React.useMemo(
(): Model => ({
graph: {
id: 'g1',
type: 'graph'
},
nodes: [
{
id: 'n1',
type: 'node',
x: 50,
y: 50,
width: 20,
height: 20
}
]
}),
[]
)
);
return null;
});

export const ContextMenus: React.FunctionComponent = () => {
const [activeKey, setActiveKey] = React.useState<string | number>(0);

Expand All @@ -111,6 +155,9 @@ export const ContextMenus: React.FunctionComponent = () => {
<Tab eventKey={2} title={<TabTitleText>Context Menu on Node</TabTitleText>}>
<ContextMenuOnNode />
</Tab>
<Tab eventKey={3} title={<TabTitleText>Promise Context Menu on Node</TabTitleText>}>
<ContextMenuPromise />
</Tab>
</Tabs>
</div>
);
Expand Down
1 change: 1 addition & 0 deletions packages/demo-app-ts/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import '@patternfly/patternfly/patternfly-addons.css';
import '@patternfly/patternfly/patternfly-theme-dark.css';

ReactDOM.render(<App />, document.getElementById('root'));
20 changes: 17 additions & 3 deletions packages/module/src/behavior/withContextMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as React from 'react';
import { observer } from 'mobx-react';
import { Spinner } from '@patternfly/react-core';
import { GraphElement as TopologyElement } from '../types';
import ElementContext from '../utils/ElementContext';
import ContextMenu from '../components/contextmenu/ContextMenu';
Expand All @@ -12,14 +13,16 @@ export interface WithContextMenuProps {
}

export const withContextMenu = <E extends TopologyElement>(
actions: (element: E) => React.ReactElement[],
actions: (element: E) => React.ReactElement[] | Promise<React.ReactElement[]>,
container?: Element | null | undefined | (() => Element),
className?: string,
atPoint: boolean = true
atPoint: boolean = true,
waitElement: React.ReactElement = <Spinner className="pf-u-mx-md" size="md" />
) => <P extends WithContextMenuProps>(WrappedComponent: React.ComponentType<P>) => {
const Component: React.FunctionComponent<Omit<P, keyof WithContextMenuProps>> = props => {
const element = React.useContext(ElementContext);
const [reference, setReference] = React.useState<Reference | null>(null);
const [elementActions, setElementActions] = React.useState<React.ReactElement[] | null>(null);
const onContextMenu = React.useCallback((e: React.MouseEvent) => {
e.preventDefault();
e.stopPropagation();
Expand All @@ -33,6 +36,17 @@ export const withContextMenu = <E extends TopologyElement>(
);
}, []);

React.useEffect(() => {
if (reference) {
const actionsElements = actions(element as E);
Promise.resolve(actionsElements).then((resultActions) => {
setElementActions(resultActions);
});
} else {
setElementActions(null);
}
}, [element, reference]);

return (
<>
<WrappedComponent {...(props as any)} onContextMenu={onContextMenu} contextMenuOpen={!!reference} />
Expand All @@ -44,7 +58,7 @@ export const withContextMenu = <E extends TopologyElement>(
open
onRequestClose={() => setReference(null)}
>
{actions(element as E)}
{elementActions || waitElement}
</ContextMenu>
) : null}
</>
Expand Down

0 comments on commit a3d5e19

Please sign in to comment.