urbit/pkg/interface/webterm/components/input.tsx

129 lines
3.3 KiB
TypeScript
Raw Normal View History

import { BaseInput, Box, Row } from '@tlon/indigo-react';
2020-05-01 05:54:12 +03:00
import React, { Component } from 'react';
2021-07-08 02:17:30 +03:00
export class Input extends Component<any, {}> {
inputRef: React.RefObject<unknown>;
2020-05-01 05:54:12 +03:00
constructor(props) {
super(props);
this.state = {};
2020-05-01 05:54:12 +03:00
this.keyPress = this.keyPress.bind(this);
2020-11-07 00:32:13 +03:00
this.paste = this.paste.bind(this);
this.click = this.click.bind(this);
2020-05-01 05:54:12 +03:00
this.inputRef = React.createRef();
}
componentDidUpdate() {
2020-08-18 02:15:35 +03:00
if (
2021-05-14 01:39:54 +03:00
document.activeElement == this.inputRef.current
2020-08-18 02:15:35 +03:00
) {
2021-05-14 01:39:54 +03:00
// @ts-ignore ref type issues
2020-08-18 02:15:35 +03:00
this.inputRef.current.focus();
2021-05-14 01:39:54 +03:00
// @ts-ignore ref type issues
2020-05-01 05:54:12 +03:00
this.inputRef.current.setSelectionRange(this.props.cursor, this.props.cursor);
}
2020-08-18 02:15:35 +03:00
}
2020-05-01 05:54:12 +03:00
2020-08-18 02:15:35 +03:00
keyPress(e) {
const key = e.key;
2020-11-07 00:32:13 +03:00
// let paste and leap events pass
2021-05-14 01:39:54 +03:00
if ((e.getModifierState('Control') || e.getModifierState('Meta'))
2020-11-07 00:32:13 +03:00
&& (e.key === 'v' || e.key === '/')) {
2020-05-01 05:54:12 +03:00
return;
}
let belt = null;
if (key === 'ArrowLeft')
belt = { aro: 'l' };
else if (key === 'ArrowRight')
belt = { aro: 'r' };
else if (key === 'ArrowUp')
belt = { aro: 'u' };
else if (key === 'ArrowDown')
belt = { aro: 'd' };
else if (key === 'Backspace')
belt = { bac: null };
else if (key === 'Delete')
belt = { del: null };
else if (key === 'Tab')
belt = { ctl: 'i' };
else if (key === 'Enter')
belt = { ret: null };
else if (key.length === 1)
belt = { txt: [key] };
else
belt = null;
2020-05-01 05:54:12 +03:00
if (belt && e.getModifierState('Control')) {
if (belt.txt !== undefined)
belt = { ctl: belt.txt[0] };
} else
if (belt &&
(e.getModifierState('Meta') || e.getModifierState('Alt'))) {
if (belt.bac !== undefined)
belt = { met: 'bac' };
2020-05-01 05:54:12 +03:00
}
if (belt !== null) {
this.props.api.belt(belt);
2020-05-01 05:54:12 +03:00
}
e.preventDefault();
}
paste(e) {
const clipboardData = e.clipboardData || (window as any).clipboardData;
const clipboardText = clipboardData.getData('Text');
this.props.api.belt({ txt: [...clipboardText] });
e.preventDefault();
}
click(e) {
// prevent desynced cursor movement
e.preventDefault();
e.target.setSelectionRange(this.props.cursor, this.props.cursor);
2020-05-01 05:54:12 +03:00
}
2020-08-18 02:15:35 +03:00
render() {
const line = this.props.line;
let prompt = 'connecting...';
if (line) {
if (line.lin) {
prompt = line.lin.join('');
2021-07-07 19:43:30 +03:00
} else if (line.klr) {
// TODO render prompt style
prompt = line.klr.reduce((l, p) => (l + p.text.join('')), '');
}
}
2020-08-18 02:15:35 +03:00
return (
<Row flexGrow={1} position='relative'>
<Box flexShrink={0} width='100%' color='black' fontSize={0}>
<BaseInput
autoFocus
autoCorrect="off"
autoCapitalize="off"
color='lightGray'
minHeight={0}
2020-11-20 01:59:16 +03:00
display='inline-block'
width='100%'
spellCheck="false"
tabindex={0}
wrap="off"
fontFamily="mono"
id="term"
cursor={this.props.cursor}
onKeyDown={this.keyPress}
onClick={this.click}
onPaste={this.paste}
2021-05-14 01:39:54 +03:00
// @ts-ignore indigo-react doesn't let us pass refs
ref={this.inputRef}
defaultValue="connecting..."
value={prompt}
/>
</Box>
</Row>
2020-05-01 05:54:12 +03:00
);
}
}
export default Input;