import React = require('react'); import { observer } from 'mobx-react'; import { observable, action, trace } from 'mobx'; import "./EditableView.scss"; import * as Autosuggest from 'react-autosuggest'; export interface EditableProps { /** * Called to get the initial value for editing * */ GetValue(): string; /** * Called to apply changes * @param value - The string entered by the user to set the value to * @returns `true` if setting the value was successful, `false` otherwise * */ SetValue(value: string, shiftDown?: boolean): boolean; OnFillDown?(value: string): void; OnTab?(): void; /** * The contents to render when not editing */ contents: any; fontStyle?: string; fontSize?: number; height?: number; display?: string; autosuggestProps?: { resetValue: () => void; value: string, onChange: (e: React.ChangeEvent, { newValue }: { newValue: string }) => void, autosuggestProps: Autosuggest.AutosuggestProps }; oneLine?: boolean; editing?: boolean; onClick?: (e: React.MouseEvent) => boolean; } /** * Customizable view that can be given an arbitrary view to render normally, * but can also be edited with customizable functions to get a string version * of the content, and set the value based on the entered string. */ @observer export class EditableView extends React.Component { @observable _editing: boolean = false; constructor(props: EditableProps) { super(props); this._editing = this.props.editing ? true : false; } @action onKeyDown = (e: React.KeyboardEvent) => { if (e.key === "Tab") { this.props.OnTab && this.props.OnTab(); } else if (e.key === "Enter") { if (!e.ctrlKey) { if (this.props.SetValue(e.currentTarget.value, e.shiftKey)) { this._editing = false; } } else if (this.props.OnFillDown) { this.props.OnFillDown(e.currentTarget.value); this._editing = false; } } else if (e.key === "Escape") { this._editing = false; } } @action onClick = (e: React.MouseEvent) => { e.nativeEvent.stopPropagation(); if (!this.props.onClick || !this.props.onClick(e)) { this._editing = true; } e.stopPropagation(); } stopPropagation(e: React.SyntheticEvent) { e.stopPropagation(); } @action setIsFocused = (value: boolean) => { this._editing = value; } render() { if (this._editing) { return this.props.autosuggestProps ? this._editing = false), onPointerDown: this.stopPropagation, onClick: this.stopPropagation, onPointerUp: this.stopPropagation, value: this.props.autosuggestProps.value, onChange: this.props.autosuggestProps.onChange }} /> : this._editing = false)} onPointerDown={this.stopPropagation} onClick={this.stopPropagation} onPointerUp={this.stopPropagation} style={{ display: this.props.display, fontSize: this.props.fontSize }} />; } else { if (this.props.autosuggestProps) this.props.autosuggestProps.resetValue(); return (
{this.props.contents}
); } } }