From 7ad448396bc375baf26ebb2ebec85483fc3f5c5a Mon Sep 17 00:00:00 2001 From: xiaowei Date: Thu, 5 Nov 2020 19:22:26 +0800 Subject: [PATCH] feat: add draft contextMenu component --- src/components/contextMenu/index.tsx | 60 +++++---- src/components/contextMenu/style.scss | 5 + stories/components/ContextMenu.stories.tsx | 140 +++++++++++++++++++++ 3 files changed, 181 insertions(+), 24 deletions(-) create mode 100644 stories/components/ContextMenu.stories.tsx diff --git a/src/components/contextMenu/index.tsx b/src/components/contextMenu/index.tsx index cd464dcba..b968e1818 100644 --- a/src/components/contextMenu/index.tsx +++ b/src/components/contextMenu/index.tsx @@ -1,24 +1,36 @@ -// import * as React from 'react'; -// import { prefixClaName } from 'mo/common/className'; -// import { ContextView } from 'monaco-editor/esm/vs/base/browser/ui/contextview/contextview'; -// import { StandardMouseEvent } from 'monaco-editor/esm/vs/base/browser/mouseEvent'; - -// export interface IContextMenuProps { - -// } - -// const ContextMenu: React.FunctionComponent = function(props) { -// const view = new ContextView(); - -// return ( -//
-// { -// props.children -// } -//
-// ); -// } - -// export { -// ContextMenu -// } +import * as React from 'react'; +import { HTMLElementType } from 'mo/common/dom'; +import { useContextView } from 'mo/components/contextview'; +import './style.scss'; + +export interface IContextMenu { + anchor: HTMLElementType; + render: () => React.ReactNode +} + +export function useContextMenu(props: IContextMenu) { + const { anchor, render } = props; + + if (!anchor) { + return; + } + + const contextView = useContextView(); + + const onContextMenu = (e: MouseEvent) => { + e.preventDefault(); + contextView!.show({ + x: e.clientX, + y: e.clientY, + }, render); + }; + + anchor.addEventListener('contextmenu', onContextMenu); + + const dispose = () => { + contextView!.hide(); + anchor.removeEventListener('contextmenu', onContextMenu); + }; + + return { contextView, dispose }; +} diff --git a/src/components/contextMenu/style.scss b/src/components/contextMenu/style.scss index e69de29bb..04266d1e0 100644 --- a/src/components/contextMenu/style.scss +++ b/src/components/contextMenu/style.scss @@ -0,0 +1,5 @@ +@import 'mo/style/const'; +$name: 'context-menu'; + +// #{prefix($name)} { +// } diff --git a/stories/components/ContextMenu.stories.tsx b/stories/components/ContextMenu.stories.tsx new file mode 100644 index 000000000..93b805e27 --- /dev/null +++ b/stories/components/ContextMenu.stories.tsx @@ -0,0 +1,140 @@ + +import * as React from 'react'; +import { useContextMenu } from 'mo/components/contextMenu'; +import { useEffect } from 'react'; +import '../demo.scss'; + +export const ContextMenuDemo = () => { + useEffect(() => { + const contextView1 = useContextMenu({ + anchor: document.getElementById('topLeft'), + render() { + return ( + + ); + }, + }); + + const contextView2 = useContextMenu({ + anchor: document.getElementById('topRight'), + render() { + return ( + + ); + }, + }); + + const contextView3 = useContextMenu({ + anchor: document.getElementById('bottomLeft'), + render() { + return ( + + ); + }, + }); + + const contextView4 = useContextMenu({ + anchor: document.getElementById('bottomRight'), + render() { + return ( + + ); + }, + }); + + return function cleanup() { + contextView1?.dispose(); + contextView2?.dispose(); + contextView3?.dispose(); + contextView4?.dispose(); + }; + }); + + return ( +
+
+ Right Click me! +
+
+ Right Click me! +
+
+ Right Click me! +
+
+ Right Click me! +
+
+ ); +}; + + +ContextMenuDemo.story = { + name: 'Basic Demo', +}; + +export default { + title: 'ContextMenu', + component: ContextMenuDemo, +};