Skip to content

Commit

Permalink
Fixed #472 - New Component: Terminal
Browse files Browse the repository at this point in the history
  • Loading branch information
mertsincan committed Jul 1, 2021
1 parent e78af03 commit 821e81e
Show file tree
Hide file tree
Showing 9 changed files with 234 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/assets/style/primereact.css
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,4 @@
@import '../../components/virtualscroller/VirtualScroller.css';
@import '../../components/speeddial/SpeedDial.css';
@import '../../components/blockui/BlockUI.css';
@import '../../components/terminal/Terminal.css';
2 changes: 2 additions & 0 deletions src/components/primereact.all.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,3 +95,5 @@ export * from './utils/Utils';
export * from './virtualscroller/VirtualScroller';
export * from './speeddial/SpeedDial';
export * from './blockui/BlockUI';
export * from './terminalservice/TerminalService';
export * from './terminal/Terminal';
22 changes: 22 additions & 0 deletions src/components/terminal/Terminal.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
.p-terminal {
height: 18rem;
overflow: auto;
}

.p-terminal-prompt-container {
display: flex;
align-items: center;
}

.p-terminal-input {
flex: 1 1 auto;
border: 0 none;
background-color: transparent;
color: inherit;
padding: 0;
outline: 0 none;
}

.p-terminal-input::-ms-clear {
display: none;
}
11 changes: 11 additions & 0 deletions src/components/terminal/Terminal.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import * as React from 'react';

export interface TerminalProps {
id?: string;
style?: object;
className?: string;
welcomeMessage?: string;
prompt?: string;
}

export declare class Terminal extends React.Component<TerminalProps, any> {}
176 changes: 176 additions & 0 deletions src/components/terminal/Terminal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { TerminalService } from '../terminalservice/TerminalService';
import { classNames } from '../utils/Utils';

export class Terminal extends Component {

static defaultProps = {
id: null,
style: null,
className: null,
welcomeMessage: null,
prompt: null
};

static propTypes = {
id: PropTypes.string,
style: PropTypes.object,
className: PropTypes.string,
welcomeMessage: PropTypes.string,
prompt: PropTypes.string
};

constructor(props) {
super(props);

this.state = {
commandText: '',
commands: [],
index: 0
}

this.onClick = this.onClick.bind(this);
this.onInputChange = this.onInputChange.bind(this);
this.onInputKeyDown = this.onInputKeyDown.bind(this);
this.response = this.response.bind(this);
this.clear = this.clear.bind(this);
}

onClick() {
this.input.focus();
}

onInputChange(e) {
this.setState({ commandText: e.target.value });
}

onInputKeyDown(e) {
const code = e.which || e.keyCode;
const commands = this.state.commands;

switch (code) {
//up
case 38:
if (commands && commands.length) {
const prevIndex = this.state.index - 1 < 0 ? commands.length - 1 : this.state.index - 1;
const command = commands[prevIndex];

this.setState({
index: prevIndex,
commandText: command.text
});
}
break;

//enter
case 13:
if (!!this.state.commandText) {
let newCommands = [...commands];
let text = this.state.commandText;

newCommands.push({ text });

this.setState((prevState) => ({
index: prevState.index + 1,
commandText: '',
commands: newCommands
}), () => {
TerminalService.emit('command', text);
});
}

break;

default:
break;
}
}

response(res) {
let commands = this.state.commands;

if (commands && commands.length > 0) {
let _commands = [...commands];
_commands[_commands.length - 1].response = res;

this.setState({ commands: _commands });
}
}

clear() {
this.setState({
commands: [],
index: 0
});
}

componentDidMount() {
TerminalService.on('response', this.response);
TerminalService.on('clear', this.clear);
}

componentDidUpdate() {
this.container.scrollTop = this.container.scrollHeight;
}

componentWillUnmount() {
TerminalService.off('response', this.response);
TerminalService.off('clear', this.clear);
}

renderWelcomeMessage() {
if (this.props.welcomeMessage) {
return <div>{this.props.welcomeMessage}</div>;
}

return null;
}

renderCommand(command, index) {
const { text, response } = command;

return (
<div key={`${text}${index}`}>
<span className="p-terminal-prompt">{this.props.prompt}&nbsp;</span>
<span className="p-terminal-command">{text}</span>
<div className="p-terminal-response">{response}</div>
</div>
)
}

renderContent() {
const commands = this.state.commands.map((c, i) => this.renderCommand(c, i));

return (
<div className="p-terminal-content">
{commands}
</div>
)
}

renderPromptContainer() {
return (
<div className="p-terminal-prompt-container">
<span className="p-terminal-prompt">{this.props.prompt}&nbsp;</span>
<input ref={(el) => this.input = el} type="text" value={this.state.commandText} className="p-terminal-input"
autoComplete="off" onChange={this.onInputChange} onKeyDown={this.onInputKeyDown} />
</div>
)
}

render() {
const className = classNames('p-terminal p-component', this.props.className);
const welcomeMessage = this.renderWelcomeMessage();
const content = this.renderContent();
const prompt = this.renderPromptContainer();

return (
<div ref={(el) => this.container = el} id={this.props.id} className={className} style={this.props.style} onClick={this.onClick}>
{welcomeMessage}
{content}
{prompt}
</div>
);
}
}
6 changes: 6 additions & 0 deletions src/components/terminal/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"main": "./terminal.cjs.js",
"module": "./terminal.esm.js",
"unpkg": "./terminal.min.js",
"types": "./terminal.d.ts"
}
7 changes: 7 additions & 0 deletions src/components/terminalservice/TerminalService.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export interface TerminalServiceOptions {
on(action: string, fn: any): void;
emit(action: string, params?: any): void;
off(action: string, fn: any): void;
}

export declare const TerminalService: TerminalServiceOptions;
3 changes: 3 additions & 0 deletions src/components/terminalservice/TerminalService.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { EventBus } from '../utils/Utils';

export const TerminalService = EventBus();
6 changes: 6 additions & 0 deletions src/components/terminalservice/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"main": "./terminalservice.cjs.js",
"module": "./terminalservice.esm.js",
"unpkg": "./terminalservice.min.js",
"types": "./terminalservice.d.ts"
}

0 comments on commit 821e81e

Please sign in to comment.