1+ import * as React from 'react' ;
2+ import { autorun } from 'mobx' ;
3+ import { disposeOnUnmount , observer } from 'mobx-react' ;
4+
5+ import {
6+ Menu ,
7+ Submenu ,
8+ Separator ,
9+ Item ,
10+ contextMenu
11+ } from 'react-contexify' ;
12+
13+ import { styled } from '../styles' ;
14+
15+ import { UnreachableCheck } from '../util/error' ;
16+
17+ import { ContextMenuItem , ContextMenuState } from '../model/ui/context-menu' ;
18+
19+ @observer
20+ export class HtmlContextMenu < T > extends React . Component < {
21+ menuState : ContextMenuState < T > ,
22+ onHidden : ( ) => void
23+ } > {
24+
25+ componentDidMount ( ) {
26+ // Automatically show the menu when this is rendered:
27+ disposeOnUnmount ( this , autorun ( ( ) => {
28+ const menuState = this . props . menuState ;
29+
30+ // Annoyingly, the menu is not listening immediately after the component
31+ // is mounted, so we have to delay this slightly:
32+ setTimeout ( ( ) => {
33+ contextMenu . show ( {
34+ id : 'menu' ,
35+ event : menuState . event
36+ } ) ;
37+ } , 10 ) ;
38+ } ) ) ;
39+ }
40+
41+ render ( ) {
42+ return < ThemedMenu
43+ id = 'menu'
44+ onVisibilityChange = { this . onVisibilityChange }
45+ >
46+ { this . props . menuState . items . map ( this . renderItem ) }
47+ </ ThemedMenu >
48+ }
49+
50+ renderItem = ( item : ContextMenuItem < T > , i : number ) => {
51+ if ( item . type === 'separator' ) {
52+ return < Separator key = { i } /> ;
53+ } else if ( item . type === 'option' ) {
54+ return < Item
55+ key = { i }
56+ onClick = { ( ) => item . callback ( this . props . menuState . data ) }
57+ disabled = { item . enabled === false }
58+ >
59+ { item . label }
60+ </ Item >
61+ } else if ( item . type === 'submenu' ) {
62+ return < Submenu
63+ key = { i }
64+ label = { item . label }
65+ disabled = { item . enabled === false }
66+ >
67+ { item . items . map ( this . renderItem ) }
68+ </ Submenu >
69+ } else throw new UnreachableCheck ( item , i => i . type ) ;
70+ }
71+
72+ onVisibilityChange = ( visible : boolean ) => {
73+ if ( ! visible ) this . props . onHidden ( ) ;
74+ } ;
75+
76+ }
77+
78+ const ThemedMenu = styled ( Menu ) `
79+ --contexify-menu-bgColor: ${ p => p . theme . mainLowlightBackground } ;
80+ --contexify-item-color: ${ p => p . theme . mainColor } ;
81+ --contexify-separator-color: ${ p => p . theme . containerBorder } ;
82+
83+ --contexify-rightSlot-color: ${ p => p . theme . containerWatermark } ;
84+ --contexify-activeRightSlot-color: ${ p => p . theme . mainColor } ;
85+
86+ --contexify-arrow-color: ${ p => p . theme . containerWatermark } ;
87+ --contexify-activeArrow-color: ${ p => p . theme . mainColor } ;
88+
89+ --contexify-activeItem-color: #fff;
90+ --contexify-activeItem-bgColor: #3498db;
91+ ` ;
0 commit comments