11import React , { ChangeEvent , FormEvent , KeyboardEvent , useCallback , useRef , useState } from 'react' ;
22import { useDispatch , useSelector } from 'react-redux' ;
33
4- import { wsExecuteStdin } from './reducers/output/execute' ;
4+ import { Button , ButtonSet , IconButton } from './ButtonSet' ;
5+ import PopButton , { ButtonProps , MenuProps } from './PopButton' ;
6+ import { wsExecuteStdin , wsExecuteStdinClose } from './reducers/output/execute' ;
57import { enableStdinSelector } from './selectors' ;
68
79import styles from './Stdin.module.css' ;
@@ -20,6 +22,10 @@ const Stdin: React.FC = () => {
2022 e . preventDefault ( ) ;
2123 form . current ?. dispatchEvent ( new Event ( 'submit' , { bubbles : true , cancelable : true } ) ) ;
2224 }
25+
26+ if ( e . key === 'd' && e . ctrlKey && content . length === 0 ) {
27+ dispatch ( wsExecuteStdinClose ( ) ) ;
28+ }
2329 } ,
2430 [ dispatch , form , content ] ,
2531 ) ;
@@ -42,26 +48,73 @@ const Stdin: React.FC = () => {
4248 [ dispatch , content , setContent ] ,
4349 ) ;
4450
51+ const menuContainer = useRef < HTMLDivElement | null > ( null ) ;
52+
53+ return (
54+ < div data-test-id = "stdin" >
55+ < form onSubmit = { handleSubmit } className = { styles . form } ref = { form } >
56+ < div className = { styles . multiLine } >
57+ < textarea
58+ rows = { 1 }
59+ onKeyDown = { handleKeyDown }
60+ onChange = { handleChange }
61+ name = "content"
62+ autoComplete = "off"
63+ spellCheck = "false"
64+ className = { styles . text }
65+ value = { content }
66+ disabled = { disabled }
67+ > </ textarea >
68+ < p className = { styles . sizer } > { content } </ p >
69+ </ div >
70+
71+ < ButtonSet className = { styles . buttons } >
72+ < Button isPrimary isSmall type = "submit" disabled = { disabled } iconRight = { ( ) => '⏎' } >
73+ Send
74+ </ Button >
75+
76+ < PopButton Button = { MoreButton } Menu = { MoreMenu } menuContainer = { menuContainer } />
77+ </ ButtonSet >
78+ </ form >
79+ < div ref = { menuContainer } />
80+ </ div >
81+ ) ;
82+ } ;
83+
84+ const MoreButton = React . forwardRef < HTMLButtonElement , ButtonProps > ( ( { toggle } , ref ) => {
85+ const disabled = ! useSelector ( enableStdinSelector ) ;
86+
87+ return (
88+ < IconButton
89+ isSmall
90+ type = "button"
91+ ref = { ref }
92+ title = "Execution control"
93+ onClick = { toggle }
94+ disabled = { disabled }
95+ >
96+ ⋮
97+ </ IconButton >
98+ ) ;
99+ } ) ;
100+ MoreButton . displayName = 'MoreButton' ;
101+
102+ const MoreMenu : React . FC < MenuProps > = ( { close } ) => {
103+ const dispatch = useDispatch ( ) ;
104+
105+ const stdinClose = useCallback ( ( ) => {
106+ dispatch ( wsExecuteStdinClose ( ) ) ;
107+ close ( ) ;
108+ } , [ dispatch , close ] ) ;
109+
45110 return (
46- < form onSubmit = { handleSubmit } className = { styles . form } data-test-id = "stdin" ref = { form } >
47- < div className = { styles . multiLine } >
48- < textarea
49- rows = { 1 }
50- onKeyDown = { handleKeyDown }
51- onChange = { handleChange }
52- name = "content"
53- autoComplete = "off"
54- spellCheck = "false"
55- className = { styles . text }
56- value = { content }
57- disabled = { disabled }
58- > </ textarea >
59- < p className = { styles . sizer } > { content } </ p >
60- </ div >
61- < button type = "submit" disabled = { disabled } >
62- Send
63- </ button >
64- </ form >
111+ < ul className = { styles . menu } >
112+ < li >
113+ < button type = "button" className = { styles . button } onClick = { stdinClose } >
114+ Close stdin
115+ </ button >
116+ </ li >
117+ </ ul >
65118 ) ;
66119} ;
67120
0 commit comments