Skip to content

Commit fbf3cd5

Browse files
committed
Add RowInput component
1 parent a53eae7 commit fbf3cd5

File tree

1 file changed

+141
-2
lines changed

1 file changed

+141
-2
lines changed

gui/src/renderer/components/cell/Input.tsx

Lines changed: 141 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
import React, { useCallback, useContext, useState } from 'react';
1+
import React, { useCallback, useContext, useEffect, useRef, useState } from 'react';
22
import styled from 'styled-components';
33
import { colors } from '../../../config.json';
44
import { mediumText } from '../common-styles';
5-
import { CellDisabledContext } from './Container';
5+
import { CellDisabledContext, Container } from './Container';
66
import StandaloneSwitch from '../Switch';
7+
import ImageView from '../ImageView';
78

89
export const Switch = React.forwardRef(function SwitchT(
910
props: StandaloneSwitch['props'],
@@ -183,3 +184,141 @@ export function AutoSizingTextInput({ onChangeValue, ...otherProps }: IInputProp
183184
</StyledAutoSizingTextInputContainer>
184185
);
185186
}
187+
188+
const StyledCellInputRowContainer = styled(Container)({
189+
backgroundColor: 'white',
190+
marginBottom: '1px',
191+
});
192+
193+
const StyledSubmitButton = styled.button({
194+
border: 'none',
195+
backgroundColor: 'transparent',
196+
padding: '14px 0',
197+
});
198+
199+
const StyledInputWrapper = styled.div({}, (props: { marginLeft: number }) => ({
200+
position: 'relative',
201+
flex: 1,
202+
width: '171px',
203+
marginLeft: props.marginLeft + 'px',
204+
marginRight: '25px',
205+
lineHeight: '24px',
206+
minHeight: '24px',
207+
fontFamily: 'Open Sans',
208+
fontWeight: 'normal',
209+
fontSize: '16px',
210+
padding: '14px 0',
211+
maxWidth: '100%',
212+
}));
213+
214+
const StyledTextArea = styled.textarea({}, (props: { invalid?: boolean }) => ({
215+
position: 'absolute',
216+
top: 0,
217+
left: 0,
218+
width: '100%',
219+
height: '100%',
220+
backgroundColor: 'transparent',
221+
border: 'none',
222+
flex: 1,
223+
lineHeight: '24px',
224+
fontFamily: 'Open Sans',
225+
fontWeight: 'normal',
226+
fontSize: '16px',
227+
resize: 'none',
228+
padding: '14px 0',
229+
color: props.invalid ? colors.red : 'auto',
230+
}));
231+
232+
const StyledInputFiller = styled.div({
233+
whiteSpace: 'pre-wrap',
234+
overflowWrap: 'break-word',
235+
minHeight: '24px',
236+
color: 'transparent',
237+
});
238+
239+
interface IRowInputProps {
240+
onChange?: (value: string) => void;
241+
onSubmit: (value: string) => void;
242+
onFocus?: (event: React.FocusEvent<HTMLTextAreaElement>) => void;
243+
onBlur?: (event?: React.FocusEvent<HTMLTextAreaElement>) => void;
244+
paddingLeft?: number;
245+
invalid?: boolean;
246+
autofocus?: boolean;
247+
}
248+
249+
export function RowInput(props: IRowInputProps) {
250+
const [value, setValue] = useState('');
251+
const textAreaRef = useRef() as React.RefObject<HTMLTextAreaElement>;
252+
253+
const submit = useCallback(() => props.onSubmit(value), [props.onSubmit, value]);
254+
const onChange = useCallback(
255+
(event: React.ChangeEvent<HTMLTextAreaElement>) => {
256+
const value = event.target.value;
257+
setValue(value);
258+
props.onChange?.(value);
259+
},
260+
[props.onChange],
261+
);
262+
const onKeyDown = useCallback(
263+
(event: React.KeyboardEvent<HTMLTextAreaElement>) => {
264+
if (event.key === 'Enter') {
265+
event.preventDefault();
266+
submit();
267+
}
268+
},
269+
[submit],
270+
);
271+
272+
const globalKeyListener = useCallback(
273+
(event: KeyboardEvent) => {
274+
if (event.key === 'Escape') {
275+
event.stopPropagation();
276+
props.onBlur?.();
277+
}
278+
},
279+
[props.onBlur],
280+
);
281+
282+
useEffect(() => {
283+
if (props.autofocus) {
284+
textAreaRef.current?.focus();
285+
}
286+
}, []);
287+
288+
useEffect(() => {
289+
if (props.invalid) {
290+
textAreaRef.current?.focus();
291+
}
292+
}, [props.invalid]);
293+
294+
useEffect(() => {
295+
document.addEventListener('keydown', globalKeyListener, true);
296+
return () => document.removeEventListener('keydown', globalKeyListener, true);
297+
}, []);
298+
299+
return (
300+
<StyledCellInputRowContainer>
301+
<StyledInputWrapper marginLeft={props.paddingLeft ?? 0}>
302+
<StyledInputFiller>{value}</StyledInputFiller>
303+
<StyledTextArea
304+
ref={textAreaRef}
305+
onChange={onChange}
306+
onKeyDown={onKeyDown}
307+
rows={1}
308+
value={value}
309+
invalid={props.invalid}
310+
onFocus={props.onFocus}
311+
onBlur={props.onBlur}
312+
/>
313+
</StyledInputWrapper>
314+
<StyledSubmitButton onClick={submit}>
315+
<ImageView
316+
source="icon-tick"
317+
height={22}
318+
tintColor={colors.green}
319+
tintHoverColor={colors.green90}
320+
/>
321+
</StyledSubmitButton>
322+
</StyledCellInputRowContainer>
323+
);
324+
}

0 commit comments

Comments
 (0)