1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
5 import * as React from 'react';
6 import { Chips } from '~/components/chips/chips';
7 import { Input, withStyles, WithStyles } from '@material-ui/core';
8 import { StyleRulesCallback } from '@material-ui/core/styles';
10 interface ChipsInputProps<Value> {
12 getLabel?: (value: Value) => string;
13 onChange: (value: Value[]) => void;
14 createNewValue: (value: string) => Value;
17 type CssRules = 'chips' | 'input' | 'inputContainer';
19 const styles: StyleRulesCallback = () => ({
35 export const ChipsInput = withStyles(styles)(
36 class ChipsInput<Value> extends React.Component<ChipsInputProps<Value> & WithStyles<CssRules>> {
42 filler = React.createRef<HTMLDivElement>();
46 this.updateCursorPosition();
49 setText = (event: React.ChangeEvent<HTMLInputElement>) => {
50 this.setState({ text: event.target.value });
53 handleKeyPress = ({ key }: React.KeyboardEvent<HTMLInputElement>) => {
54 if (key === 'Enter') {
55 this.createNewValue();
56 } else if (key === 'Backspace') {
57 this.deleteLastValue();
61 createNewValue = () => {
62 if (this.state.text) {
63 const newValue = this.props.createNewValue(this.state.text);
64 this.setState({ text: '' });
65 this.props.onChange([...this.props.values, newValue]);
69 deleteLastValue = () => {
70 if (this.state.text.length === 0 && this.props.values.length > 0) {
71 this.props.onChange(this.props.values.slice(0, -1));
75 updateCursorPosition = () => {
77 clearTimeout(this.timeout);
79 this.timeout = setTimeout(() => this.forceUpdate());
82 componentDidUpdate(prevProps: ChipsInputProps<Value>){
83 if(prevProps.values !== this.props.values){
84 this.updateCursorPosition();
90 <div className={this.props.classes.chips}>
93 filler={<div ref={this.filler} />}
97 value={this.state.text}
98 onChange={this.setText}
99 onKeyDown={this.handleKeyPress}
101 className: this.props.classes.input,
102 style: this.getInputStyles(),
105 className={this.props.classes.inputContainer} />
109 getInputStyles = (): React.CSSProperties => ({
110 width: this.filler.current
111 ? this.filler.current.offsetWidth + 8
113 right: this.filler.current
114 ? `calc(${this.filler.current.offsetWidth}px - 100%)`