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