1import { useState, useEffect } from 'react';
2import * as React from 'react';
3
4import { Typography } from '@material-ui/core';
5import Tab from '@material-ui/core/Tab';
6import Tabs from '@material-ui/core/Tabs';
7import TextField from '@material-ui/core/TextField';
8import { makeStyles } from '@material-ui/core/styles';
9
10import Content from '../Content';
11
12/**
13 * Styles
14 */
15const useStyles = makeStyles((theme) => ({
16 container: {
17 margin: theme.spacing(2, 0),
18 padding: theme.spacing(0, 2, 2, 2),
19 },
20 textarea: {
21 '& textarea.MuiInputBase-input': {
22 resize: 'vertical',
23 },
24 },
25 tabContent: {
26 margin: theme.spacing(2, 0),
27 },
28 preview: {
29 overflow: 'auto',
30 borderBottom: `solid 3px ${theme.palette.grey['200']}`,
31 minHeight: '5rem',
32 },
33 previewPlaceholder: {
34 color: theme.palette.text.secondary,
35 fontStyle: 'italic',
36 },
37}));
38
39type TabPanelProps = {
40 children: React.ReactNode;
41 value: number;
42 index: number;
43} & React.HTMLProps<HTMLDivElement>;
44function TabPanel({ children, value, index, ...props }: TabPanelProps) {
45 return (
46 <div
47 role="tabpanel"
48 hidden={value !== index}
49 id={`editor-tabpanel-${index}`}
50 aria-labelledby={`editor-tab-${index}`}
51 {...props}
52 >
53 {value === index && children}
54 </div>
55 );
56}
57
58const a11yProps = (index: number) => ({
59 id: `editor-tab-${index}`,
60 'aria-controls': `editor-tabpanel-${index}`,
61});
62
63type Props = {
64 inputProps?: any;
65 inputText?: string;
66 loading: boolean;
67 onChange: (comment: string) => void;
68};
69
70/**
71 * Component for issue comment input
72 *
73 * @param inputProps Reset input value
74 * @param loading Disable input when component not ready yet
75 * @param onChange Callback to return input value changes
76 */
77function CommentInput({ inputProps, inputText, loading, onChange }: Props) {
78 const [input, setInput] = useState<string>(inputText ? inputText : '');
79 const [tab, setTab] = useState(0);
80 const classes = useStyles();
81
82 useEffect(() => {
83 if (inputProps) setInput(inputProps.value);
84 }, [inputProps]);
85
86 useEffect(() => {
87 onChange(input);
88 }, [input, onChange]);
89
90 return (
91 <div>
92 <Tabs value={tab} onChange={(_, t) => setTab(t)}>
93 <Tab label="Write" {...a11yProps(0)} />
94 <Tab label="Preview" {...a11yProps(1)} />
95 </Tabs>
96 <div className={classes.tabContent}>
97 <TabPanel value={tab} index={0}>
98 <TextField
99 fullWidth
100 label="Comment"
101 placeholder="Leave a comment"
102 className={classes.textarea}
103 multiline
104 value={input}
105 variant="filled"
106 rows="4" // TODO: rowsMin support
107 onChange={(e: any) => setInput(e.target.value)}
108 disabled={loading}
109 />
110 </TabPanel>
111 <TabPanel value={tab} index={1} className={classes.preview}>
112 {input !== '' ? (
113 <Content markdown={input} />
114 ) : (
115 <Typography className={classes.previewPlaceholder}>
116 Nothing to preview.
117 </Typography>
118 )}
119 </TabPanel>
120 </div>
121 </div>
122 );
123}
124
125export default CommentInput;